tslib 使用教程

1. tslib 简介

tslib 是触摸屏驱动和应用层之间的适配层(tslib 库是 Linux 系统下,专门为触摸屏开发的应用层函数库),它把应用程序中读取触摸屏 input_event 结构体类型数据并进行解析的操作过程进行了封装,向使用者提供了封装好的 API 接口。tslib 从触摸屏中获得原始的坐标数据,并通过一系列的去噪、去抖、坐标变换等操作,来去除噪声并将原始的触摸屏坐标转换为相应的屏幕坐标。

2. 交叉编译 tslib

下载源码

https://github.com/libts/tslib/releases

配置工具链

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:~/100ask_imx6ull_mini-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin

编译工程

./configure --host=arm-linux-gnueabihf --prefix=/
make
make install DESTDIR=$PWD/tmp

编译生成文件

目录 包含文件说明
bin/ tslib 提供的小工具,可以用于测试触摸屏
etc/ 配置文件 ts.conf
include/ 头文件 tslib.h
lib/ 编译 tslib 源码所得到的库文件
lib/ts/ tslib 插件
配置文件 ts.conf 提供了一些配置参数,用户可以对其进行修改
ts.conf 内容 说明
module_raw input 支持 input 输入事件
module pthres pmin 调节按压力灵敏度。pmin 用于调节按压力灵敏度,默认等于 1
module dejitter delta 过滤噪声。tslib 提供了触摸屏去噪算法插件,默认参数 delta=100
module linear 坐标变换。如 XY 坐标互换、坐标旋转等

拷贝文件到工具链目录

cd tmp/
cp include/* ~/100ask_imx6ull_mini-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
cp -d lib/*so* ~/100ask_imx6ull_mini-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/

3. 移植 tslib

3.1 拷贝文件到开发板

  • bin/ 目录下的所有可执行文件 ;
  • etc/ 目录下的配置文件 ts.conf ;
  • lib/ 目录下的所有库文件;
cp bin/* /bin
cp etc/ts.conf /etc
cp lib/*so* -d /lib
cp lib/ts -rf /lib

3.2 移除 GUI 并重启开发板

mv /etc/init.d/S07hmi /root
mv /etc/init.d/S99myirhmi2 /root
mv /etc/init.d/s05lvgl /root
reboot

3.3 配置环境变量

环境变量 说明
TSLIB_FBDEVICE 显示设备的设备节点
TSLIB_TSDEVICE 触摸屏设备的设备节点
TSLIB_CONFFILE ts.conf 配置文件的所在路径
TSLIB_PLUGINDIR 插件所在路径
# /etc/profile
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_PLUGINDIR=/usr/lib/ts
# /usr/lib/ts is where the "input.so" located

4. tslib 库函数

4.1 ts_open() 函数

打开触摸屏设备。

#include "tslib.h"
struct tsdev *ts_open(const char *dev_name, int nonblock);

参数 dev_name:指定触摸屏的设备节点;

参数 nonblock:表示是否以非阻塞方式打开触摸屏设备,如果 nonblock 等于 0 表示阻塞方式,如果为非 0 值则表示以非阻塞方式打开。

返回值:调用成功返回一个 struct tsdev * 指针,指向触摸屏设备句柄;如果打开设备失败,将返回 NULL

4.2 ts_setup() 函数

ts_setup() 相比 ts_open(),除了打开触摸屏设备外,还对触摸屏设备进行了配置。

#include "tslib.h"
struct tsdev *ts_setup(const char *dev_name, int nonblock)

参数 dev_name:指定触摸屏的设备节点。当 dev_name 设置为 NULL 时,ts_setup() 函数内部会读取 TSLIB_TSDEVICE 环境变量作为触摸屏的设备节点。

参数 nonblock:表示是否以非阻塞方式打开触摸屏设备。

返回值:调用成功返回一个 struct tsdev * 指针,指向触摸屏设备句柄;如果打开设备失败,将返回 NULL

4.3 ts_close() 函数

关闭触摸屏设备。

#include "tslib.h"
int ts_close(struct tsdev *);

4.4 ts_config() 函数

配置触摸屏设备。即解析 ts.conf 文件中的配置信息,加载相应的插件。

#include "tslib.h"
int ts_config(struct tsdev *ts);

参数 ts:指向触摸屏句柄。

返回值:成功返回 0,失败返回 -1

4.5 ts_read() 函数

读取单点触摸数据。

struct ts_sample {
    int x;                  //X 坐标
    int y;                  //Y 坐标
    unsigned int pressure;  // 按压力大小
    struct timeval tv;      // 时间
};
#include "tslib.h"
int ts_read(struct tsdev *ts, struct ts_sample *samp, int nr);

参数 ts:指向一个触摸屏设备句柄。参数 samp:指向一个 struct ts_sample 对象。

参数 nr:表示对一个触摸点的采样数,设为 1 即可。

4.6 ts_read_mt() 函数

用于读取多点触摸数据。

struct ts_sample_mt {     
    int x;                  // X 坐标    
    int y;                  // Y 坐标    
    unsigned int pressure;  // 按压力大小    
    int slot;               // 触摸点 slot    
    int tracking_id;        // ID    
    ··· ···
    struct timeval tv;      // 时间
    short pen_down;         // BTN_TOUCH 的状态   
    short valid;            // 此次样本是否有效标志 触摸点数据是否发生更新
};
#include "tslib.h" 
int ts_read_mt(struct tsdev *ts, struct ts_sample_mt **samp, int max_slots, int nr);

参数 ts:指向一个触摸屏设备句柄。参数 samp:指向一个 struct ts_sample_mt 对象。

参数 max_slots:表示触摸屏支持的最大触摸点数(可以通过调用 ioctl() 函数获取到)。

参数 nr:表示对一个触摸点的采样数。

5. 测试代码

5.1 单点触摸测试程序

#include <stdio.h>
#include <stdlib.h>
#include <tslib.h>

int main(int argc, char **argv)
{
    int ret;
    struct tsdev *ts;
    struct ts_sample samp;

    /* 打开并配置触摸屏设备 */
    ts = ts_setup(NULL, 0);
    if (!ts)
    {perror("ts_setup");
        return -1;
    }
    while (1) {
        /* 读数据 */
        ret = ts_read(ts, &samp, 1);
        if (ret < 0)
        {perror("ts_read");
            ts_close(ts);
            exit(1);
        }
        /* 如果按下则打印坐标 */
        if (samp.pressure)
            printf("(%d, %d)\n", samp.x, samp.y);
    }
        ts_close(ts);
        return 0;
}

5.2 多点触摸测试程序

#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;
    /* 保存每一个触摸点上一次的按压力, 初始为 0 表示松开 */
    unsigned int pressure[12] = {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++)
        {
            // valid 有效表示有更新
            if (mt_ptr[i].valid)
            {if (mt_ptr[i].pressure) // 如果按压力 >0 
                {if (pressure[mt_ptr[i].slot]) // 如果上一次的按压力 >0
                        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);
}
正文完
 1