本系列文章:
Android STB 遥控器适配
Android STB ROM体积精简
Android STB 添加系统接口
Android STB 高效调试技巧
Android STB 海思平台调试
Android STB HDMI开发
Android STB 编译自定义jar
在目前的机顶盒市场中,海思和Amlogic(之前还有Mstar)是主流的芯片方案。因此,在这几种芯片上适配红外和蓝牙遥控器也就成为了机顶盒厂家的常见工作,本篇文章简单介绍下遥控器的适配方式。
使用"getevent -l"可以查看该机顶盒上适配的遥控器及对应的event,然后再随便按个按键,串口输出如下:
130|root@Hi3798MV300:/ # getevent -l
add device 1: /dev/input/event3
name: "YYYKQ"
could not get driver version for /dev/input/mouse2, Not a typewriter
could not get driver version for /dev/input/mouse1, Not a typewriter
add device 2: /dev/input/event2
name: "qwerty"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 3: /dev/input/event1
name: "Hi mouse"
add device 4: /dev/input/event0
name: "Hi keyboard"
could not get driver version for /dev/input/mice, Not a typewriter
/dev/input/event3: EV_MSC MSC_SCAN 00070051
/dev/input/event3: EV_KEY KEY_DOWN DOWN
/dev/input/event3: EV_SYN SYN_REPORT 00000000
/dev/input/event3: EV_MSC MSC_SCAN 00070051
/dev/input/event3: EV_KEY KEY_DOWN UP
/dev/input/event3: EV_SYN SYN_REPORT 00000000
以上内容表示适配了四套遥控器,名称分别为"YYYKQ"、“qwerty”、“Hi mouse”、“Hi keyboard”,目前使用的遥控器为"YYYKQ"遥控器。下面的六行内容意思为:前三行代表Usage ID为0x51的按键被按下,后面的三行代表Usage ID为0x51的按键弹起。
使用"dumpsys input"可以查看每套遥控器对应的kl文件,串口输出如下:
130|root@Hi3798MV300:/ # dumpsys input
INPUT MANAGER (dumpsys input)
Event Hub State:
BuiltInKeyboardId: -2
Devices:
-1: Virtual
Classes: 0x40000023
Path:
Descriptor: a718a782d34bc767f4689c232d64d527998ea7fd
Location:
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Virtual.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
1: qwerty
Classes: 0x00000014
Path: /dev/input/event2
Descriptor: 0a920d0216027e6e2f378f49650573230b560922
Location:
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0100
KeyLayoutFile:
KeyCharacterMapFile:
ConfigurationFile: /system/usr/idc/qwerty.idc
HaveKeyboardLayoutOverlay: false
2: Hi mouse
Classes: 0x00000008
Path: /dev/input/event1
Descriptor: ddfb717d907e8defcc82f81ba273111db984c56a
Location:
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0000, vendor=0x0001, product=0x0002, version=0x0100
KeyLayoutFile:
KeyCharacterMapFile:
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
3: Hi keyboard
Classes: 0x00000063
Path: /dev/input/event0
Descriptor: 485d69228e24f5e46da1598745890b214130dbc4
Location:
ControllerNumber: 1
UniqueId:
Identifier: bus=0x0000, vendor=0x0001, product=0x0001, version=0x0100
KeyLayoutFile: /system/usr/keylayout/Vendor_0001_Product_0001.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
5: YYYKQ
Classes: 0x8000016b
Path: /dev/input/event3
Descriptor: aef83b05c01603404d15b0155c07acee382a4de5
Location:
ControllerNumber: 2
UniqueId:
Identifier: bus=0x0005, vendor=0x0416, product=0x0300, version=0x0000
KeyLayoutFile: /system/usr/keylayout/Vendor_0416_Product_0300.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
由上面的输出内容可知,"YYYKQ"对应的kl文件为/system/usr/keylayout/Vendor_0416_Product_0300.kl。
除了上面两个命令,还有一些遥控器方面常用命令,如禁用/启用遥控器命令如下:
芯片 | 禁用红外遥控器 | 启动红外遥控器 |
---|---|---|
Amlogic905L | remotecfg | ./system/bin/remotecfg.sh |
Hi3798MVxx | stop ir_user | start ir_user |
Mstar9380 | busybox devmem 0x1f007b00 16 0x0000 | busybox devmem 0x1f007b00 16 0x01bf |
按下遥控器的一个按键后,系统中的处理逻辑为:物理键值——>Linux键值——>按键名称——>Android键值。
可以先用"android_ir_user -D"命令查看一下机顶盒适配的所有红外码值,然后按下某个具体按键,如2014格式的上键,串口输出如下:
Received key: 0xb9461420,linux_keycode =0x67,103,1, UP, protocol: .
该内容的意义如下:
1>1420为遥控器头码
3>46为遥控器物理键值
4>b9为校验值
5>0x67转换为实际值就是103,代表该按键对应的Linux键值
在device/hisilicon/bigfish/system/ir_user/key_pars/key.xml中寻找0xb9461420,可以查到该键值对应的按键名称,如下:
<key value="0xb9461420" name="KEY_UP" /> <!--key up-->
以上内容表示0xb9461420对应的是上键。
然后在device/hisilicon/bigfish/system/ir_user/key_pars/linux_key.h中,可以查看该按键对应的Linux键值,如下:
{
"KEY_UP", 103 },
以上内容表示的是上键对应的Linux键值是103。
接下来就是要寻找对应的kl文件,如上述的"dumpsys input"命令输出的内容中,Vendor_0001_Product_0001.kl就是红外遥控器对应的kl文件,在代码中具体的文件为:device/hisilicon/bigfish/prebuilts/Vendor_0001_Product_0001.kl,上键对应的内容如下:
key 103 DPAD_UP
按如上步骤,红外遥控器底层键值就已经适配完成。接下来就要适配上层Android键值,上层键值的实现主要在framework代码中实现,具体为以下文件。
frameworks/base/core/java/android/view/KeyEvent.java中,内容如下:
public static final int KEYCODE_DPAD_UP = 19;
frameworks/native/include/input/KeycodeLabels.h中,内容如下:
{
"DPAD_UP", 19 },
frameworks/base/core/res/res/values/attrs.xml中,内容如下:
<enum name="KEYCODE_DPAD_UP" value="19" />
frameworks/native/include/android/keycodes.h中,内容如下:
AKEYCODE_DPAD_UP = 19,
海思上适配红外遥控器的流程到此结束。
Amlogic红外遥控器的适配流程整体上与海思相似,不同的是海思上是key.xml,Amlogic上是remote*.conf。并且海思上的key.xml里可以对应多套红外遥控器键值,而一个remote*.conf只能对应一套红外键值,并且代码里有多个remote*.conf,需要在device/amlogic/p201_iptv/p201_iptv.mk中查看对应的remote*.conf,如下:
ifeq ($(strip $(CHINA_MOBILE_ENABLE)),true)
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinamobile.conf:system/etc/remote.conf \
$(LOCAL_PATH)/remote_chinamobile1.conf:system/etc/remote1.conf \
$(LOCAL_PATH)/remote_chinamobile2.conf:system/etc/remote2.conf
else ifeq ($(strip $(CHINA_TELECOM_ENABLE)),true)
ifeq ($(strip $(BUILD_SH_TELECOM_APKS)),true)
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinatelecom_sh.conf:system/etc/remote.conf
else
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinatelecom.conf:system/etc/remote.conf
endif
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinatelecom1.conf:system/etc/remote1.conf
else ifeq ($(strip $(CHINA_UNICOM_ENABLE)),true)
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinaunicom.conf:system/etc/remote.conf \
$(LOCAL_PATH)/remote1.conf:system/etc/remote1.conf
else ifeq ($(strip $(BUILD_SD_MOBILE_APKS)),true)
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote_chinamobile2.conf:system/etc/remote2.conf
else
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/remote.conf:system/etc/remote.conf \
$(LOCAL_PATH)/remote1.conf:system/etc/remote1.conf
endif
Amlogic上没有android_ir_user脚本,所以不能执行"android_ir_user"命令,要看某一按键的物理键值,可以按某一按键,然后使用"dmesg"命令来看,关键内容如下:
<6>[ 827.604760@0] remote: press ircode = 0x46,
<6>[ 827.604787@0] remote: scancode = 0x0067,maptable = 1,code:0xb9461420
以上内容表示该按键的物理键值是0x46,遥控器头码是1420,b9为校验值,0x67转换为实际值就是103,代表该按键对应的Linux键值。remote*.conf文件的内容如下:
factory_code = 0x14200001 //遥控器码值类型,如该例子代表该文件是2014码值类型的
work_mode = 0 //工作模式设置,1为硬件,0位软件,一般默认选择0
repeat_enable = 1 //是否支持按下一直连发键
repeat_delay = 400 //按下按键到第一个连发键到时间间隔,单位为ms
repeat_peroid = 120 //两个连发键之间的时间间隔,单位为ms
release_delay = 80 // 释放按键时间间隔,单位为 ms
debug_enable = 1 //是否打开驱动调试打印
factory_infcode = 2 //可简单为添加的第几套码值,从0开始,依次增加
key_begin
0x46 103
key_end
以上就是Amlogic的红外遥控器适配与海思存在差异的地方,其余均与海思一致,不再赘述。
Mstar红外遥控器适配与海思相似,一个键值配置文件可以对应多套码值,具体文件为device/mstar/ponkan/preinstall32/irkey.cfg。如2014码值格式的上键对应的内容如下:
{
0x0246, KEY_UP },
不同芯片平台对蓝牙键值的适配方式是一样的,有差异的是hid-input.c文件的位置,具体如下:
1>海思:device/hisilicon/bigfish/sdk/source/kernel/linux-3.18.y.patch/drivers/hid/hid-input.c
2>Amlogic:common/drivers/hid/hid-input.c
3>Mstar:vendor/mstar/kernel/drivers/hid/hid-input.c
先看一张蓝牙遥控器的码值表,如下:
按键名称 | 红外键值 | 蓝牙键值 | Android键值 |
---|---|---|---|
电源 | DC | 0x66(07) | 179 |
确定 | CE | 0x41(0C) | 23 |
上 | CA | 0x52(07) | 19 |
下 | D2 | 0x51(07) | 20 |
左 | 99 | 0x50(07) | 21 |
右 | C1 | 0x4F(07) | 22 |
音量+ | 80 | 0xE9(0C) | 24 |
音量- | 81 | 0xEA(0C) | 25 |
频道+ | 85 | 0x4B(07) | 166 |
频道- | 86 | 0x4E(07) | 167 |
主页 | 88 | 0x223(0C) | 3 |
菜单 | 82 | 0x65(07) | 82 |
设置 | 8D | 0xEB(0C) | 176 |
返回 | 95 | 0x224(0C) | 4 |
静音 | 9C | 0xE2(0C) | 164 |
语音 | - | 0x3E(07) | 142 |
上面的键值表中第二列表示物理键值,第三列表示蓝牙键,第四列代表上层Android键值。该表中不涉及按键的Linux键值,也就是说明某个按键的Linux键值是可以任意定义的(虽然可以任意定义,但不建议这样做,接下来会详细说明)。
上表的第三列中蓝牙键值有不同的备注,"07"代表的普通蓝牙键值,"0c"代表多媒体键值,这两种类型键值的适配方式也不同,具体如下:
"07"类型键值的适配,就以上键为例,由之前章节得知改建对应的Linux键值为103,所以上键对应的蓝牙键值在hid_keyboard数组中对应的值就是103。其位置由蓝牙键值0x52决定,0x52转换为十进制为82,所以其位置就是hid_keyboard[82]。综合起来也就是hid_keyboard[82]位置的值为103,如下:
static const unsigned char hid_keyboard[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,240,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,250,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
如果某个"0c"类型键值在适配过程中,发现kl文件与hid_keyboard数组中的值不对应,建议修改kl文件。
"0c"类型键值的适配,以设置为例,在HID_UP_CONSUMER中对应的代码为:
case 0x0eb: map_key_clear(KEY_SETUP); break;
case后面的值为为对应的蓝牙键值,map_key_clear内的值为对应的按键名称。
要明确蓝牙键值对应哪个kl文件,仍可用上面提及的"dumpsys input",如frameworks/base/data/keyboards/Vendor_0416_Product_0300.kl。kl文件中的配置,与红外适配时相同,不再赘述。
映射到上层Android键值的部分,也与红外就键值适配时相同,涉及以下几个文件:
frameworks/base/core/java/android/view/KeyEvent.java
frameworks/base/core/res/res/values/attrs.xml
frameworks/native/include/android/keycodes.h
frameworks/native/include/input/KeycodeLabels.h
至此,Android TV上适配遥控器键值已全部完成。