[转]2.6内核输入子系统分析
2008-04-25 14:45
232 查看
前面对s3c2410的触摸屏驱动进行了分析,现深入一层,对其所在的输入子系统进行刺探。
首先引用一个不错的帖子,对2.6内核的输入子系统进行一个大致的描述:
引:
注:
原文请看一下网址: http://bbs.ustc.edu.cn/cgi/bbstcon?board=Kernel&file=M.1179398612.A
看了以上的内容,相信你对2.6内核的输入子系统应该有个大概的了解了,
现在我就input_dev、input_handle、input_handler这三者建立联系的过程进行详细的分析:
首先引用一个不错的帖子,对2.6内核的输入子系统进行一个大致的描述:
引:
在做触摸屏?对于输入子系统,相信你也早看了网上一些介绍文章文章了, 读一下就可了解对其基本架构,剩下的只是一些源码细节阅读。 输入子系统的3层间的联系是很简单的,驱动层的核心结构为struct input_dev: struct input_dev { ... struct list_head h_list; ... }; 在input_register_device时就会将input_dev与input_handle联系起来; 所谓联系就是将有关的input_handle链入以input_dev中h_list为Hash头的链中; 而事件处理层的核心结构是struct input_handler: struct input_handler { ... struct list_head h_list; ... }; 在input_register_handler时同样会将input_handler与input_handle联系起来, 所谓联系就是将有关的input_handle链入以input_handler中h_list为Hash头的链中; 由上可见input_handle即是一个用于关联驱动层input_dev和事件处理 层input_handler的中间结构: struct input_handle { ... struct input_dev *dev; struct input_handler *handler; struct list_head d_node; struct list_head h_node; }; 其中d_node用于input_dev链,h_node用于input_handler链,有了input_handle, 就把相关dev与handler联系起来,相互能容易的找到。
注:
原文请看一下网址: http://bbs.ustc.edu.cn/cgi/bbstcon?board=Kernel&file=M.1179398612.A
看了以上的内容,相信你对2.6内核的输入子系统应该有个大概的了解了,
现在我就input_dev、input_handle、input_handler这三者建立联系的过程进行详细的分析:
触摸屏驱动中,s3c2410ts_probe函数的最后一步,调用input_register_device函数开始进入三者建立联系的过程: void input_register_device(struct input_dev *dev) { struct input_handle *handle; struct input_handler *handler; struct input_device_id *id; ........................................................................................ INIT_LIST_HEAD(&dev->h_list); list_add_tail(&dev->node, &input_dev_list); list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); .......................................................................................... } 注: 我只保留重要的部分,省略号部分不是我关心的,以下同。 list_for_each_entry(handler, &input_handler_list, node)的作用在于: 从input_handler_list的链表中提取input_handler的指针。 ################################################################################## 那这个input_handler的指针又是何时存放在input_handler_list链表里面的呢? 答案是像tsdev.c这些接口驱动里面调用input_register_handler 进而调用list_add_tail(&handler->node, &input_handler_list); 把其input_handler指针加进input_handler_list里面,详细请查看源码,在此不做详细分析。 ################################################################################### 获取了input_handler指针后通过input_match_device进行匹配选择: static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev) { int i; for (; id->flags || id->driver_info; id++) { ................................................................ MATCH_BIT(evbit, EV_MAX); MATCH_BIT(keybit, KEY_MAX); MATCH_BIT(relbit, REL_MAX); MATCH_BIT(absbit, ABS_MAX); MATCH_BIT(mscbit, MSC_MAX); MATCH_BIT(ledbit, LED_MAX); MATCH_BIT(sndbit, SND_MAX); MATCH_BIT(ffbit, FF_MAX); MATCH_BIT(swbit, SW_MAX); return id; } return NULL; } 该函数拿刚才获得的input_handler指针所拥有的特性表handler->id_table 与我们所注册的input_dev的特性表dev.id进行对照。 仍以触摸屏驱动s3c2410-ts.c与触摸屏接口tsdev.c为例: s3c2410-ts.c: ts.dev.evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); ts.dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(&ts.dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(&ts.dev, ABS_Y, 0, 0x3FF, 0, 0); input_set_abs_params(&ts.dev, ABS_PRESSURE, 0, 1, 0, 0); ts.dev.id.bustype = BUS_RS232; ts.dev.id.vendor = 0xDEAD; ts.dev.id.product = 0xBEEF; ts.dev.id.version = S3C2410TSVERSION; tsdev.c: static struct input_device_id tsdev_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, .relbit = { BIT(REL_X) | BIT(REL_Y) }, },/* A mouse like device, at least one button, two relative axes */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, },/* A tablet like device, at least touch detection, two absolute axes */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, },/* A tablet like device with several gradations of pressure */ {},/* Terminating entry */ }; 可以看到,tsdev.c接口定义了三项特性,对应id为0、1、2, input_match_device函数依次取出其中的选项与s3c2410-ts.c里面定义的input_dev的选项进行对比。 这里对比的标准是tsdev.c里面定义的选项s3c2410-ts.c里面必须满足,否则continue,继续判断下一个id号的选项。 详细请看MATCH_BIT这个宏的定义: #define MATCH_BIT(bit, max) / for (i = 0; i < NBITS(max); i++) / if ((id->bit[i] & dev->bit[i]) != id->bit[i]) / break; / if (i != NBITS(max)) / continue; 例如: 在这里,tsdev.c定义的id为0的选项里面定义的BIT(EV_REL)这一项 在s3c2410-ts.c里面定义的input_dev设备上是不具备的, 所以,执行到MATCH_BIT(evbit, EV_MAX);后直接continue, 继续判断tsdev.c里面id为1的选项,直到找到合适的,然后返回真,否则返回NULL。 ########################################################################################### 在list_for_each_entry(handler, &input_handler_list, node) 这个大循环里与我们所注册的input_dev所匹配的不限于一个接口, 例如,以下是我的调试记录: s3c2410 TouchScreen successfully loaded kbd input_match_device mousedev input_match_device mousedev_connect joydev input_match_device evdev input_match_device evdev_connect tsdev input_match_device tsdev_connect evbug input_match_device evbug_connect 可以看到,对于s3c2410-ts.c里面定义的input_dev设备,同时与其匹配的就有 mousedev、evdev、tsdev、evbug等众多接口(不知道我的理解是否正确,如果理解错了,还望指正^_^) ########################################################################################### 找到匹配的选项以后,就可以开始着手把input_dev、input_handle、input_handler这三者联系齐来了,具体调用 handle = handler->connect(handler, dev, id)函数, 主要的目的是填充input_handle结构,然后接着调用 input_link_handle(handle)函数: static void input_link_handle(struct input_handle *handle) { list_add_tail(&handle->d_node, &handle->dev->h_list); list_add_tail(&handle->h_node, &handle->handler->h_list); } 看到吧,就是上面那位大侠提到的,把input_handle分别链入input_dev和input_handler中h_list为Hash头的链中。 好了,到此,input_dev、input_handle、input_handler这三者总算是联系起来了^_^ 转:http://www.cnitblog.com/luofuchong/archive/2007/08/24/32382.html
相关文章推荐
- 2.6内核输入子系统分析
- [转]2.6内核输入子系统分析-续
- 2.6内核输入子系统分析
- 2.6内核输入子系统分析-续
- 2.输入系统驱动(4)-内核输入子系统原理分析
- [转]2.6内核输入子系统三层联系
- 内核输入子系统分析
- 42 linux内核里的输入子系统分析
- linux内核输入子系统分析
- linux 2.6内核makefile分析
- Linux 内核 SCSI IO 子系统分析
- input子系统学习笔记九 evdev输入事件驱动分析
- 输入子系统设备模型分析
- linux2.6内核ppp分析
- Linux2.6 内核进程调度分析
- linux input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- linux2.6内核内存描述符与线性区分析
- Linux内核内存管理子系统分析【转】
- input子系统学习笔记九 evdev输入事件驱动分析
- 29内核输入子系统多点上报机制实现