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
都是将自己加入各自的链表,然后再和对方链表中匹配的进行连接。
相关文章推荐
- linux驱动子系统之输入子系统(5)
- linux输入子系统 结构概述
- linux input输入子系统分析《一》:初识input输入子系统
- linux输入子系统(6)--- evdev_handler的实现
- Linux 输入(input)子系统架构分析
- Linux输入子系统分析 (2) -- evdev handler初始化
- 输入服务子系统框架代码分析(韦东山的视频总结及针对linux-2.6.30.4)
- linux输入子系统(3)
- linux的输入子系统---按键事件
- linux输入子系统(2)
- linux input输入子系统分析《一》:初识input输入子系统
- [input] Linux 输入子系统(二)
- linux输入子系统(4)
- 我对linux驱动 输入子系统的理解
- Linux输入子系统(Input Subsystem)
- linux 输入子系统(4) intput_dev 接口描述
- linux驱动子系统之输入子系统(1)
- linux输入子系统
- linux驱动子系统之输入子系统(5)
- LINUX设备驱动之输入子系统(一)