linux内核input子系统解析
时间:2017-01-04作者:华清远见
Android、X windows、qt等众多应用对于linux系统中键盘、鼠标、触摸屏等输入设备的支持都通过、或越来越倾向于标准的input输入子系统。 因为input子系统已经完成了字符驱动的文件操作接口,所以编写驱动的核心工作是完成input系统留出的接口,工作量不大。但如果你想更灵活的应用它,就需要好好的分析下input子系统了。 一、input输入子系统框架 下图是input输入子系统框架,输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core -> Event handler -> userspace 到达用户空间传给应用程序。
注意:keyboard.c不会在/dev/input下产生节点,而是作为ttyn终端(不包括串口终端)的输入。 二、Input driver编写要点 1、分配、注册、注销input设备
struct input_dev *input_allocate_device(void) 2、设置input设备支持的事件类型、事件码、事件值的范围、input_id等信息 参见usb键盘驱动:usbkbd.c
usb_to_input_id(dev, &input_dev->id);//设置bustype、vendo、product等 include/linux/input.h中定义了支持的类型(下面列出的是2.6.22内核的情况)
#define EV_SYN 0x00 一个设备可以支持一个或多个事件类型。每个事件类型下面还需要设置具体的触发事件码。比如:EV_KEY事件,需要定义其支持哪些按键事件码。 3、如果需要,设置input设备的打开、关闭、写入数据时的处理方法 参见usb键盘驱动:usbkbd.c
input_dev->open = usb_kbd_open; 4、在发生输入事件时,向子系统报告事件 用于报告EV_KEY、EV_REL、EV_ABS等事件的函数有:
void input_report_key(struct input_dev *dev, unsigned int code, int value) 如果你觉得麻烦,你也可以只记住1个函数(因为上述函数都是通过它实现的) void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 三、Event Handler层解析 1、Input输入子系统数据结构关系图
2、input_handler结构体 以evdev.c中的evdev_handler为例:
static struct input_handler evdev_handler = { 3、input字符设备注册过程
drivers/input/input.c中: input_fops定义:
static const struct file_operations input_fops = { Input_dev和input_handler匹配后调用input_handler的connect。以evdev_handler为例:
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);//为每个匹配evdev_handler的设备创建一个evdev。
INIT_LIST_HEAD(&evdev->client_list);
evdev->exist = 1;
evdev_table[minor] = evdev;//记录evdev的位置,字符设备/dev/input/evnetx访问时根据次设备号及EVDEV_MINOR_BASE终在evdev_open中找到对应的evdev 4、input字符设备的打开过程
static int input_open_file(struct inode *inode, struct file *file) 5、input字符设备的其它操作 由于在open阶段已经把设备文件的操作操作方法重定位了到了具体的input_handler,所以其它接口操作(read、write、ioctl等),由各个input_handler的fops方法决定。如evdev.c中的:evdev_fops。
发表评论
|