实例代码如下:

  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. Android进阶笔记13:RoboBinding(实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架)

    1.RoboBinding RoboBinding是一个实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架.从简单的角度看,他移除了如addXXListen ...

  2. mysql root给其它用户授权问题

    今天登录mysql,给其它用户授权遇到问题 mysql> grant all privileges on testdb.* to 'dbuser'@'10.4.14.14' identified ...

  3. Linux kill -9 和 kill -15 的区别

    “我的天呀!”,网页编辑没有自动保存草稿的功能.害的我昨天写的东西都没有了.算了,不计较这些了.反正也没写多少. 嘻嘻. 大家对kill -9 肯定非常熟悉,在工作中也经常用到.特别是你去重启tomc ...

  4. 使用openoffice将word文件转换为pdf格式遇到问题:The type com.sun.star.lang.XEventListener cannot be resolved. It is indirectly referenced from required

    The type com.sun.star.lang.XEventListener cannot be resolved. It is indirectly referenced from requi ...

  5. LeetCode 122

    Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...

  6. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  7. 如何通过wifi在android手机上安装调试应用

    如何通过wifi在android手机上安装调试应用 1. 首先还是要打开手机的usb调试选项,并通过usb线连接手机.2. 然后执行“adb tcpip 5555”,把adb从usb模式切换到tcpi ...

  8. px和em之间的转换

    很多网页设计者在写css时都是在通用选择器中就设置了字体的大小,中文情况下一般为12px.然而IE浏览器却无法调整那些使用px作为单位的字体大小.其实使用em作为单位是可以避免这一情况的. 一.em和 ...

  9. Memcached学习(三)

    通过Java客户端实现与Memcached的交互,Java客户端的实现了使用了开源的Memcached-Java-Client,开源地址在GitHub上. 如下是通过该开源库实现的Memcached交 ...

  10. 初识 AutoLayout

    一.使用"公式": 1.frame: 原点以及自身的位置来确定自身的位置 2.autoLayout: 根据参照视图的位置  来定义自己的位置 3.autoLayout: 相对布局  ...