TinyX和Tslib

TinyX是XFree86的一个配置子集,一般用于实现嵌入式Linux的图形界面。TinyX本身只提供了触摸屏支持的接口,需要配合Tslib才能 实现触摸屏操作。Tslib是一个触摸屏的库,它提供诸如滤波、去抖、校准之类的功能,为不同的触摸屏提供了一个统一的接口。
本文将移植TinyX和Tslib到运行Linux的S3C2440(ARM9)开发板上,触摸屏型号为H3600,带驱动。开发环境:Ubuntu8.10,arm-linux-gcc 3.4.1,XFree86-4.8.0,tslib-1.0,开发板Linux2.6.13。

编译Tslib

对于一般的Linux程序源代码,其安装方法为:configure,make,make install。但是在Tslib中需要通过autogen.sh文件来产生configure文件。下载后的源码可能由于格式问题,运行时会出现找不到文件的错误,需要使用dos2unix转换一遍。生成configure文件:
$./autogen.sh
这里有个技巧来避免一个编译错误,建立cache文件来欺骗配置程序。
$echo "ac_cv_func_malloc_0_nonnull=yes" > arm­linux.cache
$./configure \
--prefix=$PWD/build
--host=arm-linux
--cache-file=arm-linux.cache


配置程序的这些参数分别表示安装目录为当前目录下的build文件夹,采用arm-linux交叉编译,读取cache文件。其他参数可用configure -help或者README文件查看。
然后是编译:
$make
$make instal
如果一切正常,在build文件夹下就是编译好的Tslib,其中etc 目录下的配置文件 ts.conf指定了使用何种形式的触摸屏,根据液晶屏具体型号选择哪一条语句去掉注释。我将module_raw input和module_raw h3600两句去掉了注释。
下一步就可以将生成拷入开发板测试。运行前需要根据文件位置配置环境变量,下面是一个例子:
export LD_LIBRARY_PATH=/home/tslib/lib
export TSLIB_TSDEVICE=/dev/h3600_tsraw
export TSLIB_CONFFILE=/home/tslib/etc/ts.conf
export TSLIB_PLUGINDIR=/home/tslib/lib/ts
使用./bin文件夹下ts_calibrate程序校准屏幕,然后用ts_test测试。如果一切正常,我们可以进行下一步了。

编译TinyX

介绍编译TinyX的文章较多,步骤也比较复杂。这里只对一些难点和与Tslib有关的方面作介绍。
首先是下载ncurse和zlib源代码并交叉编译,编译后的头文件和库文件根据编译时包含路径的不同,可能需要将其放不同位置,一般为arm- linux-gcc/arm-linux/include(lib)或者tslib/include(lib),在编译错误时可以根据错误信息将需要的文 件拷入相应的目录中。Ubuntu还需要安装ed editor,否则会编译报错。
 TinyX 的编译主要就是正确配置 config/cf/cross.def文件 和 config/cf/host.def文件。Cross.def 文件里主要是编译环境的设置,host.def是编译条件的设置。详细说明可参考cf目录下的README文件,但建议首先复制一份已经配置好的文件再修改。编译报错的另一个主要原因就是这两个文件配置问题。
由于需要支持触摸屏,host.def中应加入如下语句:
#define TouchScreen YES
#define HasTsLib YES
此时编译会报错,找不到tslib.h。发现该文件在Tslib/src中,于是将Tslib/src中的文件全部拷入tinyx/programs /Xserver/hw/tinyX/linux/即可。继续编译出现ld找不到-lts问题,将编译好的tslib/lib文件夹中文件拷入arm- linux-gcc/arm-linux/lib。
这回可以编译通过了,编译一般需要10~20分钟,编译后大小根据配置文件不同约为20~40MB。但是在开发板上运行,触摸屏完全没有反应,只能从代码中寻找答案。TinyX的代码主要在programs/Xserver/hw/tinyx/中,很多地方是值得一读的。
TinyX对设备的初始化代码是tinyx/programs/Xserver/hw/tinyx/fbdev/fbinit.c。下面这个子程序是输入设备的初始化,注意其中关于触摸屏初始化部分:
void
InitInput (const int argc, const char **argv)
{
  KdInitInput (&LinuxMouseFuncs, &LinuxKeyboardFuncs);
#ifdef TOUCHSCREEN
  KdInitTouchScreen (&TsFuncs);
#endif
}
再看tinyx.h文件并没有定义TOUCHSCREEN,所以根本不会对触摸屏初始化。故应该在tinyx.h文件加入#define TOUCHSCREEN。
另外在programs/Xserver/hw/tinyX/linux/tslib.c中对触摸屏的查找是根据TsNames数组来进行的,其中可能没有开发板上的触摸屏名称。在开发板Linux的/dev下查找,一般是带ts的,将其加入TsNames数组。
最后可以编译了,命令略有不同:
$make World
$make install DESTDIR=安装目录
TinyX的编译基本算是结束了,实际编译将会遇到许多问题,可以参考其他相关资料。

开发板设置

生成的文件比较大,经常使用U盘或者SD卡将其挂载到开发板上。TinyX由于路径改变会出现找不到库文件问题,可以在挂载时选择文件路径或者建立软连接解决。
为了实现自动启动TinyX,可在启动脚本(如/etc/init.d/rcS)中加入一个shell脚本,一个例子如下:
#!/bin/sh
#挂载SD卡
mount -t vfat /dev/mmcblk0p1 /home/tinyx/
#删除因掉电产生的临时文件
rm /tmp/.X0-lock
#这里加入上文tslib的环境变量
#后台启动TinyX
/home/tinyx/bin/Xfbdev &
如果一切顺利,应该在屏幕上看到黑白栅格,中间的光标随着触点移动。这样,一个基本输入输出就算完成了。

参考文献

李先静. 交叉编译场景分析(arm-linux)

马龙华 彭哲. 基于Scilab的ARM-Linux嵌入式计算及应用. 科学出版社