Linux Input 事件读取与解析
事件通路
Linux Input 子系统将按键、键盘、鼠标和触摸屏等设备上报的数据组织为输入事件。evdev 接口通过 /dev/input/eventX 向用户空间提供这些事件。
text
输入设备 → 设备驱动 → Input 子系统 → evdev → /dev/input/eventX → 应用程序设备发现
bash
ls -l /dev/input/
cat /proc/bus/input/devices
grep -E 'Name|Handlers' /proc/bus/input/devicesName 描述设备,Handlers 列出对应处理器与 event 节点。节点编号可能随注册顺序变化,应先确认映射,不要直接假定 event0 始终为同一设备。
text
N: Name="20cc000.snvs:snvs-powerkey"
H: Handlers=kbd event0
N: Name="goodix-ts"
H: Handlers=event1
N: Name="gpio_keys@0"
H: Handlers=kbd event2struct input_event 与事件含义
包含 <linux/input.h> 后使用系统提供的 struct input_event,不要自行假定结构体的字节长度或重定义时间字段。
| 字段 | 含义 |
|---|---|
| time | 事件时间信息,布局以目标系统头文件为准 |
| type | 事件类型,如 EV_KEY、EV_REL、EV_ABS、EV_SYN |
| code | 类型内的具体编号,如 KEY_ENTER、KEY_POWER、ABS_X |
| value | 对应事件值,解释方式取决于 type 和 code |
对于 EV_KEY,value 为 0 表示松开,1 表示按下,2 表示自动重复。判断指定按键应同时检查 type 与 code:
c
if (ev.type == EV_KEY && ev.code == KEY_ENTER) {
if (ev.value == 1) {
printf("KEY_ENTER pressed\n");
} else if (ev.value == 0) {
printf("KEY_ENTER released\n");
}
}EV_SYN / SYN_REPORT 标记一组事件的同步边界。一次按下与松开操作可能产生以下事件序列:
text
EV_KEY KEY_ENTER 1
EV_SYN SYN_REPORT 0
EV_KEY KEY_ENTER 0
EV_SYN SYN_REPORT 0读取接口与阻塞行为
未设置非阻塞模式时,read() 通常等待事件可读后返回。返回值是字节数;缓冲区足够大时,一次可以接收多个事件。程序应检查错误、零返回和读取长度,再按 sizeof(struct input_event) 解析。
C 语言事件读取示例
以下保留单事件读取示例。运行前将节点改为实际设备,并确认读取权限。示例没有处理所有退出场景;生产代码还应区分 EINTR、设备断开和非阻塞返回。
c
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int fd;
ssize_t ret;
struct input_event ev;
fd = open("/dev/input/event0", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
while (1) {
ret = read(fd, &ev, sizeof(ev));
if (ret < 0) {
perror("read");
break;
}
if (ret != sizeof(ev))
continue;
printf("type=%u code=%u value=%d\n",
ev.type,
ev.code,
ev.value);
}
close(fd);
return 0;
}bash
gcc -Wall -Wextra input_read.c -o input_read
./input_read输出形式如下,数值用于说明事件含义,不代表目标板的实测日志:
text
type=1 code=28 value=1
type=0 code=0 value=0
type=1 code=28 value=0
type=0 code=0 value=0验证与常见问题
- 无输出:确认选择的设备是否产生事件,区分正常阻塞与设备选错。
- 打开失败:记录错误码,检查节点存在性和权限。
- 收到多个事件:按结构体大小逐条解析,并使用 SYN_REPORT 确认事件分组。
- 键值不符:先记录 type、code、value,再确认设备实际使用的按键或坐标编码。
本文说明接口与示例用法,尚未附特定开发板的完整验证日志。实测时应记录设备名称、内核版本、操作动作与对应事件。
参考资料
- Linux 内核文档:Input 子系统用户空间接口
- 目标系统头文件:
<linux/input.h>、<linux/input-event-codes.h>。
