输入设备种类繁多Linux 系统为了统一管理这些输入设备,实现了一套能兼容所有输入设备的框架:input 子系统,使用 input 子系统驱动的输入设备可以通过统一的数据结构提交给内核,该数据结构包括输入的时间、类型、代号以及具体的键值或坐标,而内则通过/dev/input 目录下的文件接口传递给用户空间。通过下面的命令可以查看当前系统支持的输入设备
- cat /proc/bus/input/devices
这个开发板上有两个按键,当按键有动作时会产生输入事件,通过读取/dev/input/event0就能知道哪个按键产生了什么样的动作。在开发 input 子系统驱动时,常常会使用 evtest 工具进行测试,运行 evtest 工具,它列出了系统当前可用的/dev/input/event0输入事件文件,并且列出了这些事件对应的设备名,点击按键可以看到如下输出
在内核源码的/include/uapi/linux/input.h 文件中有着输入事件的结构体定义
- struct input_event {
- struct timeval time;
- __u16 type;
- __u16 code;
- __s32 value;
- };
time:该变量用于记录事件产生的时间戳,既 evtest 输出的 time 值
type:输入设备的事件类型。系统常用的默认类型有 EV_KEY、 EV_REL 和 EV_ABS,分别用于表示按键状态改变事件、相对坐标改变事件及绝对坐标改变事件, EV_SYN 用于分隔事件,无特别意义。
code:事件代号,它以更精确的方式表示事件。例如在 EV_KEY 事件类型中, code 的值常用于表示键盘上具体的按键
value:事件的值。对于 EV_KEY 事件类型,当按键按下时,该值为 1;按键松开时,该值为 0
/dev/input/event*的事件编号与设备的联系不是固定的,它通常按系统检测到设备的先后顺序安排 event 文件的编号,这对编写应用程序控制不太方便,我们可以通过/dev/input/by-path目录查看具体的硬件设备
编程实现通过按键切换LED状态
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <linux/input.h>
- #include <linux/input-event-codes.h>
- #define KEY_PATH "/dev/input/by-path/platform-gpio-keys-event"
- #define LED_PATH_BRI "/sys/class/leds/blue:heartbeat/brightness"
- int main(int argc,char **argv)
- {
- int keyfd,ledfd;
- u_int8_t ledstate = 0;
- struct input_event event;
- keyfd = open(KEY_PATH,O_RDONLY);
- if(keyfd < 0)
- {
- printf("input event open failed\n");
- return -1;
- }
- ledfd = open(LED_PATH_BRI,O_RDWR);
- if(ledfd < 0)
- {
- printf("led file open failed\n");
- return -1;
- }
- while(1)
- {
- if(read(keyfd, &event, sizeof(event)) == sizeof(event))
- {
- if(event.type != EV_SYN)
- {
- printf("input event code:%d value:%d\n",event.code,event.value);
- if(event.code == BTN_1 && event.value == 0)
- {
- ledstate = !ledstate;
- write(ledfd,ledstate==0?"0":"1",1);
- }
- else if(event.code == KEY_WAKEUP && event.value == 0)
- break;
- }
- }
- }
- close(keyfd);
- close(ledfd);
- printf("test finish\n");
- return 0;
- }
运行效果
|