实例代码如下:

  1. #include <linux/input.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4.  
  5. #include <asm/irq.h>
  6. #include <asm/io.h>
  7.  
  8. #define BUTTON_IRQ 123
  9. static struct input_dev *button_dev ;/*输入设备结构体*/
  10. static irqreturn_t button_interrupt(int irq, void *dummy) /*中断处理函数*/
  11. {
  12. input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & );/*向输入子系统报告产生按键事件*/ ===========》》》》》【3
  13. input_sync(button_dev);/*通知接受者,一个报告发送完毕*/
  14. return IRQ_HANDLED;
  15. }
  16.  
  17. static int __init button_init(void)
  18. {
  19. int error;
  20. if (request_irq(BUTTON_IRQ, button_interrupt, , "button", NULL)) { /*申请中断*/
  21. printk(KERN_ERR "button.c: Can't allocate irq %d\n", BUTTON_IRQ);
  22. return -EBUSY;
  23. }
  24. button_dev=input_allocate_device();/*分配一个设备结构体*/ ===========》》》》》》【1
  25. if(!button_dev)
  26. {
  27. printk(KERN_ERR"button.c:Not enough memory\n");
  28. error= -ENOMEM;
  29. goto err_free_irq;
  30. }
  31. button_dev.evbit[] = BIT_MASK(EV_KEY);/*设置按键信息*/ 设置输入设备所支持的事件类型
  32. button_dev.keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
  33.  
  34. error=input_register_device(button_dev);/*注册一个输入设备*/ ===========》》》》》》【2
  35. if(error)
  36. {
  37. printk(KERN_ERR"failed to register device\n");
  38. goto err_free_dev;
  39. }
  40. return ;
  41.  
  42. err_free_dev:
  43. input_free_device(button_dev);
  44. err_free_irq:
  45. free_irq(BUTTON_IRQ,button_interrupt);
  46. return error;
  47. }
  48.  
  49. static void __exit button_exit(void)
  50. {
  51. input_unregister_device(button_dev);/*注销按键设备*/
  52. free_irq(BUTTON_IRQ, button_interrupt);/*释放按键占用的中断*/
  53. }
  54.  
  55. module_init(button_init);
  56. module_exit(button_exit);
  1. 1input_allocate_device()函数分配一个input_dev结构体,输入设备用input_dev结构体描述。
  1. struct input_dev *input_allocate_device(void)
  2. {
  3. struct input_dev *dev;
  4.  
  5. dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);/*分配一个input_dev结构体,并初始化为0*/
  6. if (dev) {
  7. dev->dev.type = &input_dev_type;/*初始化设备类型*/
  8. dev->dev.class = &input_class;/*设置为输入设备类*/
  9. device_initialize(&dev->dev);/*初始化device结构*/
  10. mutex_init(&dev->mutex);/*初始化互斥锁*/
  11. spin_lock_init(&dev->event_lock);/*初始化事件自旋锁*/
  12. INIT_LIST_HEAD(&dev->h_list);/*初始化链表*/
  13. INIT_LIST_HEAD(&dev->node);/*初始化链表*/
  14.  
  15. __module_get(THIS_MODULE);
  16. }
  17.  
  18. return dev;
  19. }

【2】input_register_device()将input_dev结构体注册到输入子系统核心中。

  1. int input_register_device(struct input_dev *dev)
  2. {
  3. static atomic_t input_no = ATOMIC_INIT();
  4. struct input_handler *handler;
  5. const char *path;
  6. int error;
  7.  
  8. /* Every input device generates EV_SYN/SYN_REPORT events. */
  9. __set_bit(EV_SYN, dev->evbit);/*设置input_dev所支持的事件类型,由input_dev的evbit成员来表示*/
  10.  
  11. /* KEY_RESERVED is not supposed to be transmitted to userspace. */
  12. __clear_bit(KEY_RESERVED, dev->keybit);
  13.  
  14. /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
  15. input_cleanse_bitmasks(dev);
  16.  
  17. /*
  18. * If delay and period are pre-set by the driver, then autorepeating
  19. * is handled by the driver itself and we don't do it in input.c.
  20. */
  21. init_timer(&dev->timer);/*初始化一个timer定时器,为处理重复击键*/
  22. if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
  23. dev->timer.data = (long) dev;
  24. dev->timer.function = input_repeat_key;
  25. dev->rep[REP_DELAY] = ;/*这两个值没有定义则设为默认,为自动处理重复按键定义*/
  26. dev->rep[REP_PERIOD] = ;
  27. }
  28.  
  29. /*检查函数是否定义,未定义则使用默认*/
  30. if (!dev->getkeycode)
  31. dev->getkeycode = input_default_getkeycode;/*得到键值*/
  32.  
  33. if (!dev->setkeycode)
  34. dev->setkeycode = input_default_setkeycode;/*设置键值*/
  35.  
  36. dev_set_name(&dev->dev, "input%ld",
  37. (unsigned long) atomic_inc_return(&input_no) - );/*设置input_dev中的device 的名字,以input0/1/2出现在sysfs文件系统中*/
  38.  
  39. error = device_add(&dev->dev);
  40. if (error)
  41. return error;
  42.  
  43. path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
  44. printk(KERN_INFO "input: %s as %s\n",
  45. dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
  46. kfree(path);
  47.  
  48. error = mutex_lock_interruptible(&input_mutex);
  49. if (error) {
  50. device_del(&dev->dev);
  51. return error;
  52. }
  53.  
  54. list_add_tail(&dev->node, &input_dev_list);/*加入链表*/
  55.  
  56. list_for_each_entry(handler, &input_handler_list, node)
  57. input_attach_handler(dev, handler);/*调用input_attach_handler来匹配input_dev和handler*/===========》》》》》》【2.1
  58.  
  59. input_wakeup_procfs_readers();
  60.  
  61. mutex_unlock(&input_mutex);
  62.  
  63. return ;
  64. }
  1.   其中input_dev所支持的事件类型在include/linux/input.h中定义,如下:
     
     2.1input_attach_handler()匹配input_devhandler
  1. static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
  2. {
  3. const struct input_device_id *id;
  4. int error;
  5.  
  6. id = input_match_device(handler, dev);/*handler 与dev之间的匹配*/
  7. if (!id)
  8. return -ENODEV;
  9.  
  10. error = handler->connect(handler, dev, id);/*匹配成功,则调用connect将handler与dev连接起来*/
  11. if (error && error != -ENODEV)
  12. printk(KERN_ERR
  13. "input: failed to attach handler %s to device %s, "
  14. "error: %d\n",
  15. handler->name, kobject_name(&dev->dev.kobj), error);
  16.  
  17. return error;
  18. }

