Button驱动

  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/init.h>  
  5. #include <linux/delay.h>  
  6. #include <linux/poll.h>  
  7. #include <linux/irq.h>  
  8. #include <asm/irq.h>  
  9. #include <linux/interrupt.h>  
  10. #include <asm/uaccess.h>  
  11. #include <mach/regs-gpio.h>  
  12. #include <mach/hardware.h>  
  13. #include <linux/platform_device.h>  
  14. #include <linux/cdev.h>  
  15. #include <linux/miscdevice.h>  
  16.   
  17. #include <linux/gpio.h>  
  18. #include <linux/sched.h>  
  19.   
  20. #define DEVICE_NAME     "buttons_liu"  
  21.   
  22.   
  23. //#define DEBUG   
  24. struct button_irq_desc {  
  25.     int irq;  
  26.     int pin;  
  27.     int pin_setting;  
  28.     int number;  
  29.     char *name;   
  30. };  
  31.   
  32. static struct button_irq_desc button_irqs [] = {  
  33.     {IRQ_EINT8 , S3C2410_GPG0 ,  S3C2410_GPG0_EINT8  , 0, "KEY0"},  
  34.     {IRQ_EINT11, S3C2410_GPG3 ,  S3C2410_GPG3_EINT11 , 1, "KEY1"},  
  35.     {IRQ_EINT13, S3C2410_GPG5 ,  S3C2410_GPG5_EINT13 , 2, "KEY2"},  
  36.     {IRQ_EINT14, S3C2410_GPG6 ,  S3C2410_GPG6_EINT14 , 3, "KEY3"},  
  37.     {IRQ_EINT15, S3C2410_GPG7 ,  S3C2410_GPG7_EINT15 , 4, "KEY4"},  
  38.     {IRQ_EINT19, S3C2410_GPG11,  S3C2410_GPG11_EINT19, 5, "KEY5"},  
  39. };  

  40. //static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};  
  41. static int key_values = 0;  
  42.   
  43. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
  44.   
  45. static volatile int ev_press = 0;  
  46.   
  47.   
  48. static irqreturn_t buttons_interrupt(int irq, void *dev_id)  
  49. {  
  50.     struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;  
  51.     int down;  
  52.     // udelay(0);  
  53.       
  54.     /*上升沿触发,GPIO DAT 应该为非0 的数*/  
  55.     down = !s3c2410_gpio_getpin(button_irqs->pin);  //按下down = 1 = !0 //松开down = 0 = !1  
  56.     if (!down) {   
  57.     //printk("rising\n");  
  58.     key_values = button_irqs->number;  
  59.         ev_press = 1;                          //表示中断发生了  
  60.         wake_up_interruptible(&button_waitq);  
  61.     }  
  62.    else {  
  63.     //printk("falling\n");  
  64.     ev_press = 0;  
  65.     return 0;                        // irqrequest_t,可能返回两个特殊的值:IRQ_NONE和IRQ_HANDLED.  
  66.    }                                 // 当中断处理程序检测到一个中断时,但该中断对应的设备并不是在注册处理函数期间指定的产生源时,返回IRQ_NONE;  
  67.     return IRQ_RETVAL(IRQ_HANDLED);  // 当中断处理程序被正确调用,且确实是它所对应的设备产生了中断时,返回IRQ_HANDLED    
  68. }  
  69.   
  70.   
  71. static int s3c24xx_buttons_open(struct inode *inode, struct file *file)  
  72. {  
  73.     int i;  
  74.     int err = 0;  
  75.       
  76.     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {  
  77.     if (button_irqs[i].irq < 0) {  
  78.         continue;  
  79.     }  
  80.   
  81.     /* 设置中断触发方式 IRQ_TYPE_EDGE_FALLING,IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_BOTH ;我们这里设置为上升沿触发*/  
  82.         //err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,   
  83.         //                  button_irqs[i].name, (void *)&button_irqs[i]);  
  84.         err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_RISING,   
  85.                           button_irqs[i].name, (void *)&button_irqs[i]);  
  86.         if (err)  
  87.             break;               //request_irq 返回0表示成功。  
  88.     }  
  89.   
  90.     if (err) {  
  91.         i--;  
  92.         for (; i >= 0; i--) {  
  93.         if (button_irqs[i].irq < 0) {  
  94.         continue;  
  95.         }  
  96.         disable_irq(button_irqs[i].irq);  
  97.             free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);  
  98.         }  
  99.         return -EBUSY;  
  100.     }  
  101.   
  102.     ev_press = 0;  
  103.       
  104.     return 0;  
  105. }  
  106.   
  107.   
  108. static int s3c24xx_buttons_close(struct inode *inode, struct file *file)  
  109. {  
  110.     int i;  
  111.       
  112.     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {  
  113.     if (button_irqs[i].irq < 0) {  
  114.         continue;  
  115.     }  
  116.     free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);  
  117.     }  
  118.   
  119.     return 0;  
  120. }  
  121.   
  122.   
  123. static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)  
  124. {  
  125.     unsigned long err;  
  126.     //int i=0;  
  127.     if (!ev_press) {  
  128.     if (filp->f_flags & O_NONBLOCK)  
  129.         return -EAGAIN;  
  130.     else  
  131.         wait_event_interruptible(button_waitq, ev_press);  
  132.     }  
  133.     if(count != sizeof key_values)  
  134.     return -EINVAL;  
  135.     ev_press = 0;  
  136.     err = copy_to_user(buff, &key_values, sizeof(key_values));  
  137.     return sizeof(key_values);  
  138. }  
  139.   
  140. static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait)  
  141. {  
  142.     unsigned int mask = 0;  
  143.     poll_wait(file, &button_waitq, wait);  
  144.     if (ev_press)  
  145.         mask |= POLLIN | POLLRDNORM;  
  146.     return mask;  
  147. }  
  148.   
  149.   
  150. static struct file_operations dev_fops = {  
  151.     .owner   =   THIS_MODULE,  
  152.     .open    =   s3c24xx_buttons_open,  
  153.     .release =   s3c24xx_buttons_close,   
  154.     .read    =   s3c24xx_buttons_read,  
  155.     .poll    =   s3c24xx_buttons_poll,  
  156. };  
  157.   
  158. static struct miscdevice misc = {  
  159.     .minor = MISC_DYNAMIC_MINOR,  
  160.     .name = DEVICE_NAME,  
  161.     .fops = &dev_fops,  
  162. };  
  163.   
  164. static int __init dev_init(void)  
  165. {  
  166.     int ret;  
  167.   
  168.     ret = misc_register(&misc);  
  169. #ifdef DEBUG  
  170.     printk("debug test\n");//ykz  
  171. #endif  
  172.     printk (DEVICE_NAME"\tinitialized\n");  
  173.   
  174.     return ret;  
  175. }  
  176.   
  177. static void __exit dev_exit(void)  
  178. {  
  179.     misc_deregister(&misc);  
  180. }  
  181.   
  182. module_init(dev_init);  
  183. module_exit(dev_exit);  
  184. MODULE_LICENSE("GPL");  
  185. MODULE_AUTHOR("FriendlyARM Inc.");

 

 request_irq(unsignedintirq,   irq_handler_thandler,     unsignedlongflags,     constchar*name,      void*dev)

 发生对应于第 1个参数 irq 的中断时,则调用第 2 个参数handler 为要注册的中断服务函数(也就是把 handler() 中断服务函数注册到内核中 )。

 第 3 个参数 flags 指定了快速中断或中断共享等中断处理属性

 第 4 个参数 name,通常是设备驱动程序的名称

 第 5 个参数 dev_id 中断名称 可作为共享中断时的中断区别参数,也可以用来指定中断服务函数需要参考的数据地址。建议将设备结构指针作为dev_id参数

 

posted @ 2014-11-20 19:51  来杯绿茶  阅读(291)  评论(0编辑  收藏  举报