tslib简单流程分析

首先说,本人水平有限,如有错误欢迎指正。
tslib的校准过程,从tests/Ts_calibrate.c文件的main函数开始:

int main()
{
struct tsdev ts;/设备结构体*/
calibration cal;
int cal_fd;
char cal_buffer[256];
char *tsdevice = NULL;
char *calfile = NULL;
unsigned int i;
先来看一下tsdev这个结构体:
struct tsdev {
int fd;
struct tslib_module_info *list;
struct tslib_module_info list_raw; / points to position in ‘list’ where raw reads
come from. default is the position of the
ts_read_raw module. */
};在这个结构体中,只关心list_raw这个结构体指针,在来看一下这个结构体:
struct tslib_module_info {
struct tsdev *dev;
struct tslib_module_info next;/ next module in chain*/
void handle;/ dl handle*/
const struct tslib_ops *ops;
};

这个结构体中,只关心tslib_ops *ops这个结构体指针,继续看这个结构体:
struct tslib_ops {
int (*read)(struct tslib_module_info *inf, struct ts_sample *samp, int nr);
int (*fini)(struct tslib_module_info *inf);
};

可以看到,int (*read)();这个函数指针,就是从驱动设备,读取坐标数据的。
那这个函数是在哪注册的呢!看plugins\Input-raw.c这个文件中有一个
static const struct tslib_ops __ts_input_ops = {
.read = ts_input_read,
.fini = ts_input_fini,
};这个结构体,就是注册__ts_read_raw这个函数的。这个函数之后再看。

那现在首先就搞清楚了,校准的时候是从那个地方读取的数据。
signal(SIGSEGV, sig);
signal(SIGINT, sig);
signal(SIGTERM, sig);

if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {/*打开环境变量中指定的TSLIB_TSDEVICE设备*/
    ts = ts_open(tsdevice,0);

struct tsdev *ts_open(const char *name, int nonblock)
{
struct tsdev *ts;
int flags = O_RDONLY;

if (nonblock)
flags |= O_NONBLOCK;

ts = malloc(sizeof(struct tsdev));
if (ts) {
memset(ts, 0, sizeof(struct tsdev));

ts->fd = open(name, flags);
if (ts->fd == -1)
goto free;
}

return ts;

free:
free(ts);
return NULL;
}这是ts_open函数,比较简单,申请内存,然后初始化申请到的内存为0,之后使用C库函数open打开设备。最后返回tsdev结构体。flags由于传进函数的参数是0,所以flags在打开设备时,是以只读方式。
} else {

ifdef USE_INPUT_API

    ts = ts_open("/dev/input/event0", 0);

else

    ts = ts_open("/dev/touchscreen/ucb1x00", 0);

endif /* USE_INPUT_API */

}

if (!ts) {
    perror("ts_open");
    exit(1);
}
if (ts_config(ts)) {

int ts_config(struct tsdev *ts)
{
char buf[BUF_SIZE], *p;
FILE *f;
int line = 0;
int ret = 0;

char *conffile;

if( (conffile = getenv(“TSLIB_CONFFILE”)) == NULL) {
conffile = strdup (TS_CONF);
}

f = fopen(conffile, “r”);
if (!f) {
perror(“Couldnt open tslib config file”);
return -1;
}

buf[BUF_SIZE - 2] = ‘\0’;
while ((p = fgets(buf, BUF_SIZE, f)) != NULL) {
char *e;
char *tok;
char *module_name;

line++;

/* Chomp */
e = strchr(p, ‘\n’);
if (e) {
*e = ‘\0’;
}

/* Did we read a whole line? */
if (buf[BUF_SIZE - 2] != ‘\0’) {
ts_error(“%s: line %d too long\n”, conffile, line);
break;
}

tok = strsep(&p, ” \t”);

/* Ignore comments or blank lines.
* Note: strsep modifies p (see man strsep)
*/

if (p==NULL || *tok == ‘#’)
continue;

/* Search for the option. */
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);
} else {
ts_error(“%s: Unrecognised option %s:%d:%s\n”, conffile, line, tok);
break;
}
if (ret != 0) {
ts_error(“Couldnt load module %s\n”, module_name);
break;
}
}

if (ts->list_raw == NULL) {
ts_error(“No raw modules loaded.\n”);
ret = -1;
}

fclose(f);

return ret;
}这个函数主要的作用是,读取etc\ts.conf文件,查看选择的是哪种方式,并且加载相应的模块。那么我使用的是module input raw,所以加载input-raw模块,事实上在这里,才确定是如何读取位置坐标信息的。
perror(“ts_config”);
exit(1);
}

if (open_framebuffer()) {/*这个地方我还不太懂,但是大概就是打开指定的显示设备*/
    close_framebuffer();
    exit(1);
}

