码迷,mamicode.com
首页 > 移动开发 > 详细

Linux/Android——input子系统核心 (三)【转】

时间:2017-11-09 14:47:04      阅读:319      评论:0      收藏:0      [点我收藏+]

标签:传递   process   一点   generated   err   string   use   交互   fbi   

本文转载自:http://blog.csdn.net/jscese/article/details/42123673

 之前的博客有涉及到linux的input子系统,这里学习记录一下input模块.

input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备,

常用的输入设备也就是鼠标,键盘,触摸屏。

稍微细分一点整个输入体系,就是 硬件驱动层input核心中转层事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分别提供接口.

之前有分析usbtouchscreen的驱动,也就是硬件驱动部分,这里简单记录一下input核心中转处理 input.c .

 

                                              撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42123673

input_init:

 源码位于/kernel/drivers/input/input.c ,模块初始调用口subsys_initcall(input_init),

由kernel启动的时候由kernel_init——>do_basic_setup();——>do_initcalls调用到,这个启动逻辑,后续有机会去学习一下,

这里首先调用到初始函数:

 

[objc] view plain copy
 
  1. static int __init input_init(void)  
  2. {  
  3.     int err;  
  4.   
  5.     err = class_register(&input_class); //注册input class,可在/sys/class下看到对应节点文件  
  6.     if (err) {  
  7.         pr_err("unable to register input_dev class\n");  
  8.         return err;  
  9.     }  
  10.   
  11.     err = input_proc_init(); //proc fs的下的一些初始操作,函数原型在input.c,可查看/proc/bus/input  
  12.     if (err)  
  13.         goto fail1;  
  14.   
  15.     err = register_chrdev(INPUT_MAJOR, "input", &input_fops); // 注册input字符设备,主节点为INPUT_MAJOR==13,可以去input_fops里看注册函数,注册到/dev/input  
  16.     if (err) {  
  17.         pr_err("unable to register char major %d", INPUT_MAJOR);  
  18.         goto fail2;  
  19.     }  
  20.   
  21.     return 0;  
  22.   
  23.  fail2:    input_proc_exit();  
  24.  fail1:    class_unregister(&input_class);  
  25.     return err;  
  26. }  


这就是最开始的初始化过程了.

 

 

可以看下注册方法函数:

 

[objc] view plain copy
 
  1. static const struct file_operations input_fops = {  
  2.     .owner = THIS_MODULE,  
  3.     .open = input_open_file,  
  4.     .llseek = noop_llseek,  
  5. };  

 

这里面关注open file方法即可,后面分析。

 

input.c中还有很多其它的接口以及全局数据,后面陆续联通,先从设备驱动最先调用到的注册 input_register_device

 

input_register_device:

[objc] view plain copy
 
  1. /** 
  2.  * input_register_device - register device with input core 
  3.  * @dev: device to be registered 
  4.  * 
  5.  * This function registers device with input core. The device must be 
  6.  * allocated with input_allocate_device() and all it‘s capabilities 
  7.  * set up before registering. 
  8.  * If function fails the device must be freed with input_free_device(). 
  9.  * Once device has been successfully registered it can be unregistered 
  10.  * with input_unregister_device(); input_free_device() should not be 
  11.  * called in this case. 
  12.  */  
  13.   
  14. int input_register_device(struct input_dev *dev)  
  15. {  
  16.     static atomic_t input_no = ATOMIC_INIT(0);    
  17.         //这个原子变量,代表总共注册的input设备,每注册一个加1,因为是静态变量,所以每次调用都不会清零的  
  18.     struct input_handler *handler;  
  19.     const charchar *path;  
  20.     int error;  
  21.   
  22.     __set_bit(EV_SYN, dev->evbit);  //EN_SYN 这个是设备都要支持的事件类型,所以要设置  
  23.   
  24.     /* 
  25.      * If delay and period are pre-set by the driver, then autorepeating 
  26.      * is handled by the driver itself and we don‘t do it in input.c. 
  27.      */  
  28.         // 这个内核定时器是为了重复按键而设置的  
  29.     init_timer(&dev->timer);  
  30.     if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {  
  31.         dev->timer.data = (long) dev;  
  32.         dev->timer.function = input_repeat_key;  
  33.         dev->rep[REP_DELAY] = 250;  
  34.         dev->rep[REP_PERIOD] = 33;  
  35.         //如果没有定义有关重复按键的相关值,就用内核默认的  
  36.     }  
  37.   
  38.     if (!dev->getkeycode)  
  39.         dev->getkeycode = input_default_getkeycode;  
  40.     if (!dev->setkeycode)  
  41.         dev->setkeycode = input_default_setkeycode;  
  42.         //以上设置的默认函数由input核心提供  
  43.     dev_set_name(&dev->dev, "input%ld",  
  44.              (unsigned long) atomic_inc_return(&input_no) - 1);  
  45.         //设置input_dev中device的名字,这个名字会在/class/input中出现  
  46.     error = device_add(&dev->dev);  
  47.         //将device加入到linux设备模型中去  
  48.     if (error)  
  49.         return error;  
  50.   
  51.     path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);  
  52.     printk(KERN_INFO "input: %s as %s\n",  
  53.         dev->name ? dev->name : "Unspecified device", path ? path : "N/A");  
  54.     kfree(path);  
  55.         //这个得到路径名称,并打印出来  
  56.     error = mutex_lock_interruptible(&input_mutex);  
  57.     if (error) {  
  58.         device_del(&dev->dev);  
  59.         return error;  
  60.     }  
  61.   
  62.     list_add_tail(&dev->node, &input_dev_list);  
  63.         // 将新分配的input设备连接到input_dev_list链表上  
  64.     list_for_each_entry(handler, &input_handler_list, node)  
  65.         input_attach_handler(dev, handler);  
  66.         //遍历input_handler_list链表,配对 input_dev 和 input_handler  
  67.         //input_attach_handler 这个函数是配对的关键,下面将详细分析  
  68.     input_wakeup_procfs_readers();  
  69.         // 和proc文件系统有关,暂时不考虑  
  70.     mutex_unlock(&input_mutex);  
  71.   
  72.     return 0;  
  73.    }  



