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

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

文章目录


前言-需求场景

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

遥控器资料如下:

一、参考资料

设置遥控器按键

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

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

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

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

二、需求分析

这里要有几个关键点:

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

三、修改文件

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

四、实现方案

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

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

配置了irkey1 如下:

java 复制代码
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>,
 			<0x11	KEY_HOMEPAGE>,
 			<0x13	KEY_SELECT>,
			<0x43	KEY_MENU>,
			<0x21	KEY_1>,
			<0x22	KEY_2>,
			<0x23	KEY_3>,
			<0x24	KEY_4>,
			<0x25	KEY_5>,
			<0x26	KEY_6>,
			<0x27	KEY_7>,
			<0x28	KEY_8>,
			<0x29	KEY_9>,
			<0x20	KEY_0>,
			<0x13	KEY_REPLY>,
			<0x0D	KEY_BACKSPACE>,
 			<0x00   BTN_MOUSE>;
 	};

核心配置-配置客户编码

rockchip,usercode = <0x01FE>;

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

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

配置红外按键

scancode KEY 宏 对应的物理按键 / 功能
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层适配了一次而已。

java 复制代码
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 如下:

java 复制代码
按了红外遥控器 物理设置按键,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 按键映射和系统处理上。

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

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

先看日志:

java 复制代码
PhoneWindowManager.java 打印日志如下:
2017-08-04 18:34:15.583   444-534   WindowManager           system_server                        D  interceptKeyTq keycode=0 interactive=true keyguardActive=false policyFlags=22000000
2017-08-04 18:34:15.584   444-533   WindowManager           system_server                        D  interceptKeyTi keyCode=0 down=true repeatCount=0 keyguardOn=false canceled=false
2017-08-04 18:34:15.586   444-533   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
2017-08-04 18:34:15.586   444-533   WindowManager           system_server                        D  No fallback.
2017-08-04 18:34:15.766   444-534   WindowManager           system_server                        D  interceptKeyTq keycode=0 interactive=true keyguardActive=false policyFlags=22000000
2017-08-04 18:34:15.767   444-533   WindowManager           system_server                        D  interceptKeyTi keyCode=0 down=false repeatCount=0 keyguardOn=false canceled=false
2017-08-04 18:34:15.769   444-533   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
2017-08-04 18:34:15.769   444-533   WindowManager           system_server                        D  No fallback.

日志解读

java 复制代码
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 映射问题。

java 复制代码
 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 适配按键功能也需要掌握
  • 对比蓝牙遥控器,按键映射逻辑可能稍微区别,实际验证问题还是有一定的共同之处的。
相关推荐
Strugglingler3 个月前
Linux Device Drivers-第十章 中断处理
linux·irq·工作队列·tasklet·中断共享
南方者8 个月前
大模型推理中 IRQ 中断优化:从机制解析到性能调优实践
大模型·irq
时光飞逝的日子2 年前
Cortex-A7:ARM官方推荐的嵌套中断实现机制
中断·sys·cortex-a7·嵌套·中断服务函数·irq
Y多了个想法3 年前
HiSilicon352 android9.0 适配红外遥控器
android·海思·hisilicon352·红外遥控器·ir