MTK TP input子系统笔记

来源:互联网 发布:windows打开pages 编辑:程序博客网 时间:2024/05/17 23:54

一直都有报TP问题,但一般情况下都是效果类的,只要叫fae来改就行,也不是驱动能分析的,他们都有固有的一套参数来调试;再者,虽然每家TP厂的代码都不一样,但都要符合原理,都要能够正确的将最后的触点数据上报到input子系统。所以的话,TP这一块如果想直接做好业务这一块的话就要多多联系fae,他们才是最熟悉代码的人,加功能、修复bug,他们可以搞定。
但如果是上层出现问题丢给我们,那就要求驱动人员对input子系统的上报流程基本了解,这样的话也好定位问题;定位问题也是方案解决公司研发人员需要修炼的最基本的技能,其实对代码的了解不需要太深刻,我们只是在应用而已,这可能就是被称为工程师而不是程序员的原因吧。说归说,但我们研发也要有研发的样子,要对代码、原理做到精通。
接下来进入正题:屏幕上产生的触摸点是怎样上报到上层系统的呢?

Linux最经典的一句话就是:一切皆文件。

Linux的各种逻辑就是对文件进行读写增删(这时候我却又想到了数据库的基本操作,增删查改,哈哈),也就是说核心层和用户层的接口就是在于一个文件,你比如TP的操作就是底层将信息储存在 /sys/class/input/eventn 中,然后上层对其进行读取识别,然后根据其中的信息进行事件处理(所以文件系统应该是学linux必须要掌握的了吧,我先打脸,现在对文件系统还不是很熟悉)。
看一张图:
这里写图片描述
先看这个关键的文件节点是怎么创建的。
Input子系统的核心文件:/kernel-3.18/drivers/input/input.c
模块初始化代码:

static int __init input_init(void){    int err;    err = class_register(&input_class);    ……    err = input_proc_init();    ……    err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),                     INPUT_MAX_CHAR_DEVICES, "input");    ……}

class_register(&input_class) 是注册类的方式,可以在 /sys/class 下看到对应节点文件;
input_proc_init() 代码:

static int __init input_proc_init(void){    struct proc_dir_entry *entry;    proc_bus_input_dir = proc_mkdir("bus/input", NULL);//创建proc中的路径    ……    entry = proc_create("devices", 0, proc_bus_input_dir,                &input_devices_fileops);//创建proc中的节点    ……    entry = proc_create("handlers", 0, proc_bus_input_dir,                &input_handlers_fileops); //创建proc中的节点    ……}

register_chrdev_region(MKDEV(INPUT_MAJOR, 0), INPUT_MAX_CHAR_DEVICES, “input”);
注册input字符设备,主节点为INPUT_MAJOR==13,可以去input_fops里看注册函数,注册到/dev/input;
相应的对应关系可以使用adb 命令进入文件系统之后,cat /proc/bus/input/devices ,查看各个设备对应的event多少,比如

I: Bus=0000 Vendor=0000 Product=0000 Version=0000N: Name="himax-touchscreen"P: Phys=S: Sysfs=/devices/virtual/input/input9U: Uniq=H: Handlers=gpufreq_ib event8B: PROP=2B: EV=bB: KEY=400 0 0 0 2000000 0 40000800 40 0 0 0B: ABS=6658000 0

Name就是对应的输入设备的名称,这里是 himax 的触摸屏,event8 就是事件序号,
我们在调试的时候直接 adb shell getevent /dev/input/event8,来实时捕捉 event8 中储存的数据。

getevent 查看我们所想要的是对应的 eventn。


然后分析下底层,TP 的驱动文件中处理事件的函数一般是 touch_event_handler,
其中最后一步上报坐标点都是下列格式:

input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w);input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);input_mt_sync(ts->input_dev);

这些函数跟踪的话会发现都会调用 input_handle_event,
比如:

 input_report_abs ->input_event  ->input_handle_event   ->dev->event(dev, type, code, value);     ->evdev.c/evdev_event()     ->evdev_events      -> evdev_pass_values

将 type、value、code 存储在 evdev_client 的 struct input_event buffer[] 中。


再看 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::openDeviceLocked  打开*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  

再往上就是对这些数据的处理了。

到这里就把上报数据的传递过程串起来了。
关于上层的处理,后面再整理。

吃水不忘挖井人:
input子系统详解:http://blog.csdn.net/column/details/input.html

原创粉丝点击