首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

input_system输入子系统解析(2)

input_system输入子系统解析(2)

总结:
TP的操作就是底层将信息储存在 /sys/class/input/eventn 中,然后上层对其进行读取识别,然后根据其中的信息进行事件处理。

--------------------------------------------- kernel层 --------------------------------------------------

驱动层:(在具体的设备驱动文件中注册driver/input/touchscreen)
1、注册input_dev,进入input_register_device()
(1)把input_dev添加到input_dev_list链表中
list_add_tail(&dev->node, &input_dev_list);

(2)判断input_handler的id,是否有支持这个设备的驱动
list_for_each_entry(handler, &input_handler_list, node); //遍历查找input_handler_list链表里所有input_handler
input_attach_handler(dev, handler); //判断两者id,若两者支持便进行连接。

事件处理层:(./kernel-3.18/drivers/input/evdev.c)
2、注册input_handler,进入input_register_handler()
(1)把input_handler添加到input_handler_list链表中
list_add_tail(&handler->node, &input_handler_list);

(2)判断input_dev的id,是否有支持这个驱动的设备
list_for_each_entry(dev, &input_dev_list, node); //遍历查找input_dev_list链表里所有input_dev
input_attach_handler(dev, handler);//判断两者id,若两者支持便进行连接。

3、判断input_handler和input_dev的id,进入input_attach_handler()
(1)匹配两者id
id = input_match_device(handler, dev); //匹配input_handler和dev的id,匹配不成功退出函数

(2)匹配成功调用input_handler ->connect
error = handler->connect(handler, dev, id); //匹配成功建立连接

核心层:(kernel-4.4/drivers/input/input.c)
4、建立input_handler和input_dev的连接,进入input_handler->connect()
(1)input_register_handle函数,将handle通过d_node挂到input device的h_list,通过h_node挂到handler的h_list上,两者的.h_list都指向了同一个handle结构体,然后通过.h_list 来找到handle的成员.dev和handler,便能找到对方,便建立了连接connect
list_add_tail_rcu(&handle->d_node, &dev->h_list); //连接input_dev->h_list
list_add_tail_rcu(&handle->h_node, &handler->h_list); //连接input_handler->h_list

5、有事件发生时,比如触摸中断,在中断函数中需要进入input_event()上报事件,TP上报流程如下
驱动中调用input_report_abs上报绝对坐标
->input_event ------ input.h
->input_handle_event ------ input.c
->dev->event(dev, type, code, value); ------input.c
->evdev.c/evdev_event() ------ evdev.c
->evdev_events ------ evdev.c
-> evdev_pass_values ------ evdev.c
然后将 type、value、code 存储在 evdev_client 的 struct input_event buffer[] 中,input_event buffer存放在一个设备节点文件,在evdev_connect中注册生成了 /sys/class/input/event%d ,这个字符设备文件就是连接kernel与framework的桥梁了。

----------------------------------------接下来到framework层---------------------------------------------

6、再看 framework 上层怎么读取这个文件中的 buffer 的,我们从 InputReader.cpp 来分析
在frameworks/native/services/inputflinger/InputReader.cpp中
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
->void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;

size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

跟踪到在构造函数里,mEventHub 是 eventHub 的实例,那么就是调用 eventHub 的 getEvents 方法。

在frameworks/native/services/inputflinger/EventHub.cpp中
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {

for (;😉 {

scanDevicesLocked(); //这个往里走就是通过EventHub:penDeviceLocked 打开*DEVICE_PATH = “/dev/input” 这个设备 ,最终用的open,实际到kernel层就是input设备注册的open

int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //这里的device->fd就是/dev/input/eventn这个设备文件,就是从这里读取出event的buffer

再往上就是对这些数据的处理了。
返回列表