LV015-按键实例
一、功能分析
这一部分,我们编写一个应用程序,获取按键状态, 判断按键当前是按下、松开或长按状态。从上一节笔记中的打印信息可知,对于按键来说,它的事件上报流程如下所示(以字母 A 键为例):
(1)KEY_A :上报 KEY_A 事件
(2)SYN_REPORT :同步
如果是按下,则上报 KEY_A 事件时, value = 1;如果是松开,则 value = 0;如果是长按,则 value = 2。
二、代码实例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
// /proc/bus/input/devices 命令查看输入事件
int main(int argc, char *argv[])
{
int fd = -1;
struct input_event in_ev = {{0}};
/* 校验传参 */
if (2 != argc)
{
fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
exit(-1);
}
/* 打开文件 */
if (0 > (fd = open(argv[1], O_RDONLY)))
{
perror("open error");
exit(-1);
}
while(1)
{
/* 循环读取数据 */
if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event)))
{
perror("read error");
exit(-1);
}
if (EV_KEY == in_ev.type)
{
//按键事件
switch (in_ev.value)
{
case 0:
printf("code<%d>: lift\n", in_ev.code);
break;
case 1:
printf("code<%d>: press\n", in_ev.code);
break;
case 2:
printf("code<%d>: long press\n", in_ev.code);
break;
default:
break;
}
}
}
return 0;
}在循环中,调用 read()读取输入设备上报的数据, 当按键按下或松开(以及长按)动作发生时, read()会读取到输入设备上报的数据,首先判断此次上报的事件是否是按键类事件(EV_KEY),如果是按键类事件、 接着根据 value 值来判断按键当前的状态是松开、按下还是长按。
三、开发板测试
1. 开发板自带的按键

运行程序之后,按下 KEY0 或松开 KEY0 以及长按情况下,终端会打印出相应的信息,code = 114(KEY_VOLUMEDOWN 按键)。
2. 电脑键盘
正点原子 出厂系统 带有各种驱动,支持键盘的识别,连接到开发板的 USB HOST 接口上,当键盘插入之后,终端将会打印出相应的驱动加载信息:

驱动加载成功之后,可以查看下该键盘设备对应的设备节点,使用命令 "cat /proc/bus/input/devices",在打印信息中找到键盘设备的信息:

可以看到我插入的无线键盘名字为 Compx 2.4G Receiver,其实没搞懂我这个无线 USB 键盘怎么还有个鼠标的信息,不过这里我们只是用键盘,用上面的/dev/input/event3 这个节点即可,我们运行刚才的测试程序,然后按下键盘上不同的按键:

我们可以通过 input-event-codes.h - include/uapi/linux/input-event-codes.h - Linux source code v4.15 - Bootlin 头文件找到每个值对应的含义,如 code = 30 对应的是键盘上的字母 A 键, code = 48 对应的是字母 B 键, code = 46 对应的是字母 C 键, code = 32 对应的是字母 D 键, code = 28 对应的是 回车 键, code = 57 对应的是 空格 键。
#define KEY_A 30
#define KEY_D 32
#define KEY_C 46
#define KEY_B 48
#define KEY_SPACE 57