总结【2】:注册input device 就是为input device 设置默认值,并将其挂接到input_dev_list中,并且与挂载在input_handler_list中的handler相匹配,如果匹配成功,则调用connect。

【3】input_report_key()向输入子系统报告发生的事件:

  1. static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
  2. {
  3. input_event(dev, EV_KEY, code, !!value);
  4. }
  1. input_event()报告指定typevalue的输入事件:
  1. void input_event(struct input_dev *dev,
  2. unsigned int type, unsigned int code, int value)
  3. {
  4. unsigned long flags;
  5.  
  6. if (is_event_supported(type, dev->evbit, EV_MAX)) {
  7.  
  8. spin_lock_irqsave(&dev->event_lock, flags);
  9. add_input_randomness(type, code, value);
  10. input_handle_event(dev, type, code, value);//向输入子系统传送事件信息,,不继续深入分析了-------------------------!!
  11. spin_unlock_irqrestore(&dev->event_lock, flags);
  12. }
  13. }
  1.  

linux 输入子系统(2)----简单实例分析系统结构(input_dev层)的更多相关文章

  1. linux 输入子系统(3)----事件处理(input_handler层)

    输入子系统主要设计input_dev.input_handler.input_handle.如下: [1]每个struct input_dev代表一个输入设备 struct input_dev { c ...

  2. linux输入子系统简述【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/7678035 1,linux输入子系统简述 其实驱动这部分大多还是转载别人的,linux ...

  3. 7.Linux 输入子系统分析

    为什么要引入输入子系统? 在前面我们写了一些简单的字符设备的驱动程序,我们是怎么样打开一个设备并操作的呢? 一般都是在执行应用程序时,open一个特定的设备文件,如:/dev/buttons .... ...

  4. Linux输入子系统框架分析(1)

    在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...

  5. Linux输入子系统详解

    input输入子系统框架  linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(Input ...

  6. linux输入子系统

    linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(InputCore)和输入子系统设备驱 ...

  7. Linux输入子系统(Input Subsystem)

    Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析  http://b ...

  8. linux输入子系统概念介绍

    在此文章之前,我们讲解的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥.非阻塞.定时器去抖动. 上一节文章链接:http://blo ...

  9. linux输入子系统(input subsystem)之evdev.c事件处理过程

    1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...

随机推荐

  1. C# 之 无法嵌入互操作类型(Word 或 Excel 操作)

    Microsoft.Office.Interop.Excel.Application eApp = new Microsoft.Office.Interop.Excel.ApplicationClas ...

  2. 几个常用myeclipse快捷键

    Ctrl + D:直接删除光标所在行 Alt + ↑:向上移动光标所在行 Alt + ↓:向下移动光标所在行 Ctrl + Alt + ↑:直接向上复制光标所在行内容 Ctrl + Alt + ↓:直 ...

  3. java io文件学习笔记

    File f = new file("D:"+File.separator+"test.txt"); File.separator跨系统文件分隔符 f.crea ...

  4. Uva120 Stacks of Flapjacks 翻煎饼

    水水题.给出煎饼数列, 一次只能让第一个到第i个数列全部反转,要求把数列排序为升序. 算法点破后不值几钱... 只要想办法把最大的煎饼放到最后一个,然后就变成前面那些煎饼的数列的子题目了.递归或循环即 ...

  5. python(3)-内置函数

    >>> abs(-1) #绝对值,小数也可以,不能是其它字符 1 >>> all([1,2,3,4,5,6,7]) #如果传入的列表所有元素都为真,则True Tr ...

  6. Redis中的关系查询(范围查询,模糊查询等...)

    本文部分转自于:http://blog.csdn.net/dc_726/article/details/42784317 本文对Redis如何保存关系型数据,以及如何对其匹配.范围.模糊查询进行举例讲 ...

  7. [改善Java代码]避免带有变长参数的方法重载

    建议4: 避免带有变长参数的方法重载 在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection ...

  8. Quartz Scheduler(2.2.1) - Integration with Spring

    1. maven 依赖: <properties> <spring.version>3.2.3.RELEASE</spring.version> <quart ...

  9. javaweb 乱码总结

    可能的错误地方: 1.jsp页面编码 2.表单编码 3.servlet可接受编码 4.tomcat中server.xml文件中的指定编码 所有的编码要统一,一般使用“UTF-8”比较好 我最近一次出错 ...

  10. [转]WCF 4 安全性和 WIF 简介

      转自:http://www.cnblogs.com/WizardWu/archive/2010/10/04/1841793.html 本帖简介 .NET 新一代的 Windows Identity ...