Linux input子系统代码阅读简单记录
网上可以找到很多关于linux输入子系统的分析和代码导读,这些文章看的再多,都只是别人的总结,自己始终都是需要看源代码的。对代码的理解,想长时间的记住,是不现实的,干脆把阅读分析时的顺序记录下来,如果以后再次看这部分的代码,参照这个阅读顺序,应该回忆的也会快一些。
1. /linux-2.6.38/include/linux/input.h 和 /linux-2.6.38/drivers/input/input.c 文件
1.1 核心的3个结构,struct input_dev,struct input_handler,struct input_handle,用面向对象的思路来看,这3个是核心的父类。
struct input_handler结构对应字符设备,换句话说,在用户空间,当使用 /dev/input/event0 等设备文件的时候,对应的内核代码入口点,就是由struct input_handler实现。
struct input_dev结构是对具体的硬件设备的抽象,通常都会处理中断程序,把用户的输入传递到struct input_handler。
struct input_handle结构的功能,是把struct input_dev连接到struct input_handler上,可以在看代码的过程中逐步体会。
1.2 这3个核心父类的主要api接口
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
int __must_check input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
void input_reset_device(struct input_dev *);
int __must_check input_register_handler(struct input_handler *);
void input_unregister_handler(struct input_handler *);
int input_handler_for_each_handle(struct input_handler *, void *data,
int (*fn)(struct input_handle *, void *));
int input_register_handle(struct input_handle *);
void input_unregister_handle(struct input_handle *);
int input_grab_device(struct input_handle *);
void input_release_device(struct input_handle *);
int input_open_device(struct input_handle *);
void input_close_device(struct input_handle *);
int input_flush_device(struct input_handle *handle, struct file *file);
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
1.3 在input子系统中,有两个全局性的链表,static LIST_HEAD(input_dev_list); 和 static LIST_HEAD(input_handler_list);
1.3.1 void input_reset_device(struct input_dev *)函数就是把一个input_dev添加到input_dev_list链表上,同时,还会在input_handler_list链表中找到和这个input_dev相匹配的struct input_handler,并且把相匹配的input_dev和input_handler 连接(connect)起来(通过input_handle建立连接关系)。当连接上之后,input_dev上发生的中断事件,就可以传递到input_handler,进而传递到用户空间。
1.3.2 int __must_check input_register_handler(struct input_handler *)函数就是把一个struct input_handler添加到input_handler_list链表上,同时,会从input_dev_list中找出所有的可以和它匹配的input_dev,并且把相匹配的input_dev和input_handler 连接(connect)起来(通过input_handle建立连接关系)。当连接上之后,input_dev上发生的中断事件,就可以传递到input_handler,进而传递到用户空间。
1.3.3 前面提到的“并且把他们connect起来",是由struct input_handler的一个api函数来实现的,函数原型为int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);用面向对象的思路来看,这是一个虚函数,需要由struct input_handler的每一个子类来具体实现。