Skip to content

LV015-按键实例

一、功能分析

这一部分,我们编写一个应用程序,获取按键状态, 判断按键当前是按下、松开或长按状态。从上一节笔记中的打印信息可知,对于按键来说,它的事件上报流程如下所示(以字母 A 键为例):

(1)KEY_A :上报 KEY_A 事件

(2)SYN_REPORT :同步

如果是按下,则上报 KEY_A 事件时, value = 1;如果是松开,则 value = 0;如果是长按,则 value = 2。

二、代码实例

c
#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. 开发板自带的按键

image-20240922071435579

运行程序之后,按下 KEY0 或松开 KEY0 以及长按情况下,终端会打印出相应的信息,code = 114(KEY_VOLUMEDOWN 按键)。

2. 电脑键盘

正点原子 出厂系统 带有各种驱动,支持键盘的识别,连接到开发板的 USB HOST 接口上,当键盘插入之后,终端将会打印出相应的驱动加载信息:

image-20240922071822793

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

image-20240922072031507

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

QQ_1726961419688

我们可以通过 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 对应的是 空格 键。

c
#define KEY_A			30
#define KEY_D			32
#define KEY_C			46
#define KEY_B			48
#define KEY_SPACE		57