当前位置: 首页 > news >正文

tslib库介绍与使用

一、tslib 框架分析

1. tslib介绍

tslib 是一个触摸屏的开源库,可以使用它来访问触摸屏设备。编译 tslib 后,可以得到 libts 库,还可以得到各种工具:较准工具、测试工具。

tslib主要代码架构如下
在这里插入图片描述

“plugins”目录里的“插件”,或称为“module”。这个目录下的每个文件都是一个 module,每个 module 都提供 2 个函数:read、read_mt,前者用于读取单点触摸屏的数据,后者用于读取多点触摸屏的数据。

2. tslib框架

要分析 tslib 的框架,先看看示例程序怎么使用,我们参考 ts_test.c 和ts_test_mt.c,前者用于一般触摸屏(比如电阻屏、单点电容屏),后者用于多点触摸屏。

tslib的架构如下:

在这里插入图片描述

进入测试程序ts_test.c,使用ts_setup进行初始化。

ts_setup调用了ts_open,调用 ts_open 后,可以打开某个设备节点,构造出一个 tsdev 结构体。然后调用 ts_config 读取配置文件(/etc/ts.conf)的处理,假设/etc/ts.conf 内容如下:

module_raw input
module pthres pmin=1
module dejitter delta=100
module linear

每行表示一个“module”(普通模块)或“moduel_raw”(原始模块)。

对于所有的“module”,会调用ts_load_module,最终调用__ts_attach将新module插入 tsdev.list 链表头。

int __ts_attach(struct tsdev *ts, struct tslib_module_info *info)
{info->dev = ts;info->next = ts->list;ts->list = info;return 0;
}

info代表新module,假设设备ts已有一个模块链:A -> B(模块 A 是链表头,ts->list 指向模块 A;模块 A 的 next 指向模块 B,模块 B 的 next 为 NULL)。

__ts_attach函数执行三步操作,最终将新模块 info 插入到链表头部:

  • info->dev = ts:新模块关联到设备 ts;
  • info->next = ts->list:新模块的 next 指向原有链表头(模块 A);
  • ts->list = info:设备的链表头更新为新模块 info。
  • 新的模块链变为:新模块 info -> 模块 A -> 模块 B。

同理对于所有的“module_raw”,都会插入 tsdev.list_raw 链表头,一般只有一个“module_raw”。但注意这里tsdev.list 中最后一个“module”会指向 ts_dev.list_raw 的头部。

int __ts_attach_raw(struct tsdev *ts, struct tslib_module_info *info)
{struct tslib_module_info *next, *prev, *prev_list = ts->list_raw;// 头插法info->dev = ts;info->next = prev_list;ts->list_raw = info;/** ensure the last item in the normal list now points to the* top of the raw list.*/// 普通模块链为空,或已指向原原始链头部if (ts->list == NULL || ts->list == prev_list) {/* main list is empty, ensure it points here */ts->list = info;   // 让普通链头部直接指向新原始模块(连接两个链)return 0;}// 普通模块链有其他模块,需找到其末尾并连接for (next = ts->list, prev = next;next != NULL && next != prev_list;next = prev->next, prev = next);prev->next = info;  // 让普通链的末尾节点指向新原始模块(连接两个链)return 0;
}

无论是调用 ts_read 还是 ts_read_mt,都是通过 tsdev.list 中的模块来处理数据的。这里写模块是递归调用的,比如linear模块的read函数。

