Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98169
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 384
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-06 16:52
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-06 20:20:14

    Linux系统提供了input子系统,按键、触摸屏、键盘、鼠标等输入都可以利用input接口函数来实现设备驱动。
    在Linux内核中,input设备用input_dev结构体描述,使用input子系统实现输入设备驱动的时候,驱动的核心工作是向系统报告按键、触摸屏、键盘、鼠标等输入事件(event,通过input_event结构体描述),不再需要关心文件操作接口,因为input子系统已经完成了文件操作接口。
    具体可参考http://blog.csdn.net/ylyuanlu/article/details/6704744

驱动程序代码如下

点击(此处)折叠或打开

  1. //moudle.h 包含了大量加载模块需要的函数和符号的定义
  2. #include <linux/module.h>
  3. //kernel.h以便使用printk()等函数
  4. #include <linux/kernel.h>
  5. //fs.h包含常用的数据结构,如struct file等
  6. #include <linux/fs.h>
  7. //uaccess.h 包含copy_to_user(),copy_from_user()等函数
  8. #include <linux/uaccess.h>
  9. //io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
  10. #include <linux/io.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/pci.h>
  13. //init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
  14. #include <linux/init.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/cdev.h>
  18. #include <linux/gpio.h>
  19. #include <linux/irq.h>
  20. #include <linux/sched.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/poll.h>
  23. #include <linux/input.h>
  24. //irq.h中断与并发请求事件
  25. #include <asm/irq.h>
  26. //下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
  27. //#include <mach/gpio.h>
  28. #include <mach/regs-gpio.h>
  29. #include <plat/gpio-cfg.h>
  30. #include <mach/hardware.h>
  31. #include <mach/map.h>

  32. static struct timer_list button_timer;//定时器
  33. static struct input_dev *button_dev;//输入子系统设备

  34. struct pin_desc {
  35.     int irq;
  36.     char *name;
  37.     unsigned int pin;
  38.     unsigned int button_val;
  39. };

  40. static struct pin_desc pins_desc[6] = {
  41.     {IRQ_EINT(0), "S1", S3C64XX_GPN(0), KEY_L},
  42.     {IRQ_EINT(1), "S2", S3C64XX_GPN(1), KEY_S},
  43.     {IRQ_EINT(2), "S3", S3C64XX_GPN(2), KEY_ENTER},
  44.     {IRQ_EINT(3), "S4", S3C64XX_GPN(3), KEY_LEFTSHIFT},
  45.     {IRQ_EINT(4), "S5", S3C64XX_GPN(4), KEY_BACKSPACE},
  46.     {IRQ_EINT(5), "S6", S3C64XX_GPN(5), KEY_SPACE},
  47. };

  48. static struct pin_desc *irq_pd;

  49. /*中断服务函数*/
  50. static irqreturn_t button_input_irq(int irq, void *dev_id)
  51. {
  52.     /* 10ms后启动定时器 */
  53.     irq_pd = (struct pin_desc *)dev_id;
  54.     mod_timer(&button_timer, jiffies+HZ/100); //jiffies是系统的定时器时间,HZ/100表示10ms
  55.     
  56.     return IRQ_HANDLED;
  57. }

  58. static void button_timer_function(unsigned long data)
  59. {
  60.     struct pin_desc * pindesc = irq_pd;
  61.     unsigned int pinval;

  62.     if (!pindesc)
  63.         return;
  64.     
  65.     pinval = gpio_get_value(pindesc->pin);

  66.     if (pinval)
  67.     {
  68.         /* 松开 : 最后一个参数: 0-松开, 1-按下 */

  69.         input_event(button_dev, EV_KEY, pindesc->button_val, 0);

  70.         input_sync(button_dev);
  71.     }
  72.     else
  73.     {
  74.         /* 按下 */

  75.         input_event(button_dev, EV_KEY, pindesc->button_val, 1);

  76.         input_sync(button_dev);
  77.     }
  78. }


  79. static int button_input_init(void)
  80. {
  81.     int i, ret;

  82.     

  83.     /* 1. 分配一个input_dev结构体 */

  84.     button_dev = input_allocate_device();;



  85.     /* 2. 设置 */

  86.     /* 2.1 能产生哪类事件 */

  87.     set_bit(EV_KEY, button_dev->evbit);//按键类事件

  88.     set_bit(EV_REP, button_dev->evbit);//重复类事件

  89.     

  90.     /* 2.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT,BACKSPACE,SPACE */

  91.     set_bit(KEY_L, button_dev->keybit);

  92.     set_bit(KEY_S, button_dev->keybit);

  93.     set_bit(KEY_ENTER, button_dev->keybit);

  94.     set_bit(KEY_LEFTSHIFT, button_dev->keybit);

  95.     set_bit(KEY_BACKSPACE, button_dev->keybit);

  96.     set_bit(KEY_SPACE, button_dev->keybit);



  97.     /* 3. 注册 */
  98.     ret = input_register_device(button_dev);

  99.     if( ret )
  100.     {
  101.         printk("input_register_device error!\n");
  102.         return -EFAULT;
  103.     }

  104.     

  105.     /* 4. 硬件相关的操作 */

  106.     init_timer(&button_timer);//初始化定时器
  107.     button_timer.function = button_timer_function;//设置定时器处理函数
  108.     add_timer(&button_timer);

  109.     

  110.     for (i = 0; i < 6; i++)

  111.     {
  112.         ret = request_irq(pins_desc[i].irq, button_input_irq, IRQ_TYPE_EDGE_BOTH, pins_desc[i].name, &pins_desc[i]);

  113.         if( ret )
  114.         {
  115.             printk("request IRQ_EINT(%d) error!\n",i);
  116.             free_irq(IRQ_EINT(i), &pins_desc[i]);
  117.         }

  118.     }

  119.     

  120.     return 0;
  121. }

  122. static void button_input_exit(void)
  123. {
  124.     int i;

  125.     for (i = 0; i < 6; i++)

  126.     {

  127.         free_irq(pins_desc[i].irq, &pins_desc[i]);

  128.     }



  129.     del_timer(&button_timer);

  130.     input_unregister_device(button_dev);

  131.     input_free_device(button_dev);    
  132. }

  133. module_init(button_input_init);
  134. module_exit(button_input_exit);

  135. MODULE_LICENSE("GPL");

阅读(1250) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~