AM335x使用tslib实现QT5校准

本文使用的文件系统是Ti的ti-processor-sdk-linux-am335x-evm-06.03.00.106。官方说明,触摸校准使用weston-calibrator或使用tslib库。参照(有些链接仅自己查资料的记录):
https://e2e.ti.com/support/processors/f/791/p/903802/3342761?tisearch=e2e-sitesearch&keymatch=ts_calibration#3342761

帖中回复:I apologize for the delayed response. TI supports resistive touchscreen 1) using weston/wayland, or 2) without weston, but using tslib. The default filesystems in the PSDK use weston.

https://e2e.ti.com/support/processors/f/791/t/495706?AM572x-touch-screen-calibration
https://e2e.ti.com/support/processors/f/791/t/160683?tisearch=e2e-sitesearch&keymatch=tslib
https://e2e.ti.com/support/processors/f/791/t/594835?Linux-AM3352-Touchscreen-issues

PSDK文件系统中,没有编译好的tslib且QT插件也没有提供tslib的支持。需要自己重新编译。本文编译的方法按照YOCTO中编译的方法,没有按网上自己下载源码编译。
本文介绍的QT校准方法是,编译tslib库,无需编译QT即可使用校准数据。原理是:利用linux内核的虚拟事件(uinput)生成(鼠标,软键盘,6轴传感器等都可以用)对应的event,再让QT使用虚拟事件。ts_uinput后台运行,监控接收触摸event0的事件,经过校准后,由用户层写入虚拟事件到内核,对应生成event1的数据。

1.编译tslib
参照:https://e2e.ti.com/support/processors/f/791/t/601742?Linux-PROCESSOR-SDK-AM335X-Adding-tslib-to-kernel

    MACHINE=am335x-evm bitbake tslib
    Command to install:
   opkg install ipk_name.ipk

编译完成后,把’…/build/arago-tmp-external-linaro-toolchain/work/armv7ahf-neon-linux-gnueabi/tslib/1.1-r0.arago1/deploy-ipks/armv7ahf-neon/'目录下的*.ipk文件拷贝到自己的板子,执行opkg install *.ipk安装即可。YOCTO编译请参照:https://editor.csdn.net/md?articleId=110860271
安装好后,执行如下命令测试:

#ts_calibrate
#ts_test

2.编译QT支持tslib,
自己编译QT是成功,但是并未成功支持tslib,写下来主要是为了记录操作过程。而且本文校准方法最终未使用编译QT支持tslib的方法。
参照:https://e2e.ti.com/support/processors/f/791/t/670333
https://e2e.ti.com/support/processors/f/791/t/689235?tisearch=e2e-sitesearch&keymatch=yocto%2520qt

   However under /linux-devkit/sysroots/x86_64-arago-linux/usr/lib I see libQt5Core.so.5.7.1 for example.

If I understand your question right you do not want to build full PSDK only the qt with bitbake.
If yes, you could check the recipes under /tisdk/sources/meta-qt5/recipes-qt/qt5.
Here is command for qtbase for example:
MACHINE=<target_board> bitbake qtbase

编译时bitbake指令:MACHINE=<target_board> bitbake qtbase
编译前如何添加tslib支持,因为默认是-no-tslib。自己尝试在/tisdk/sources/meta-qt5/recipes-qt/qt5/qtbase_git.bb文件中的do_configure()中直接更改(此方法不可取,直接更改YOCTO中文件了),虽然QT编译目录下的config.pro文件中显示-tslib了,但安装到自己的板子上,tslib插件仍然没有。后来查阅资料,YOCTO中想增加编译属性可以:方法一: 在recipe的附件文件即.bbappend文件中添加该依赖属性
PACKAGECONFIG_append = " f1"

方法二: 在bsp包的配置文件conf/local.conf中增加recipde的依赖属性
PACKAGECONFIG_append_pn-[recipename] = " f1"
见:https://www.cnblogs.com/liushuhe1990/articles/13217942.html


yocto中增加包依赖配置 / how to add packageconfig in yocto

https://wiki.phytec.com/pages/viewpage.action?pageId=151257902

