云计算百科
云计算领域专业知识百科平台

RK3566-Android11-红外遥控器按键适配

RK3566-Android11-红外遥控器按键适配

文章目录

  • 前言-需求场景
  • 一、参考资料
  • 二、需求分析
  • 三、修改文件
  • 四、实现方案
    • 配置设备树-红外客户编码和按键编码
      • 核心配置-配置客户编码
      • 配置红外按键
      • 细节说明
    • PhoneWindowManager- Framework层适配验证
  • 五、知识点扩展
    • getevent 验证是否配置了设备树映射按键
    • Framework层看是否接收并处理红外按键
      • 日志解读
      • 解决方案分析
      • PhoneWindowManager – framework层 坑点
  • 总结

前言-需求场景

产品使用的是RK3566 主控,用到了红外遥控器功能。客户拿了一个遥控器过来,让对接红外遥控器,后面就用这个遥控器码值,系统对接成功先。

遥控器资料如下: 在这里插入图片描述

一、参考资料

设置遥控器按键

LubanCat-RK3562/RK3566/RK3568系列板卡快红-外

遥控器按键事件-PhoneWindowManager-配合实现文件管理器菜单功能

MTK-Android12-适配蓝牙遥控器按键

Linux驱动-PWM-pwm输入捕获实验(二)- 字符设备-中断捕获基础知识点

二、需求分析

这里要有几个关键点:

  • 内核相关:rk 红外irq 基本用的都是pwm3 口,所以 如何保证硬件环境、系统驱动配置 这个基本功,方便排查问题
  • 设备树配置:irq 和 蓝牙遥控器配置不一样的,irq 遥控器按键映射直接配置在设备树里面的,区别于蓝牙遥控器物理映射
  • framework 层配置:不管蓝牙遥控器还是irq 遥控器,最终按键值通过底层Linux 映射传递到framework层,在framework层处理: 这一点特别关键,如何配置按键、按键如何映射、最终如何传递到framework层 都是相关知识点内容。

三、修改文件

配置红外按键码和客户编码:kernel/arch/arm64/boot/dts/rockchip/rk3568evb.dtsi
中间层直接匹配处理案件功能:frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

四、实现方案

配置设备树-红外客户编码和按键编码

路径:kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi

配置了irkey1 如下:

ir_key1 {
rockchip,usercode = <0x01FE>;
rockchip,key_table =
//<0x45 KEY_POWER>,
<0x19 KEY_BACK>,
<0x51 KEY_LEFT>,
<0x16 KEY_UP>,
<0x50 KEY_RIGHT>,
<0x1A KEY_DOWN>,
<0x10 KEY_VOLUMEDOWN>,
<0x18 KEY_VOLUMEUP>,
<0x42 KEY_BRIGHTNESSDOWN>,
<0x4A KEY_BRIGHTNESSUP>,
<0x40 KEY_POWER>,
<0x11KEY_HOMEPAGE>,
<0x13KEY_SELECT>,
<0x43KEY_MENU>,
<0x21KEY_1>,
<0x22KEY_2>,
<0x23KEY_3>,
<0x24KEY_4>,
<0x25KEY_5>,
<0x26KEY_6>,
<0x27KEY_7>,
<0x28KEY_8>,
<0x29KEY_9>,
<0x20KEY_0>,
<0x13KEY_REPLY>,
<0x0DKEY_BACKSPACE>,
<0x00 BTN_MOUSE>;
};

核心配置-配置客户编码

rockchip,usercode = <0x01FE>;

这样配置了 开机后红外遥控器自动和机器连上的,就是找这个客户编码。

假如有不同的遥控器,支持不同的遥控器,那么就多配置几个irkeyn ,然后不同的客户编码即可。

在这里插入图片描述

配置红外按键

scancodeKEY 宏值对应的物理按键 / 功能
0x19 KEY_BACK 158 返回键(逆时针箭头)
0x51 KEY_LEFT 105 左方向键
0x16 KEY_UP 103 上方向键
0x50 KEY_RIGHT 106 右方向键
0x1A KEY_DOWN 108 下方向键
0x10 KEY_VOLUMEDOWN 114 音量减
0x18 KEY_VOLUMEUP 115 音量加
0x42 KEY_BRIGHTNESSDOWN 224 亮度减
0x4A KEY_BRIGHTNESSUP 225 亮度加
0x40 KEY_POWER 116 电源键
0x11 KEY_HOMEPAGE 172 主页(房子图标)
0x13 KEY_SELECT 353 ⚠️ 见下方冲突说明
0x43 KEY_MENU 139 设置 / 菜单键(原 KEY_SETUP 改来的)
0x21~0x29 KEY_1~KEY_9 2~10 数字键 1~9
0x20 KEY_0 11 数字键 0
0x13 KEY_REPLY 232 ⚠️ 与上面 0x13 重复
0x0D KEY_BACKSPACE 14 退格 / 删除
0x00 BTN_MOUSE 272 鼠标左键

细节说明

设备树中配置的按键宏KEY 并 不一定一定会在Linux 层映射为Framework层的按键值,所以先保证宏定义没问题 哪怕Linux 映射没有回传到Framework层,那么要么补充映射、要么直接定义其它宏定义KEY 按键再在Framework层完成适配。

PhoneWindowManager- Framework层适配验证

在 interceptKeyBeforeDispatching 方法中,找一个按键和设备树中配置的对应上,做跳转系统设置的功能。

