#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/device.h>//新版内核 #include <linux/gpio.h> #include <plat/gpio-cfg.h> static struct class *key_irq_class; static struct class_device *key_class_irq; volatile unsigned long *gpncon=NULL; volatile unsigned long *gpndat=NULL; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */ static volatile int ev_press = 0; struct key_desc{ unsigned int pin; unsigned int key_val; }; /*键值:按下时,0x01,0x02,0x03,0x04,0x05,0x06*/ /*键值:松开时,0x81,0x82,0x83,0x84,0x85,0x86*/ static unsigned char key_num; struct key_desc keys_desc[6]={ {1,0x01}, {2,0x02}, {3,0x03}, {4,0x04}, {5,0x05}, {6,0x06}, }; static irqreturn_t key_irq(int irq, void *dev_id) { struct key_desc *pin=(struct key_desc*)dev_id; unsigned int pinval; pinval=gpio_get_value(S3C64XX_GPN(pin->pin)); if(pinval) { key_num=0x80|pin->key_val; } else { key_num=pin->key_val; } //printk("*********************"); //printk("key_num= %x\n",key_num); //printk("*********************"); //ev_press=1;/*表示中断发生了*/ wake_up_interruptible(&button_waitq);/*唤醒休眠的进程*/ return IRQ_HANDLED; } static int key_drv_open(struct inode * inode, struct file * file) { request_irq(IRQ_EINT(1),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S1",&keys_desc[0]); request_irq(IRQ_EINT(2),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S2",&keys_desc[1]); request_irq(IRQ_EINT(3),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S3",&keys_desc[2]); request_irq(IRQ_EINT(4),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S4",&keys_desc[3]); request_irq(IRQ_EINT(5),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S5",&keys_desc[4]); request_irq(IRQ_EINT(6),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S6",&keys_desc[5]); return 0; } static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos) { return 0; } ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos) { //返回四个引脚的电平 if(size != 1) return -EINVAL; /*如果没有按键动作发生就休眠*/ wait_event_interruptible(button_waitq, ev_press); /*如果有按键动作,返回键值*/ copy_to_user(buf,&key_num,1); ev_press=0; return 1; } int key_drv_release(struct inode * inode, struct file * file) { free_irq(IRQ_EINT(1),&keys_desc[0]); free_irq(IRQ_EINT(2),&keys_desc[1]); free_irq(IRQ_EINT(3),&keys_desc[2]); free_irq(IRQ_EINT(4),&keys_desc[3]); free_irq(IRQ_EINT(5),&keys_desc[4]); free_irq(IRQ_EINT(6),&keys_desc[5]); return 0; } static struct file_operations key_drv_openration ={ .owner = THIS_MODULE, .open = key_drv_open, .write =key_drv_write, .read=key_drv_read, .release=key_drv_release, }; int major; static int key_drv_init(void) { major=register_chrdev(0,"key_irq",&key_drv_openration); key_irq_class = class_create(THIS_MODULE, "key_irq"); //自动创建设备节点 /* 新版的内核不能用class_device_create 要用device_create*/ key_class_irq = device_create(key_irq_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */ gpncon = (volatile unsigned long*)ioremap(0x7F008830,16); gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位? /*本例中使用的是unsigned long类型刚好是4个字节*/ return 0; } static void key_drv_exit(void) { unregister_chrdev(major,"key_irq"); device_unregister(key_class_irq); class_destroy(key_irq_class); iounmap(gpncon); return 0; } module_init(key_drv_init); module_exit(key_drv_exit); MODULE_LICENSE("GPL");
测试程序:
#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> int main(int argc,char **argv) { int fd; unsigned char key_val; int cnt; fd=open("/dev/key",O_RDWR); if(fd < 0) { printf("can not open!!!\n"); return 0; } while(1) { read(fd,&key_val,1); printf("key_val = 0x%x\n", key_val); } return 0; }测试结果:
[root@Pillar /driver/key/key_IRQ]#./main &
[root@Pillar /driver/key/key_IRQ]#*********************key_num= 81
*********************key_val = 0x81
*********************key_num= 82
*********************key_val = 0x82
*********************key_num= 3
******************************************key_num= 3
******************************************key_num= 83
*********************key_val = 0x3