您现在的位置是:首页 > 手机 > 正文

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

发布时间:2022-05-31 13:38:31来源:

导读 大家好,小科来为大家解答以上问题。【i MX6ULL】驱动开发13—电容触摸驱动实践(下)这个很多人还不知道,现在让我们一起来看看吧! 解答:1

大家好,小科来为大家解答以上问题。【i.MX6ULL】驱动开发13—电容触摸驱动实践(下)这个很多人还不知道,现在让我们一起来看看吧!

解答:

1、 最后一篇文章介绍了电容式触摸驱动程序的编程,包括设备树和驱动程序(IIC驱动中断输入子系统)的修改,并通过实时打印触摸坐标值来测试触摸功能。

2、 在本文中,我们先介绍一下测试触摸库——tslib,它可以用于图形化触摸测试。之后,分析了触摸协议上报的原理和通过输入子系统上报的数据的具体含义。

3、 1tslib的使用

4、 Tslib是一个开源程序,可以为触摸屏驱动获取的样本提供滤波、去抖、校准等功能。它通常作为触摸屏驱动程序的适配层,为上层应用程序提供统一的接口。

5、 1.1tslib库迁移

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

7、 最新版本是1.22,但本文先用1.21版本。

8、 1.1.1在Ubuntu上编译tslib

9、 将下载的源代码复制到ubuntu虚拟机中,然后解压:

10、 tarxvftslib-1.21.tar.bz2

11、 编译tslib时,需要先在ubuntu中安装一些文件。

12、 sudoapt-get安装自动配置

13、 sudo安装自动制造

14、 sudoapt-get安装libtool

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

16、 cdtslib-1.21/。/autogen.sh。/configure-host=arm-Linux-gnueabihf-prefix=/home/xxpcb/myTest/imx6ull/otherlib/tslib/tslib/

17、 制造

18、 进行安装

19、 编译后,makeinstall会将编译结果复制到指定的tslib目录:

20、 您可以看到最终的编译生成了五个文件夹。

21、 1.1.2tslib配置在开发板上。

22、 将五个编译好的文件夹复制到开发板的根文件系统中:

23、 sudocp*-rf~/myTest/nfs/rootfs/

24、 然后打开电路板的/etc/ts.conf文件,找到下面一行:

25、 模块_原始输入

26、 如果此句前面有“#”注释,则删除“#”。我默认没有,不需要修改。

27、 打开电路板的/etc/profile文件。我的板此时没有这个文件,所以我创建了一个新文件,然后向其中添加了以下内容:

28、 导出tslib_tsdevice=/dev/input/event2

29、 导出tslib_CALIBFILE=/etc/pointercal

30、 导出TSLIB_CONFFILE=/etc/ts.conf

31、 导出TSLIB_PLUGINDIR=/lib/ts

32、 exportTSLIB_CONSOLEDEVICE=none

33、 导出TSLIB_FBDEVICE=/dev/fb0

34、 TSLIB_TSDEVICE:触摸设备文件,根据具体情况设置为/dev/input/event1或event2(如果鼠标和键盘连接,这个数字可能会发生变化,比如我连接无线键盘后,触摸又变成了事件)。

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

TSLIB_PLUGINDIR:tslib插件目录位置

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

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

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

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

使用如下指令:

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

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

多点触摸协议,即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区分触摸点

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

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

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

ABS_MT_POSITION_Xx[0]
ABS_MT_POSITION_Yy[0]
SYN_MT_REPORT
ABS_MT_POSITION_Xx[1]
ABS_MT_POSITION_Yy[1]
SYN_MT_REPORT
SYN_REPORT
首先每上报一个点的x和y

然后上报一个SYN_MT_REPORT

依次循环上报其它点

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

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

ABS_MT_POSITION_Xx[1]
ABS_MT_POSITION_Yy[1]
SYN_MT_REPORT
SYN_REPORT
当第二个触点也离开后,上报的时序如下(就是上报空数据):

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

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

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

ABS_MT_SLOT0
ABS_MT_TRACKING_ID45
ABS_MT_POSITION_Xx[0]
ABS_MT_POSITION_Yy[0]
ABS_MT_SLOT1
ABS_MT_TRACKING_ID46
ABS_MT_POSITION_Xx[1]
ABS_MT_POSITION_Yy[1]
SYN_REPORT
每个数据点前,先上报ABS_MT_SLOT事件,带上一个触摸点ID,此ID由触摸IC提供

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

然后上报一个点的x和y

依次循环上报其它点

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

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

ABS_MT_SLOT0
ABS_MT_POSITION_Xx[0]
SYN_REPORT
当slot0中触点离开后,上报的时序如下:

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

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

ABS_MT_SLOT1
ABS_MT_TRACKING_ID-1
SYN_REPORT
总结对比一下两个触摸协议的区别:

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

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

/**
*dev:MT设备对应的input_dev
*num_slots:设备要使用的slot的数量,也就是触摸点的数量
*flags:其他一些flags信息
*return:0-成功负值-失败
*/
intinput_mt_init_slots(structinput_dev*dev,
unsignedintnum_slots,
unsignedintflags)
其中第3个参数,可设置的flags包括:

#defineINPUT_MT_POINTER0x0001/*pointerdevice,e.g.trackpad*/
#defineINPUT_MT_DIRECT0x0002/*directdevice,e.g.touchscreen*/
#defineINPUT_MT_DROP_UNUSED0x0004/*dropcontactsnotseeninframe*/
#defineINPUT_MT_TRACK0x0008/*usein-kerneltracking*/
#defineINPUT_MT_SEMI_MT0x0010/*semi-mtdevice,fingercounthandledmanually*/
可以使用‘|’运算来同时设置多个flags标识

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

