http://wenku.baidu.com/link?url=W_TNQV2ymtUqfT4pDFc8596RRwDQK0MLR3jF4FGv8hGDjPy4CqWssMDsniijA0QB8UzEx6MwVu5QUCqoOaXkw01ONWu-FTWPWxZa27Nnmd7
移植了新内核版本2.6.38,然后想重新做个qt文件系统,我利用busybox制作一个基本文件系统,烧写到开发板上,然后就想先试试tslib触摸屏校准是否好用,刚开始使用的是tslib1.14这个版本,编译后下载到文件系统上,设置好环境变量,运行ts_calibrate,然后就出来了一句话:“selecteddevice is not a touchscreen I understand”,点击触摸屏无反应,赶紧查看原因,
1、查看内核启动信息,有如下内容:
mousedev: PS/2 mousedevice common for all mice
samsung-ts s3c2410-ts:driver attached, registering input device
input: S3C24XXTouchScreen as /devices/virtual/input/input0
2.cddev/input,ls,显示有event0mice mouse0,再ls-l
crw------- 1 0 0 13, 64Jan 1 00:00 event0
crw------- 1 0 0 13, 63Jan 1 00:00 mice
crw------- 1 0 0 13, 32Jan 1 00:00 mouse0
3.然后cat /proc/bus/input/devices
I: Bus=0019 Vendor=deadProduct=beef Version=0102
N: Name="S3C24XXTouchScreen"
P: Phys=
S:Sysfs=/devices/virtual/input/input0
U: Uniq=
H: Handlers=mouse0event0
B: PROP=0
B: EV=b
B: KEY=400 0 0 0 0 0 00 0 0 0
B: ABS=3
4.cat/dev/input/event0,点击触摸屏,显示乱码。
5.没办法了,我换上了以前能用的tslib文件,问题依旧啊。
~~~~~~~~把我郁闷滴,人都快被折磨疯了,网上能试的方法都差不多了,我又记起了我新下载的tslib文件,是从官网上下载的,不同于网上流传的1.14版本,然后
#./autogen.sh
#./configure--host=arm-linux --prefix=/$BUILD/tslib/install
#make 2>>install.log
#make install2>>install.log
不同于以前版本的编译,下面旧版本的编译方式,注意到红色的信息,新版本是不需要的。
#./autogen.sh
#./configure--host=arm-linux ac_cv_func_malloc_0_nonnull=yes CC=arm-linux-gcc--prefix=$BUILD/tslib/install?
#make 2>>install.log?
#make install2>>install.log?
------------------------------------------------------------------------
编译好后,打包下载到开发板上,运行?ts_calibrate,点击触摸屏,它有反应了,ww,又试了目录下其他几个程序,ok(废话,当然行的)。
触摸屏驱动虽然移植成功了可是tslib没有作用,触摸屏还是没有用,$W( `) b; O' N6 V3 `* N
我用ts_test测试终端打印了
tslib: Selected deviceuses a different version of the event protocol than tslib wascompiled for
查看tslib源代码发现打印该信息的语句在tslib的源代码的plugs文件夹中input-raw.c的,H0 d3 m$ K2 H: G" J& C& D
static intcheck_fd(struct tslib_input*i)函数中,发现tslib在加载linux触摸屏驱动模块时会检查内核的输入子系统的
版本号:
if (ioctl(ts->fd,EVIOCGVERSION, &version) < 0) {
fprintf(stderr, "tslib:Selected device is not a Linux input event device\n");
return -1;
}
上面程序段将驱动的版本号存放在整型的version中
if (version !=EV_VERSION) {
fprintf(stderr, "tslib:Selected device uses a different version of the event protocol thantslib was compiled for\n");
return -1;
}
该程序将获得的版本号version与本tslib的面向的版本号匹配,若不同则打印:
tslib: Selected deviceuses a different version of the event protocol than tslib wascompiled for
信息
再看arm交叉编译工具中的头文件库中的linux/input.h中的EV_VERSION定义为
#define EV_VERSION0x010000;
而linux内核include/linux/input.h中的EV_VERSION定义为
#define EV_VERSION0x010001
由此可见问题就出现在内核的输入子系统的版本号不匹配的问题
解决办法:
1.将内核源代码里的include/linux/input.h中的
#define EV_VERSION0x010001
改为:
#define EV_VERSION0x010000
2.将arm交叉编译工具中的头文件库中的"
linux/input.h中的
#define EV_VERSION0x010000
改为
#define EV_VERSION0x010001
再编译tslib库
(8) 触摸屏校准
校准的办法是进入开发板的tslib1.4文件夹:
#cd??/usr/local/tslib1.4/bin
执行校准:
进入开发板的:
#cd??/usr/local/tslib1.4/bin
执行:
#./ts_calibrate
这时候,屏幕上会出现“+”提示,用触摸笔点击“+”中心,随后会出现另外一个,同样的操作。依次完成5个“+”的校准。校准程序就会生成一个校准文件:/etc/pointercal
我的校准文件的内容如下:
-15552 96 1104588 3221984 -19944688 -55648
该校准文件就是很多GUI程序使用的。比如QT等。
(9) 校准中错误的解决
Segmentation fault
说明ts.conf中的行前面有空格。删除非注释行前的空格即可。
No raw modules loaded.
则将ts.conf文件中的#module_raw inpu 的注释符号去掉(左边不能留空格)。
selected device is nota touchscreen I understand
将ts.conf文件中的#module_rawh3600 的注释符号去掉(左边不能留空格)。如果依然错误,就尝试其它行的。
ts_config: No such fileor directory
ts_read: Invalidargument
说明ts.conf中的配置项错误,比如module_rawh3600行前加注释,修改为其他的等待。
编译过程如下:
$ ./autogen.sh
$ ./configure--host=arm-linux --prefix=/home/latelee/lib/tslib
$ make
$ make install
网上流行的编译方法如下:
$ ./autogen.sh
$ echo"ac_cv_func_malloc_0_nonnull=yes"> tmp.cache
$ ./configure--host=arm-linux --cache-file=tmp.cache --enable-inputapi=no--prefix=/home/latelee/lib/tslib
$ make
$ make install
有两点不同:
一,没有“ac_cv_func_malloc_0_nonnull=yes”,编译过程没有报错;
二,去掉“--enable-inputapi=no”,网上说法不在此处提及,单看README文件的描述:
TSLIB_TSDEVICE???TSdevice file name.
Default (non inputapi):/dev/touchscreen/ucb1x00
Default (inputapi):/dev/input/event0
板子的触摸屏设备文件正是/dev/input/event0(默认值,可以在配置文件ts.conf中设置这个环境变量)。
makeinstall后,会在/home/latelee/lib/tslib目录生成4个子目录:
include lib etc bin
生成的库位于lib中,该目录下还有一个子目录ts,它包含了许多校准用到的库(如input.so等)。etc下的ts.conf为配置文件,bin目录下为校准、测试工具(如校准的ts_calibrate,测试用的ts_test)。
配置文件如下:
# Late Lee 2011-03-31for touchscreen test
export?TSLIB_ROOT=/usr/local/tslib
export?TSLIB_TSDEVICE=/dev/input/event0
export?TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export?TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
export?TSLIB_CALIBFILE=/etc/pointercal
export?TSLIB_CONSOLEDEVICE=none
export?TSLIB_FBDEVICE=/dev/fb0
export?LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib
(该文件的日期为上个月最后一天,离今已十余天,为了这个花费的时日可不少。)
使用TSLIB_ROOT这个变量比较好,因为只要将编译生成后的tslib文件夹复制到某个位置,再修改这个变量即可,其它的不用修改。
配置文件ts.conf内容如下:
module_raw input
module pthres pmin=1
module variancedelta=30
module dejitterdelta=100
module linear
module_raw有许多种,这里只使用input(即Linux的input子系统,设备文件名称为/dev/input/event0),其它的删除掉。后面的几个module还没有深入了解,它们使用的库就在tslib/lib/ts中,最后三个模块的字面意思是“方差(滤波)”、“去抖动(去噪)”、“线性(坐标变换)”,对这些东西不了解,不发表意见。
错误3:
[root@Fofia/bin]#ts
ts open
tslib: Selected deviceis not a Linux input event device
原因解析:input-raw.c函数须要按照底层驱动做恰当批改。
(1)tiny6410触摸屏驱动不供给ioctl接口,所以要删除代码中与ioctl有关的所有函数。
(2)tiny6410触摸屏驱动传给上层的数据是一个32位无符号整型数据,&#26684;式为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 theLinux input device API:
?*? Copyright (C)2002 Nicolas Pitre
?*
?* This file is placedunder the LGPL.? Please see the file
?* COPYING for moredetails.
?*
?*
?* Read raw pressure,x,y,and timestamp a touchscreen device.
?*/
#include"config.h"
#include<errno.h>
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#ifdefHAVE_UNISTD_H
#include<unistd.h>
#endif
#include<sys/time.h>
#include<sys/types.h>
#include<linux/input.h>
#ifndefEV_SYN /* 2.4 kernel headers */
#define EV_SYN 0 x00
#endif
#ifndefEV_CNT
#define EV_CNT (EV_MAX&#43;1)
#endif
#ifndefABS_CNT
#define ABS_CNT (ABS_MAX&#43;1)
#endif
#ifndefKEY_CNT
#define KEY_CNT (KEY_MAX&#43;1)
#endif
#include"tslib-private.h"
#defineGRAB_EVENTS_WANTED?? ?1
#defineGRAB_EVENTS_ACTIVE?? ?2
struct tslib_input {
structtslib_module_info module;
intcurrent_x;
intcurrent_y;
intcurrent_p;
intsane_fd;
intusing_syn;
intgrab_events;
};
#defineDIV_ROUND_UP(n,d)(((n)&#43;(d)- 1)/ (d))
#defineBIT(nr) (1UL << (nr))
#defineBIT_MASK(nr) (1UL << ((nr)% BITS_PER_LONG))
#defineBIT_WORD(nr) ((nr)/ BITS_PER_LONG)
#defineBITS_PER_BYTE 8
#defineBITS_PER_LONG (sizeof(long)* BITS_PER_BYTE)
#defineBITS_TO_LONGS(nr) DIV_ROUND_UP(nr,BITS_PER_BYTE * sizeof(long))
static intcheck_fd(structtslib_input *i)
{
/*与ioctl有关,全部注释掉???
structtsdev *ts = i->module.dev;
intversion;
longevbit[BITS_TO_LONGS(EV_CNT)];
longabsbit[BITS_TO_LONGS(ABS_CNT)];
longkeybit[BITS_TO_LONGS(KEY_CNT)];
if(ioctl(ts->fd,EVIOCGVERSION,&version)< 0){
fprintf(stderr,"tslib: Selected device is not a Linuxinput event device ");
return-1;
}
if(version< EV_VERSION){
fprintf(stderr,"tslib: Selected device uses a differentversion of the event protocol than tslib was compiled for ");
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 atouchscreen (mustsupport ABS and KEY event types)");
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 atouchscreen (mustsupport ABS_X and ABS_Y events)");
return-1;
}
Sincesome touchscreens (eg.infrared)physically can""t measure pressure,
theinput system doesn""t report it on those. Tslib relies onpressure,thus
weset 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 atouchscreen (mustsupport BTN_TOUCH events)");
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 ed input device ");
return-1;
}
i->grab_events= GRAB_EVENTS_ACTIVE;
}
*/
return0;
}
//这个函数是须要批改的,因为tiny6410触摸屏驱动与tslib的接口不雷同
static intts_input_read(structtslib_module_info *inf,
structts_sample *samp,int nr)
{
structtsdev *ts = inf->dev;
intret = nr;
inttotal = 0;
unsignedpoint;
fprintf(stderr,"tslibstart read raw ");
while(total< nr){
ret= read(ts->fd,&point,sizeof(unsigned));
if(ret<sizeof(unsigned))
{
fprintf(stderr,"readpoint linux error ");
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",samp->x,samp->y,samp->pressure);
samp&#43;&#43;;
total&#43;&#43;;
}
returntotal;
}
static intts_input_fini(structtslib_module_info *inf)
{
structtslib_input *i = (structtslib_input *)inf;
structtsdev *ts = inf->dev;
/*
if(i->grab_events== GRAB_EVENTS_ACTIVE){
if(ioctl(ts->fd,EVIOCGRAB,(void *)0)){
fprintf(stderr,"tslib: Unable to un-grab ed input device");
}
}
*/
?? ?free(inf);
?? ?return 0;
}
static const structtslib_ops __ts_input_ops = {
.read= ts_input_read,
.fini= ts_input_fini,
};
static intparse_raw_grab(structtslib_module_info *inf,char *str,void *data)
{
structtslib_input *i = (structtslib_input *)inf;
unsignedlong v;
interr = errno;
v= strtoul(str,NULL,0);
if(v ==ULONG_MAX && errno == ERANGE)
return-1;
errno= err;
switch((int)data){
case1:
if(v)
i->grab_events= GRAB_EVENTS_WANTED;
break;
default:
return-1;
}
return0;
}
static const structtslib_vars raw_vars[] =
{
{"grab_events",(void *)1,parse_raw_grab },
};
#defineNR_VARS (sizeof(raw_vars)/ sizeof(raw_vars[0]))
TSAPI structtslib_module_info *input_mod_init(structtsdev *dev,const char *params)
{
structtslib_input *i;
i= malloc(sizeof(structtslib_input));
if(i ==NULL)
returnNULL;
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);
returnNULL;
}
return&(i->module);
}
#ifndefTSLIB_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源代码写错了,返回&#20540;应当是读取的字节数也就是return total,本来代码为returnret,一开端没有改.
一.编译
解压tslib-1.4.1.tar.bz2,
# tar jxvftslib-1.4.1.tar.bz2
# cd tslib.1.4.1
指定交叉编译器:
#exportCC=/usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc ?
生成configure文件
#./autogen.sh
如果无法执行./autogen.sh
解决办法:
sudo apt-get installautoconf
sudo apt-get installautomake
sudo apt-get installlibtool
?
#exportPATH=/usr/local/arm/4.2.2-eabi/usr/bin:$PATH
#echo"ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
#./configure--host=arm-linux --prefix=$PWD/build_ok --cache-file=arm-linux.cache--enable-inputapi=no
make
make install
注意,上面中的--prefix选项,这个选项是在tslib-1.3的目录下生成一个build目录,把安装的文件拷贝到这个目录下,这个build下的文件很重要,以后的移植,就跟这个文件夹密切相关。
二.配置文件系统
build文件夹拷贝到开发板相应的地方。我的就是拷贝到/home/tslib下
mkdir home/tslib
chmod 777 home/tslib
?为了实现Tslib的正确运行,需要对如下的Tslib的环境变量进行配置:
TSLIB_TSDEVICE ?//触摸屏设备文件名。
TSLIB_CALIBFILE?//校准的数据文件,由ts_calibrate校准程序生成。
SLIB_CONFFILE ?//配置文件名。
TSLIB_PLUGINDIR//插件目录
TSLIB_CONSOLEDEVICE//控制台设备文件名
TSLIB_FBDEVICE?//设备名
环境变量,可以放在文件系统里的etc/profile
exportT_ROOT=/home/tslib/
exportLD_LIBRARY_PATH=$T_ROOT/lib
exportTSLIB_CONSOLEDEVICE=none
exportTSLIB_FBDEVICE=/dev/fb0 ? ??
exportTSLIB_TSDEVICE=/dev/event0
exportTSLIB_PLUGINDIR=$T_ROOT/lib/ts
exportTSLIB_CONFFILE=$T_ROOT/etc/ts.conf
exportTSLIB_CALIBFILE=/etc/pointercal
如果找不到/dev/fb0,解决办法如下:
mknod /dev/fb0 c 29 0
mknod /dev/fb1 c 29 1
如果出现selecteddevice is not a touchscreen I understand的错误
更换节点后仍然出现这个错误,那即使版本有问题了,换版本,解决问题
移植过程如下:
解压
修改tslib/plugins/input-raw.c
把其中的ts_input_read函数改成如下:
static intts_input_read(struct tslib_module_info *inf,
structts_sample *samp, int nr)
{
//printf ("HEAD=== ts_input_read in INPUT-RAW.C\n");
struct tslib_input *i =(struct tslib_input *)inf;
struct tsdev *ts =inf->dev;
struct input_event ev;
int ret = nr;
int total = 0;
unsigned long jjts;
while(total<nr)
{
ret = read(ts->fd, &jjts, sizeof(jjts));
if(ret==-1) continue;
samp->pressure=(jjts>>31) & 0x01;
samp->x=(jjts>>16) & 0xffff;
samp->y=jjts & 0xffff;
samp++;
total++;
}
ret=total;
return ret;
}
然后编译tslib
./autogen.sh
echo"ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure--host=arm-linux --cache-file=arm-linux.cache --enable-inputapi=no--prefix=/usr/local/tslib
make
make install
vi/usr/local/tslib/etc/ts.conf
修改ts.conf为
module_raw??input
module pthres pmin=1
module variancedelta=30
module dejitterdelta=10000
module linear
复制tslib到开发板对应的目录,我这里用的nfs挂载
cp /usr/local/tslib//opt/my/rootfs_nfs/usr/local/ -r