LV15-03-输入类设备-02-按键应用开发实例

本文主要是输入类设备控制——按键应用开发实例的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.2的64位版本
VMware® Workstation 17 Pro 17.6.0 build-24238078
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
Linux开发板环境 Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
其他网站 kernel - Linux source code (v4.15) - Bootlin linux内核源码在线查看
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
https://elixir.bootlin.com/linux/latest/source 在线阅读linux kernel源码
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)

一、功能分析

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

(1)KEY_A :上报 KEY_A 事件

(2)SYN_REPORT :同步

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

二、代码实例

1. 代码编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#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 对应的是 空格 键。

image-20240922073809426