tslib 库
tslib 简介
tslib 库,这是 Linux 系统下,专门为触摸屏开发的应用层函数库,开源
功能与作用:作为触摸屏驱动和应用层之间的适配层,封装了读取和解析触摸屏数据的复杂过程,提供API接口
数据处理:从触摸屏获取原始坐标数据,进行去噪、去抖和坐标变换等操作,转换为屏幕坐标
配置文件:包含配置文件 ts.conf,用户可以修改以调整参数
与Qt的集成:tslib 可作为 Qt 的触摸屏输入插件,提供触摸输入支持,但并非唯一选择
移植应用:介绍如何将 tslib 库移植到开发板平台
tslib 移植
下载 tslib 源码
- git 仓库下载源码 https://github.com/libts/tslib/releases
编译 tslib 源码
-
前期准备工作
-
将 tslib 源码拷贝到 Ubuntu 系统
-
解压 tslib 压缩包
-
将其解压到当前目录下:
-
tar -xzf tslib-1.16.tar.gz
-
-
在家目录下创建一个 tools 目录,然后在 tools 目录下创建 tslib 目录,等会编译 tslib 库的时候将安装目录指定到这里
-
进入到 tslib-1.16 目录,准备进行编译 tslib 源码
-
对交叉编译工具的环境进行设置
- source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
-
-
第一步是配置工程
-
./configure --host=arm-poky-linux-gnueabi --prefix=/home/dt/tools/tslib/
-
可以执行./configure --help 查看它的配置选项以及含义
-
–host 设置为交叉编译器名称的前缀
-
–prefix 选项则用于指定库文件的安装路径
-
-
第二步是编译工程
- 直接执行 make
-
第三步是安装,将编译得到的库文件、可执行文件等安装到一个指定的目录下
- make install
tslib 安装目录下的文件夹介绍
-
bin 目录
- tslib 提供的小工具,可以用于测试触摸屏
-
etc 目录
-
有一个配置文件 ts.conf
-
ts.conf 文件的内容
-
module_raw input:取消注释以启用 input 输入事件支持
-
module pthres pmin=1:启用按压力测试,pmin 调节按压力灵敏度,默认值为1
-
module dejitter delta=100:启用触摸屏去噪算法插件,delta 默认参数为100
-
module linear:启用触摸屏坐标变换功能,如坐标互换和旋转
-
-
-
include 目录
-
目录结构:include 目录下仅包含一个头文件 tslib.h
-
头文件内容:tslib.h 包含结构体数据结构和 API 接口的声明
-
API 使用:使用 tslib 提供的 API 时,需要包含 tslib.h 头文件
-
-
lib 目录
-
包含编译 tslib 源码得到的库文件,默认是动态库文件
-
静态库:通过配置 tslib 工程可以生成静态库文件
-
ts 目录:存放一些插件库
-
-
share 目录
在开发板上测试 tslib
-
文件拷贝步骤
-
将安装目录 bin/目录下的所有可执行文件拷贝到开发板/usr/bin 目录下
-
将安装目录 etc/目录下的配置文件 ts.conf 拷贝到开发板/etc 目录下
-
将安装目录 lib/目录下的所有库文件拷贝到开发板/usr/lib 目录下
-
-
配置环境变量
-
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/usr/lib/ts -
TSLIB_CONSOLEDEVICE:配置控制台设备文件名,设置为 none
-
TSLIB_FBDEVICE:配置显示设备名称,指定显示设备的设备节点
-
TSLIB_TSDEVICE:配置触摸屏对应的设备节点,根据实际情况设置
-
TSLIB_CONFFILE:配置 ts.conf 文件路径
-
TSLIB_PLUGINDIR:配置插件所在路径
-
将这些配置写入 /etc/profile 文件中,以确保每次启动系统时都能生效
-
-
多点触摸测试工具
-
单点触摸测试工具(ts_print、ts_test)
-
多点触摸测试工具(ts_print_mt、ts_test_mt)
-
ts_print 和 ts_print_mt 可以在终端打印触摸点信息,而 ts_test 和
ts_test_mt 则支持在 LCD 上画线-
执行ts_print 命令,在触摸屏上滑动、或按下、松开触摸屏将会在终端打印出相应的信息
-
ts_print_mt 也是如此,不过它支持多点触摸
-
-
查看测试工具源码
- 如果你对这些测试工具的实现感兴趣,可以在 tslib 源码目录下的 tests 文件夹中找到相应的源码
-
tslib 库函数的使用介绍
打开和关闭触摸屏设备
-
打开触摸屏设备
-
打开触摸屏设备函数 - ts_open
-
#include “tslib.h”
struct tsdev *ts_open(const char *dev_name, int nonblock); -
dev_name:触摸屏的设备节点
-
nonblock:是否以非阻塞方式打开设备,0 表示阻塞,非 0 表示非阻塞
-
返回值:
成功:返回指向触摸屏设备句柄的指针 (struct tsdev *)
失败:返回 NULL
-
-
打开和配置触摸屏设备函数 - ts_setup
-
#include “tslib.h”
struct tsdev *ts_setup(const char *dev_name, int nonblock) -
dev_name:触摸屏的设备节点,可设置为 NULL,此时从环境变量 TSLIB_TSDEVICE 获取设备节点
-
nonblock:是否以非阻塞方式打开设备,0 表示阻塞,非 0 表示非阻塞
-
ts_setup()相比 ts_open(),除了打开触摸屏设备外,还对触摸屏设备进行了配置
-
-
-
关闭触摸屏设备函数 - ts_close
- int ts_close(struct tsdev *);
配置触摸屏设备
-
功能:解析 ts.conf 文件中的配置信息,加载相应的插件
-
#include “tslib.h”
int ts_config(struct tsdev *ts) -
ts:指向触摸屏句柄的指针
-
成功返回 0,失败返回-1
读取触摸屏数据
-
读取单点触摸数据 - ts_read
-
#include “tslib.h”
int ts_read(struct tsdev *ts, struct ts_sample *samp, int nr)-
功能:
读取单点触摸数据并存放在 samp 指针所指向的内存中 -
ts:指向触摸屏设备句柄的指针
-
samp:指向一个 struct ts_sample 对象的指针,描述单个触摸点的信息
- struct ts_sample {
int x; //x坐标
int y; //y坐标
unsigned int pressure; //按压力大小
struct timeval tv; //时间
};
- struct ts_sample {
-
nr:采样数,设置为 1 即可
-
-
-
读取多点触摸数据 - ts_read_mt
-
#include “tslib.h”
int ts_read_mt(struct tsdev *ts, struct ts_sample_mt **samp, int max_slots, int nr)-
功能:
读取多点触摸数据,将数据存放在 samp 指针所指向的 struct ts_sample_mt 数组中 -
ts:指向触摸屏设备句柄的指针
-
samp:指向 struct ts_sample_mt 数组的指针,描述多个触摸点的信息,每个触摸点使用一个 struct ts_sample_mt 对象
-
struct ts_sample_mt 结构体
-
-
max_slots:触摸屏支持的最大触摸点数
- 应用程序可以通过 ioctl() 函数获取触摸屏支持的最大触摸点数和坐标的最大分辨率等信息
-
nr:表示对一个触摸点的采样数,设置为 1 即可
-
-
基于 tslib 库函数编写触摸屏应用程序
单点触摸应用程序
#include <stdio.h>
#include <stdlib.h>
#include <tslib.h> //包含tslib.h头文件
int main(int argc, char *argv[])
{
struct tsdev *ts = NULL;
struct ts_sample samp;// 定义一个结构体用于存储触摸屏样本数据
int pressure = 0;//用于保存上一次的按压力,初始为0,表示松开
/* 打开并配置触摸屏设备 */
ts = ts_setup(NULL, 0);
//从环境变量 TSLIB_TSDEVICE 获取设备节点
//以阻塞方式打开设备
if (NULL == ts) {// 检查是否成功打开设备
fprintf(stderr, "ts_setup error");
exit(EXIT_FAILURE);
}
/* 读数据 */
for ( ; ; ) {
if (0 > ts_read(ts, &samp, 1)) {// 从触摸屏设备读取一个样本数据
fprintf(stderr, "ts_read error");
ts_close(ts);
exit(EXIT_FAILURE);
}
if (samp.pressure) {//按压力>0
if (pressure) //若上一次的按压力>0
printf("移动(%d, %d)\n", samp.x, samp.y);
else
printf("按下(%d, %d)\n", samp.x, samp.y);
}
else
printf("松开\n");//打印坐标
pressure = samp.pressure; // 更新上一次的按压力为当前样本的按压力
}
ts_close(ts);// 关闭触摸屏设备
exit(EXIT_SUCCESS);// 退出程序,返回成功状态
}
-
程序
-
打开并配置设备:调用 ts_setup 函数打开并配置触摸屏设备
- 从环境变量 TSLIB_TSDEVICE 获取设备节点,以阻塞方式打开设备
-
检查设备是否打开:检查 ts_setup 是否成功,如果失败则输出错误信息并退出
-
无限循环读取数据:进入无限循环,读取触摸屏数据
-
读取数据:调用 ts_read 函数读取一个样本数据
- 检查读取结果:检查 ts_read 是否成功,如果失败则输出错误信息并退出
-
处理按压力:根据当前样本的按压力进行处理
-
按压力大于0:如果当前样本的按压力大于0,进一步判断上一次的按压力
-
上一次按压力大于0:如果上一次的按压力也大于0,打印“移动”
-
如果上一次的按压力等于0,打印“按下”
-
-
按压力小于等于0:如果当前样本的按压力等于0,打印“松开”
-
-
更新按压力:更新上一次的按压力为当前样本的按压力
-
-
关闭设备:关闭触摸屏设备
-
退出程序,返回成功状态
-
-
编译
-
${CC} -I /home/alientek/linux/IMX6ULL/tool/tslib/include -L /home/alientek/linux/IMX6ULL/tool/tslib/lib -lts -o testApp testApp.c
-
-I 选项用于指定头文件路径,指向 tslib 安装目录的 include 目录,缺少时会找不到 tslib.h
-
-I 选项用于指定头文件路径,指向 tslib 安装目录的 include 目录,缺少时会找不到 tslib.h
-
编译时需要链接到动态库文件,使用 -l 选项指定链接库
-
动态库文件命名方式为 lib+名字+.so,例如 -l ts 对应 libts.so
-
-
验证
- 单点触摸应用程序测试
多点触摸应用程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <tslib.h>
int main(int argc, char *argv[])
{
struct tsdev *ts = NULL;
struct ts_sample_mt *mt_ptr = NULL;
struct input_absinfo slot;
int max_slots;
unsigned int pressure[12] = {0}; //用于保存每一个触摸点上一次的按压力,初始为0,表示松开
int i;
/* 打开并配置触摸屏设备 */
ts = ts_setup(NULL, 0);
if (NULL == ts) {
fprintf(stderr, "ts_setup error");
exit(EXIT_FAILURE);
}
/* 获取触摸屏支持的最大触摸点数 */
if (0 > ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot)) {
perror("ioctl error");
ts_close(ts);
exit(EXIT_FAILURE);
}
max_slots = slot.maximum + 1 - slot.minimum;
printf("max_slots: %d\n", max_slots);
/* 内存分配 */
mt_ptr = calloc(max_slots, sizeof(struct ts_sample_mt));
/* 读数据 */
for ( ; ; ) {
if (0 > ts_read_mt(ts, &mt_ptr, max_slots, 1)) {
perror("ts_read_mt error");
ts_close(ts);
free(mt_ptr);
exit(EXIT_FAILURE);
}
for (i = 0; i < max_slots; i++) {
if (mt_ptr[i].valid) {//有效表示有更新!
if (mt_ptr[i].pressure) { //如果按压力>0
if (pressure[mt_ptr[i].slot])//如果上一次的按压力>0
//short valid; //此次样本是否有效标志 触摸点数据是否发生更新
printf("slot<%d>, 移动(%d, %d)\n", mt_ptr[i].slot, mt_ptr[i].x, mt_ptr[i].y);
else
printf("slot<%d>, 按下(%d, %d)\n", mt_ptr[i].slot, mt_ptr[i].x, mt_ptr[i].y);
}
else
printf("slot<%d>, 松开\n", mt_ptr[i].slot);
pressure[mt_ptr[i].slot] = mt_ptr[i].pressure;
}
}
}
/* 关闭设备、释放内存、退出 */
ts_close(ts);
free(mt_ptr);
exit(EXIT_SUCCESS);
}
-
程序
-
打开并配置触摸屏设备
-
调用 ts_setup 函数初始化触摸屏设备
-
如果初始化失败,输出错误信息并退出程序
-
-
获取触摸屏支持的最大触摸点数
-
使用 ioctl 获取最大触摸点数
-
如果获取失败,输出错误信息,关闭设备并退出程序
-
-
为触摸样本分配内存
-
读数据:
进入无限循环-
调用 ts_read_mt 函数读取多点触摸数据
- 如果读取失败,输出错误信息,关闭设备,释放内存并退出程序
-
遍历所有触摸点数据,检查每个触摸点数据是否有效
-
如果有效,检查压力值
-
如果压力大于0
-
如果上一次的压力大于0,输出“移动”信息
-
否则,输出“按下”信息
-
-
否则,输出“松开”信息
-
-
更新压力值
-
-
-
关闭触摸屏设备,释放内存并退出程序
-
-
验证
- 多点触摸应用程序测试结果