https://www.yoctoproject.org/docs/2.4.2/ref-manual/ref-manual.html

在yocto参考文档中有对PAKAGECONFIG变量中有详细的说明,  更详细的信息可参考ref-manual.
PACKAGECONFIG说明

在yocto的recipe的bb文件中, 一般都有PACKAGECONFIG变量的一些配置.

在ref-manual中提到, PACKAGECONFIG变量定义于在一个基础recipe的配置使能或者禁止某些属性.

在recipe的PACKAGECONFIG变量的基本架构如下:
PACKAGECONFIG[f1] = "--with-f1,--without-f1,build-deps-f1,rt-deps-f1"

在一个recipe中, 如果f1属性使能,--with-f1, build-deps-f1就会应用于这个recipe,

而如果f1属性被禁止, --without-f1 和 rt-deps-f1则会被应用.
使能recipe的某个属性

如果要增加使能recipe的某个属性的话, 有以下两种方法

方法一: 在recipe的附件文件即.bbappend文件中添加该依赖属性
PACKAGECONFIG_append = " f1"

方法二: 在bsp包的配置文件conf/local.conf中增加recipde的依赖属性
PACKAGECONFIG_append_pn-[recipename] = " f1"

[recipename]需要对应改成该recipe的名字
重新定义recipe的属性(一般不推荐)

由于bsp的原有的layer中的recipe一般都有添加了必要的属性, 所以一般不推荐使用以下方法重新定义recipe的属性.

方法一:  在recipe的.bbappend文件中定义包的属性
PACKAGECONFIG="f4 f5"

方法二: 在bsp包的配置文件conf/local.conf中重新定义recipe的属性
PACKAGECONFIG_pn-[recipename] = " f4 f5"
应用实例

接下来, 以qtbase增加sql-sqlite为例, 对PACKAGECONFIG进行介绍.

在qtbase的recipe文件qtbase_git.bb中, sql-sqlite的属性配置为
PACKAGECONFIG[sql-sqlite] = "-sql-sqlite -system-sqlite,-no-sql-sqlite,sqlite3"

当sql-sqlite属性使能后, sqlite3会应用于qtbase中.

有一下两种方法, 使能qtbase的sql-sqlite属性.

方法一: 在qtbase_git.bbappend文件中增加sql-sqlite属性
PACKAGECONFIG_append = " sql-sqlite"

方法二: 在conf/local.conf文件中增加sql-sqlite属性
PACKAGECONFIG_append_pn-qtbase = " sql-sqlite"

后面添加增加依赖包的方式没有再试了,不知道是否有效。因为突然查阅到另一种不用编译的方法。见第3节。

3.ts_uinput生成虚拟的触摸事件
https://github.com/libts/tslib#setup-and-configure-tslib
https://www.cnblogs.com/sky-heaven/p/8116664.html
https://blog.csdn.net/weixin_44775117/article/details/94858349

以下内容是Github tslib说明的摘抄,开机自启服务部分按照自己的环境更改。
use the filtered result in your system (X.org method)

If you’re using X.org graphical X server, things should be very easy. Install tslib and xf86-input-tslib, reboot, and you should instantly have your ts.conf filters running, without configuring anything else yourself.
use the filtered result in your system (ts_uinput method)

TL;DR: Run tools/ts_uinput_start.sh during startup and use /dev/input/ts_uinput as your evdev input device.

tslib tries to automatically find your touchscreen device in /dev/input/event* on Linux. Now make ts_uinput use it, instead of your graphical environment directly:

ts_uinput -d -v

-d makes the program return and run as a daemon in the background. -v makes it print the new /dev/input/eventX device node before returning.

Now make your graphical environmen use that new event device, using evdev drivers.

For Qt5 for example you'd probably set something like this:

QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/eventX QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/eventX:rotate=0

For X11 you'd probably edit your xorg.conf Section "InputDevice" for your touchscreen to have

Option "Device" "/dev/input/eventX"

For Wayland, you'd make libinput use the new /dev/input/eventX and so on. Please see your system's documentation on how to use a specific evdev input device.

