1.input_dev结构体 是硬件驱动层,代表一个input设备
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 evbit[BITS_TO_LONGS(EV_CNT)];//支持所有的事件类型 8 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//支持按键事件 9 unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//支持相对位移事件 10 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//支持绝对位移事件 11 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//支持其它事件 12 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//支持led事件 13 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//支持声音事件 14 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//支持受力事件 15 unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//支持开关机时间 16 17 unsigned int keycodemax; 18 unsigned int keycodesize; 19 void *keycode; 20 int (*setkeycode)(struct input_dev *dev, int scancode, int keycode); 21 int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode); 22 23 struct ff_device *ff; 24 25 unsigned int repeat_key;//最近一次按键值 26 struct timer_list timer; 27 28 int sync; 29 30 int abs[ABS_MAX + 1]; 31 int rep[REP_MAX + 1]; 32 33 unsigned long key[BITS_TO_LONGS(KEY_CNT)];//反应设备当前的按键状态 34 unsigned long led[BITS_TO_LONGS(LED_CNT)];//反应设备当前的led状态 35 unsigned long snd[BITS_TO_LONGS(SND_CNT)];//反应设备当前的声音输入状态 36 unsigned long sw[BITS_TO_LONGS(SW_CNT)];//反应设备当前的开关状态 37 38 int absmax[ABS_MAX + 1]; 39 int absmin[ABS_MAX + 1]; 40 int absfuzz[ABS_MAX + 1]; 41 int absflat[ABS_MAX + 1]; 42 int absres[ABS_MAX + 1]; 43 44 int (*open)(struct input_dev *dev);//第一次打开设备时调用,初始化设备 45 void (*close)(struct input_dev *dev);//最后一个应用程序释放设备时用,关闭设备 46 int (*flush)(struct input_dev *dev, struct file *file);//用于处理传递给设备的事件,如led或声音事件 47 int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); 48 49 struct input_handle *grab;//当前占有该设备的input_handle 50 51 spinlock_t event_lock; 52 struct mutex mutex; 53 54 unsigned int users;//打开该设备的用户数量(input_handlers) 55 bool going_away; 56 57 struct device dev; 58 59 struct list_head h_list;//该链表头用于链接此input_dev所关联的input_handle 60 struct list_head node;//用于将此input_dev链接到input_dev_list 61 };
2. input_handler结构体 是事件处理层,代表一个事件处理器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);//connect用于建立handler和device的联系 7 void (*disconnect)(struct input_handle *handle);//disconnect用于解除handler和device的联系 8 void (*start)(struct input_handle *handle); 9 10 const struct file_operations *fops; 11 int minor; 12 const char *name; 13 14 const struct input_device_id *id_table;//用于和input_dev匹配 15 const struct input_device_id *blacklist; 16 17 struct list_head h_list;//用于链接和此input_hanler相关的input_handle 18 struct list_head node;//用于将该input_handler链入input_handler_list 19 };
3. input_handle 结构体 个人认为属于核心层,代表一个配对的input设备与input事件处理器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 };
4. evdev
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 struct evdev { 2 int exist; 3 int open; 4 int minor; 5 struct input_handle handle; 6 wait_queue_head_t wait; 7 struct evdev_client *grab; 8 struct list_head client_list; 9 spinlock_t client_lock; /* protects client_list */ 10 struct mutex mutex; 11 struct device dev; 12 };
5. evdev_client
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 struct evdev_client { 2 struct input_event buffer[EVDEV_BUFFER_SIZE]; 3 int head; 4 int tail; 5 spinlock_t buffer_lock; /* protects access to buffer, head and tail */ 6 struct fasync_struct *fasync; 7 struct evdev *evdev; 8 struct list_head node; 9 };
4. 五个数据结构之间的关系
struct evdev 当某个struct input_dev和evdev_handler匹配成功后就新建一个struct evdev,看到这里是不是有点和
struct input_handle产生的时间一致呀,起始该结构体内部就包含一个struct input_handle;不过结合了
一些其他信息,可以把它看做是struct input_handle的升级版。
struct evdev_client 主要跟应用程序有关.每打开一次设备就新建一个struct evdev_client,里面保存了应用程序要读取的数据
以及数据的位置。
input_dev 通过全局的input_dev_list链接在一起。设备注册的时候实现这个操作。
input_handler 通过全局的input_handler_list链接在一起。事件处理器注册的时候实现这个操作(事件处理器一般内核自带,一般不需要我们来写)
input_hande 没有一个全局的链表,它注册的时候将自己分别挂在了input_dev 和 input_handler 的h_list上了。通过input_dev 和input_handler就可以找到
input_handle 在设备注册和事件处理器, 注册的时候都要进行配对工作,配对后就会实现链接。通过input_handle也可以找到input_dev和 input_handler。
我们可以看到,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个。