从ETTI Touch 到 uevent 机制分析

来源:互联网 发布:澳洲国立大学 知乎 编辑:程序博客网 时间:2024/05/16 01:53

Touch调试环境:yocto

调试过ETTI touch的人都知道,ETTI Touch 是人类历史上最容易调试的Touch,不涉及driver ,不涉及Makefile,Kconfig,也不涉及中断信号的处理。

既然ETTI Touch 那么容易调试,那为什么各大 Touch 厂家不把自家的Touch做成ETTI Touch的处理方式,不更好的方便调试吗?

总结了一下,原因有两个:

1、  Touch 调试本来就不复杂。

2、  ETTI这种处理方式是要付出代价的,所谓“鱼与熊掌不可兼得”。付出什么代价?下文会进行分析。

先来看看ETTI Touch调试的过程。(以串口屏为例)

分四步走:配置内核,把可执行程序跟配置文件放到rootfs里面,修改启动脚本,触摸矫正。


配置内核:

# make ARCH=arm menuconfig

选上以下两项:

--->[Device Drivers]

       ---> [Input devicesupport]

               ---> [Event interface]

 

     ---> [Device Drivers]

             ---> [Input device support] 

                     ---> [Miscellaneous devices]  

                             ---> [User level driver support]

即:

CONFIG_INPUT_MISC=y

CONFIG_INPUT_UINPUT=y

这样,新内核启动,可以看到以下节点:

/dev/input/uinput 或者是 /dev/uinput

 

把可执行程序跟配置文件放到rootfs里面:

主要是往rootfs存放 Touch 的可儿执行程序,和配置文件。这里,配置文件需要修改一下读取数据的设备节点。

eGTouchL.ini 里面修改 :     SerialPath0                             /dev/ttyX

 

修改启动脚本:

这里主要是修改 rc.local ,把Touch 的可执行程序启动的命令添加上。但修改完毕后会发现,触摸屏启动比较慢,因为 rc.local 是最后一个被执行的启动脚本,如果有需要,这里提示把启动命令行放到执行较前的启动脚本里面就可以了。

 

触摸校正:

校正很简单,校正完之后,把数据更新到“/etc/X11/xorg.conf.d/99-calibration.conf”里面即可。这里抛下一个问题,如果在yocto下调试,怎样把校正程序校正之后的数据打印出来?有兴趣,或者有需要的人士去研究一下吧。

到处为止,触摸屏就能够正常工作。下面,我们来分析一下触摸屏的工作原理是什么。


Linux内核引入uevent机制的目的:

一句话,很简单,就是为了能让用户空间也能向内核注入event数据。

当配置完内核配置选项:

CONFIG_INPUT_MISC=y

CONFIG_INPUT_UINPUT=y

机子运行起来可以看到“/dev/uinput”的设备节点。

这个“/dev/uinput”设备节点,你可以自己写一个应用程序去打开它,如:

char *dev = "/dev/uinput“;int fd = open(dev, O_WRONLY | O_NDELAY);

配置完毕。过程(略)。

然后往里面写数据:

struct uinput_user_dev device···write(fd,& device,sizeof(device));

这样,就可以把用户空间的数据写入内核里面。接下来,我们看看内核 uevent 里面做了什么事情:

drivers/input/misc/uinput.c

433 static ssize_t uinput_inject_event(struct uinput_device *udev,434                    const char __user *buffer, size_t count)435 {436     struct input_event ev;437 438     if (count < input_event_size())439         return -EINVAL;440 441     if (input_event_from_user(buffer, &ev))442         return -EFAULT;443 444     input_event(udev->dev, ev.type, ev.code, ev.value);445 446     return input_event_size();447 }448 449 static ssize_t uinput_write(struct file *file, const char __user *buffer,450                 size_t count, loff_t *ppos)451 {452     struct uinput_device *udev = file->private_data;453     int retval;454 455     if (count == 0)456         return 0;457 458     retval = mutex_lock_interruptible(&udev->mutex);459     if (retval)460         return retval;461 462     retval = udev->state == UIST_CREATED ?463             uinput_inject_event(udev, buffer, count) :464             uinput_setup_device(udev, buffer, count);465 466     mutex_unlock(&udev->mutex);467 468     return retval;469 }

我们知道,当用户空间调用 write 函数的时候,会调用到uinput.c 的uinput_write 函数。

从上面的代码可以看到uinput_write 函数首先从 user 空间拷贝数据到kernel 空间,然后调用uinput_inject_event 函数来处理。uinput_inject_event里面有一行代码:

input_event(udev->dev, ev.type, ev.code, ev.value);

看到这里,已经很明朗了,最终还是会调用到input_event 把数据上报到系统去。

这时候,在按着touch 的时候,你可以在机器上使用串口命令:

Cat /dev/input/event*

或者

Cat /dev/input/ touchscreen*

都可以看到打印源源不断的数据。

分析到这里,我们就能知道 ETTI Touch 的工作流程:

那么对比一下其他tp厂家的做法,如墩泰,思立微等:

从两者的比较可以看出,ETTI的处理过程多出了“从user空间到kernel空间,再到user空间的过程”,如果涉及到多点触摸,当数据量较大的时候,肯定会影响到执行效率。如果配置够强大,这方面的差异性也可以忽略掉,根据自己的需求而定。






0 0