ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Linux下struct input_event结构体详解

2026/9/24 12:09:47 拓冰建站 浏览量
Linux下struct input_event结构体详解 4.4 触控屏应用接口4.4.1 输入子系统简介连接操作系统的输入设备可不止一种也许是一个标准 PS/2 键盘也许是一个 USB鼠标或者是一块触摸屏甚至是一个游戏机摇杆 Linux 在处理这些纷繁各异的输入设备的时候采用的办法还是找中间层来屏蔽各种细节请看下图在 Linux 的内核中对输入设备的使用实际上运用了 3 大块来管理他们分别是所谓的输入设备驱动层、输入子系统核心层以及事件触发层。他们各自的工作分别是1输入设备驱动层每一种设备都有其特定的 驱动程序 他们被妥当地装载到操作系统的设备模型框架内封装硬件所提供的功能向上提供规定的接口。2核心层此处将收集由设备驱动层发来的数据整合之后触发某一事件。3事件触发层这一层是我们需要关注的我们可以通过在用户空间读取相应设备的节点文件来获知某设备的某一个动作。在最靠近应用程序的事件触发层上内核所获知的各类输入事件比如键盘被按了一下触摸屏被滑了一下等都将被统一封装在一个叫做 input_event 的结构体当中这个结构体定义如下(/usr/inlucde/linux/input.h) vincentubuntu:/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 中读取数据并显示当前触摸屏的实时原始数据vincentubuntu:~/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博客