(1)在tslib目录下有设置环境变量的文本文件:settsenv.sh,内容:
export T_ROOT=/system
export LD_LIBRARY_PATH=$T_ROOT/lib
export TSLIB_CONSOLEDEVICE=
export TSLIB_FBDEVICE=/dev/graphics/fb0
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_PLUGINDIR=$T_ROOT/lib/ts
export TSLIB_CONFFILE=$T_ROOT/etc/tslib/ts.conf
export TSLIB_CALIBFILE=/data/data/pointercal
设定的TSLIB的TS设备,FB设备,配置文件,动态库文件的路径。当然,具体的要用的可以在程序代码中重新设定。
(2)tslib目录下的etc目录ts.conf是配置文件,内容:
# Uncomment if you wish to use the linux input layer event interface
module_raw input1
# 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=100
module linear
可见,上面有很多模块可以调用,最终是选择了input1,也即是linux的input获取方式。这些模块的源代码在plugins目录下都有定义。
(3)分析流程,接触摸屏分析之一,在ts_main中:
void get_sample (struct tsdev *ts, calibration *cal, int index, int x, int y, char *name)
{
put_cross(x, y, 2 | XORMODE); //画十字座标
getxy (ts, &cal->x [index], &cal->y [index]); //取得x,y的LCD坐标值
put_cross(x, y, 2 | XORMODE);
last_x = cal->xfb [index] = x;
last_y = cal->yfb [index] = y; //赋值cal的触摸屏坐标
}
(4)解析getxy
struct ts_sample {
int x;
int y;
unsigned int pressure;
struct timeval tv;
};
void getxy(struct tsdev *ts, int *x, int *y)
{
#define MAX_SAMPLES 128
struct ts_sample samp[MAX_SAMPLES]; //采样128次
do
{
if (index < MAX_SAMPLES-1)
index++;
if (ts_read_raw(ts, &samp[index], 1) < 0) { //循环读取采样数据保存到samp数组中
close_framebuffer ();
exit(1);
}
} while (samp[index].pressure > 0);//(samp[0].pressure == 0);
//然后根据采样的samp值运算得到*x,*y。
}
int ts_read_raw(struct tsdev *ts, struct ts_sample *samp, int nr)
{
int result = ts->list_raw->ops->read(ts->list_raw, samp, nr); //执行采样读函数
return result;
}
(5)那上述最后的函数指针是在哪里执行的呢?可以回溯到tsmain函数里面的ts_config,它用来配置ts设备。
int ts_config(struct tsdev *ts)
{
//读取ts.conf文件
if (strcasecmp(tok, "module") == 0) {
module_name = strsep(&p, " /t");
ret = ts_load_module(ts, module_name, p);
}
else if (strcasecmp(tok, "module_raw") == 0) {
module_name = strsep(&p, " /t");
ret = ts_load_module_raw(ts, module_name, p);
} //选择确定的模块加入,选择的是input1
}
载入模块的函数定义:
int ts_load_module(struct tsdev *ts, const char *module, const char *params)
{
return __ts_load_module(ts, module, params, 0);
}
int ts_load_module_raw(struct tsdev *ts, const char *module, const char *params)
{
return __ts_load_module(ts, module, params, 1);
}
int __ts_load_module(struct tsdev *ts, const char *module, const char *params, int raw)
{
char fn[1024];
struct tslib_module_info *info;
strcpy(fn,getenv("TSLIB_PLUGINDIR")); //TSLIB_PLUGINDIR=$T_ROOT/lib/ts
strcat(fn, "/");
strcat(fn, module);
strcat(fn, ".so");
void *handle = dlopen(fn, RTLD_NOW);
init = dlsym(handle, "mod_init"); //获得特定的mod_init,也即input-raw.c这个文件模块
info = init(ts, params); //用params初始化ts。
__ts_attach(ts, info); //再将info与ts绑定
}
(6)接着看input-raw.c里面的处理。
mod_init()-》i->module.ops = &__ts_input_ops;
static const struct tslib_ops __ts_input_ops = {
.read = ts_input_read,
.fini = ts_input_fini,
};
这里的read指针的赋值函数就是(4)末尾要执行的那个。
static int ts_input_read(struct tslib_module_info *inf,struct ts_sample *samp, int nr)
{
struct tslib_input *i = (struct tslib_input *)inf; //从特定的input1的所在功能模块获得inf参数输入,也即触摸屏参数转化后
struct input_event ev;
struct tsdev *ts = inf->dev;
read(ts->fd, &ev, sizeof(struct input_event)); //读入ts设备 特定的input event信息
samp->x = i->current_x = ev.value;
samp->y = i->current_y;
samp->pressure = i->current_p; //赋给samp的值,从而获得LCD的x,y
}
到这步为止,获得了完整的5个点的LCD参数。
(7)真正的校正函数perform_calibration:
perform_calibration(calibration *cal) 通过传入的cal所带的5个点的XY两个方向的触摸屏值和LCD值,经过运算得到最终的7个cal.a[7]参数。