Chinaunix首页 | 论坛 | 博客
  • 博客访问: 828069
  • 博文数量: 860
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-20 19:57
个人简介

对技术执着

文章分类

全部博文(860)

文章存档

2019年(16)

2018年(12)

2015年(732)

2013年(85)

2012年(15)

我的朋友

分类: LINUX

2013-05-29 18:45:23

原文地址:linux输入子系统(5) 作者:chumojing

第2章 输入子系统的事件驱动

上一章已经说过输入子系统分为三层,最上面的一层是事件处理层,我们暂时称它为事件驱动,这是相对于上一章的设备驱动来讲的。

上一章介绍了设备驱动注册时要与匹配的handler连接,报告的事件也会分发给连接的handler,这一章介绍handler的相关操作。

2.1      重要的数据结构

首先介绍input_handle,这个结构体用来连接input_devinput_handler。它的代码如程序清单 2.1所示。

程序清单 2.1  input_handle

/* include/linux/input.h */

struct input_handle {

         void *private;                                                                                                                                                 

 

         int open;                                                                                                                                                         

         const char *name;                                                                                                                                           

 

         struct input_dev *dev;                                                                                                                                    

         struct input_handler *handler;                                                                                                                        

 

         struct list_head    d_node;                                                                                                                              

         struct list_head    h_node;                                                                                                                              

};

各个成员的含义如下:

私有数据指针。

记录本设备被打开的次数。

创建此handlehandler所赋予的名字。

指向附着的input_dev

指向创建此handlehandler

链表节点,用来加入附着的input_dev

链表节点,用来加入附着的input_handler

程序清单 1.11中,我们看到input_devinput_handler匹配过程中用到了input_device_id。它的代码如程序清单 2.2所示。

程序清单 2.2  input_device_id

/* include/linux/mod_devicetable.h */

struct input_device_id {

         kernel_ulong_t flags;                                                                                                                            

 

         __u16 bustype;                                                                                                                                     

         __u16 vendor;

         __u16 product;

         __u16 version;

 

         kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];                           

         kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];

         kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];

 

         kernel_ulong_t driver_info;                                                                                                                  

};

各个成员的含义如下:

定义需要匹配input_id的哪些域(使用方法参考程序清单 1.11)。

对应input_id的四个数据域。

存储支持事件的位图,与input_dev中的同名数据成员功能一致。

指示结构体中是否含有驱动信息。

input_handler这个结构体是事件驱动的主体,每一种处理方式对应一个handler结构体。它的定义如程序清单 2.3所示。

程序清单 2.3   input_handler

/* include/linux/input.h */

struct input_handler {

         void *private;                                                                                                                                                 

 

         void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);                         

         int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);        

         void (*disconnect)(struct input_handle *handle);                                                                                           

         void (*start)(struct input_handle *handle);                                                                                                     

 

         const struct file_operations *fops;                                                                                                                  

         int minor;                                                                                                                                                        

         const char *name;                                                                                                                                           

 

         const struct input_device_id *id_table;                                                                                                           

         const struct input_device_id *blacklist;                                                                                                          

 

         struct list_head    h_list;                                                                                                                                 

         struct list_head    node;                                                                                                                                  

};

每个成员的具体解释如下:

私有数据指针。

事件处理函数指针。设备驱动报告的事件最终由这个函数来处理(参考程序清单 1.14)

连接handlerinput_dev的函数指针。

断开连接函数指针。

为给定的handle启动handler函数指针。

文件操作结构体。

这个handler可以使用的32个次设备号的最小值。

handler的名字。

可以处理的input_device_ids列表(用法参考程序清单 1.11)。

需要被忽略的input_device_ids列表。

用来连接handle的链表链表节点。每个与此handler相关的handle都放入此链表。

用来放入全局handler链表的节点。

2.2      input_handler的注册

首先介绍存放注册的input_handler所用的数据结构。如所程序清单 2.4示。

程序清单 2.4  input core全局数据

/* driver/input/input.c */

static LIST_HEAD(input_dev_list);                                                       /* 设备链表头                                        */

static LIST_HEAD(input_handler_list);                                                 /* handler链表头                                     */

 

static DEFINE_MUTEX(input_mutex);                                                 /* 保护以上两个链表                            */

 

static struct input_handler *input_table[8];                                              /*存放注册的input_handler的指针数组*/

程序清单 1.9处注册的input_dev结构体加入到上面的input_dev_list当中,下面将要介绍的注册input_handler,其实就是将input_hangler加入到input_handler_list当中。input_table中存放进行文件操作的handler,使用它们次设备号的最高三比特在input_table中寻址,因此每个handler最多支持32个设备节点。由上面的代码可以看出输入子系统最多允许8个进行文件操作的input_handler同时存在。

input_register_handler的代码如程序清单 2.5所示。

程序清单 2.5  input_register_handler

int input_register_handler(struct input_handler *handler)

{

         struct input_dev *dev;

         int retval;

 

         retval = mutex_lock_interruptible(&input_mutex);

         if (retval)

                   return retval;

 

         INIT_LIST_HEAD(&handler->h_list);                                                                                               

 

         if (handler->fops != NULL) {                                                                                                              

                   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_for_each_entry(dev, &input_dev_list, node)                                                                                  

                   input_attach_handler(dev, handler);                                                                                    

 

         input_wakeup_procfs_readers();

 

 out:

         mutex_unlock(&input_mutex);

         return retval;

}

EXPORT_SYMBOL(input_register_handler);

程序含义如下:

初始化handler中的链表节点,为加入input_handler_list做准备。

如果此handler需要进行文件操作。

如果相应的次设备号段被占用。

handler注册进input_table

handler加入input_handler_list链表。

遍历input_dev_list链表中的每一个input_dev结构体。

handler与每一个input_dev进行匹配。

input_attach_handler的代码如程序清单 1.10所示,这里不再赘述。

总结一下input_handler的注册过程:见自己加入input_handler_listinput_table,然后与input_dev_list中的input_dev比较并与匹配的建立连接。

参考1.4input_dev的注册这一节,我们发现input_devinput_handler都是将自己加入各自的链表,然后再和对方链表中匹配的进行连接。

阅读(164) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册