static int linear_read(struct tslib_module_info *info, struct ts_sample *samp,int nr_samples)
{struct tslib_linear *lin = (struct tslib_linear *)info;int ret;int xtemp, ytemp;// 使用链表的下一个模块来读取ret = info->next->ops->read(info->next, samp, nr_samples);if (ret >= 0) {int nr;for (nr = 0; nr < ret; nr++, samp++) {#ifdef DEBUGfprintf(stderr,

linear模块的readmt函数

static int linear_read_mt(struct tslib_module_info *info,struct ts_sample_mt **samp,int max_slots, int nr_samples)
{struct tslib_linear *lin = (struct tslib_linear *)info;int ret;int xtemp, ytemp;int i;int nr;if (!info->next->ops->read_mt)return -ENOSYS;ret = info->next->ops->read_mt(info->next, samp, max_slots, nr_samples);if (ret < 0)return ret;for (nr = 0; nr < ret; nr++) {#ifdef DEBUG

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

二、交叉编译tslib

设置环境变量

//  对于 IMX6ULL ,命令如下
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/vsea/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

交叉编译 tslib

//交叉编译 tslib:
cd tslib-1.21
./configure --host=arm-linux-gnueabihf --prefix=/
make
make install DESTDIR=$PWD/tmp

注意这里不能写–prefix=$(pwd)/tmp,ts_config函数会通过宏定义TS_CONF找到配置文件的路径。

如果设置了–prefix=$(pwd)/tmp会导致宏定义TS_CONF对应路径为

/home/vsea/linux_study/tslib-1.21/tmp/etc/ts.conf,如果移植到开发板上去就要创建同样过长的路径。

使用–prefix=/和DESTDIR=$PWD/tmp 导致宏定义TS_CONF对应路径为/etc/ts.conf

在tslib-1.21目录下使用grep命令可以查询对应路径

grep “TS_CONF” * -nwr

​ TS_CONF = ${sysconfdir}/ts.conf

grep “sysconfdir” * -nwr

​ sysconfdir = ${prefix}/etc

grep “prefix” * -nwr

​ prefix = /

这样我们在移植ts.conf文件时只需把文件拷贝到开发板的/etc目录下。

把头文件、库文件放到工具链目录下:

//  对于 IMX6ULL ,命令如下
cd tslib-1.21/tmp/
cp include/* /home/vsea/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
cp -d lib/*so* /home/vsea/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/

测试tslib

先在开发板上使用 NFS 挂载 Ubuntu的目录,再把前面编译出来的 tslib-1.21/tmp/部分文件复制到板子上

cp /mnt/tslib-1.21/tmp/lib/ts -rfd /lib   		// 复制库文件
cp /mnt/tslib-1.21/tmp/lib/*so* -d /lib
cp /mnt/tslib-1.21/tmp/bin/* /bin		 		// 复制测试文件
cp /mnt/tslib-1.21/tmp/etc/ts.conf -d /etc 		// 复制/etc/ts.conf

cp -rfd 是处理 “包含符号链接的目录” 时的高效命令:

  • -r 保证目录递归复制;
  • -f 确保强制操作,适合自动化;
  • -d 保留符号链接,不解析实际内容,维持原始目录结构。

对于 IMX6ULL,首先需要关闭默认的 qt gui 程序,才可以执行 ts_test_mt

mv /etc/init.d/*hmi* /root
mv /etc/init.d/*lvgl* /root
reboot

执行测试文件

export TSLIB_PLUGINDIR=/lib/ts
ts_test_mt

三、基于tslib编写程序

需求:当两个手指点击屏幕时,不断打印 2 个触点的距离。

用两个手指点击屏幕时,会得到以下数据

开发板上电容屏对应的设备节点是/dev/input/event1

hexdump /dev/input/event1

在这里插入图片描述

当ABS_MT_SLOT 0和ABS_MT_SLOT 1表示要上报一个触点信息

ABS_MT_TRACKING_ID -1 表示对应的触点被松开了

驱动程序使用 slot、tracking_id 来标识一个触点;当 tracking_id 等于-1 时,标识这个触点被松开了。

触摸屏可能支持多个触点,比如 5 个:tslib 为了简化处理,即使只有 2 个触点,ts_read_mt 函数也会返回 5 个触点数据,可以根据标志位判断数据是否有效。

int ts_read_mt(struct tsdev *ts, struct ts_sample_mt **samp, int max_slots,int nr)
假设nr设置为1,max_slots设置为5,那么读到的数据保存在:samp[0][0]、
samp[0][1]、samp[0][2]、samp[0][3]、samp[0][4]中。
假设nr设置为2,max_slots设置为5,那么读到的数据保存在:samp[0][0]、
samp[0][1] 、 samp[0][2] 、 samp[0][3] 、 samp[0][4] 和 samp[1][0] 、
samp[1][1]、samp[1][2]、samp[1][3]、samp[1][4]中。

ts_sample_mt结构体

struct ts_sample_mt {/* ABS_MT_* event codes. linux/include/uapi/linux/input-event-codes.h* has the definitions.*/int		x;int		y;unsigned int	pressure;int		slot;int		tracking_id;int		tool_type;int		tool_x;int		tool_y;unsigned int	touch_major;unsigned int	width_major;unsigned int	touch_minor;unsigned int	width_minor;int		orientation;int		distance;int		blob_id;struct timeval	tv;/* BTN_TOUCH state */short		pen_down;/* valid is set != 0 if this sample* contains new data; see below for the* bits that get set.* valid is set to 0 otherwise*/short		valid;
};

当valid非0时,表示含有新数据。

参照测试程序ts_test_mt.c编写程序

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <linux/input.h>
#include <sys/ioctl.h>
#include "tslib.h"
// #include "fbutils.h"
// #include "testutils.h"int distance(struct ts_sample_mt *point1, struct ts_sample_mt *point2)
{int x = point1->x - point2->x;int y = point1->y - point2->y;return x * x + y * y;
}int main(int argc, char **argv)
{struct tsdev *ts;int ret;int i;int max_slots = 1;struct ts_sample_mt **samp_mt = NULL;struct ts_sample_mt **pre_samp_mt = NULL;struct input_absinfo slot;int point_pressed[20] = {0};// 初始化触摸屏设备ts = ts_setup(NULL, 0);if (!ts){printf("ts_setup failed\n");return -1;}// 计算触摸屏支持最大触摸点数if (ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot) < 0){perror("ioctl EVIOGABS");ts_close(ts);return errno;}max_slots = slot.maximum + 1 - slot.minimum;samp_mt = malloc(sizeof(struct ts_sample_mt *));if (!samp_mt){ts_close(ts);return -1;}// 分配的内存 会被自动初始化为0samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));if (!samp_mt[0]){free(samp_mt);ts_close(ts);return -1;}pre_samp_mt = malloc(sizeof(struct ts_sample_mt *));if (!pre_samp_mt){ts_close(ts);return -1;}pre_samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));if (!pre_samp_mt[0]){free(pre_samp_mt);ts_close(ts);return -1;}for (i = 0; i < max_slots; i++){pre_samp_mt[0][i].valid = 0;}while (1){// 读取当前帧的多点触摸数据ret = ts_read_mt(ts, samp_mt, max_slots, 1);for (i = 0; i < max_slots; i++){if (samp_mt[0][i].valid){memcpy(&pre_samp_mt[0][i], &samp_mt[0][i], sizeof(struct ts_sample_mt));}}int cnt = 0;for (i = 0; i < max_slots; i++){// tracking_id != -1 表示触摸未结束if (pre_samp_mt[0][i].valid && pre_samp_mt[0][i].tracking_id != -1){// 记录有效触摸点的索引point_pressed[cnt++] = i;}}//  若检测到两个触摸点,计算并打印距离if (cnt == 2){printf("distance = %08d\n", distance(&pre_samp_mt[0][point_pressed[0]], &pre_samp_mt[0][point_pressed[1]]));}}return 0;
}

编译程序

 arm-buildroot-linux-gnueabihf-gcc 10_mt_cal_distance.c -o mt_cal_distance -lts
http://www.dtcms.com/a/516797.html

相关文章:

  • CyclicBarrier
  • 有哪个网站做正品港货网站建设中常见的问题
  • 【GD32】输出时钟配置
  • 昆明网站建设系统有哪些心理服务网站建设内容
  • 企业网站开发需求文档百度广告怎么投放多少钱
  • 官网站内优化怎么做深圳网站建设燦
  • wordpress本地备份网站首页排名seo搜索优化
  • 全星质量管理 QMS:构建高科技制造业数字化质量生态,筑牢全链路管控
  • Python 应用上架 Microsoft Store 完整指南(2025)
  • 免费低代码平台怎么选?斑斑低代码与云表低代码深度测评!
  • 大型网站开发框架有哪些wordpress选项下拉菜单
  • App 使用 HTTPS 的工程化实战,从接入到真机排查的一线指南
  • JDK 21 API增强详解
  • 化妆品可做的团购网站有哪些有个能写文章做任务的网站
  • 【JVM】详解 类加载器与类加载过程
  • 织梦移动网站模板免费下载佛山国内快速建站
  • 九九乘法表(C语言)
  • AI赋能:下一代海外社媒推广的智能化路径
  • i2c 时序解析
  • 基于线程池的配电房图像检测
  • 天河网站+建设信科网络龙口网页设计
  • 企业官网网站建设咨询手机网站模板下载免费
  • 线性代数直觉(三):特征值(eigenvalue)与特征向量(eigenvector)为何物?
  • 学生个人网站建设模板郑州开发软件公司
  • [Agent可视化] 智能体核心(Rust) | WASI沙箱 | `grpc_server.rs`
  • 东莞网站建设方案托管桂林做网站的公司有哪些
  • 所有搜索引擎蜘蛛不来网站了最新军事报道
  • Java | Lombok @Builder.Default 排障指南:为什么 build 时默认值丢失?
  • 东莞网站快速优化排名中国品牌网站建设
  • 计算机网络 网站代理公司注册新公司的费用