目录
tslib的简介
tslib 是一个用于 Linux 系统中触摸屏输入设备的轻量级库,特别常用于嵌入式开发。它主要提供了一组工具和 API,用于对触摸屏输入事件进行校准、过滤和处理,使得触摸屏可以更精确、更稳定地与系统交互。
应用场景如下:
- 嵌入式 Linux 设备(如工业控制、车载系统、POS 终端)。
- 需要轻量级触摸屏处理库的开发环境。
- 与 Qt、SDL 等图形界面结合使用。
tslib的源码和make及make install后得到的文件下载
tslib-1.21的源码下载地址:
https://pan.baidu.com/s/1Yc1IiRqECn6SyJHI9-6Ksg?pwd=t4zj
附:tslib-1.21make及make install后得出的输入文件下载地址:
https://pan.baidu.com/s/1U6_JUJEiJLAdniZW5wLEoQ?pwd=x4w6
tslib的主要功能
-
校准 (Calibration)
提供ts_calibrate
工具,可以对触摸屏进行几何校准,解决触摸位置和显示坐标不匹配的问题。 -
事件过滤 (Filtering)
提供了一系列的过滤器,比如去抖动、线性化等,保证输入事件的平滑性和准确性。 -
事件捕获 (Event Capture)
捕获触摸屏输入设备(如/dev/input/eventX
或/dev/tsX
)的触摸事件,并转化为标准格式供上层应用使用。 -
兼容性强
支持多种触摸屏控制器(例如 eGalax、Goodix 等)和多种 Linux 输入子系统。
tslib的工作原理
- 应用程序通过调用
tslib
的 API 读取触摸事件。 - tslib 内部从触摸屏设备获取原始事件。
- 通过过滤器链对原始事件进行处理(如校准、去抖动)。
- 输出处理后的事件数据供应用程序使用。
tslib的核心组成部分
-
库文件
提供了核心的触摸屏数据处理和 API,比如ts_read()
、ts_config()
。 -
工具程序
ts_calibrate
: 校准工具,用于生成校准数据。ts_test
: 用于测试触摸屏事件和显示触摸点。ts_print
: 打印触摸事件的工具。
-
配置文件
通常是/etc/ts.conf
,可以配置过滤器、设备路径等。
tslib的框架和核心函数分析
tslib的框架
从上面的框架可以看出,tslib有三个核心函数,分别为ts_setup、ts_read、ts_read_mt。其中ts_setup依靠两个核心函数分别为ts_open和ts_config来实现。
tslib的核心函数ts_setup()
的分析(对如何获取设备名和数据处理流程的分析)
函数ts_setup()
自身的主要代码
我们打开源码\tslib-1.21\tests\ts_test.c
,转到主函数,发现第134有如下代码:
ts = ts_setup(NULL, 0);
我们转到函数ts_setup()
的定义,如下:
位置:\tslib-1.21\src\ts_setup.c
struct tsdev *ts_setup(const char *dev_name, int nonblock)
{
const char * const *defname;
struct tsdev *ts = NULL;
#if defined (__linux__)
char *fname = NULL;
#endif /* __linux__ */
dev_name = dev_name ? dev_name : getenv("TSLIB_TSDEVICE");
if (dev_name != NULL) {
ts = ts_open(dev_name, nonblock);
} else {
defname = &ts_name_default[0];
while (*defname != NULL) {
ts = ts_open(*defname, nonblock);
if (ts != NULL)
break;
++defname;
}
}
#if defined (__linux__)
if (!ts) {
fname = scan_devices();
if (!fname)
return NULL;
ts = ts_open(fname, nonblock);
free(fname);
}
#endif /* __linux__ */
/* if detected try to configure it */
if (ts && ts_config(ts) != 0) {
ts_error("ts_config: %s\n", strerror(errno));
ts_close(ts);
return NULL;
}
return ts;
}
我们可以看到它有两个输入参数,一个是dev_name
,另一个是nonblock
。
dev_name
显然是表示设备名。
nonblock
表示读取数据的时候是阻塞方式还是非阻塞方式,当nonblock
的值为1(或非 0)时,表示非阻塞模式,当nonblock
的值为0时,为阻塞方式,所以在文件ts_test.c
中,是以阻塞方式打开触摸屏设置的,因为给的参数值为0嘛,这意味着从触摸屏读取数据时,如果数据尚未准备好,进程会阻塞,直到数据可用。延伸阅读:Linux系统的阻塞方式和非阻塞方式是什么意思?
在这里,参数dev_name
的值传递为NULL,即空指针,那么在函数ts_setup()
里有下在这一行:
dev_name = dev_name ? dev_name : getenv("TSLIB_TSDEVICE");
可见,如果有值,则用它本身的值,如果值为NULL,那么 getenv("TSLIB_TSDEVICE")
的结果将作为 dev_name 的值。
所以源码\tslib-1.21\tests\ts_test.c
里会去取 getenv("TSLIB_TSDEVICE")
的结果作为设备名。函数getenv()
的意思是从环境变量里获取设备名,比如这里会从环境变量TSLIB_TSDEVICE
里获取设备名。
那如果既没有传递设备名,也没有设置环境变,函数ts_setup()
它会像下面这样做:
static const char * const ts_name_default[] = {
"/dev/input/ts",
"/dev/input/touchscreen",
"/dev/touchscreen/ucb1x00",
NULL
};
if (dev_name != NULL) {
ts = ts_open(dev_name, nonblock);
} else {
defname = &ts_name_default[0];
while (*defname != NULL) {
ts = ts_open(*defname, nonblock);
if (ts != NULL)
break;
++defname;
}
}
即,它会去遍历字符串数组ts_name_default中的各个成员,发现第一个不为NULL值的成员并且能够打开成功的话,即用这个成员作为设备名。
如果到这里还没有成功打开设备,在定义了宏__linux__
的情况下,它会去扫描系统中的设备,代码如下:
#if defined (__linux__)
if (!ts) {
fname <