tslib 代码分析1

来源:互联网 发布:房卡棋牌游戏源码教程 编辑:程序博客网 时间:2024/06/04 19:56
------------------------------------------------------------
author: hjjdebug
date: 2015年 10月 19日 星期一 17:21:49 CST
------------------------------------------------------------
tslib 代码分析

序言1:tslib 是开源软件,c 语言写成,架构完美,值得阅读。
序言2:程序是用来处理数据的, 那么,tslib 也不会例外,它处理的数据,就是ts设备
读出的数据,那么我们看它怎么处理。

分析实例: 本篇先分析ts_print_raw, ts_print 应用程序
************************************************************
一: ts_print_raw  例子
************************************************************
程序非常简短,就是
struct tsdev *ts_open(char *devname),
tsconfig(struct tsdev *ts),
ts_read_raw(struct tsdev *ts, struct ts_sample *sample int nr),

后面就要分别解释这三句了。
1. 打开一个ts设备,
分配一个tsdev 结构,打开传递的设备名称就可以了。

************************************************************
2. 配置这个ts设备
************************************************************
----------------------------------------
2.1:打开ts的配置文件,
----------------------------------------
2.1.1: 这个文件的名称是由环境变量TSLIB_CONFILE 提供
    如果环境变量为空,就用程序默认的。
2.1.2: 配置文件有特定的格式,有空格和tab 分割为域,
    第一个域只能是module,或module_raw 关键字,后面的为名称和参数。
2.1.3:分析配置文件,
    然后通过ts_load_module(ts,module_name,param) 或者ts_load_module_raw 来把模块加载到内存,
    并配置ts 结构变量
    其中module_raw 是必须要有的。

----------------------------------------
2.2: 细看 static int __ts_load_module(struct tsdev *ts, const char *module, const char *params, int raw)
----------------------------------------
2.2.1: 目的,ts_load_module 还是为了构建ts设备结构,
    它首先是进行静态构建,若不成功再进行动态构建,
    成功后,将module信息与ts设备相关联。
2.2.2: 静态构建module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.2.1: 什么是module,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
每一个module,是由一个module 名称和module 初始化函数构成的,
静态构建就是预先定义好了modules 变量,现在根据传来的module 名称,搜索这个表,找到对应的初始化函数,
调用这个初始化函数,初始化函数会返回module结构指针。
static const struct {
    const char *name;
    tslib_module_init mod_init;
} tslib_modules[] = {};

具体的module 是由tslib_modules来定义的, 可惜,我们一个module 都没有定义。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.2.2: module初始化函数是什么?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
现在即没有具体的module, 也没有具体的初始化函数,但它们必须符合一定规范。初始化函数是这样的一个函数原型.
typedef struct tslib_module_info *(*tslib_module_init)(struct tsdev *dev, const char *params);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.2.3: module_info 是什么?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module_info 被定义为一个链表,有next 指针,保留有ts设备地址,动态加载库handle,还有一项为option 指针
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;
};

该option 指针指向2个函数指针,一个read, 一个finishi
struct tslib_ops {
    int (*read)(struct tslib_module_info *inf, struct ts_sample *samp, int nr);
    int (*fini)(struct tslib_module_info *inf);
};



----------------------------------------
2.2.3: 动态构建module.
----------------------------------------
动态构建module 是通过加载动态链接库来完成的,它有很多优点,例如可以只加载所需要的module, 不使用的不加载。
要不怎么叫动态加载呢!
2.2.3.1: 动态加载module 到内存。
是的,传来的模块的名字就是要加载的动态库的名字,通过dlopen来加载。通过dlsym找到module 初始化入口函数,
执行它,返回module 指针。

2.2.3.2: 什么是架构
现在一个具体的module 都没有,怎么就开始写出代码了(ts_load_module.c), 是的,这就叫架构,它要求将来要写的代码
必须符合一定的规范,才能被已经生成的代码所认识。并为先前的代码所管理。
tslib模块的架构要求, 每个模块要有一个初始化函数,动态库的导出函数叫:mod_int
这就叫接口,是代码控制与实现的剥离。