可以看到前面都是一些初始设置,加入到input.c 的全局input_dev 链表里面,同时下面就行匹配对应handler的时候需要遍历 handler 链表:

 

[objc] view plain copy
 
  1. static LIST_HEAD(input_dev_list);  
  2. static LIST_HEAD(input_handler_list);  


可以看到用到了一个list_for_each_entry, 刚开始看到还没看懂,这是一个宏定义,原型是在/kernel/include/linux/list.h:

 

 

[objc] view plain copy
 
  1. /** 
  2.  * list_for_each_entry    -    iterate over list of given type 
  3.  * @pos:    the type * to use as a loop cursor. 
  4.  * @head:    the head for your list. 
  5.  * @member:    the name of the list_struct within the struct. 
  6.  */  
  7. #define list_for_each_entry(pos, head, member)                \  
  8.     for (pos = list_entry((head)->next, typeof(*pos), member);    \  
  9.          &pos->member != (head);     \    //就是个for循环,跳出条件遍历了一遍,又回到链表头  
  10.          pos = list_entry(pos->member.next, typeof(*pos), member))  

 

 

 

input_attach_handler(dev, handler)则是匹配这个要注册dev的handler:

 

[objc] view plain copy
 
  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); //返回匹配的id,类型是struct input_device_id  
  7.     if (!id)  
  8.         return -ENODEV;  
  9.   
  10.     error = handler->connect(handler, dev, id); //<span><span class="comment">//配对成功调用handler的connect函数,这个函数在事件处理器中定义,主要生成一个input_handle结构,并初始化,还生成一个事件处理器相关的设备结构</span></span>  
  11.     if (error && error != -ENODEV)  
  12.         pr_err("failed to attach handler %s to device %s, error: %d\n",  
  13.                handler->name, kobject_name(&dev->dev.kobj), error);  
  14.   
  15.     return error;  
  16. }  

 

 

可以看下匹配 id 的结构:

 

[objc] view plain copy
 
  1. struct input_device_id {  
  2.   
  3.     kernel_ulong_t flags;  
  4.   
  5.     __u16 bustype;  
  6.     __u16 vendor;  
  7.     __u16 product;  
  8.     __u16 version;  
  9.   
  10.     kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];  
  11.     kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];  
  12.     kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];  
  13.     kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];  
  14.     kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];  
  15.     kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];  
  16.     kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];  
  17.     kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];  
  18.     kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];  
  19.   
  20.     kernel_ulong_t driver_info;  
  21. };  

 

 

 

有两个函数input_match_device 以及 下面的 connect需要了解:

 

input_match_device:

 

[objc] view plain copy
 
  1. static const struct input_device_id *input_match_device(struct input_handler *handler,  
  2.                             struct input_dev *dev)  
  3. {  
  4.     const struct input_device_id *id;  
  5.     int i;  
  6.   
  7.     for (id = handler->id_table; id->flags || id->driver_info; id++) {  
  8.   
  9.         if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)  //匹配总线id  
  10.             if (id->bustype != dev->id.bustype)  
  11.                 continue;  
  12.   
  13.         if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)  //匹配生产商id  
  14.             if (id->vendor != dev->id.vendor)  
  15.                 continue;  
  16.   
  17.         if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) //匹配产品id  
  18.             if (id->product != dev->id.product)  
  19.                 continue;  
  20.   
  21.         if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) //匹配版本  
  22.             if (id->version != dev->id.version)  
  23.                 continue;  
  24.   
  25.         MATCH_BIT(evbit,  EV_MAX);  //匹配id的evbit和input_dev中evbit的各个位,如果不匹配则continue,数组中下一个设备  
  26.         MATCH_BIT(keybit, KEY_MAX);  
  27.         MATCH_BIT(relbit, REL_MAX);  
  28.         MATCH_BIT(absbit, ABS_MAX);  
  29.         MATCH_BIT(mscbit, MSC_MAX);  
  30.         MATCH_BIT(ledbit, LED_MAX);  
  31.         MATCH_BIT(sndbit, SND_MAX);  
  32.         MATCH_BIT(ffbit,  FF_MAX);  
  33.         MATCH_BIT(swbit,  SW_MAX);  
  34.   
  35.         if (!handler->match || handler->match(handler, dev))  
  36.             return id;  
  37.     }  
  38.   
  39.     return NULL;  
  40. }  

 

 

MATCH_bit 原型:

 

[objc] view plain copy
 
  1. #define MATCH_BIT(bit, max) \  
  2.         for (i = 0; i < BITS_TO_LONGS(max); i++) \  
  3.             if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \  
  4.                 break; \  
  5.         if (i != BITS_TO_LONGS(max)) \  
  6.             continue;  

 

 

可以看到这么多步的目的除了初始以及添加input_dev到链表,就是为了去匹配 input_handler_list 中对应的handler ,

匹配的最终是需要比对handler以及input_dev中的 id,其中input_dev 中的id类型为 input_id :

 

[objc] view plain copy
 
  1. struct input_id {  
  2.     __u16 bustype;  
  3.     __u16 vendor;  
  4.     __u16 product;  
  5.     __u16 version;  
  6. };  


这跟上面 input_handler 结构里面的 input_device_id 匹配id 变量,来确认 handler!

 

在最开始的时候就有提到,整个input输入体系,分三个层次,现在的input核心层做的事就是:

在硬件驱动层调用 input_register_device时 ,往内核注册驱动的同时,根据硬件的相关id去匹配 适用的事件处理层(input_handler)!

这里匹配上之后就会调用对应 input_handler 的connect 函数。

 

input_handler:

input_dev 变量代表的是硬件设备,前文Linux/Android——输入子系统input_event传递 (二)中有介绍

input_handler 变量代表的是事件处理器

同样在input.h 中定义:

 

[objc] view plain copy
 
  1. /** 
  2.  * struct input_handler - implements one of interfaces for input devices 
  3.  * @private: driver-specific data 
  4.  * @event: event handler. This method is being called by input core with 
  5.  *  interrupts disabled and dev->event_lock spinlock held and so 
  6.  *  it may not sleep 
  7.  * @filter: similar to @event; separates normal event handlers from 
  8.  *  "filters". 
  9.  * @match: called after comparing device‘s id with handler‘s id_table 
  10.  *  to perform fine-grained matching between device and handler 
  11.  * @connect: called when attaching a handler to an input device 
  12.  * @disconnect: disconnects a handler from input device 
  13.  * @start: starts handler for given handle. This function is called by 
  14.  *  input core right after connect() method and also when a process 
  15.  *  that "grabbed" a device releases it 
  16.  * @fops: file operations this driver implements 
  17.  * @minor: beginning of range of 32 minors for devices this driver 
  18.  *  can provide 
  19.  * @name: name of the handler, to be shown in /proc/bus/input/handlers 
  20.  * @id_table: pointer to a table of input_device_ids this driver can 
  21.  *  handle 
  22.  * @h_list: list of input handles associated with the handler 
  23.  * @node: for placing the driver onto input_handler_list 
  24.  * 
  25.  * Input handlers attach to input devices and create input handles. There 
  26.  * are likely several handlers attached to any given input device at the 
  27.  * same time. All of them will get their copy of input event generated by 
  28.  * the device. 
  29.  * 
  30.  * The very same structure is used to implement input filters. Input core 
  31.  * allows filters to run first and will not pass event to regular handlers 
  32.  * if any of the filters indicate that the event should be filtered (by 
  33.  * returning %true from their filter() method). 
  34.  * 
  35.  * Note that input core serializes calls to connect() and disconnect() 
  36.  * methods. 
  37.  */  
  38. struct input_handler {  
  39.   
  40.     voidvoid *private;  
  41.   
  42.     void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);  
  43.     bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);  
  44.     bool (*match)(struct input_handler *handler, struct input_dev *dev);  
  45.     int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);  //上面就是调用这个函数指针  
  46.     void (*disconnect)(struct input_handle *handle);  
  47.     void (*start)(struct input_handle *handle);  
  48.   
  49.     const struct file_operations *fops;  
  50.     int minor;  
  51.     const charchar *name;  
  52.   
  53.     const struct input_device_id *id_table; //这个就是上面说到的 会跟input_dev中的input_id 比对 id项的  
  54.   
  55.     struct list_head    h_list;  
  56.     struct list_head    node;  
  57. };  


这个结构详细的含义,注释有。

 

这个结构里面暂时只需要理解的:

注册input_dev ,在事件处理数据链表里面匹配上 input_handler ,就会调用其 *connect 函数指针 进行连接,

将input_dev 跟 input_handler 进行绑定, 后续的运作事件的handler处理将会走这个input_handler的 *event !

在上篇input_event 传递中最后调用到event阶段.

 

这里简单记录到这里,下篇介绍input_handler 的处理机制~

 

Linux/Android——input子系统核心 (三)【转】

标签:传递   process   一点   generated   err   string   use   交互   fbi   

原文地址:http://www.cnblogs.com/zzb-Dream-90Time/p/7808452.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!