LV040-tslib简介
一、tslib 是什么
官网在这里:tslib。

tslib 是专门为 触摸屏设备 所开发的 Linux 应用层函数库,并且是开源,也就意味着我们可以直接获取到 tslib 的源代码 。
tslib 为触摸屏驱动和应用层之间的适配层, 它把应用程序中读取触摸屏 struct input_event 类型数据(这是输入设备上报给应用层的原始数据)并进行解析的操作过程进行了封装,向使用者提供了封装好的 API 接口。
tslib 从触摸屏中获得原始的坐标数据, 并通过一系列的去噪、去抖、坐标变换等操作,来去除噪声并将原始的触摸屏坐标转换为相应的屏幕坐标。
tslib 有一个配置文件 ts.conf, 该配置文件中提供了一些配置参数、用户可以对其进行修改 ,后面会详细进行学习。
tslib 可以作为 Qt 的触摸屏输入插件,为 Qt 提供触摸输入支持, 如果在嵌入式 Linux 硬件平台下开发过 Qt 应用程序的话应该知道;当然,并不是只有 tslib 才能作为 Qt 的插件、为其提供触摸输入支持,还有很多插件都可以,只不过大部分都会选择使用 tslib。
二、tslib 移植
1. 下载源码
首先下载 tslib 源码包,进入到 tslib 的 git 仓库下载源码 :Releases · libts/tslib (github.com):

ALPHA 开发板出厂系统中已经移植了 tslib,并且版本为 1.16,可以在开发板执行 ts_finddev 命令查看到它的版本信息,如下所示:

所以为了统一,我们也下载 1.16 版本的 tslib,往下翻找到 1.16 版本的下载链接: Release tslib 1.16 · libts/tslib (github.com) :

下载 tar.bz2 或 tar.gz 格式压缩包,或者 tar.xz 压缩包,这里我下载 tar.gz 格式的压缩包文件,点 击文字即可下载。下载好后我们解压一下:

解压后有上图这些文件。
2. 编译源码
- (1)创建安装目录
我们创建一个 out 目录作为编译成果物存放的位置:
cd ~/8linux_lib/tslib-1.16/
mkdir out
- (2)配置工程
./configure --host=arm-linux-gnueabihf --prefix=/home/sumu/8linux_lib/tslib-1.16/out至于工程是如何配置的,可以执行./configure --help 查看它的配置选项以及含义。其中--host 选项用于指定交叉编译得到的库文件是运行在哪个平台,通常将--host 设置为交叉编译器名称的前缀,如 arm-linux-gnueabihf-gcc 前缀就是 arm-linux-gnueabihf;--prefix 选项则用于指定库文件的安装路径,我们将安装路径设置为之前创建的 /home/sumu/8linux_lib/tslib-1.16/out 目录。 配置完成后如下图所示:

- (3)编译工程
make编译完毕之后如下图所示:

- (4)安装
make install安装完毕之后如下所示:

这样 out 目录下就是我们的成果物了。
3. 移植到开发板
移植的最后一步就是把 tslib 安装目录下的库文件、 etc 下的配置文件以及编译得到的测试工具拷贝到开发板 Linux 系统目录下。
(1)将安装目录 bin/目录下的所有可执行文件拷贝到开发板/usr/bin 目录下
(2)将安装目录 etc/目录下的配置文件 ts.conf 拷贝到开发板/etc 目录下;
(3)将安装目录 lib/目录下的所有库文件拷贝到开发板/usr/lib 目录下
将安装目录下的测试工具、库文件以及配置文件拷贝到开发板之后,接着需要配置一些环境变量,因为 tslib 工作的时候它需要依赖于一些环境变量,例如它会通过读取环境变量来得知 ts.conf 配置文件、库文件 的路径以及我们要测试的触摸屏对应的设备节点等。
# TSLIB_CONSOLEDEVICE 用于配置控制台设备文件名,直接配置为 none 即可
export TSLIB_CONSOLEDEVICE=none
# TSLIB_FBDEVICE 用于配置显示设备的名称, tslib 提供了手指触摸画线的测试工具,需要在 LCD 上显示,所以这里需要指定一个显示设备的设备节点。
export TSLIB_FBDEVICE=/dev/fb0
# TSLIB_TSDEVICE 用于配置触摸屏对应的设备节点,根据实际情况配置。
export TSLIB_TSDEVICE=/dev/input/event1
# TSLIB_CONFFILE 用于配置 ts.conf 文件的所在路径。
export TSLIB_CONFFILE=/etc/ts.conf
# TSLIB_PLUGINDIR 用于配置插件所在路径。
export TSLIB_PLUGINDIR=/usr/lib/ts如果想每次启动系统都能生效,可以把这些命令放置在/etc/profile 脚本中执行;出厂系统中已经配置好 了,无需进行配置。
三、编译输出目录简介
我们前面编译安装后,输出目录有以下文件:

二级目录有以下文件:
sumu@sumu-virtual-machine:~/8linux_lib/tslib-1.16/out$ tree -L 2
.
├── bin
│ ├── ts_calibrate
│ ├── ts_finddev
│ ├── ts_harvest
│ ├── ts_print
│ ├── ts_print_mt
│ ├── ts_print_raw
│ ├── ts_test
│ ├── ts_test_mt
│ ├── ts_uinput
│ └── ts_verify
├── etc
│ └── ts.conf
├── include
│ └── tslib.h
├── lib
│ ├── libts.la
│ ├── libts.so -> libts.so.0.9.1
│ ├── libts.so.0 -> libts.so.0.9.1
│ ├── libts.so.0.9.1
│ ├── pkgconfig
│ └── ts
└── share
└── man
8 directories, 16 files1. bin
bin 目录下有一些 tslib 提供的小工具,可以用于测试触摸屏,如下所示:

这些测试工具的源码实现,可以在 tslib 源码中找到,具体路径为 tslib 源码目录下的 tests 文件夹中:

2. etc
etc 目录下有一个配置文件 ts.conf :

我们打开 ts.conf 文件看看它有哪些配置选项

module_raw input:取消注释,使能支持 input 输入事件;
module pthres pmin = 1:如果我们的设备支持按压力大小测试,那么可以把它的注释取消, pmin 用于调节按压力灵敏度,默认就是等于 1。
module dejitter delta = 100: tslib 提供了触摸屏去噪算法插件,如果需要过滤噪声样本, 取消注释,默认参数 delta = 100。
module linear: tslib 提供了触摸屏坐标变换的功能,如将 X、 Y 坐标互换、坐标旋转等之类,如果我们需要实现坐标变换,可以把注释去掉。
3. include
include 目录下只有一个头文件 tslib.h,该头文件中包含了一些结构体数据结构以及 API 接口的申明,使用 tslib 提供的 API 就需要包含该头文件。

4. lib
lib 目录下包含了编译 tslib 源码所得到的库文件,默认这些都是动态库文件,也可以通过配置 tslib 工程使其生成静态库文件。lib/ts 目录下存放的是一些插件库。

5. share

没去了解,可以忽略。
四、tslib 框架分析
tslib 的主要代码如图 :

核心在于“plugins”目录里的“插件”,或称为“ module”。这个目录下的每个文件都是一个 module,每个 module 都提供 2 个函数: read、 read_mt,前者用于读取单点触摸屏的数据,后者用于读取多点触摸屏的数据。
要分析 tslib 的框架,先看看示例程序怎么使用,我们参考 ts_test.c 和 ts_test_mt.c,前者用于一般触摸屏(比如电阻屏、单点电容屏),后者用于多点触摸屏。

调用 ts_open 后,可以打开某个设备节点,构造出一个 tsdev 结构体。然后调用 ts_config 读取配置文件的处理,假设/etc/ts.conf 内容如下:
module_raw input
module pthres pmin=1
module dejitter delta=100
module linear每行表示一个“ module”或“ moduel_raw”。对于所有的“module”,都会插入 tsdev.list 链表头,也就是 tsdev.list 执行配置文件中最后一个“ module”,配置文件中第一个“ module”位于链表的尾部。
对于所有的“ module_raw”,都会插入 tsdev.list_raw 链表头,一般只有一个“ module_raw”。
注意: tsdev.list 中最后一个“ module”会指向 ts_dev.list_raw 的头部。无论是调用 ts_read 还是 ts_read_mt,都是通过 tsdev.list 中的模块来处理数据的。这写模块是递归调用的,比如 linear 模块的 read 函数如图 :

linear 模块的 read_raw 函数如图 :

因为是递归调用,所有最先使用 input 模块读取设备节点得到原始数据,再依次经过 pthres 模块、 dejitter 模块、 linear 模块处理后,才返回最终数据。