input子系统学习笔记七 handler处理器注册分析

感谢终结者投递本文】

        input_handler 是输入子系统的主要数据结构,一般将其称为handler处理器,表示对输入事件的具体处理。input_handler 为输入设备的功能实现了一个接口,输入事件最终传递到handler 处理器,handler 处理器根据一定的规则,然后对事件进行处理,具体的规则将在下面详细介绍。

关键数据结构

        struct input_dev 物理输入设备的基本数据结构,包含设备相关的一些信息

        struct input_handler 事件处理结构体,定义怎么处理事件的逻辑

        struct input_handle 用来创建 input_dev 和 input_handler 之间关系的结构体

input_handler 结构体

        input_handler 是输入设备的事件处理接口,为处理事件提供一个统一的函数模板,程序员应该根据具体的需要实现其中的一些函数,并将其注册到输入子系统中。该结构体的定义如下:

C/C++代码
  1. struct input_handler {  
  2.         void *private;/*定义了一个 private 指针,表示驱动特定的数据。这里的驱动指的就是 handler 处理器。*/  
  3.         void (*event)(struct input_handle *handle, unsigned int type,  
  4.         unsigned int code, int value);/*定义了一个 event()处理函数,这个函数将被输入子系统调用去处理发送给设备的事件。例如将发送一个事件命令 LED 灯点亮,实际控制硬件的点亮操作就可以放在 event()函数中实现。*/  
  5.         int (*connect)(struct input_handler *handler, struct input_dev  
  6.                 *dev,const struct input_device_id *id);/* 定 义 了 一 个 connect() 函 数 , 该 函 数 用 来 连 接 handler 和 input_dev 。 在input_attach_handler()函数的第 10 行,就是回调的这个自定义函数。*/  
  7.         void (*disconnect)(struct input_handle *handle);  
  8.         void (*start)(struct input_handle *handle);  
  9.         const struct file_operations *fops;/*表示 handler 实现的文件操作集,这里不是很重要。*/  
  10.         int minor;//表示设备的次设备号。  
  11.         const char *name;/* 表示handler 的名字,显示在/proc/bus/input/handlers 目录中。*/  
  12.         const struct input_device_id *id_table;/*定义了一个 id_table 表,表示驱动能够处理的表。*/  
  13.         const struct input_device_id *blacklist;/*指向一个 input_device_id 表,这个表包含 handler 应该忽略的设备。*/  
  14.         struct list_head h_list;/*定义了一个链表 h_list,表示与这个 input_handler 相联系的下一个 handler。*/  
  15.         struct list_head node;/*定义了一个链表 node,将其连接到全局的 input_handler_list 链表中,所有的input_handler 都连接在其上。*/  
  16. };  
input_handle 结构体

        input_register_handle()函数用来注册一个新的 handle 到输入子系统中。input_handle 的主要功能是用来连接 input_dev 和 input_handler。其结构如下:

C/C++代码
  1. struct input_handle {  
  2.         void *private;/*定义了 private 表示 handler 特定的数据。*/  
  3.         int open;/*定义了一个 open 变量,表示 handle 是否正在被使用,当使用时,会将事件分发给设备处理。*/  
  4.         const char *name;/*定义了一个 name 变量,表示 handle 的名字。*/  
  5.         struct input_dev *dev;/*定义了 dev 变量指针,表示该 handle 依附的 input_dev 设备。*/  
  6.         struct input_handler *handler;/*定义了一个 handler 变量指针,指向 input_handler,该 handler 处理器就是与设备相关的处理器。*/  
  7.         struct list_head d_node;/*定义了一个 d_node 变量,使用这个变量将 handle 放到设备相关的链表中,也就是放到 input_dev->h_list 表示的链表中。*/  
  8.         struct list_head h_node;/*定义了一个 h_node 变量,使用这个变量将 handle 放到 input_handler 相关的链表中,也就是放到 handler->h_list 表示的链表中。*/  
  9. }; 