Let’s recap the data flow here:

driver --> raw read --> filter(s) … --> ts_uinput --> libevdev read --> GUI app/toolkit
module module(s) … daemon e.g. in libinput

回到顶部
symlink /dev/input/ts_uinput to the new event file

/dev/input/event numbers are not persistent. In order to know in advance, what enumerated input device file is created by ts_uinput, you can use a symlink:

use the included tools/ts_uinput_start.sh script that starts ts_uinput -d -v and creates the symlink called /dev/input/ts_uinput for you, or

if you're using systemd, create the following udev rule, for example /etc/udev/rules.d/98-touchscreen.rules:

SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{name}=="ts_uinput", SYMLINK+="input/ts_uinput"

回到顶部
running as systemd service (optional)

in case you have to use non-default paths, create a file containing the environment for tslib, like /etc/ts.env

TSLIB_CALIBFILE=/etc/pointercal
TSLIB_CONFFILE=/etc/ts.conf
TSLIB_PLUGINDIR=/usr/lib/ts

and create a systemd service file, like /usr/lib/systemd/system/ts_uinput.service

[Unit]
Description=touchscreen input
Wants=dev-input-ts_raw.device
After=dev-input-ts_raw.device

[Service]
Type=oneshot
EnvironmentFile=/etc/ts.env
ExecStart=/bin/sh -c ‘exec /usr/bin/ts_uinput &> /var/log/ts_uinput.log’

[Install]
WantedBy=multi-user.target

and

#systemctl enable ts_uinput

will enable it permanently.

从以上可以看出,使用ts_uinput虚拟个输入事件,等同于把event0的触摸屏数据,添加个校准过滤重新建事个eventX的事件。然后QT直接把输入定向到新创建的事件即可。
只要执行 ts_uinput -d -v。去/dev/input/目录查找相应文件。

4.配置QT使用新建立的事件及测试
按照tslib官方介绍的操作

QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/eventX 
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/eventX:rotate=0

事实上出了问题,怎么配置都不成功。使能export QT_LOGGING_RULES=qt.qpa.input=true查看,发现Qt调用了多个事件输入(同时有libinput和evdevtouch的,也就是开启evdevtouch的同时,libinput驱动输入未关闭)。同时,自己写的QT应用程序,可以打印触摸坐标的,也显示每次触摸有两条触摸数据输出,而且一个对(未校准前),一个错,导致触摸不对。
使用 evtest 测试,发现新生成的event1事件中,打印的坐标是有经过校准的正确坐标数据。
也可使用如下方法调试触摸输出: hexdump -d /dev/input/event0。
Qt 5.x 相对于 4.8 及以前版本在窗口系统上有较大幅度改动,原来的 QWS 被 QPA 完全取代,导致输入设备配置简化了很多,执行界面程序也不需要再加上-qws。

找到触摸屏event

用的 USB 接口驱动触摸屏,当你插入 usb 的电容屏时,在 dev/input 下面会出现相应的设备节点。假如cat /dev/event0,触摸屏幕有乱码输出,则说明 usb 触摸屏驱动产生中断并且将采集数据上报 input 子系统了。

另外也可以使用 hexdump 命令,它是 Linux 下的一个二进制文件查看工具,它可以将二进制文件转换为 ASCII、八进制、十进制、十六进制格式进行查看,默认显示十六进制格式,使用 -d 命令参数显示十进制,详细使用参考:Linux命令学习总结:hexdump

使用 hexdump 命令查看触摸信息,快速触摸屏幕右下角后的打印信息如下:

$ hexdump -d /dev/input/event0
0000000 15989 00000 18969 00004 00004 00004 00001 00009 # 其它事件
0000010 15989 00000 18969 00004 00001 00272 00001 00000 # BTN_MOUSE,按下
0000020 15989 00000 18969 00004 00003 00000 16333 00000 # ABS_X
0000030 15989 00000 18969 00004 00003 00001 09599 00000 # ABS_Y
0000040 15989 00000 18969 00004 00000 00000 00000 00000 # 同步事件
0000050 15989 00000 49415 00005 00004 00004 00001 00009 # 其它事件
0000060 15989 00000 49415 00005 00001 00272 00000 00000 # BTN_MOUSE,松开
0000070 15989 00000 49415 00005 00000 00000 00000 00000 # 同步事件

