11. 输入检测¶
本章介绍在Android中使用gpio-keys驱动将GPIO配置为按键并进行检测。
gpio-keys驱动是Linux内核为通过GPIO引脚连接的按键设备设计的通用驱动,属于输入子系统的一部分。 其核心作用是:监测GPIO引脚的电平变化(高/低电平切换),将其转换为输入子系统可识别的按键事件(如KEY_PRESS、KEY_RELEASE),并上报给用户空间,最终被应用程序捕获处理。
11.1. 配置引脚¶
参考“40pin引脚对照图”章节,查看需要使用的GPIO引脚, 修改设备树源码来进行配置,并重新编译镜像。
如果对设备树不熟悉的用户,请学习野火配套的《嵌入式Linux驱动开发实战指南》的 Linux设备树 章节内容。
以使能LubanCat-4-V1的GPIO4_A0为例,修改SDK源码/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s-lubancat-4-v1.dtsi (其他板卡修改板卡对应的设备树),在设备树中添加以下节点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | gpio_keys: gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
status = "okay";
//autorepeat;
Key0{
label = "KEY_0";
linux,code = <KEY_0>;
gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_LOW>;
pinctrl-0 = <&button_key0_pin>;
interrupt-parent = <&gpio4>;
interrupts = <RK_PA0 IRQ_TYPE_EDGE_FALLING>;
};
};
&pinctrl {
keys {
button_key0_pin: button-key0-pin {
rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
};
|
linux,code 中的事件可从内核中的linux-event-codes.h或者rk-input.h中选择,需确认dtsi引用的是linux-event-codes.h还是rk-input.h。
如果按键按下电平为高,可将gpios设置为GPIO_ACTIVE_HIGH,interrupts设置为IRQ_TYPE_EDGE_RISING,button_key0_pin设置为pcfg_pull_none或者pcfg_pull_down。
修改为如下图所示,如果与其他节点冲突需关闭冲突节点再添加:


参考 编译 Android 镜像 章节重新编译镜像并将编译出来的镜像烧录到板卡。
11.2. 检查事件注册¶
可以通过getevent命令查看系统事件注册情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #连接shell终端
adb shell
#检查系统event
getevent
#信息输出如下
add device 1: /dev/input/event4
name: "adc-keys"
add device 2: /dev/input/event2
name: "headset-keys"
add device 3: /dev/input/event5
name: "gpio-keys"
add device 4: /dev/input/event0
name: "febd0030.pwm"
add device 5: /dev/input/event1
name: "rk805 pwrkey"
add device 6: /dev/input/event3
name: "rockchip-es8388 Headset"
|
其中name为gpio-keys的event就是我们添加的GPIO按键,对应/dev/input/event5。
11.3. 使用shell命令检测按键¶
可以通过getevent命令检测系统事件上报,将选定的GPIO引脚接按键或者杜邦线 分别短接 到板卡40pin 3.3V和GND模拟按键按下松开。
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 | #连接shell终端
adb shell
#检查系统event
getevent
#以上gpio-keys对应的event为5,所以输入5进行选择,然后按回车
5
#按下按键或者杜邦线分别短接40pin 3.3v和GND
#信息输出如下
130|rk3588s_lubancat_4_v1_mipi1080p:/ $ getevent
add device 1: /dev/input/event3
name: "rockchip-es8388 Headset"
add device 2: /dev/input/event2
name: "headset-keys"
add device 3: /dev/input/event5
name: "gpio-keys"
add device 4: /dev/input/event1
name: "rk805 pwrkey"
add device 5: /dev/input/event0
name: "febd0030.pwm"
add device 6: /dev/input/event4
name: "adc-keys"
5
/dev/input/event5: 0001 000b 00000001
/dev/input/event5: 0000 0000 00000000
/dev/input/event5: 0001 000b 00000000
/dev/input/event5: 0000 0000 00000000
|
11.4. 使用安卓应用检测按键¶
野火提供的安卓综合测试应用能很方便的检测按键。
11.4.2. 实现方式¶
参考野火应用源码ebf_android_app/app/src/main/java/com/example/ebf_android_app/ButtonDetectionActivity.java
1、视图初始化
在onCreate()中调用initViews(),获取布局中的按钮(开始检测/停止检测/清空日志)、日志文本框(eventLogTextView)和滚动视图(logScrollView)。
2、广播接收器注册
调用registerKeyEventReceiver()创建KeyEventReceiver广播接收器,并通过IntentFilter指定只接收ACTION_KEY_EVENT类型的广播。
3、按钮点击事件绑定
为 “开始检测”、“停止检测”、“清空日志” 按钮设置点击监听器,分别控制检测状态和日志显示。
4、按键事件处理
按键按下记录当前按键码(currentKeyCode)和按下时间(keyDownTime),通过KeyEvent.keyCodeToString()获取按键名称,调用appendLog()添加 “按键按下” 日志(含键码和名称)。
按键释放计算按键按下时长,调用sendKeyEventBroadcast()发送包含键码、名称和时长的广播。
5、广播通信阶段
发送广播创建ACTION_KEY_EVENT类型的Intent,通过setPackage(getPackageName())指定广播仅发送到当前应用。 向Intent中添加额外数据:键码(EXTRA_KEY_CODE)、键名(EXTRA_KEY_NAME)、按下时长(EXTRA_PRESS_DURATION)。 调用sendBroadcast()发送广播。
接收广播接收器通过onReceive()监听ACTION_KEY_EVENT广播,解析Intent中的键码、名称和时长。用appendLog()添加“接收到广播”日志,展示完整的按键事件信息。
6、资源释放
在onDestroy()中,重置isDetecting状态为false,并注销广播接收器,避免内存泄漏。
11.5. 自定义按键¶
以上测试是将按键绑定到KEY_0,按下按键等于按下键盘上的数字“0”按键,如果不希望按键影响系统,可以自定义按键在安卓hal进行绑定,可参考以下文章进行修改: