input_handler 是输入子系统的主要数据结构,一般将其称为handler处理器,表示对输入事件的具体处理。input_handler 为输入设备的功能实现了一个接口,输入事件最终传递到handler 处理器,handler 处理器根据一定的规则,然后对事件进行处理,具体的规则将在下面详细介绍。
struct input_dev 物理输入设备的基本数据结构,包含设备相关的一些信息
struct input_handler 事件处理结构体,定义怎么处理事件的逻辑
struct input_handle 用来创建 input_dev 和 input_handler 之间关系的结构体
input_handler 是输入设备的事件处理接口,为处理事件提供一个统一的函数模板,程序员应该根据具体的需要实现其中的一些函数,并将其注册到输入子系统中。该结构体的定义如下:
- struct input_handler {
- void *private;/*定义了一个 private 指针,表示驱动特定的数据。这里的驱动指的就是 handler 处理器。*/
- void (*event)(struct input_handle *handle, unsigned int type,
- unsigned int code, int value);/*定义了一个 event()处理函数,这个函数将被输入子系统调用去处理发送给设备的事件。例如将发送一个事件命令 LED 灯点亮,实际控制硬件的点亮操作就可以放在 event()函数中实现。*/
- int (*connect)(struct input_handler *handler, struct input_dev
- *dev,const struct input_device_id *id);/* 定 义 了 一 个 connect() 函 数 , 该 函 数 用 来 连 接 handler 和 input_dev 。 在input_attach_handler()函数的第 10 行,就是回调的这个自定义函数。*/
- void (*disconnect)(struct input_handle *handle);
- void (*start)(struct input_handle *handle);
- const struct file_operations *fops;/*表示 handler 实现的文件操作集,这里不是很重要。*/
- int minor;//表示设备的次设备号。
- const char *name;/* 表示handler 的名字,显示在/proc/bus/input/handlers 目录中。*/
- const struct input_device_id *id_table;/*定义了一个 id_table 表,表示驱动能够处理的表。*/
- const struct input_device_id *blacklist;/*指向一个 input_device_id 表,这个表包含 handler 应该忽略的设备。*/
- struct list_head h_list;/*定义了一个链表 h_list,表示与这个 input_handler 相联系的下一个 handler。*/
- struct list_head node;/*定义了一个链表 node,将其连接到全局的 input_handler_list 链表中,所有的input_handler 都连接在其上。*/
- };
input_register_handle()函数用来注册一个新的 handle 到输入子系统中。input_handle 的主要功能是用来连接 input_dev 和 input_handler。其结构如下:
- struct input_handle {
- void *private;/*定义了 private 表示 handler 特定的数据。*/
- int open;/*定义了一个 open 变量,表示 handle 是否正在被使用,当使用时,会将事件分发给设备处理。*/
- const char *name;/*定义了一个 name 变量,表示 handle 的名字。*/
- struct input_dev *dev;/*定义了 dev 变量指针,表示该 handle 依附的 input_dev 设备。*/
- struct input_handler *handler;/*定义了一个 handler 变量指针,指向 input_handler,该 handler 处理器就是与设备相关的处理器。*/
- struct list_head d_node;/*定义了一个 d_node 变量,使用这个变量将 handle 放到设备相关的链表中,也就是放到 input_dev->h_list 表示的链表中。*/
- struct list_head h_node;/*定义了一个 h_node 变量,使用这个变量将 handle 放到 input_handler 相关的链表中,也就是放到 handler->h_list 表示的链表中。*/
- };
input_register_handler()函数注册一个新的 input handler 处理器。这个 handler 将为输入设备使用,一个 handler 可以添加到多个支持它的设备中,也就是一个 handler 可以处理多个输入设备的事件。函数的参数传入简要注册的 input_handler 指针,该函数的代码如下:
- int input_register_handler(struct input_handler *handler)
- {
- struct input_dev *dev;
- int retval;
- retval = mutex_lock_interruptible(&input_mutex);/*对 input_mutex 进行了加锁。当加锁失败后,则返回。*/
- if (retval)
- return retval;
- INIT_LIST_HEAD(&handler->h_list);/*初始化 h_hlist 链表,该链表连接与这个 input_handler 相联系的下一个 handler。*/
- if (handler->fops != NULL) {/*其中的 handler->minor 表示对应 input 设备结点的次设备号。 handler->minor以右移 5 位作为索引值插入到 input_table[ ]中,*/
- if (input_table[handler->minor >> 5]) {
- retval = -EBUSY;
- goto out;
- }
- input_table[handler->minor >> 5] = handler;
- }
- list_add_tail(&handler->node, &input_handler_list);/*调用 list_add_tail()函数,将 handler 加入全局的 input_handler_list 链表中, 该链表包含了系统中所有的 input_handler。*/
- list_for_each_entry(dev, &input_dev_list, node)
- input_attach_handler(dev, handler);/*input_attach_handler()函数的作用是匹配 input_dev_list 链表中的 input_dev 与 handler。如果成功会将 input_dev 与 handler 联系起来。*/
- input_wakeup_procfs_readers();
- out:
- mutex_unlock(&input_mutex);/*解互斥锁并退出。*/
- return retval;
- }
input_handle 是用来连接input_dev和input_handler的一个中间结构体。事件通过input_handle 从 input_dev 发送到 input_handler,或者从 input_handler 发送到 input_dev 进行处理。在使用 input_handle 之前,需要对其进行注册,注册函数是 input_register_handle()。
注册函数 input_register_handle()
input_register_handle()函数用来注册一个新的 handle 到输入子系统中。该函数接收一个input_handle 类型的指针,该变量要在注册前对其成员初始化。input_register_handle()函数的代码如下:
- int input_register_handle(struct input_handle *handle)
- {
- struct input_handler *handler = handle->handler;/*从 handle 中取出一个指向 input_handler 的指针,为下面的操作使用。 */
- struct input_dev *dev = handle->dev;/*从 handle 中取出一个指向 input_dev 的指针,为下面的操作使用。 */
- int error;
- /*
- * We take dev->mutex here to prevent race with
- * input_release_device().
- */
- error = mutex_lock_interruptible(&dev->mutex);/*给竞争区域加一个互斥锁。*/
- if (error)
- return error;
- /*
- * Filters go to the head of the list, normal handlers
- * to the tail.
- */
- if (handler->filter)
- list_add_rcu(&handle->d_node, &dev->h_list);
- else
- list_add_tail_rcu(&handle->d_node, &dev->h_list);/*调用 list_add_tail_rcu()函数将 handle 加入输入设备的 dev->h_list 链表中。*/
- mutex_unlock(&dev->mutex);
- /*
- * Since we are supposed to be called from ->connect()
- * which is mutually exclusive with ->disconnect()
- * we can't be racing with input_unregister_handle()
- * and so separate lock is not needed here.
- */
- list_add_tail_rcu(&handle->h_node, &handler->h_list);
- if (handler->start)/*如果定义了 start()函数,则调用它。*/
- handler->start(handle);
- return 0;
- }
结点 1、2、3 表示input_dev设备,其通过input_dev->node变量连接到全局输入设备链input_dev_list中.结点4、5、6表示input_handler处理器,其通过input_handler->node连接到全局handler处理器链表input_handler_list中。结点7是一个input_handle的结构体,其用来连接input_dev和input_handler。input_handle的dev成员指向了对应的input_dev设备,input_handle的handler成员指向了对应的 input_handler。外结点7的input_handle另设备,通过d_node连接到了结点2的input_dev上的h_list链表上。另一方面,结点7的input_handle通过h_node连接到了结点5的input_handler的h_list链表上。通过这种关系,input_dev将和input_handler联系了起来。