篇头
每隔段时间,总会忘记些东西。在Android上配置红外遥控和蓝牙遥控,是必备技能。之前也写过红外遥控的配置方法,因红外更常遇到。而蓝牙配得少一些,就没意识到更要做总结,以为早就会了,如今配置蓝牙遥控器,一下子居然没配对,经过一番折腾,所以必须记录一下,在此分享给大家。
一、规格书
- 从规格书中,获取按键布局(取值)情况。
二、红外按键配置
- 配置方法略,此处给出红外的安卓映射值,蓝牙按键的配置,需配置为与红外的安卓按键一致
key 77 BACK
key 26 MENU
key 2 DPAD_CENTER
key 10 DPAD_DOWN
key 67 DPAD_UP
key 78 HOME
key 6 DPAD_LEFT
key 14 DPAD_RIGHT
key 27 VOLUME_UP
key 88 VOLUME_DOWN
key 87 POWER
key 91 VOLUME_MUTE
key 49 SETTINGS
key 53 ZOOM_IN
key 52 ZOOM_OUT
key 255 AUDIO
key 48 TV_INPUT
key 64 APP_SWITCH
三、蓝牙按键配置
3.1 查看设备号
- 此处目的是为了获得 vendor=0x568a, product=0x9869,安卓系统默认通过此2项来匹配kl文件
- version项目可选,一般就不使用了,除了特别需求
- 提取打印:Identifier: bus=0x0005, vendor=0x568a, product=0x9869, version=0x0001
3.1.1 方式一:dumpsys input
- 首先使用手动配对,连接上蓝牙遥控器
console:/ # dumpsys input
INPUT MANAGER (dumpsys input)
…… 略 ……
Event Hub State:
BuiltInKeyboardId: -2
Devices:
…… 略 ……
9: 语音助手 Keyboard
Classes: 0x800000a1
Path: /dev/input/event8
Enabled: true
Descriptor: 64be8d24c5c36a9695b6e91253242e7413e8d0d8
Location:
ControllerNumber: 0
UniqueId: 67:35:d9:5f:90:7b
Identifier: bus=0x0005, vendor=0x568a, product=0x9869, version=0x0001
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
3.1.2 方式二: cat /proc/bus/input/devices
130|console:/ # cat /proc/bus/input/devices
…… 略……
I: Bus=0005 Vendor=568a Product=9869 Version=0001
N: Name="语音助手 Keyboard"
P: Phys=
S: Sysfs=/devices/virtual/misc/uhid/0005:568A:9869.0001/input/input8
U: Uniq=67:35:d9:5f:90:7b
H: Handlers=leds event8
B: PROP=0
B: EV=120013
B: KEY=10000 7 ff980078 7ff febeffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=1f
…… 略……
console:/ #
3.2 配置kl文件
根据vendor=0x568a, product=0x9869,将kl文件命名为Vendor_568a_Product_9869.kl。
3.2.1 方案商原始配置
- 从3.1.1节的KeyLayoutFile: /system/usr/keylayout/Generic.kl这句打印,以及第一章的遥控器规格书,可以得知方案商的默认配置
- 遥控器方案商将自己的蓝牙按键映射为标准的蓝牙键盘按键
3.2.2 Generic.kl 文件
- 此文件是keyboard输入设备的默认keylayout
- 我们需要从此文件提取键值,也就是kl文件的第2列,这个键值方案商并未给出
举个例子,此处拿出四个按键,请比对遥控器规格书和kl文件
key 59 F1 //备注:对应遥控器 Source按键
key 60 F2 //备注:对应遥控器 Settings按键
key 63 F5 //备注:对应遥控器 F+按键
key 64 F6 //备注:对应遥控器 F-按键
3.2.3 重映射蓝牙按键
- 根据我们的需要,我们把蓝牙按键映射为相同的红外按键的Android键值码,也就是第3列
- 如SETTINGS,对应到Andoird KeyEvent.java的按键,就是 KEYCODE_SETTINGS
key 59 TV_INPUT //备注:对应遥控器 Source按键
key 60 SETTINGS //备注:对应遥控器 Settings按键
key 63 ZOOM_OUT //备注:对应遥控器 F+按键
key 64 ZOOM_IN //备注:对应遥控器 F-按键
3.2.4 完成 Vendor_568a_Product_9869.kl
key 158 BACK
key 127 MENU
key 40 DPAD_CENTER
key 152 POWER
key 172 HOME
key 108 DPAD_DOWN
key 103 DPAD_UP
key 105 DPAD_LEFT
key 106 DPAD_RIGHT
key 113 VOLUME_MUTE
key 114 VOLUME_DOWN
key 115 VOLUME_UP
key 60 SETTINGS
key 64 ZOOM_IN
key 63 ZOOM_OUT
key 194 AUDIO
key 59 TV_INPUT
key 186 APP_SWITCH
key 28 DPAD_CENTER
3.2.5 部署kl文件
- 找到相关的AOSP mk文件及目录,一般就在device/xxxx下面
- 添加部署语句,将kl部署到/system/usr/keylayout下
- 其他可选路径,如/vendor/usr/keylayout下 或者 /oem/usr/keylayout下,
PRODUCT_COPY_FILES += \
$(LOCAL_MODULE_PATH)/Vendor_568a_Product_9869.kl:$(TARGET_COPY_OUT_SYSTEM)/usr/keylayout/Vendor_568a_Product_9869.kl
- 编译完成后,可查找确认,配置文件已写对
四、调试
4.1 成功的情况
- 通过 dumpsys input 命令,可以看到已成功解析到我们所部署的文件
- KeyLayoutFile: /system/usr/keylayout/Vendor_568a_Product_9869.kl
9: 语音助手 Keyboard
Classes: 0x800000a1
Path: /dev/input/event8
Enabled: true
Descriptor: 64be8d24c5c36a9695b6e91253242e7413e8d0d8
Location:
ControllerNumber: 0
UniqueId: 67:35:d9:5f:90:7b
Identifier: bus=0x0005, vendor=0x568a, product=0x9869, version=0x0001
KeyLayoutFile: /system/usr/keylayout/Vendor_568a_Product_9869.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
4.2 失败的情况
4.2.1 状态显示
- 通过 dumpsys input 命令,可以看到KeyLayoutFile依旧指向默认的Generic.kl
- KeyLayoutFile: /system/usr/keylayout/Generic.kl
9: 语音助手 Keyboard
Classes: 0x800000a1
Path: /dev/input/event8
Enabled: true
Descriptor: 64be8d24c5c36a9695b6e91253242e7413e8d0d8
Location:
ControllerNumber: 0
UniqueId: 67:35:d9:5f:90:7b
Identifier: bus=0x0005, vendor=0x568a, product=0x9869, version=0x0001
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
4.2.2 开启debug打印
- android\frameworks\native\libs\input\InputDevice.cpp
- 此文件是匹配probe kl 的关键源文件,在getInputDeviceConfigurationFilePathByName函数中进行解析和匹配kl文件。
- 开启打印:#define DEBUG_PROBE 1
打印举例:
- 代表已匹配到
06-18 16:28:38.075 4030 4166 D InputDevice: Probing for system provided input device configuration file: path='/system/usr/keylayout/Vendor_568a_Product_9869.kl'
06-18 16:28:38.076 4030 4166 D InputDevice: Found
4.2.3 kl 有错误的情况
- kl:16: Expected key code label, got ‘F24’. 代表kl文件里面有个按键配置成了F24,但在按键定义中,找不到F24这个Label的按键
- 例如在kl中定义:key 194 F24 ,就会有如下错误
06-18 16:38:06.524 4038 4173 D InputDevice: Probe failed to find input device configuration file: name='Vendor_568a_Product_9869_Version_0001', type=1
06-18 16:38:06.524 4038 4173 D InputDevice: Probing for system provided input device configuration file: path='/odm/usr/keylayout/Vendor_568a_Product_9869.kl'
06-18 16:38:06.524 4038 4173 D InputDevice: Probing for system provided input device configuration file: path='/vendor/usr/keylayout/Vendor_568a_Product_9869.kl'
06-18 16:38:06.524 4038 4173 D InputDevice: Probing for system provided input device configuration file: path='/system/usr/keylayout/Vendor_568a_Product_9869.kl'
06-18 16:38:06.525 4038 4173 D InputDevice: Found
06-18 16:38:06.526 4038 4173 E KeyLayoutMap: /system/usr/keylayout/Vendor_568a_Product_9869.kl:16: Expected key code label, got 'F24'.
4.3 如何获取蓝牙按键扫描码?
原本映像,配置蓝牙遥控器的“扫描码”,应该是用0007003a的尾数0x3a,结果却不对,通过一通折腾,和下面的0x003b匹配上了……,姑且都叫扫描码吧。
- 以第一节的Source按键为例:
- 方案商定义:信号源按键: Source Key_F1 07003A 30 ,将其映射为F1按键,但其中并没有扫描码
- 方法:(1)手动连接蓝牙遥控 (2)执行getevent命令 (3)遥控器按下 Source 按键
- 如下:003b 即为 source按键的蓝牙按键扫描码,转换为十进制为:59 , 值同3.2.2节source按键
console:/ # getevent
add device 1: /dev/input/event10
name: "语音助手"
add device 2: /dev/input/event9
name: "语音助手 Consumer Control"
add device 3: /dev/input/event8
name: "语音助手 Keyboard"
…… 略 ……
/dev/input/event8: 0004 0004 0007003a
/dev/input/event8: 0001 003b 00000001
/dev/input/event8: 0000 0000 00000000
/dev/input/event8: 0004 0004 0007003a
/dev/input/event8: 0001 003b 00000000
/dev/input/event8: 0000 0000 00000000