您的位置:首页 > 编程语言

S3C6410 按键驱动(五) --- 驱动源代码(我采用自动分配设备号的方法,注册设备)

2012-09-22 18:03 483 查看
/**********wzk_key.c ************/
/******wzk*********/
#include "wzk_key.h"

int DOWN = 0;
/*
#define DEVICE_NAME	"keys"
#define KEY_MAJOR 232

static unsigned long key_table [] = {
S3C64XX_GPN(0),
S3C64XX_GPN(1),
S3C64XX_GPN(2),
S3C64XX_GPN(3),
S3C64XX_GPN(4),
S3C64XX_GPN(5),

};
*/

//timer
void my_timer_callback(unsigned long tmp)
{
DOWN = 0;
printk("timer\n");
}

void init_mytimer(void)
{

init_timer(&mytimer);
mytimer.data = 5;
mytimer.expires = jiffies + 1;
mytimer.function = my_timer_callback;
add_timer(&mytimer);

return;
}

void start_timer(int time_value)
{

int ret;

DOWN = 1;
ret = mod_timer(&mytimer,jiffies + msecs_to_jiffies(time_value));
if(ret)
{
printk("mod_timer error!\n");
return;
}

return;
}

void clear_keys(void)
{
int i;
for(i = 0; i < 6; i++)
{
key_values[i] = '0';
}

return;
}

static irqreturn_t keys_interrupt(int irq,void *dev_id)
{
struct key_irq *key_irqs = (struct key_irq *)dev_id;
int number;

clear_keys();

number = key_irqs->number;
printk("number = %d\n",number);
if(DOWN == 0)
{
switch(number)
{
case 0:
//			key_values[number] = '1';
start_timer(1000);
break;
case 1:
//			key_values[number] = '1';
start_timer(1000);
break;
case 2:
//			key_values[number] = '1';
start_timer(1000);
break;

case 3:
//			key_values[number] = '1';
start_timer(1000);
break;

case 4:
//			key_values[number] = '1';
start_timer(1000);
break;

case 5:
//			key_values[number] = '1';
start_timer(1000);
break;

/*
tmp = readl(S3C64XX_GPNDAT);
down = !(tmp & (1 << number));
break;
*/
default:
key_values[number] = '0';
return IRQ_RETVAL(IRQ_HANDLED);
}

key_values[number] = '1';
ev_press = 1;
wake_up_interruptible(&key_waitq);
/*
if(down != (key_values[number] & 1))
{
key_values[number] = '0' + down;
ev_press = 1;

wake_up_interruptible(&key_waitq);
*/
printk("interrupt\n");
}
return IRQ_RETVAL(IRQ_HANDLED);
}

int s3c6410_keys_open(struct inode *inode,struct file *file)
{

int num;
int ret;

for(num = 0; num < KEYNUM; num++)
{
ret = request_irq(key_irqs[num].irq,keys_interrupt,key_irqs[num].flags,key_irqs[num].name,(void*)&key_irqs[num]);
}

init_mytimer();
return 0;
}

int s3c6410_keys_close(struct inode *inode,struct file *file)
{
int i;
int ret;
for(i = 0; i < KEYNUM; i++)
{
free_irq(key_irqs[i].irq,(void*)&key_irqs[i]);
}

ret = del_timer(&mytimer);
if(ret)
{
printk("timer is using ...\n");
}
return 0;
}

static int s3c6410_keys_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
unsigned long err;
if(!ev_press)
{
wait_event_interruptible(key_waitq,ev_press);
printk("ev_press = %d\n",ev_press);
}

ev_press = 0;

err = copy_to_user((void *)buff,(const void*)(&key_values),min(sizeof(key_values),count));

return min(sizeof(key_values),count);
}

static unsigned int s3c6410_keys_poll(struct file *file,struct poll_table_struct *wait)
{
unsigned int mask = 0;
poll_wait(file,&key_waitq,wait);
if(ev_press)
mask |= POLLIN | POLLRDNORM;
return mask;
}

