欢迎光临散文网 会员登陆 & 注册

【i.MX6ULL】驱动开发13——电容触摸驱动实践(下)

2022-03-05 18:20 作者:码农爱学习-B站  | 我要投稿

上篇文章介绍了电容触摸驱动的编写,包括设备树的修改和驱动程序(IIC驱动+中断+input子系统),并通过将触摸坐标值实时打印出来的方式,对触摸功能进行测试。

本篇,先来介绍一会测试触摸是库——tslib,使用它可以进行图形化的触摸测试。之后,再回头来分析分析触摸协议上报的原理以及通过input子系统上报的数据的具体含义。

1 tslib的使用

Tslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用提供了一个统一的接口

1.1 tslib库移植

首先下载tslib库的源码:https://github.com/libts/tslib/tags

目前最新的是1.22,不过本篇先使用1.21版本

1.1.1 ubuntu上编译tslib

将下载的源码拷贝到ubuntu虚拟机中,然后解压:

编译 tslib 的时候需要先在 ubuntu 中安装一些文件

在 ubuntu 中创建一个名为“tslib”的目录存放编译结果,然后执行以下指令进行编译:

编译完成后,make install会将编译成果复制到指定的tslib目录中:

可以看到最终编译生成的是5个文件夹。

1.1.2 开发板上配置tslib

将编译出的5个文件夹整个复制到开发板的根文件系统中:

然后打开板子的/etc/ts.conf 文件,找到下面这一行:

如果这句前面有“#”注释,就删除掉“#“,我这个默认是没有的,所以不用修改

打开板子的/etc/profile文件,我的板子此时没有这个文件,所以我新建了一个该文件,然后在里面加入如下内容:

  • TSLIB_TSDEVICE :触摸设备文件,要根据具体情况设置为/dev/input/event1还是event2(如果接口鼠标键盘,这个编号可能还会变,比如我接了无线键盘后,触摸就又变成了event)

  • TSLIB_CALIBFILE :校准文件,此文件可以不存在,校准的时候会自动生成

  • TSLIB_CONFFILE :触摸配置文件,在移植 tslib 的时候会生成

  • TSLIB_PLUGINDIR :tslib 插件目录位置

  • TSLIB_CONSOLEDEVICE :控制台设置,这里不设置,设为none

  • TSLIB_FBDEVICE:FB 设备,也就是屏幕,也要根据实际情况配置设置为/dev/fb0或是其它

1.2 tslib库测试

1.2.1 屏幕校准

电容屏可以不用校准,不过也可以看看tslib的校准测试用例,输入如下指令:

校准完成以后如果不满意,删除掉/etc/pointercal文件即可

1.2.2 多点触摸拖拽测试

使用如下指令:

然后会出现一个触摸测试界面,先测试Drag功能,手指接触屏幕后进行移动,屏幕上的十字标记就会跟着移动:

1.2.3 多点触摸划线测试

还是刚才的指令,再来测试Draw功能,手指接触屏幕后进行移动,屏幕上就会出现滑过的轨迹线:

2 多点触摸(MT)协议讲解

多点触摸协议,即Multi-touch (MT) Protocol,该协议的介绍,在linux内核源码中有对应的文档,如下图:

多点电容触摸的协议分为两种类型:TypeA和TypeB,目前基本都是使用TypeB协议。

  • TypeA协议适用于触摸点不能被区分或者追踪,此类设备上报原始数据。

  • TypeB协议适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过slot更新某一个触摸点的信息。

触摸点的信息通过一系列的 ABS_MT事件上报给linux内核,这些事件的定义在include/uapi/linux/input.h中:

比较常用的有:

  • ABS_MT_SLOT :上报触摸点ID

  • ABS_MT_POSITION_X:上报触摸点的X坐标信息

  • ABS_MT_POSITION_Y:上报触摸点的Y坐标信息

  • ABS_MT_TRACKING_ID:TypeB区分触摸点

下面具体介绍两种协议的区别。

2.1 TypeA协议

TypeA协议适用于触摸点不能被区分或者追踪,此类设备上报原始数据。