倒数第四、三、二行分别为 type、code 和 value,在 linux/input.h 都有定义,Linux 中输入设备的事件类型有:

#define EV_SYN 0x00 // 同步事件
#define EV_KEY 0x01 // 按键事件
#define EV_REL 0x02 // 相对坐标
#define EV_ABS 0x03 // 绝对坐标
#define EV_MSC 0x04 // 其它事件

type 是事件类型,为 3 就是 EV_ABS=0x03,为 0 就是 EV_SYN=0x00(作为事件的分隔)。

code 的话根据事件类型而定,如果是 type 为 EV_ABS,code 为 0 就是 ABS_X,code 为 1 就是 ABS_Y。

然后 value 就是在 type 和 code 的前提下的值,比如 type 为 EV_ABS,code 为 0 就是 ABS_X,那么 value 就代表触摸点的 x 轴绝对值。

比如 type 为 EV_KEY,code 为 272 就是 BTN_MOUSE,code 为 330 就是 BTN_TOUCH,那么 value 为 1 表示按下,为 0 表示松开。比如 type 为 EV_ABS,code 为 24 就是 ABS_PRESSURE,value 为 1 表示按下,为 0 表示松开。

测试看出触摸屏触摸产生的坐标值范围为 X:016384,Y:09600,同时该触摸屏没有上传 ABS_PRESSURE。

通过 cat /proc/bus/input/devices 应该就能够看到触摸设备的相关信息。比如:

$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=222a Product=0001 Version=0110
N: Name=“ILITEK ILITEK-TP”
P: Phys=usb-11000000.xhci-1.4/input1
S: Sysfs=/devices/soc/11000000.xhci/usb1/1-1/1-1.4/1-1.4:1.1/0003:222A:0001.0004/input/input2
U: Uniq=
H: Handlers=mouse0 js0 event0
B: PROP=0
B: EV=1b
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10

上面的信息有触摸屏 vid,pid,版本等,以及 ABS 表示触摸屏的绝对坐标掩码,掩码上面表示 16 进制,所以 3=0x0000003=0000 0000 0000 0000 0000 0000 0011,其中为 1 的比特的位置就表示触摸屏会报告这一类型的事件,前面的 bit0 和 bit1,那么看 linux/input.h 文件就表示事件 code 码有 ABS_X=0x00 , ABS_Y=0x01, 这两个分别表示触摸屏报告触摸的 x 坐标,y 坐标。而 bit24 为 0,则表示触摸屏驱动没有上传 ABS_PRESSURE。详情请参考:linux读取触摸屏事件数据

Qt使用电容屏

使用电容屏的 Qt 程序,不用移植 tslib 库,就可以直接读取输入设备文件(/etc/input/eventx),除非需要 tslib 校准。另外 Qt4 默认支持触屏,而 Qt5 需要设置环境变量才能支持触屏:

export QT_LOGGING_RULES=qt.qpa.input=true # 打印触屏信息
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0 # 指定输入设备的名称
export QT_QPA_EVDEV_MOUSE_PARAMETERS=/dev/input/event0 # 将触摸屏的点击事件配置成Qt的鼠标点击事件
export QT_QPA_FB_HIDECURSOR=1 # 为1则隐藏鼠标光标,为0则显示鼠标光标

对于 Qt5,设置环境变量QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS
,Qt5 自身的 libinput 就会去/dev/input/eventX读取触摸屏数据(未校准),从而使触摸正常工作。
将触摸屏的点击事件配置成 Qt 的鼠标点击事件后,会产生有一个鼠标光标。

电容屏的校准

触摸屏配置可分两种方式,一种是电容屏或由驱动校准的电阻屏配置,另一种是需要借助 tslib 校准的电阻屏配置。

所以电容屏本身是不需要校准的,不过和 Qt 配合的话就需要重新校准:

