hcr 2011-06-05
TSLIB的思考
Tslib是Linux触摸屏驱动与QT之间的一层库,用于支持event事件,在QT中也配有linux_input选项支持触摸屏,不过由于事件结构与Linux驱动传递的input event不匹配,因而不配使用。
1. 关于编译
a) QT编译
QT的编译中需要在./configure中添加-qt-mouse-tslib –I /tslib编译生成的头文件路径 –L /tslib编译生成的库文件路径
编译时设定体系 会决定使用的库是*.so 还是*.dll
b) Tslib编译
Tslib的编译方法在网上比较多见,注意的是在配置configure时,最好加上选项—prefix=/路径,这样make install能才能将库和同文件添加到指定目录,否则会在默认的/usr/local/目录下
c) tslib运行的环境变量
由于tslib库的调用需要用到较多的环境变量,然而这些环境只在tslib中有需求,比较好的策略是运行一个程序创建进程,添加环境变量,然后调用exec执行编译好的QT程序,继承关系,保证环境变量的使用
看看环境变量用处:
LD_LIBRARY_PATH=/usr/local/tslib/lib libts.so path
QWS_MOUSE_PROTO=tslib:/dev/event3 QT read device path
TSLIB_CONFILE=/usr/local/tslib/etc/ts.conf which plugin to be used
TSLIB_PLUGINDIR=/usr/local/tslib/ts plugin dir
2. 设计思路
整个设计而言,思路还是挺清晰的
通过读取ts.config决定使用的plugin,对于每一个plugin的编写,如果要保持通用性的话,接口是不变的,所以plugin返回给libts.so的结构是固定的,在代码中具体为tslib_module_info *,而该结构中提供对应plugin的一些方法,实现加载的plugin不同调用不同的操作方法。
Linux ts driver中通过通知QT有鼠标事件产生,通过readMouseData调用libts.so中的接口,再调用对应的plugin接口,从而读取input event数据。
QT中如何知道有鼠标事件产生呢?没错,需要环境变量QWS_MOUSE_PROTO,读取ts device所对应的/dev/eventX,利用inotify机制,监控/dev/eventX是否有变化(当驱动向设备文件中写入事件报告时会产生变化),一旦监控到则调用readMouseData。
3. 代码细节
a) 动态库的使用
dlopen()
功能:打开一个动态链接库
包含头文件:
#include <dlfcn.h>
函数定义:
void * dlopen( const char * pathname, int mode );
函数描述:
在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL
RTLD_GLOBAL 允许导出符号
RTLD_GROUP
RTLD_WORLD
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要加入 -ldl (指定dl库)
例如
gcc test.c -o test –ldl
dlsym
使用dlsym通过函数名称获取函数指针,返回值即为指向函数的指针,供调用使用
dlsym()的函数原型是
void* dlsym(void* handle,const char* symbol)
该函数在<dlfcn.h>文件中。
handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用
比如,在 tslib中,
struct tslib_module_info * (*init)(struct tsdev *, const char *);
init=dlsym(handle,”mod_init”);
init(ts,params);
即为调用库中的mod_init函数
b) event read
在tslib中调用read读取input_event结构,实际上是与内核中evdev.c的evdev_read对应。
在evdev_read中,使用input_event_to_user,最终调用copy_to_user,将input_event结构的数据传递给用户空间
在evdev_ioctl中,使用evdev_ioctl_handler,最终使用evdev_do_ioctl,与用户空间进行ioctl