static long s3c6410_keys_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return 0;
}

//set gpk is interrupt mode
void init_dev(void)
{
unsigned int tmp;

s3c_gpio_cfgpin(key_table[0],S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(key_table[1],S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(key_table[2],S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(key_table[3],S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(key_table[4],S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(key_table[5],S3C_GPIO_SFN(2));

tmp = readl(S3C64XX_GPNCON);
printk("%x\n",tmp);
}

static struct file_operations s3c6410_keys_fops = {
.owner	= THIS_MODULE,
.open = s3c6410_keys_open,
.unlocked_ioctl	= s3c6410_keys_ioctl,
.release = s3c6410_keys_close,
.read = s3c6410_keys_read,
.poll = s3c6410_keys_poll
};

static struct cdev cdev_keys;
struct class * my_class;
dev_t devno;

static int __init s3c6410_keys_init(void)
{
int ret;
//	dev_t devno;
printk(KERN_NOTICE "enter s3c6410_keys_init\n");

devno = MKDEV(KEY_MAJOR,0);

ret = alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
if(ret)
{
printk(KERN_NOTICE "can not register led device");
return ret;
}

cdev_init(&cdev_keys,&s3c6410_keys_fops);
cdev_keys.owner = THIS_MODULE;

ret =cdev_add(&cdev_keys,devno,1);
if(ret)
{
printk(KERN_NOTICE "can not add leds device");
return ret;
}

my_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(my_class))
{
printk("Err: Failed in creating class\n");
return -1;
}

device_create(my_class,NULL,devno,NULL,DEVICE_NAME);

init_dev();

printk(DEVICE_NAME " initialized\n");

return 0;
}

static void __exit s3c6410_keys_exit(void)
{

device_destroy(my_class,devno);
class_destroy(my_class);

cdev_del(&cdev_keys);

unregister_chrdev_region(devno,1);

printk(KERN_NOTICE "s3c6410_keys_exit\n");
}

module_init(s3c6410_keys_init);
module_exit(s3c6410_keys_exit);

MODULE_LICENSE("GPL");


/**********wzk_key.h***********/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <mach/map.h> //S3C64XX_VA_GPIO
#include <plat/gpio-cfg.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <asm/io.h>

#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/timer.h>

#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/irqs.h>

#include <linux/timer.h>
#include <linux/jiffies.h>

#define DEVICE_NAME "keys"
#define KEY_MAJOR 189

static unsigned long key_table [] = {
S3C64XX_GPN(0),
S3C64XX_GPN(1),
S3C64XX_GPN(2),
S3C64XX_GPN(3),
S3C64XX_GPN(4),
S3C64XX_GPN(5),

};

struct key_irq{

int irq;
int number;
unsigned long flags;
char *name;
};

static struct key_irq key_irqs[] = {

{IRQ_EINT(0),0,IRQF_TRIGGER_FALLING,"KEY1"},
//./include/linux/interrupt.h
//./arch/arm/mach-s3c64xx/include/mach/irqs.h
{IRQ_EINT(1),1,IRQF_TRIGGER_FALLING,"KEY2"},
{IRQ_EINT(2),2,IRQF_TRIGGER_FALLING,"KEY3"},
{IRQ_EINT(3),3,IRQF_TRIGGER_FALLING,"KEY4"},
{IRQ_EINT(4),4,IRQF_TRIGGER_FALLING,"KEY5"},
{IRQ_EINT(5),5,IRQF_TRIGGER_FALLING,"KEY6"}
};

static DECLARE_WAIT_QUEUE_HEAD(key_waitq);

#define KEYNUM 6

static volatile int ev_press = 0;
static volatile char key_values[] = {0,0,0,0,0,0};
//static volatile int press_cnt[KEYNUM] = {0,0,0,0,0,0};

static struct timer_list mytimer;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c timer struct table class file