----------------------------------------
2.2.4: 看一个具体的module, input.so.
----------------------------------------
对应的代码plugin下input-raw.c

2.2.4.1: 定义mod_init 符号
typedef struct tslib_module_info *(*tslib_module_init)(struct tsdev *dev, const char *params);
#define TSLIB_MODULE_INIT(f) TSAPI tslib_module_init mod_init = &f
TSLIB_MODULE_INIT(input_mod_init);
2.2.4.2: input_mod_init.
架构在load module 后执行input_mod_init 函数,该函数申请了一块内存
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.4.2.1: 申请tslib_input 内存
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
i = malloc(sizeof(struct tslib_input));
i->module.ops = &__ts_input_ops;
    
其中tslib_input 是包含 tslib_module_info 的结构, 它还有自己专有的属性,开始均初始化为0

struct tslib_input {
    struct tslib_module_info module;

    int    current_x;
    int    current_y;
    int    current_p;

    int    sane_fd;
    int    using_syn;
    int    grab_events;
};

static const struct tslib_ops __ts_input_ops = {
    .read    = ts_input_read,
    .fini    = ts_input_fini,
};

module.ops 也已赋值,这样以后可以通过结构指针调用到ts_input_read, ts_input_fini函数

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.4.2.2: 存储tslib_input 专有属性的数值
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ts_lib 库还提供了一个功能,分析变量函数
库: tslib_parse_vars(&i->module, raw_vars, NR_VARS, params)
它负责
把param赋值语句分割为左部和右部,然后
搜索给定的表,与左部匹配,调用表的对应函数,为该函数传递右部数据
查找的函数可能把配置的数据,存储到模块子类的属性中。
plugin:
static const struct tslib_vars raw_vars[] =
{
    { "grab_events", (void *)1, parse_raw_grab },
};
库:
struct tslib_vars {
    const char *name;
    void *data;
    int (*fn)(struct tslib_module_info *inf, char *str, void *data);
};
plugin:
static int parse_raw_grab(struct tslib_module_info *inf, char *str, void *data)
{
    struct tslib_input *i = (struct tslib_input *)inf; //指针强制转化为子类型
    根据字符串和数据,将数据存入module 的扩展属性中。

}

2.2.4.3: ts_input_read
就是从设备读取一个完整事件数据,然后根据ev.type,ev.code,ev.value 来保存其数据
2.2.4.4: ts_input_fini
fini 就是释放内存.


----------------------------------------
2.2.5: 具体的module, pthres.so
----------------------------------------
对应的代码plugin下pthres.c
看来代码我才知道,这是压力阈值的意思。
直接看pthres_read 函数, 压力比设定最小值小,或比设定最大值大,忽略之

----------------------------------------
2.2.6: 具体的module, variance.so
----------------------------------------
方差判定上次移动是否为噪声的依据是,两次的移动距离超过了delta,可能是噪声
如果两次都超过,则不是噪声,而是快速移动。
----------------------------------------
2.2.7: 具体的module, degitter.so
----------------------------------------
去抖动是把最多4个取值按照一定的权重重新计算来返回结果
参数delta 的含义:
----------------------------------------
2.2.8: 具体的module, linear.so
----------------------------------------
它吧读到的数据,与屏幕矫正的值进行了缩放
samp->x = samp->x * info->dev->res_x / lin->cal_res_x;

************************************************************
二: ts_print  代码
************************************************************
与 ts_print_raw 是一样的分析
只是一个调用ts_read_raw, 一个调用ts_read.
ts_read_raw 只有一层,不会返回给其他module.
ts_read,则是->linear->degitter->variance->pthres->read_raw 这个链来处理数据
0 0
原创粉丝点击