TypeA协议发送触摸点信息的时序如下(以 2 个触摸点为例):

  • 首先每上报一个点的x和y

  • 然后上报一个SYN_MT_REPORT

  • 依次循环上报其它点

  • 所有的点上报完后,再上报一个SYN_REPORT

当第一个触点离开后,上报的时序如下(就是只上报剩下的那一个):

当第二个触点也离开后,上报的时序如下(就是上报空数据):

如果驱动除了ABS_MT事件外还上报BTN_TOUCH或ABS_PRESSURE之一,则最后一个SYN_MT_REPORT事件可能被忽略。另外,最后的SYN_REPORT会被输入内核放弃,从而导致没有空触事件到达用户层。

2.2 TypeB协议

TypeB协议适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过slot更新某一个触摸点的信息。

TypeA协议发送触摸点信息的时序如下(以 2 个触摸点为例):

  • 每个数据点前,先上报ABS_MT_SLOT事件,带上一个触摸点ID,此ID由触摸IC提供

  • TypeB要求每个SLOT须关联一个ABS_MT_TRACKING_ID,这个ID由linux内核自动分配

  • 然后上报一个点的x和y

  • 依次循环上报其它点

  • 所有的点上报完后,再上报一个SYN_REPORT

当触点45在X方向上移动后,上报的时序如下:

当slot 0中触点离开后,上报的时序如下:

由于slot被修改为0,因此这个ABS_MT_SLOT被忽略。这条信息移除了slot 0和触点45的联系,因此销毁触点45同时释放slot 0给另外的触点再次使用。

当第二个触点离开后,上报的时序如下:

总结对比一下两个触摸协议的区别:



2.3 多点触摸API函数

了解了两种触摸协议,在编程时,就要使用其相应的API函数来实现触摸数据的上报,下面是常用的API函数。

2.3.1 input_mt_init_slots

该函数用于初始化MT的输入slots,其函数原型如下:

其中第3个参数,可设置的flags包括:

可以使用‘|’运算来同时设置多个flags标识

2.3.2 input_mt_slot

该函数用于Type B类型,用于产生 ABS_MT_SLOT事件,其函数原型如下:

2.3.3 input_mt_report_slot_state

该函数用于Type B类型,用于产生ABS_MT_TRACKING_ID和ABS_MT_TOOL_TYPE事件,其函数原型如下:

其中第2个参数,tool_type包括:

  • MT_TOOL_FINGER:手指

  • MT_TOOL_PEN:笔

  • MT_TOOL_PALM:手掌

其中第3个参数,active包括:

  • true: 连续触摸, input子系统内核会自动分配一个ABS_MT_TRACKING_ID给slot

  • false:触摸点抬起,表示某个触摸点无效了,input子系统内核会分配一个-1给slot

2.3.4 input_report_abs

该函数用于上报触摸点坐标,TypeA和TypeB类型都使用此函数上报触摸点坐标信息,其函数原型如下:

其中第2个参数,code包括:

  • ABS_MT_POSITION_X

  • ABS_MT_POSITION_Y

2.3.5 input_mt_report_pointer_emulation

如果追踪到的触摸点数量多于当前上报的数量,驱动程序使用 BTN_TOOL_TAP 事件来通知用户空间当前追踪到的触摸点总数量,然后调用 input_mt_report_pointer_emulation 函数将use_count 参数设置为 false,否则的话将 use_count 参数设置为 true。

3 input子系统上报数据含义讲解

3.1 input子系统简介

在Linux中,对于输入设备,例如按键、 鼠标、 键盘、 触摸屏等,为了更加方便统一的管理, Linux内核为此专门做了一个input子系统的框架来处理输入事件。

input是输入的意思,就是管理输入的子系统,和 pinctrl、gpio 子系统一样,都是 Linux 内核针对某一类设备而创建的框架。input 子系统框架图如下:

3.2 input输出事件

3.2.1 事件类型

evbit 表示输入事件类型,可选的事件类型定义在 include/uapi/linux/input.h 文件中,事件类型如下:

