Embedsky007的个人空间 https://www.eechina.com/space-uid-114045.html [收藏] [复制] [分享] [RSS]

博客

S5PV210(TQ210)学习笔记——输入子系统驱动

已有 14970 次阅读2015-12-25 11:06 |个人分类:技术文章| S5PV210, 嵌入式, 开发板, 天嵌

   前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了“输入子系统”的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。

  输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份:

  1. #include <linux/types.h>  
  2. #include <linux/module.h>  
  3. #include <linux/input.h>  
  4. #include <linux/timer.h>  
  5. #include <linux/interrupt.h>  
  6. #include <linux/gpio.h>  
  7.   
  8. static struct input_dev *buttons_dev;  
  9. static struct timer_list timer;  
  10. struct button_desc* button_desc = NULL;  
  11.   
  12. struct button_desc{  
  13.     char* name;  
  14.     unsigned int pin;  
  15.     unsigned int irq;  
  16.     unsigned int val;  
  17. };  
  18.   
  19. static struct button_desc buttons_desc[8] = {  
  20.     [0] = {  
  21.         .name = "S1",  
  22.         .pin = S5PV210_GPH0(0),  
  23.         .irq = IRQ_EINT(0),  
  24.         .val = KEY_L,  
  25.     },  
  26.   
  27.     [1] = {  
  28.         .name = "S2",  
  29.         .pin = S5PV210_GPH0(1),  
  30.         .irq = IRQ_EINT(1),  
  31.         .val = KEY_S,  
  32.     },  
  33.   
  34.     [2] = {  
  35.         .name = "S3",  
  36.         .pin = S5PV210_GPH0(2),  
  37.         .irq = IRQ_EINT(2),  
  38.         .val = KEY_C,  
  39.     },  
  40.   
  41.     [3] = {  
  42.         .name = "S4",  
  43.         .pin = S5PV210_GPH0(3),  
  44.         .irq = IRQ_EINT(3),  
  45.         .val = KEY_ENTER,  
  46.     },  
  47.   
  48.     [4] = {  
  49.         .name = "S5",  
  50.         .pin = S5PV210_GPH0(4),  
  51.         .irq = IRQ_EINT(4),  
  52.         .val = KEY_LEFTCTRL,  
  53.     },  
  54.   
  55.     [5] = {  
  56.         .name = "S6",  
  57.         .pin = S5PV210_GPH0(5),  
  58.         .irq = IRQ_EINT(5),  
  59.         .val = KEY_MINUS,  
  60.     },  
  61.   
  62.     [6] = {  
  63.         .name = "S7",  
  64.         .pin = S5PV210_GPH2(6),  
  65.         .irq = IRQ_EINT(22),  
  66.         .val = KEY_CAPSLOCK,  
  67.     },  
  68.   
  69.     [7] = {  
  70.         .name = "S8",  
  71.         .pin = S5PV210_GPH2(7),  
  72.         .irq = IRQ_EINT(23),  
  73.         .val = KEY_SPACE,  
  74.     },  
  75. };  
  76.   
  77. static void timer_function(unsigned long data){  
  78.     if(button_desc == NULL)  
  79.         return;  
  80.   
  81.     if(gpio_get_value(button_desc->pin)){  
  82.         input_event(buttons_dev, EV_KEY, button_desc->val, 0);  
  83.     }  
  84.     else{  
  85.         input_event(buttons_dev, EV_KEY, button_desc->val, 1);  
  86.     }  
  87.     input_sync(buttons_dev);  
  88. }  
  89.   
  90. static irqreturn_t irq_handler(int irq, void *devid){  
  91.     button_desc = (struct button_desc*)devid;  
  92.     mod_timer(&timer, jiffies + HZ/100);  
  93.     return IRQ_RETVAL(IRQ_HANDLED);  
  94. }  
  95.   
  96. static int buttons_init(void){  
  97.     int i;  
  98.       
  99.     buttons_dev = input_allocate_device();  
  100.     if(buttons_dev == NULL){  
    前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了“输入子系统”的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。

  输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份:

  1.      printk(KERN_ERR "Error: allocate input device failed!\n");  
  2.         return -ENOMEM;  
  3.     }  
  4.   
  5.     __set_bit(EV_KEY, buttons_dev->evbit);  
  6.     __set_bit(EV_REP, buttons_dev->evbit);  
  7.   
  8.     __set_bit(KEY_L,        buttons_dev->keybit);  
  9.     __set_bit(KEY_S,        buttons_dev->keybit);  
  10.     __set_bit(KEY_C,        buttons_dev->keybit);  
  11.     __set_bit(KEY_SPACE,    buttons_dev->keybit);  
  12.     __set_bit(KEY_MINUS,    buttons_dev->keybit);  
  13.     __set_bit(KEY_ENTER,    buttons_dev->keybit);  
  14.     __set_bit(KEY_LEFTCTRL, buttons_dev->keybit);  
  15.     __set_bit(KEY_CAPSLOCK, buttons_dev->keybit);  
  16.   
  17.     printk("1\n");  
  18.     if(input_register_device(buttons_dev)){  
  19.         goto error_1;  
  20.     }  
  21.   
  22.     printk("2\n");  
  23.     init_timer(&timer);  
  24.     timer.function = timer_function;  
  25.     add_timer(&timer);  
  26.   
  27.     printk("3\n");  
  28.     for(i = 0; i != 8; ++i){  
  29.         if(request_irq(buttons_desc[i].irq, irq_handler,   
  30.             IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, buttons_desc[i].name, &buttons_desc[i])){  
  31.             goto error_2;  
  32.         }  
  33.     }  
  34.     printk("4\n");  
  35.       
  36.     return 0;  
  37.   
  38. error_2:  
  39.     for(--i; i >= 0; --i){  
  40.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  41.     }  
  42.     input_unregister_device(buttons_dev);  
  43.   
  44. error_1:  
  45.     input_free_device(buttons_dev);  
  46.   
  47.     return -EBUSY;  
  48. }  
  49.   
  50. static void buttons_exit(void){  
  51.     int i;  
  52.     for(i = 0; i != 8; ++i){  
  53.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  54.     }  
  55.   
  56.     input_unregister_device(buttons_dev);  
  57.     input_free_device(buttons_dev);  
  58. }  
  59.   
  60. module_init(buttons_init);  
  61. module_exit(buttons_exit);  
  62. MODULE_LICENSE("GPL");  

 

 

  很显然,基于输入子系统的按键驱动比起直接编写的字符驱动设备要简单的多,不过按键消抖还是要加的,上面的代码加上了按键消抖。

 

TQ210v4开发板:http://www.embedsky.com/index.php?s=/Product/show/id/47.html

TQ210v3开发板:http://www.embedsky.com/index.php?s=/Product/show/id/43.html

TQ210v6开发板:http://www.embedsky.com/index.php?s=/Product/show/id/80.html


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备16069177号 | 京公网安备11010502021702
返回顶部