今天成功移植了tslib,庆祝一下。
转贴请注明出处:CSDN Eric Qu 个人专栏,QQ:12430300
一.了解tslib配置:
1.打开tslib配置文件ts.conf(make install编译后这个文件可以在目标文件夹/etc下找到)可以看到如下配置:# Uncomment if you wish to use the linux input layer event interface
module_raw input
# Uncomment if you're using a Sharp Zaurus SL-5500/SL-5000d
# module_raw collie
# Uncomment if you're using a Sharp Zaurus SL-C700/C750/C760/C860
# module_raw corgi
# Uncomment if you're using a device with a UCB1200/1300/1400 TS interface
# module_raw ucb1x00
# Uncomment if you're using an HP iPaq h3600 or similar
#module_raw h3600
# Uncomment if you're using a Hitachi Webpad
# module_raw mk712
# Uncomment if you're using an IBM Arctic II
# module_raw arctic2
module pthres pmin=1
module variance delta=30
module dejitter delta=10000
module linear
module_raw配置信息说明从什么地方读取触摸屏的笔点数据,每一个module都可以在源代码的plugins中找到对应源代码。
最后三个模块的字面意思是“方差(滤波)”、“去抖动(去 噪)”、“线性(坐标变换)”。
方差就是设置一个距离值,在这个距离内的两个点称为near,以外的称为far,滤波的时候,如果检测到当前一个点为far点,并且再下一个点与前一个点为near,当前这个点会被过滤掉。
文件中的各个设置选项之前不能有空格,否则会出现 Segmentation fault 错误2.环境变量设置
我直接了一个sell如下:
#!/bin/sh
export TSB_TSDEVICE=/dev/touchscreen #驱动触摸屏所在位置
export TSLIB_CALIBFILE=/etc/pointercal #存储校准数据的文件
export TSLIB_CONFFILE=/etc/ts.conf #配置文件
export TSLIB_PLUGINDIR=/usr/lib/ts #tslib库文件
export TSLIB_CONSOLEDEVICE=none #控制台设备文件名,没有就一定要写none,否则执行出错
#export TSLIB_FBDEVICE=dev/fb0 #frame buffer,默认为fb0
ts_calibrate #运行的程序。
二.编译
获取源代码:$ git clone https://github.com/kergoth/tslib
编译
$ ./autogen.sh
这个执行失败则是因为缺少工具,通过sudo apt-get install autoconf automake libtool安装相应工具。
$ make
$ make install
说明:--enable-input,网上很多人说是--enable-inputapi,可能这是老版本的配置吧
我的目标文件夹为/home/quqw/source_code/tslib/target,这个要写绝对路径。
make install后可以在target文件夹内看到目标文件,共4个文件夹。
bin下的文件我拷贝到嵌入式设备的bin下。
lib下的所有文件拷贝到/usr/lib下,TSLIB_PLUGINDIR需要根据ts所在文件夹做配置。
etc下有个ts.conf我直接拷到/etc下
三.逐个解决运行中的错误
错误1:
Couldnt open tslib config file: No such file or directory
ts_config: No such file or directory
原因:一般为环境变量 TSLIB_PLUGINDIR 设置问题。可以查看ts_config.c代码,打印出具体路径查看错误原因
int ts_config(struct tsdev *ts)
26 {
27 char buf[BUF_SIZE], *p;
28 FILE *f;
29 int line = 0;
30 int ret = 0;
31
32 char *conffile;
33
34 if( (conffile = getenv("TSLIB_CONFFILE")) == NULL) {
35 conffile = strdup (TS_CONF);
36 }
37
38 f = fopen(conffile, "r");
39 if (!f) {
40 ts_error("config file:%s\r\n",conffile);
41 perror("Couldnt open tslib config file");
42 return -1;
43 }
44 。。。
45 。。。
错误2:打不开module input
Couldnt load module input
No raw modules loaded.
原因分析:
查看ts.conf中module_raw的配置
编译选项需要增加 --enable_input=yes 否则没有input.so文件
错误3:
[root@Fofia /bin]# ts
ts open
tslib: Selected device is not a Linux input event device
原因分析:input-raw.c 函数需要根据底层驱动做适当修改。
(1)tiny6410触摸屏驱动不提供ioctl接口,所以要删除代码中与ioctl有关的所有函数。
(2)tiny6410触摸屏驱动传给上层的数据是一个32位无符号整型数据,格式为 unsigned ts_event = ((x << 16) | (y)) | (down << 31);
tslib无法识读。需要修改ts_input_read函数。
以下为修改后的源代码全文。
/*
* tslib/plugins/input-raw.c
*
* Original version:
* Copyright (C) 2001 Russell King.
*
* Rewritten for the Linux input device API:
* Copyright (C) 2002 Nicolas Pitre
*
* This file is placed under the LGPL. Please see the file
* COPYING for more details.
*
*
* Read raw pressure, x, y, and timestamp from a touchscreen device.
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <linux/input.h>
#ifndef EV_SYN /* 2.4 kernel headers */
# define EV_SYN 0x00
#endif
#ifndef EV_CNT
# define EV_CNT (EV_MAX+1)
#endif
#ifndef ABS_CNT
# define ABS_CNT (ABS_MAX+1)
#endif
#ifndef KEY_CNT
# define KEY_CNT (KEY_MAX+1)
#endif
#include "tslib-private.h"
#define GRAB_EVENTS_WANTED 1
#define GRAB_EVENTS_ACTIVE 2
struct tslib_input {
struct tslib_module_info module;
int current_x;
int current_y;
int current_p;
int sane_fd;
int using_syn;
int grab_events;
};
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define BIT(nr) (1UL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_PER_BYTE 8
#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
static int check_fd(struct tslib_input *i)
{
/*与ioctl有关,全部注释掉
struct tsdev *ts = i->module.dev;
int version;
long evbit[BITS_TO_LONGS(EV_CNT)];
long absbit[BITS_TO_LONGS(ABS_CNT)];
long keybit[BITS_TO_LONGS(KEY_CNT)];
if (ioctl(ts->fd, EVIOCGVERSION, &version) < 0) {
fprintf(stderr, "tslib: Selected device is not a Linux input event device\n");
return -1;
}
if (version < EV_VERSION) {
fprintf(stderr, "tslib: Selected device uses a different version of the event protocol than tslib was compiled for\n");
return -1;
}
if ( (ioctl(ts->fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
!(evbit[BIT_WORD(EV_ABS)] & BIT_MASK(EV_ABS)) ||
!(evbit[BIT_WORD(EV_KEY)] & BIT_MASK(EV_KEY)) ) {
fprintf(stderr, "tslib: Selected device is not a touchscreen (must support ABS and KEY event types)\n");
return -1;
}
if ((ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit)) < 0 ||
!(absbit[BIT_WORD(ABS_X)] & BIT_MASK(ABS_X)) ||
!(absbit[BIT_WORD(ABS_Y)] & BIT_MASK(ABS_Y))) {
fprintf(stderr, "tslib: Selected device is not a touchscreen (must support ABS_X and ABS_Y events)\n");
return -1;
}
Since some touchscreens (eg. infrared) physically can't measure pressure,
the input system doesn't report it on those. Tslib relies on pressure, thus
we set it to constant 255. It's still controlled by BTN_TOUCH - when not
touched, the pressure is forced to 0.
if (!(absbit[BIT_WORD(ABS_PRESSURE)] & BIT_MASK(ABS_PRESSURE))) {
i->current_p = 255;
if ((ioctl(ts->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
!(keybit[BIT_WORD(BTN_TOUCH)] & BIT_MASK(BTN_TOUCH)) ) {
fprintf(stderr, "tslib: Selected device is not a touchscreen (must support BTN_TOUCH events)\n");
return -1;
}
}
if (evbit[BIT_WORD(EV_SYN)] & BIT_MASK(EV_SYN))
i->using_syn = 1;
if (i->grab_events == GRAB_EVENTS_WANTED) {
if (ioctl(ts->fd, EVIOCGRAB, (void *)1)) {
fprintf(stderr, "tslib: Unable to grab selected input device\n");
return -1;
}
i->grab_events = GRAB_EVENTS_ACTIVE;
}
*/
return 0;
}
//这个函数是需要修改的,因为tiny6410触摸屏驱动与tslib的接口不相同
static int ts_input_read(struct tslib_module_info *inf,
struct ts_sample *samp, int nr)
{
struct tsdev *ts = inf->dev;
int ret = nr;
int total = 0;
unsigned point;
fprintf(stderr,"tslib start read raw\r\n");
while (total < nr) {
ret = read(ts->fd, &point, sizeof(unsigned));
if(ret<sizeof(unsigned))
{
fprintf(stderr,"read point from linux error\r\n");
ret=0;
break;
}
/* Fill out a new complete event */
if (!(point&0x80000000)) { /*按照友善驱动,最高位表示是否抬起*/
samp->x = 0;
samp->y = 0;
samp->pressure = 0;
} else {
samp->x = ((point>>16)&0x7fff);//x为高位,y为底16位
samp->y = (point&0xffff);
samp->pressure = 1;
}
fprintf(stderr, "input_raw->%d,%d,p:%d\n",samp->x, samp->y, samp->pressure);
samp++;
total++;
}
return total;
}
static int ts_input_fini(struct tslib_module_info *inf)
{
struct tslib_input *i = (struct tslib_input *)inf;
struct tsdev *ts = inf->dev;
/*
if (i->grab_events == GRAB_EVENTS_ACTIVE) {
if (ioctl(ts->fd, EVIOCGRAB, (void *)0)) {
fprintf(stderr, "tslib: Unable to un-grab selected input device\n");
}
}
*/
free(inf);
return 0;
}
static const struct tslib_ops __ts_input_ops = {
.read = ts_input_read,
.fini = ts_input_fini,
};
static int parse_raw_grab(struct tslib_module_info *inf, char *str, void *data)
{
struct tslib_input *i = (struct tslib_input *)inf;
unsigned long v;
int err = errno;
v = strtoul(str, NULL, 0);
if (v == ULONG_MAX && errno == ERANGE)
return -1;
errno = err;
switch ((int)data) {
case 1:
if (v)
i->grab_events = GRAB_EVENTS_WANTED;
break;
default:
return -1;
}
return 0;
}
static const struct tslib_vars raw_vars[] =
{
{ "grab_events", (void *)1, parse_raw_grab },
};
#define NR_VARS (sizeof(raw_vars) / sizeof(raw_vars[0]))
TSAPI struct tslib_module_info *input_mod_init(struct tsdev *dev, const char *params)
{
struct tslib_input *i;
i = malloc(sizeof(struct tslib_input));
if (i == NULL)
return NULL;
i->module.ops = &__ts_input_ops;
i->current_x = 0;
i->current_y = 0;
i->current_p = 0;
i->sane_fd = 0;
i->using_syn = 0;
i->grab_events = 0;
if (tslib_parse_vars(&i->module, raw_vars, NR_VARS, params)) {
free(i);
return NULL;
}
return &(i->module);
}
#ifndef TSLIB_STATIC_INPUT_MODULE
TSLIB_MODULE_INIT(input_mod_init);
#endif
错误4:
tslib start read raw
T: 060038, X: 9157, Y: 8445
touch ====> Add ... [ 2289, 2111 ]
Illegal instruction
解决:我发生这个错误是因为一开始input-raw.c源代码写错了,返回值应该是读取的字节数 也就是return total,原来代码为return ret,一开始没有改.
今天(2012-5-31)在real210上面做移植,又有了一些新问题:
错误5:
Segmentation fault
解决:一般是因为配置文件ts.conf格式错误。参数前面不能有空格。
错误6:
提示找不到库文件。
tslib库放置的位置必须与编译时候的默认位置相同,也就是lib文件夹下的放到/usr/lib下,etc下的放到/etc下,否则出错
2012-8-13
错误7:ts_open: No such file or directory
一般是环境变量设置问题
错误8:tslib -sh :./ts_calibrate:not found
这个是今天移植了busybox后出现的。原因是busybox是静态编译的,tslib运行时缺少动态库。
把arm-linux-gcc的动态库拷贝到/lib下解决。
上图:
![](http://hi.csdn.net/attachment/201109/13/0_1315884579ra5c.gif)