嵌入式Linux系统的电子书阅读器项目4——Input Event System
来源:互联网 发布:中国古代名菜 知乎 编辑:程序博客网 时间:2024/06/05 19:39
1.输入事件系统(Input EventSystem)架构与API
1). 输入事件系统框架设计
输入事件系统的框架如图1所示。
图1输入事件系统框架
类似其它几个子系统,输入事件子系统也是采用一个核心层+可装载组件的模式,
并且将底层实际输入设备(如 touchscreen)
所产生的原始数据(raw input data)封装层格式化的输入事件(input event)提供给Book Engine访问。
这样就隐藏了事件输入设备的复杂性与多样性。作为一个学习型项目,在输入事件系统的核心函数采用
可配置的多种实现方法,可让爱好者学习比较各种方法的优劣。
2).输入事件系统框架API概述
input eventsystem 的API声明位于include/myinpu.h头文件中。
输入事件 input_ev:
输入事件的封装结构声明如下
typedef structinput_ev { struct timeval time; int type; /* stdin, touchsceen */ int val; /* */}input_ev;
time——事件发生的系统时间
type——判断是哪个具体设备产生的输入事件(目前只有 stdin/touchscreen),相关的宏值如下:
#defineINPUT_TYPE_STDIN 0#defineINPUT_TYPE_TSC 1
val——经过抽象化的输入事件值,目前支持以下几个宏值:
#defineINPUT_VAL_UP 0 #defineINPUT_VAL_DOWN 1#defineINPUT_VAL_EXIT 2#defineINPUT_VAL_UNKNOWN -1该值是输入设备(inputdev)通过获取原始输入值(如键盘“U”、"N"、touchscreen的向右滑动10%x坐标)
经过设备模块组件内部的get_input_ev()对原始值进行逻辑处理和转换,提交给input event system core层的。
INPUT_VAL_UP——表示向上翻页事件,INPUT_VAL_DOWN——表示向下翻页事件,INPUT_VAL_EXIT——
表示退出电子书事件,INPUT_VAL_UNKNOWN——表示获取了未知值,需要异常处理。
这样就把底层输入设备不同的输入特性和采用值封装起来,提供了统一的抽象input event接口。
核心描述符 input_dev:
核心描述符声明如下,
typedef structinput_dev{ char *name; union input_method mthd; int (*init_dev)(void); int (*exit_dev)(void); int (*get_input_ev)(struct input_ev*pev); struct input_dev *next;}input_dev;mthd是一个联合体,根据不同是输入策略(如select机制,多线程等)实际实现方法,根据配置,由宏开关隔开,
根据实际需要配置成select文件描述符,或者多线程下的线程id。
next:
系统所加载的input_dev列表,注意,加载的输入设备不一定被激活使能。
加载之后,只有通过enable_input_dev_set()函数使能的设备,才能产生输入响应。
init_dev() 与 exit_dev():
实际输入设备的初始化与退出函数,需要根据设备的特性在不同输入设备组件函数中实现,
在enable_input_dev_set()与 disable_input_dev_set()函数中被调用。
get_input_ev():
实际输入设备组件的输入事件获取函数,将原始输入值经过一点逻辑处理,转换成input_ev
然后提交给input eventsystem core层。
get_rt_input_ev():
该API被用户调用,获取input_ev()的。它会从所有被enble的input dev中探测是否有输入事件产生,
然后返回结果,不同实现方法的差异,在下一节再叙述。
enable_input_dev_set()与 disable_input_dev_set():
该对函数根据输入参数列表中input dev的name使能/关闭输入加载到系统中的input_dev,只有使能的
input dev才会有输入响应。
3).输入事件系统函数多种实现方法比较
input eventsystem 的函数实现位于myinput/myinput.c文件中。
其它函数和之前的系统类似,都是链表相关的加载,调试操作,最重要的函数是get_rt_input_ev()
get_rt_input_ev()的实现方法:
轮询(query)方法:
轮询方法的get_rt_input_ev()函数实现方法如下。它是轮流调用各个输入设备的get_input_ev()函数,
有输入事件发生,返回0表示成功,否则query完所有设备之后,没有任何输入事件,则返回-1。
int ret; struct input_dev *tmp_dev = idev_h; while(tmp_dev){ //printf("use inputdev: %s\n",tmp_dev->name); if(tmp_dev->get_input_ev(pev)== 0) return 0; tmp_dev =tmp_dev->next; } return -1;该方法,适合单个enable输入设备进行初次项目验证与调试。主要缺点有:
1.CPU占用率高(轮询的老毛病)
2.当不同input_dev的get_input_ev()函数实现机制不同时(如stdin采用非阻塞机制,而tscreen设备用阻塞机制),
则容易导致非阻塞机制的设备处于饥饿状态,电子书应用进程会阻塞在tscreen设备直到获取输入值,
这样stdin设备的输入将得不到响应。这样,上层接口就得考虑底层组件的实现机制。
所以这并不是正式release项目的一个好机制,只是做初次调试而已。
Select 机制:
select机制的get_rt_input_ev()函数实现方法如下。它在每个input_dev组件的init_dev()函数的实现中,将设备描述符fd
加入了input event system core的fd_set中,来通过select机制查询input_ev是否发生。
int ret; struct input_dev *tmp_dev = idev_h; fd_set tmp_rd_set = idev_fd_set; ret = select(max_fd_val,&tmp_rd_set, NULL, NULL, NULL); if(ret > 0){ while(tmp_dev){ if(FD_ISSET(tmp_dev->mthd.fd,&tmp_rd_set)) if(tmp_dev->get_input_ev(pev)== 0) return0; tmp_dev =tmp_dev->next; } } return -1;采用select机制,就能解决轮询(query)方法中所叙述的2个问题,不管底层input_dev的get_input_ev()函数如何实现,
只要select函数中的tmp_rd_set集中的描述符有输入事件发生,则select函数将返回,而不会产生一个设备处于饥饿状态。
但是该方法也有缺点——使得电子书应用进程在select函数处阻塞,影响系统整体效率。
多线程机制:
多线程机制的get_rt_input_ev()函数实现方法如下,它为每个输入设备在每个input_dev组件的init_dev()时,开启一个线程,
然后在用户调用get_rt_input_ev()函数时,等待产生input_ev的线程提交条件信号,然后去获取该input_dev所产生的input_ev的值。
pthread_mutex_lock(&input_mutex); pthread_cond_wait(&input_cond,&input_mutex); memcpy(pev, &sh_iev,sizeof(struct input_ev)); pthread_mutex_unlock(&input_mutex); return 0;
采用多线程的方法,CPU占用较低,处理相对高效,也不会出现某设备由于实现机制而产生的饥饿问题。
2.输入事件系统(Input EventSystem)模块组件
1). stdin dev
stdin_dev 组件的实现的源代码在myinput/stdin_dev.c文件中。类似于其它子系统,stdin_dev主要也是填充
实现核心input_dev描述符,实现填充代码如下:
static structinput_dev stdin_dev = { .name = "stdin_dev", .init_dev = init_stdin_dev, .exit_dev = exit_stdin_dev, .get_input_ev =get_stdin_dev_ev,};init_stdin_dev():
由于stdin_dev设备主要是利用tty终端的标准输入stdin关联键盘的"U"/"N"/"Q"三键控制翻页与结束,
该函数作为stdin_dev的初始化函数,首选要把终端的标准输入stdin设置为non-canon模式,缓冲设为最小。
这个函数所使用的Linux系统终端相关的函数和结构的用法细节,可以参考《Unix环境高级编程一书》。
exit_stdin_dev():
该函数也是调用Linux系统终端相关API,将终端tty的状态恢复正常模式。
get_stdin_dev_ev():
该函数获取终端stdin的原始输入,并把如果遇到U/N/Q三个键输入,则input_ev的val值设为对应的
INPUT_VAL_UP/INPUT_VAL_DOWN/INPUT_VAL_EXIT,然后将输入事件提交给input system core。
2). touchscreen
Smart210 开发板触屏特性与使用方法:
Smart210 开发板触屏是7寸多点触控电容触屏,而不是@韦东山老师视频里用的电阻屏。并且,由于Smart210
使用了goodix公司非开源的电容触屏驱动,用过一个叫onewire的驱动,封装了触摸屏的event输入事件,因而韦东山
老师的源代码,需要一定修改才能在在Smart210开发板上使用。
Smart210 开发板的原版文件系统(Linux 3.0.8内核),其实在usr/lib 和 usr/lib/ts已经安装好了tslib的库,交叉工具链中也有tslib相关头文件,
它的库与原版的tslib的差异截图如下:
图2 Smart210 tslib环境变量的差异
图3 Smart210 tslib ts.config 差异
图4 Smart210 tslib 动态链接库 lib/ts 下的文件差异
图2所示为Smart210 开发板tslib相关环境的配置,注意红线处,Smart210 所用的 TSLIB_TSDEVICE 不是 通常的/dev/input/event* ,
而应该是goodix芯片电容触屏1wire模式的的专用非开源驱动设备。
图3 是ts.config 的差异,其中黄线处,module_raw 所用的库,和韦东山视频里配置的不同,Smart210 开发板有专门为它的触摸屏
设备在应用层封装了一个底层驱动使用的库,该库所在路径如图4黄线所示。该库是tslib原版代码编译出来所没有的。
Smart210 开发板只有使用了该配置,配对了相关的device和module_raw,应用层程序才能正常获取数据工作,
以上就是Smart210 电容触屏和韦东山视频里JZ2440 电阻屏配置上有差异的部分。
touchsreen模块组件的实现
touchsreen模块组件在 myinput/tscreen.c文件中实现。该组件使用了开源的tslib触摸屏库,相关源代码可以在 tslib开源库代码下载 下载到。
tslib的需要先安装配置,相关的教程可以参考这篇文章tslib编译安装方法 。
touchsreen组件也需要填充input_dev结构体,其中 init_tscreen_dev()主要是调用tslib的API进行相关的初始化,可以参考
API使用教程。
get_tscreen_ev():
该函数获取touchscreen的原始输入数据(raw input),并将其转换为input_ev对应的值,然后提交。
input_ev事件的与触屏输入的关系如图5所示
图5 input_ev与触屏动作的对应关系
通过图5可知,该函数将向左滑动10%触屏x轴横坐标定义为向上翻页,向右滑动10%定义为向下翻页。该函数即处理相关逻辑,并判断手是否一直在触屏之上,有无中途离开。is_out_of_time()函数则是用来延时消除抖动等误操作。
- 嵌入式Linux系统的电子书阅读器项目4——Input Event System
- 嵌入式Linux系统的电子书阅读器项目2——Display System
- 嵌入式Linux系统的电子书阅读器项目3——Encode & Font System
- 嵌入式Linux系统的电子书阅读器项目1——Overview
- 开源的电子书阅读器项目
- 开源的电子书阅读器项目
- ios 开源的电子书阅读器项目
- 开源的电子书阅读器项目
- 开源的电子书阅读器项目
- ios 开源的电子书阅读器项目
- Android的Event Input System
- 可用于电子书阅读器的开源阅读器软件项目
- SONY的电子书阅读器
- 图解Android - Android GUI 系统 (5) - Android的Event Input System
- 图解Android - Android GUI 系统 (5) - Android的Event Input System
- 基于MiniGUI的电子书阅读器
- 开源的电子书阅读器
- 嵌入式系统设计电子书
- 关于系统调用(一)
- 快速选择SELECT算法的深入分析与实现
- Intent 传值和 Bundle传值的区别
- Python下载网页所有图片
- LeetCode 1 Two Sum
- 嵌入式Linux系统的电子书阅读器项目4——Input Event System
- HDOJ 1789 Doing Homework again
- 图解Android事件传递之ViewGroup篇
- 王爽前辈汇编语言第三版PDF下载
- 11.、关联规则算法
- 11.1、关联规则实例
- fileupload上传文件技术
- fragment的使用
- 11.2、关联规则实例