天嵌 ARM开发社区

 找回密码
 注册
查看: 2407|回复: 0

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

[复制链接]
freewing 发表于 2015-12-25 09:17:23 | 显示全部楼层 |阅读模式
  前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,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){  
  101.         printk(KERN_ERR "Error: allocate input device failed!\n");  
  102.         return -ENOMEM;  
  103.     }  
  104.   
  105.     __set_bit(EV_KEY, buttons_dev->evbit);  
  106.     __set_bit(EV_REP, buttons_dev->evbit);  
  107.   
  108.     __set_bit(KEY_L,        buttons_dev->keybit);  
  109.     __set_bit(KEY_S,        buttons_dev->keybit);  
  110.     __set_bit(KEY_C,        buttons_dev->keybit);  
  111.     __set_bit(KEY_SPACE,    buttons_dev->keybit);  
  112.     __set_bit(KEY_MINUS,    buttons_dev->keybit);  
  113.     __set_bit(KEY_ENTER,    buttons_dev->keybit);  
  114.     __set_bit(KEY_LEFTCTRL, buttons_dev->keybit);  
  115.     __set_bit(KEY_CAPSLOCK, buttons_dev->keybit);  
  116.   
  117.     printk("1\n");  
  118.     if(input_register_device(buttons_dev)){  
  119.         goto error_1;  
  120.     }  
  121.   
  122.     printk("2\n");  
  123.     init_timer(&timer);  
  124.     timer.function = timer_function;  
  125.     add_timer(&timer);  
  126.   
  127.     printk("3\n");  
  128.     for(i = 0; i != 8; ++i){  
  129.         if(request_irq(buttons_desc[i].irq, irq_handler,   
  130.             IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, buttons_desc[i].name, &buttons_desc[i])){  
  131.             goto error_2;  
  132.         }  
  133.     }  
  134.     printk("4\n");  
  135.       
  136.     return 0;  
  137.   
  138. error_2:  
  139.     for(--i; i >= 0; --i){  
  140.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  141.     }  
  142.     input_unregister_device(buttons_dev);  
  143.   
  144. error_1:  
  145.     input_free_device(buttons_dev);  
  146.   
  147.     return -EBUSY;  
  148. }  
  149.   
  150. static void buttons_exit(void){  
  151.     int i;  
  152.     for(i = 0; i != 8; ++i){  
  153.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  154.     }  
  155.   
  156.     input_unregister_device(buttons_dev);  
  157.     input_free_device(buttons_dev);  
  158. }  
  159.   
  160. module_init(buttons_init);  
  161. module_exit(buttons_exit);  
  162. MODULE_LICENSE("GPL");  
复制代码


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


  咨询热线:020-38373101-801 805



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

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-4-29 06:01 , Processed in 1.031250 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表