您的位置:首页 > 运维架构 > Linux

linux输入子系统(5)

2011-06-23 16:53 375 查看

第2章

输入子系统的事件驱动

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

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

2.1

重要的数据结构

首先介绍
input_handle
,这个结构体用来连接
input_dev

input_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;



};

各个成员的含义如下:


私有数据指针。


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


创建此
handle

handler
所赋予的名字。


指向附着的
input_dev



指向创建此
handle

handler



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



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



程序清单

1.11

中,我们看到
input_dev

input_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

)



连接
handler

input_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_list

input_table
,然后与
input_dev_list
中的
input_dev
比较并与匹配的建立连接。

参考
1.4
input_dev
的注册
这一节,我们发现
input_dev

input_handler
都是将自己加入各自的链表,然后再和对方链表中匹配的进行连接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: