/**********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;