5 tslib
需要安装好触摸屏驱动
tslib 是一个触摸屏的开源库,可以使用它来访问触摸屏设备,可以给输入设备添加各种“filter”(过滤器,就是各种处理),地址是:http://www.tslib.org/。
编译 tslib 后,可以得到libts库,还可以得到各种工具:较准工具、测试工具。
5.1 tslib 框架分析
tslib的主要代码如下:
核心在于 “plugins” 目录里的 “插件”,或称为 “module”。这个目录下的每个文件都是一个 module,每个 module 都提供 2 个函数:read、read_mt,前者用于读取单点触摸屏的数据,后者用于读取多点触摸屏的数据。
框架:
调用ts_open后,可以打开某个设备节点,构造出一个tsdev结构体。然后调用ts_config读取配置文件的处理,假设 /etc/ts.conf 内容如下:
module_raw inputmodule pthres pmin=1module dejitter delta=100module 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 模块处理后,才返回最终数据。
5.2 编译
-
获得源码后解压
-
进入源码目录
-
配置:
./configure --host=arm-linux-gnueabihf --prefix=$PWD/tmp make make install cd tmp #然后将 include 下的文件复制到交叉编译工具的 include 中 cp include/* -rf /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux- \gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include #然后将 lib 下的文件复制到交叉编译工具的 lib 中 cp lib/* -drf /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux- \gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib
-
将编译好的 tmp 复制到开发板的文件系统
sudo cp * -rf /home/luo/linux/nfs/buildrootfs
-
在开发板中配置 tslib
-
打开/etc/ts.conf文件,找到下面这一行:module_raw input,如果有注释,就去掉
-
打开/etc/profile 文件,在里面加入如下内容:
-
export TSLIB_TSDEVICE=/dev/input/event1 #表示触摸设备文件,这里设置为/dev/input/event1,这个要根据具体情况设置
export TSLIB_CALIBFILE=/etc/pointercal #表示校准文件,如果进行屏幕校准的话校准结果就保存在这个文件中,这里设置校准文件为/etc/pointercal,此文件可以不存在,校准的时候会自动生成。
export TSLIB_CONFFILE=/etc/ts.conf #触摸配置文件,文件为/etc/ts.conf,此文件在移植 tslib 的时候会生成。
export TSLIB_PLUGINDIR=/lib/ts #表示 tslib 插件目录位置,目录为/lib/ts。
export TSLIB_CONSOLEDEVICE=none #表示控制台设置,这里不设置,因此为 none
export TSLIB_FBDEVICE=/dev/fb0 #屏幕驱动文件
5.3 测试
电容屏可以不用校准,如果是电阻屏就要先进行校准!校准的话输入如下命令:ts_calibrate
校准完成以后如果不满意,或者不小心对电容屏做了校准,那么直接删除掉/etc/pointercal
文件即可。 最后我们使用 ts_test_mt 这个软件来测试触摸屏工作是否正常,以及多点触摸是否有效,
执行如下所示命令:ts_test_mt
其中 :
- Drag 为拖拽,按下后,用手指接触屏幕,会有十字光标跟随,多点就有多个光标
- Draw 为绘制,按下后,用手指触摸屏幕,会画出线来,多个手指就同时画出多条线
- Quit 为退出。
5.4 应用测试
5.4.1 头文件
#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>
5.4.2 distance 函数
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;
}
5.4.3 main 函数
int main(int agrc, char **argv)
{struct tsdev *ts;int i, ret;struct ts_sample_mt **samp_mt;struct ts_sample_mt **pre_samp_mt;int max_slots;int point_pressed[20];struct input_absinfo slot;int touch_cnt = 0;ts = ts_setup(NULL, 0);if(ts == NULL)goto setup_fail;if(ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT),&slot) < 0)goto ioctl_fail;max_slots = slot.maximum + 1 - slot.minimum;samp_mt = malloc(sizeof(struct ts_sample_mt *));if(samp_mt == NULL){goto mem_fail;}samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));if(samp_mt == NULL){free(samp_mt);goto mem_fail;}pre_samp_mt = malloc(sizeof(struct ts_sample_mt *));if(pre_samp_mt == NULL)goto mem_fail;pre_samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));if(pre_samp_mt[0] == NULL){free(pre_samp_mt);goto mem_fail;}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);if(ret < 0){printf("ts_read_mt error!\n");ts_close(ts);return -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));touch_cnt = 0;for(i=0; i<max_slots; ++i)if(pre_samp_mt[0][i].valid && pre_samp_mt[0][i].tracking_id != -1)point_pressed[touch_cnt++] = i;if(touch_cnt == 2)printf("distance : %08d\n",distance(&pre_samp_mt[0][point_pressed[0]],&pre_samp_mt[0][point_pressed[1]]));}return 0;
setup_fail:printf("ts_setup error!\n");return -1;
ioctl_fail:perror("ioctl EVIOGABS");ts_close(ts);return errno;
mem_fail:ts_close(ts);return -ENOMEM;}
5.4.4 makefile
KERNELDIR := /home/luo/linux/IMX6ULL/linux-imx-rel_imx_4.1.15_2.1.0_ga_alpha
CURRENT_PATH := $(shell pwd)CROSS_COMPILE ?= arm-linux-gnueabihf-build: kernel_moduleskernel_modules:$(CROSS_COMPILE)gcc -o mt_cal_distance mt_cal_distance.c -ltsclean:rm mt_cal_distance
5.4.5 测试结果
会打印出两点的距离