注册input_handler

        input_register_handler()函数注册一个新的 input handler 处理器。这个 handler 将为输入设备使用,一个 handler 可以添加到多个支持它的设备中,也就是一个 handler 可以处理多个输入设备的事件。函数的参数传入简要注册的 input_handler 指针,该函数的代码如下:

C/C++代码
  1. int input_register_handler(struct input_handler *handler)  
  2. {  
  3.         struct input_dev *dev;  
  4.         int retval;  
  5.   
  6.         retval = mutex_lock_interruptible(&input_mutex);/*对 input_mutex 进行了加锁。当加锁失败后,则返回。*/  
  7.         if (retval)  
  8.                 return retval;  
  9.   
  10.         INIT_LIST_HEAD(&handler->h_list);/*初始化 h_hlist 链表,该链表连接与这个 input_handler 相联系的下一个 handler。*/  
  11.   
  12.         if (handler->fops != NULL) {/*其中的 handler->minor 表示对应 input 设备结点的次设备号。 handler->minor以右移 5 位作为索引值插入到 input_table[ ]中,*/  
  13.                 if (input_table[handler->minor >> 5]) {  
  14.                         retval = -EBUSY;  
  15.                         goto out;  
  16.                 }  
  17.                 input_table[handler->minor >> 5] = handler;  
  18.         }  
  19.   
  20.         list_add_tail(&handler->node, &input_handler_list);/*调用 list_add_tail()函数,将 handler 加入全局的 input_handler_list 链表中, 该链表包含了系统中所有的 input_handler。*/  
  21.   
  22.         list_for_each_entry(dev, &input_dev_list, node)  
  23.         input_attach_handler(dev, handler);/*input_attach_handler()函数的作用是匹配 input_dev_list 链表中的 input_dev 与 handler。如果成功会将 input_dev 与 handler 联系起来。*/  
  24.         input_wakeup_procfs_readers();  
  25.         out:  
  26.                 mutex_unlock(&input_mutex);/*解互斥锁并退出。*/  
  27.         return retval;  
  28. }  
注册input_handle

        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()函数的代码如下:

C/C++代码
  1. int input_register_handle(struct input_handle *handle)  
  2. {  
  3.         struct input_handler *handler = handle->handler;/*从 handle 中取出一个指向 input_handler 的指针,为下面的操作使用。 */  
  4.         struct input_dev *dev = handle->dev;/*从 handle 中取出一个指向 input_dev 的指针,为下面的操作使用。 */  
  5.         int error;  
  6.   
  7.         /* 
  8.         * We take dev->mutex here to prevent race with 
  9.         * input_release_device(). 
  10.         */  
  11.         error = mutex_lock_interruptible(&dev->mutex);/*给竞争区域加一个互斥锁。*/  
  12.         if (error)  
  13.                 return error;  
  14.   
  15.         /* 
  16.         * Filters go to the head of the list, normal handlers 
  17.         * to the tail. 
  18.         */  
  19.         if (handler->filter)  
  20.                 list_add_rcu(&handle->d_node, &dev->h_list);  
  21.         else  
  22.                 list_add_tail_rcu(&handle->d_node, &dev->h_list);/*调用 list_add_tail_rcu()函数将 handle 加入输入设备的 dev->h_list 链表中。*/  
  23.   
  24.         mutex_unlock(&dev->mutex);  
  25.   
  26.         /* 
  27.         * Since we are supposed to be called from ->connect() 
  28.         * which is mutually exclusive with ->disconnect() 
  29.         * we can't be racing with input_unregister_handle() 
  30.         * and so separate lock is not needed here. 
  31.         */  
  32.         list_add_tail_rcu(&handle->h_node, &handler->h_list);  
  33.   
  34.         if (handler->start)/*如果定义了 start()函数,则调用它。*/  
  35.                 handler->start(handle);  
  36.   
  37.         return 0;  
  38. }  
三者之间的关系

 

        结点 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联系了起来。

原文 http://www.ourunix.org/post/296.html

你可能感兴趣的:(数据结构,list,struct,table,input,each)