参考:遥控器按键事件-PhoneWindowManager-配合实现文件管理器菜单功能

MTK-Android12-适配蓝牙遥控器按键

系统设置的按键我们配置的就是KEYCODE_MENU 对应系统设置功能,在Framework层适配了一次而已。

if (keyCode == KeyEvent.KEYCODE_MENU) {
// modify by fangchen start
// Hijack modified menu keys for debugging features
/*final int chordBug = KeyEvent.META_SHIFT_ON;

if (down && repeatCount == 0) {
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
null, null, null, 0, null, null);
return -1;
}
}*/

Log.d(TAG,"=== KEYCODE_SETTINGS");
if (down && repeatCount == 0) {
Log.d(TAG,"===>to KEYCODE_SETTINGS");
Intent intent = new Intent(Settings.ACTION_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityAsUser(intent, UserHandle.CURRENT);
}
return 1;

// modify by fangchen end
}

五、知识点扩展

getevent 验证是否配置了设备树映射按键

如上:验证是否配置好了设备树

  • 实际验证发现即使你配置了 设置按键标准的宏KEY_SETUP 但是 Framework层并没有收到。 那解决方案两个:要么解决Linux 层内核映射传递到上层,要么写一个其它按键 在Framework层适配中转。

按了红外遥控器 物理设置按键,getevent 如下:

按了红外遥控器 物理设置按键,getevent 反馈如下:
/dev/input/event0: 0001 008d 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 008d 00000000
/dev/input/event0: 0000 0000 00000000

getevent 显示 0x008d = 十进制 141 = KEY_SETUP,说明 Linux 层设备树映射完全正常,问题出在 Android 层的 .kl 按键映射和系统处理上。

红外码 → 设备树 KEY_SETUP(141).kl 文件映射 → Android KeyEvent → 系统处理打开设置
✓ ✓ ✗ 可能缺失 ✗ 无标准处理

Framework层看是否接收并处理红外按键

先看日志:

PhoneWindowManager.java 打印日志如下:
20170804 18:34:15.583 444534 WindowManager system_server D interceptKeyTq keycode=0 interactive=true keyguardActive=false policyFlags=22000000
20170804 18:34:15.584 444533 WindowManager system_server D interceptKeyTi keyCode=0 down=true repeatCount=0 keyguardOn=false canceled=false
20170804 18:34:15.586 444533 WindowManager system_server D Unhandled key: inputToken=android.os.BinderProxy@3d008f1, title=com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher, action=0, flags=8, keyCode=0, scanCode=141, metaState=0, repeatCount=0, policyFlags=1644167168
20170804 18:34:15.586 444533 WindowManager system_server D No fallback.
20170804 18:34:15.766 444534 WindowManager system_server D interceptKeyTq keycode=0 interactive=true keyguardActive=false policyFlags=22000000
20170804 18:34:15.767 444533 WindowManager system_server D interceptKeyTi keyCode=0 down=false repeatCount=0 keyguardOn=false canceled=false
20170804 18:34:15.769 444533 WindowManager system_server D Unhandled key: inputToken=android.os.BinderProxy@3d008f1, title=com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher, action=1, flags=8, keyCode=0, scanCode=141, metaState=0, repeatCount=0, policyFlags=1644167168
20170804 18:34:15.769 444533 WindowManager system_server D No fallback.

日志解读

keyCode=0, scanCode=141
Unhandled key
No fallback.

字段值含义
scanCode=141 141 Linux 层正确上报了 KEY_SETUP,设备树没问题
keyCode=0 0 Android 层映射为 KEYCODE_UNKNOWN(未知键)
Unhandled key PhoneWindowManager 不认识这个键,没人处理
No fallback. 没有备用动作,事件直接丢弃

问题不在 PhoneWindowManager,而在它的上游 ——.kl 文件缺少 key 141 的映射。 Linux 键码 141 没有被翻译成任何 Android KEYCODE,所以传到 PhoneWindowManager 时已经是 0(UNKNOWN)了,它当然没法处理。

解决方案分析

所以这里就出现两种解决方案:

  • 解决映射问题,系统层linux kernel 层补全映射
  • 不去解决映射问题,拿一个物理按键映射其它功能在framework层映射为系统设置功能即可

PhoneWindowManager – framework层 坑点

即使你完成了映射功能,那么PhoneWindowManager 有没有实际功能也要确认的。 实际发现framework层 PhoneWindowManager 的 interceptKeyBeforeDispatching 方法中根本没有 KEYCODE_SETTINGS 的执行功能,那么先补充这个功能先如果采用方案一底层解决Linux 映射问题。

if (keyCode == KeyEvent.KEYCODE_SETTINGS) {

Log.d(TAG,"=== KEYCODE_SETTINGS");
if (down && repeatCount == 0) {
Log.d(TAG,"===>to KEYCODE_SETTINGS");
Intent intent = new Intent(Settings.ACTION_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityAsUser(intent, UserHandle.CURRENT);
}
return 1;

总结

  • 红外遥控器完整适配解决方案,涉及到哪些知识点等分析,实际工作有一定参考意义。
  • 内核层适配按键、设备树适配按键 、pwm 知识点也需要了解
  • framework层的PhoneWindowManager 适配按键功能也需要掌握
  • 对比蓝牙遥控器,按键映射逻辑可能稍微区别,实际验证问题还是有一定的共同之处的。
赞(0)
未经允许不得转载:网硕互联帮助中心 » RK3566-Android11-红外遥控器按键适配
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!