/**
*dev:MT设备对应的input_dev
*slot:当前发送的是哪个slot的坐标信息,也就是哪个触摸点
*return:无
*/
voidinput_mt_slot(structinput_dev*dev,intslot)
2.3.3input_mt_report_slot_state 该函数用于TypeB类型,用于产生ABS_MT_TRACKING_ID和ABS_MT_TOOL_TYPE事件,其函数原型如下:

/**
*dev:MT设备对应的input_dev
*tool_type:触摸类型
*active:触摸或抬起
*return:无
*/
voidinput_mt_report_slot_state(structinput_dev*dev,
unsignedinttool_type,
boolactive)
其中第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

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

/**
*dev:MT设备对应的input_dev
*code:要上报的是什么数据
*value:要上报的数据值
*return:无
*/
voidinput_report_abs(structinput_dev*dev,
unsignedintcode,
intvalue)
其中第2个参数,code包括:

ABS_MT_POSITION_X

ABS_MT_POSITION_Y

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

/**
*dev:MT设备对应的input_dev
*use_count:true-有效的触摸点数量false-追踪到的触摸点数量多于当前上报的数量
*return:无
*/
voidinput_mt_report_pointer_emulation(structinput_dev*dev,booluse_count)
3input子系统上报数据含义讲解 3.1input子系统简介 在Linux中,对于输入设备,例如按键、鼠标、键盘、触摸屏等,为了更加方便统一的管理,Linux内核为此专门做了一个input子系统的框架来处理输入事件。

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

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

各个的含义为:

#defineEV_SYN0x00/*同步事件*/
#defineEV_KEY0x01/*按键事件*/
#defineEV_REL0x02/*相对坐标事件*/
#defineEV_ABS0x03/*绝对坐标事件*/
#defineEV_MSC0x04/*杂项(其他)事件*/
#defineEV_SW0x05/*开关事件*/
#defineEV_LED0x11/*LED*/
#defineEV_SND0x12/*sound(声音)*/
#defineEV_REP0x14/*重复事件*/
#defineEV_FF0x15/*压力事件*/
#defineEV_PWR0x16/*电源事件*/
#defineEV_FF_STATUS0x17/*压力状态事件*/
例如,如果要使用按键的inpu件功能,就需要注册EV_KEY事件,若还要使用连按功能,需要注册EV_REP事件。

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

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

#defineKEY_RESERVED0
#defineKEY_ESC1
#defineKEY_12
#defineKEY_23
#defineKEY_34
#defineKEY_45
//......
#defineBTN_TOOL_QUINTTAP0x148	/*Fivefingersontrackpad*/
#defineBTN_TOUCH		0x14a
#defineBTN_STYLUS		0x14b
//......
#defineABS_X			0x00
#defineABS_Y			0x01
#defineABS_Z			0x02
#defineABS_RX			0x03
#defineABS_RY			0x04
#defineABS_RZ			0x05
#defineABS_MT_SLOT		0x2f	/*MTslotbeingmodified*/
#defineABS_MT_TOUCH_MAJOR	0x30	/*Majoraxisoftouchingellipse*/
#defineABS_MT_TOUCH_MINOR	0x31	/*Minoraxis(omitifcircular)*/
#defineABS_MT_WIDTH_MAJOR	0x32	/*Majoraxisofapproachingellipse*/
#defineABS_MT_WIDTH_MINOR	0x33	/*Minoraxis(omitifcircular)*/
#defineABS_MT_ORIENTATION	0x34	/*Ellipseorientation*/
#defineABS_MT_POSITION_X	0x35	/*CenterXtouchposition*/
#defineABS_MT_POSITION_Y	0x36	/*CenterYtouchposition*/
#defineABS_MT_TOOL_TYPE	0x37	/*Typeoftouchingdevice*/
#defineABS_MT_BLOB_ID		0x38	/*Groupasetofpacketsasablob*/
#defineABS_MT_TRACKING_ID	0x39	/*UniqueIDofinitiatedcontact*/
#defineABS_MT_PRESSURE		0x3a	/*Pressureoncontactarea*/
#defineABS_MT_DISTANCE		0x3b	/*Contacthoverdistance*/
#defineABS_MT_TOOL_X		0x3c	/*CenterXtoolposition*/
#defineABS_MT_TOOL_Y		0x3d	/*CenterYtoolposition*/
具体的定义在input.h文件中:

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

将数据内容摘出来看:

/*****************input_event类型********************/
/*编号*//*tv_sec*//*tv_usec*//*type*//*code*//*value*/
000000000f60000e53900030003003900000000
000001000f60000e539000300030035009d0000
000002000f60000e53900030003003600c10000
000003000f60000e53900030001014a00010000
000004000f60000e539000300030000009d0000
000005000f60000e53900030003000100c10000
000006000f60000e53900030000000000000000
000007000f6000011ad000500030039ffffffff
000008000f6000011ad00050001014a00000000
000009000f6000011ad00050000000000000000
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,触摸点的trackid

014a:BTN_TOUCH,触摸按键

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

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

第1行:绝对坐标事件,触摸点的trackid,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行:绝对坐标事件,触摸点的trackid,id=0xffffffff=-1,即触摸点离开了屏幕

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

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

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

130、

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

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

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

cpgt911.c../../kernel/nxp_kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/drivers/input/touchscreen/-f
修改drivers/input/touchscreen目录下的Makefile,在最下面添加下面一行:

obj-y+=gt911.o
然后(使用之前编写的编译脚本)重新编译linux内核

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

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

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

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

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

https://www.bilibili.com/video/BV1XL4y1t7kf

本文到此结束,希望对大家有所帮助。

标签:

上一篇
下一篇