for (i = 0; i < NR_COLORS; i++)
    setcolor (i, palette [i]);

put_string_center (xres / 2, yres / 4,
           "TSLIB calibration utility", 1);
put_string_center (xres / 2, yres / 4 + 20,
           "Touch crosshair to calibrate", 2);

printf("xres = %d, yres = %d\n", xres, yres);

// Read a touchscreen event to clear the buffer
//getxy(ts, 0, 0);

get_sample (ts, &cal, 0, 50,        50,        "Top left");
这个函数的函数体如下:

static void get_sample (struct tsdev *ts, calibration *cal,
int index, int x, int y, char *name)
{
static int last_x = -1, last_y;

if (last_x != -1) {

define NR_STEPS 10

int dx = ((x - last_x) << 16) / NR_STEPS;
int dy = ((y - last_y) << 16) / NR_STEPS;
int i;
last_x <<= 16;
last_y <<= 16;
for (i = 0; i < NR_STEPS; i++) {
put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
usleep (1000);
put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
last_x += dx;
last_y += dy;
}
}

put_cross(x, y, 2 | XORMODE);
getxy (ts, &cal->x [index], &cal->y [index]);
put_cross(x, y, 2 | XORMODE);

last_x = cal->xfb [index] = x;
last_y = cal->yfb [index] = y;

printf(“%s : X = %4d Y = %4d\n”, name, cal->x [index], cal->y [index]);
}这个函数,用来在显示设备上面指定的位置,显示校准用的十字图标。然后通过getxy()函数,获得当前触屏返回的坐标值。
下面看一下这个函数,
void getxy(struct tsdev *ts, int *x, int *y)
{

define MAX_SAMPLES 128

struct ts_sample samp[MAX_SAMPLES];
int index, middle;

do {
if (ts_read_raw(ts, &samp[0], 1) < 0) {
perror(“ts_read”);
close_framebuffer ();
exit(1);
}

} while (samp[0].pressure == 0);

/* Now collect up to MAX_SAMPLES touches into the samp array. */
index = 0;
do {
if (index < MAX_SAMPLES-1)
index++;
if (ts_read_raw(ts, &samp[index], 1) < 0) {
perror(“ts_read”);
close_framebuffer ();
exit(1);
}
} while (samp[index].pressure > 0);
printf(“Took %d samples…\n”,index);
middle = index/2;
if (x) {
qsort(samp, index, sizeof(struct ts_sample), sort_by_x);
if (index & 1)
*x = samp[middle].x;
else
*x = (samp[middle-1].x + samp[middle].x) / 2;
}
if (y) {
qsort(samp, index, sizeof(struct ts_sample), sort_by_y);
if (index & 1)
*y = samp[middle].y;
else
*y = (samp[middle-1].y + samp[middle].y) / 2;
}
}
红色标识的函数如下:

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);

ifdef DEBUG

fprintf(stderr,”TS_READ_RAW—-> x = %d, y = %d, pressure = %d\n”, samp->x, samp->y, samp->pressure);

endif

return result;
}
终于可以看到,经过ts_config注册到的读取坐标的函数了。整个过程结束之后,会把读取到的坐标信息,写到cal对应的成员里面。calibrate结构体的定义如下:
typedef struct {
int x[5], xfb[5];
int y[5], yfb[5];
int a[7];
} calibration;可以看到就是定义的坐标信息。xfb这个是显示器的坐标。

get_sample (ts, &cal, 1, xres - 50, 50, “Top right”);
get_sample (ts, &cal, 2, xres - 50, yres - 50, “Bot right”);
get_sample (ts, &cal, 3, 50, yres - 50, “Bot left”);
get_sample (ts, &cal, 4, xres / 2, yres / 2, “Center”);

if (perform_calibration (&cal)) {
这里进行
</pre><pre name="code" class="cpp">     printf ("Calibration constants: ");
    for (i = 0; i < 7; i++) printf("%d ", cal.a [i]);
    printf("\n");
    if ((calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
        cal_fd = open (calfile, O_CREAT | O_RDWR, 777);
    } else {
        cal_fd = open ("/etc/pointercal", O_CREAT | O_RDWR, 777);
    }
    sprintf (cal_buffer,"%d %d %d %d %d %d %d",
         cal.a[1], cal.a[2], cal.a[0],
         cal.a[4], cal.a[5], cal.a[3], cal.a[6]);
    write (cal_fd, cal_buffer, strlen (cal_buffer) + 1);
    close (cal_fd);
            i = 0;
} else {
    printf("Calibration failed.\n");
    i = -1;
}

close_framebuffer();
return i;

}
到此整个流程就结束了。我只是罗列了一下tslib校准的流程。是我当前分析源码的记录总结。
欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值