冷烟花
哎呀哎呀哎呀我的妈~蜗牛背着那重重的壳呀,一步一步地往上爬~

内核版本:3.9.5

1. input_dev,用来标识输入设备

 1 struct input_dev {
 2     const char *name;
 3     const char *phys;
 4     const char *uniq;
 5     struct input_id id;//与input_handler匹配用的id
 6 
 7     unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
 8 
 9     unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//支持所有的事件类型
10     unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//支持按键事件
11     unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//支持相对位移事件
12     unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//支持绝对位移事件
13     unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//支持其它事件
14     unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//支持led事件
15     unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//支持声音事件
16     unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//支持受力事件
17     unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//支持开关机时间
18 
19     unsigned int hint_events_per_packet;
20 
21     unsigned int keycodemax;
22     unsigned int keycodesize;
23     void *keycode;
24 
25     int (*setkeycode)(struct input_dev *dev,
26               const struct input_keymap_entry *ke,
27               unsigned int *old_keycode);
28     int (*getkeycode)(struct input_dev *dev,
29               struct input_keymap_entry *ke);
30 
31     struct ff_device *ff;
32 
33     unsigned int repeat_key;//最近一次的按键值
34     struct timer_list timer;
35 
36     int rep[REP_CNT];
37 
38     struct input_mt *mt;
39 
40     struct input_absinfo *absinfo;
41 
42     unsigned long key[BITS_TO_LONGS(KEY_CNT)];//反应设备当前的按键状态
43     unsigned long led[BITS_TO_LONGS(LED_CNT)];//反应设备当前的led状态
44     unsigned long snd[BITS_TO_LONGS(SND_CNT)];//反应设备当前的声音输入状态
45     unsigned long sw[BITS_TO_LONGS(SW_CNT)];//反应设备当前的开关状态
46 
47     int (*open)(struct input_dev *dev);//第一次打开设备时调用,初始化设备用
48     void (*close)(struct input_dev *dev);//最后一个应用程序释放设备时用,关闭设备
49     int (*flush)(struct input_dev *dev, struct file *file);/*用于处理传递给设备的事件,如LED事件和声音事件*/
50     int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
51 
52     struct input_handle __rcu *grab;//当前占有该设备的input_handle
53 
54     spinlock_t event_lock;
55     struct mutex mutex;
56 
57     unsigned int users;//打开该设备的用户数量(input handlers)
58     bool going_away;
59 
60     struct device dev;
61 
62     struct list_head    h_list;//该链表头用于链接此input_dev所关联的input_handle
63     struct list_head    node;//用于将此input_dev链接到input_dev_list
64 
65     unsigned int num_vals;
66     unsigned int max_vals;
67     struct input_value *vals;
68 
69     bool devres_managed;
70 };

2.input_handler,用来标识输入事件处理

 1 struct input_handler {
 2 
 3     void *private;
 4 
 5     void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);/*event用于处理事件*/
 6     void (*events)(struct input_handle *handle,
 7                const struct input_value *vals, unsigned int count);
 8     bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 9     bool (*match)(struct input_handler *handler, struct input_dev *dev);
10     int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);/*connect用于建立handler和device的联系*/
11     void (*disconnect)(struct input_handle *handle);/*disconnect用于解除handler和device的联系*/
12     void (*start)(struct input_handle *handle);
13 
14     bool legacy_minors;
15     int minor;//次设备号
16     const char *name;
17 
18     const struct input_device_id *id_table;//用于和input_dev匹配
19 
20     struct list_head    h_list;//用于链接和此input_handler相关的input_handle
21     struct list_head    node;//用于将该input_handler链入input_handler_list
22 };

3.input_handle,用来链接input_dev和input_handler的桥梁

 1 struct input_handle {
 2 
 3     void *private;
 4 
 5     int open;//记录设备的打开次数(有多少个应用程序访问设备)
 6     const char *name;
 7 
 8     struct input_dev *dev;//指向所属的device
 9     struct input_handler *handler;//指向所属的handler
10 
11     struct list_head    d_node;//用于将此input_handle链入所属input_dev的h_list链表
12     struct list_head    h_node;//用于将此input_handle链入所属input_handler的h_list链表
13 };

可以看到,input_device和input_handler中都有一个h_list,而input_handle拥有指向input_dev和input_handler的指针,也就是说input_handle是用来关联input_dev和input_handler的,那么为什么一个input_device和input_handler

中拥有的是h_list而不是一个handle呢?因为一个device可能对应多个handler,而一个handler也不能只处理一个device,比如说一个鼠标,它可以对应even handler,也可以对应mouse handler,因此当其注册时与系统中的handler进行匹配,就有可能产生两个实例,一个是evdev,另一个是mousedev,而任何一个实例中都只有一个handle.至于以何种方式来传递事件,就由用户程序打开哪个实例来决定.后面一个情况很容易理解,一个事件驱动不能只为一个甚至一种设备服务,系统中可能有多种设备都能使用这类handler,比如event handler就可以匹配所有的设备.在input子系统中,有8种事件驱动,每种事件驱动最多可以对应32个设备,因此dev实例总数最多可以达到256个.

这三个数据结构的关系看起来有点乱!那么就用图表示出来,看起来应该会明了很多吧!三者的关系如下所示:

可以看出input_handle是连接input_device和input_handler的桥梁,如图中的箭头所示从input_device可以通过input_handl找到input_handler,同样的input_handler可以通过 input_handle找到input_device

下一节将以even handler为例介绍设备注册以及打开的过程.

posted on 2013-06-25 18:26  冷烟花  阅读(1093)  评论(0编辑  收藏  举报