Linux下struct input_event结构体详解
2026/9/24 12:09:16 网站建设 项目流程

4.4 触控屏应用接口

4.4.1 输入子系统简介

连接操作系统的输入设备,可不止一种,也许是一个标准 PS/2 键盘,也许是一个 USB鼠标,或者是一块触摸屏,甚至是一个游戏机摇杆, Linux 在处理这些纷繁各异的输入设备的时候,采用的办法还是找中间层来屏蔽各种细节,请看下图:

在 Linux 的内核中,对输入设备的使用,实际上运用了 3 大块来管理,他们分别是所谓的输入设备驱动层输入子系统核心层,以及事件触发层。他们各自的工作分别是:

1,输入设备驱动层:

每一种设备都有其特定的 驱动程序 ,他们被妥当地装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。

2,核心层:

此处将收集由设备驱动层发来的数据,整合之后触发某一事件。
3,事件触发层:
这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件来获知某设备的某一个动作。在最靠近应用程序的事件触发层上,内核所获知的各类输入事件,比如键盘被按了一下,触摸屏被滑了一下等,都将被统一封装在一个叫做 input_event 的结构体当中,这个结构体定义如下:

(/usr/inlucde/linux/input.h) vincent@ubuntu:/usr/inlucde/linux/$ cat input.h -n 1 #ifndef _INPUT_H 2 #define _INPUT_H 3…… 20 21 struct input_event { 22 struct timeval time; 23 __u16 type; 24 __u16 code; 25 __s32 value; 26 }; 27……

该结构体有 4 个成员,其含义分别如下:
一、time:输入事件发生的时间戳,精确到微秒。时间结构体定义如下:

struct timeval { __time_t tv_sec; // 秒 long int tv_usec; // 微秒(1 微秒 = 10-3毫秒 = 10-6秒) };

二、type:输入事件的类型。比如:
EV_SYN:事件间的分割标志,有些事件可能会在时间和空间上产生延续,比如持续按住一个按键。为了更好地管理这些持续的事件,EV_SYN 用以将他们分割成一个个的小的数据包。
EV_KEY:用以描述键盘,按键或者类似键盘的设备的状态变化。
EV_REL:相对位移,比如鼠标的移动,滚轮的转动等。
EV_ABS:绝对位移,比如触摸屏上的坐标值。
EV_MSC:不能匹配现有的类型,这相当于当前暂不识别的事件。比如在 Linux系统中按下键盘中针对 Windows 系统的“一键杀毒”按键,将会产生该事件。
EV_LED:用于控制设备上的 LED 灯的开关,比如按下键盘的大写锁定键,会同时产生 ”EV_KEY” 和 ”EV_LED” 两个事件。

三、code:这个“事件的代码”用于对事件的类型作进一步的描述。比如:当发生 EV_KEY事件时,则可能是键盘被按下了,那么究竟是哪个按键被按下了呢?此时查看 code 就知道了。当发生 EV_REL 事件时,也许是鼠标动了,也许是滚轮动了。这时可以用 code 的值来加以区分。

四、value:当 code 都不足以区分事件的性质的时候,可以用 value 来确认。比如由EV_REL 和 REL_WHEEL 确认发生了鼠标滚轮的动作,但是究竟是向上滚还是向下滚呢?
再比如由由 EV_KEY 和 KEY_F 确认了发生键盘上 F 键的动作,但究竟是按下呢还是弹起呢?这时都可以用 value 值来进一步判断。
以下代码,展示了如何从触摸屏设备节点/dev/event0 中读取数据,并显示当前触摸屏的实时原始数据:

vincent@ubuntu:~/ch04/4.5$ cat ts_raw.c -``` 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdbool.h> 4 #include <unistd.h> 5 #include <string.h> 6 #include <strings.h> 7 #include <errno.h> 8 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include <fcntl.h> 12 #include <Linux/input.h> 13 14 int main(int argc, char **argv) 15 { 16 int ts = open("/dev/event0", O_RDONLY); 17 18 struct input_event buf; 19 bzero(&buf, sizeof(buf)); 20 21 while(1) 22 { 23 read(ts, &buf, sizeof(buf)); 24 25 switch(buf.type) 26 { 27 case EV_SYN: 28 printf("--------------------- SYN ------------------\n"); 29 break; 30 case EV_ABS: 31 printf("time: %u.%u\ttype: EV_ABS\t", 32 buf.time.tv_sec, buf.time.tv_usec); 33 switch(buf.code) 34 { 35 case ABS_X: 36 printf("X:%u\n", buf.value); 37 break; 38 case ABS_Y: 39 printf("Y:%u\n", buf.value); 40 break; 41 case ABS_PRESSURE: 42 printf("pressure:%u\n", buf.value); 43 } 44 } 45 } 46 return 0; 47 }

c运行

注意,以上代码打印出来的是直接从触摸屏读取的原始数据(raw data),没有经过任何校正,也没有任何滤波、去抖、消噪,因此这些数据是不能直接给应用层程序使用的,但是不用担心,这些繁琐复杂的工作已经有了很成熟的库支持了,但是有一个TSLIB 库,就是这样一个开源的、能为触摸屏获得的原始数据提供诸如滤波、去抖、消噪和校正功能的库,TSLIB 作为触摸屏驱动的适配层,为上层的应用提供了一个统一的编程接口,将使得我们编写基于触摸屏的应用更加简便。

Linux下struct input_event结构体详解_怎么使用粤嵌开发板触摸屏幕-CSDN博客

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询