各个的含义为:

例如,如果要使用按键的inpu件功能,就需要注册EV_KEY事件,若还要使用连按功能,需要注册EV_REP事件。

如果要使用触摸屏的inpu件功能,就需要注册EV_KEY事件,

3.2.2 按键值类型

evbit、keybit、relbit 等等都是存放不同事件对应的值,Linux 内核定义了很多按键值:

具体的定义在input.h文件中:

3.3 触摸数据上报实例分析

上篇文章只是将触摸坐标打印到了屏幕,实际是使用触摸屏时,需要将坐标数据通过input子系统上报应用层,现在来具体分析一下input子系统上报的这些数据的含义,例如按下触摸键后,串口会有如下打印:

将数据内容摘出来看:

  • type 为事件类型

    • 0000:EV_SYN,同步事件

    • 0001:EV_KEY,按键事件

    • 0003:EV_ABS,绝对坐标事件

  • code 为事件编码,也就是按键号

    • 0000:ABS_X,单点触摸上报X坐标值

    • 0001:ABS_Y,单点触摸上报Y坐标值

    • 0035:ABS_MT_POSITION_X,多点触摸上报X坐标值

    • 0036:ABS_MT_POSITION_Y,多点触摸上报Y坐标值

    • 0039:ABS_MT_TRACKING_ID,触摸点的track id

    • 014a:BTN_TOUCH,触摸按键

  • value 就是按键值, 为 1 表示按下, 为 0 的话表示松开

来分析一下每行输出的含义:

第1行:绝对坐标事件,触摸点的track id,id=0

第2行:绝对坐标事件,多点触摸X坐标值,X=0x9d (157)

第3行:绝对坐标事件,多点触摸Y坐标值,Y=0xc1 (193)

第4行:按键事件,触摸按键,1表示按键按下

第5行:绝对坐标事件,单点触摸X坐标值,X=0x9d (157)

第6行:绝对坐标事件,单点触摸Y坐标值,Y=0xc1 (193)

第7行:同步事件,由input_sync函数上报

第8行:绝对坐标事件,触摸点的track id,id=0xffffffff=-1,即触摸点离开了屏幕

第9行:按键事件,触摸按键,0表示没有按键

第10行:同步事件,由input_sync函数上报

注:上面的打印,有多点触摸和单点触摸的上报,实际上如果使用了多点触摸,可以将单点触摸的上报去掉,如下:

去掉后,再次测试,可以看到只有多点触摸数据的上报:


4 将触摸驱动编译到内核

自己编写的触摸驱动,每次系统启动后,都要手动加载驱动模块后才能使用,比较麻烦,现在驱动文件不需要再改了,就可以将自己的驱动直接编译到内核中。方法如下:

将自己写的触摸屏驱动文件拷贝到Linux内核的drivers/input/touchscreen/目录下:

修改 drivers/input/touchscreen 目录下的 Makefile,在最下面添加下面一行:

然后(使用之前编写的编译脚本)重新编译linux内核

再将zImage拷贝到板子中,重新启动板子。

正常情况下,在内核启动的时候就打印出触摸驱动的event编号信息,我这里确实也打印了,只是随后一直刷IIC错误:

暂时看不出来是什么原因,才这居打印看,触摸开始读数据时才会进到这里,感觉像是触摸驱动刚加载完成,就触发了中断,但在中断里通过IIC读取触摸数据时,又出现了问题。。。

一个暂时的替代方式是,可以在开机自启动文件中进行触摸驱动的加载,在/etc/init.d/rcS文件中补充如下语句即可:

5 总结

本篇首先介绍了测试触摸是库——tslib,使用它可以进行图形化的触摸测试。随后,又分析触摸协议上报的原理以及通过input子系统上报的数据的具体含义。

附:演示视频

https://www.bilibili.com/video/BV1XL4y1t7kf?spm_id_from=333.999.0.0


【i.MX6ULL】驱动开发13——电容触摸驱动实践(下)的评论 (共 条)

分享到微博请遵守国家法律