一、Qt 本身提供了一个校准软件,叫做 mousecalibration,不过只能支持 Embedded Linux(嵌入式 Linux),软件在 example->qws 目录下面,可以完成校准。但是由于不同的嵌入式平台采用的芯片差异性很大,所以这个校准程序往往无法使用。其详细说明参考:Mouse Calibration Example

二、使用 tslib校准:带 tslib 校准的方式需要移植最新版 tslib 库,再编译 Qt 源码或插件(Qt 自带的插件可以单独编译,自带插件不支持多点触摸),编译时加入 tslib 到编译选项。移植到嵌入式设备后,配置 tslib 校准服务开机启动,之后配置 Qt 宏默认使用 tslib 插件作为默认输入插件。

校准原理说明

分辨率转化和校准
其实触摸屏触摸产生的坐标值是绝对坐标,范围为 X:016384,Y:09600。所以,我们运行的 Qt 程序如果直接获取 /dev/input/eventx 产生的坐标的话,鼠标位置便会超出屏幕的显示范围(1920*1080),因此,我们需要进行一下坐标值转化。

解决方法参见官方描述:http://qt5.digitser.net/5.14/zh-CN/inputs-linux-device.html#input-on-eglfs-and-linuxfb-without-libinput
https://doc.qt.io/qt-5/embedded-linux.html

其中:Note: As of Qt 5.8, the above is only supported for the evdevtouch input backend. Other variants, such as the libinput-based one, will continue to route events to the primary screen. To force the usage of evdevtouch on systems where multiple input backends are available, set the environment variable QT_QPA_EGLFS_NO_LIBINPUT to 1.

说明:如果要使用evdevtouch输入,要QT_QPA_EGLFS_NO_LIBINPUT =1强制关闭系统默认输入libinput,对应linuxfb的显示是QT_QPA_FB_NO_LIBINPUT =1。关闭后,使用export QT_LOGGING_RULES=qt.qpa.input=true后启动QT应用,发现打印的坐标还不对。用evtest查看evtent1的输入后,发现第一个坐标打印是对的,而后有很多无效坐标。因为tslib现在支持多点触摸,可能是后面点坐标有误,从数据上看是无意义的,或是与QT底层驱动不匹配。所以就想有什么办法关闭多点触摸输出,无竟中看到https://github.com/libts/tslib/issues/141中有描述:Btw, make sure you don’t have module variance in your ts.conf file. Better start by using module_raw input and module linear only.虽然解决的问题不是我遇到的问题,把ts.conf文件仅留下module_raw input and module linear only,用evtest一测试,果然多点触摸输出没有了,event1和event0输出一样干净,只有有效数据点。

至此,触摸校准的虚拟事件生成,QT的输入配置成功。

5.最终需要的环境变量配置
/etc/ts_conf中

root@am335x-evm:~# cat /etc/ts.conf 
# Uncomment if you wish to use the linux input layer event interface
module_raw input
module linear

tslib的环境变量

root@am335x-evm:~# cat /etc/profile.d/tslib.sh 
#!/bin/sh

### Touchscreen Environment Variables ###

export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_CONSOLEDEVICE=none #去除这项后,打开一次QT后,无法再使用ts_test等应用

QT的环境变量配置

root@am335x-evm:~# cat /etc/profile.d/qt_env.sh 
#!/bin/sh

### QT Environment Variables ###
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_EGLFS_KMS_CONFIG=/etc/qt5/eglfs_kms_cfg.json
export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
export QT_QPA_EGLFS_ALWAYS_SET_MODE=1
export QT_WAYLAND_SHELL_INTEGRATION=wl-shell
export QT_QPA_FB_NO_LIBINPUT=1
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event1

其中Tslib官方说的QT_QPA_GENERIC_PLUGINS环境变量不能配置,一旦配置,会多接收到一次触发输入。感觉就像QT默认已经使用evdevtouch了,你再配置一次就是2次,会多一次输出。QT做的不够智能的地方,这个地方也被深深坑了一次。

知识扩展:
QT多点触摸
http://www.mamicode.com/info-detail-543772.html
对自己编译QT,tslib多点触摸会有帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值