记录RTK平台上适配红外&蓝牙遥控器,以便以后查看。
物理按键的定义是在ir_table.config
如:
NEC编码: 1
RCA编码: 8
0xE31CC738 :scancode
KEY_POWER : keycode
其中三个头文件分别对解析 scancode 进行了转换,路径如下:
由上述编译文件进行编译,生成对应的ir_table.bin
编译方法:
./ir_bin_create generate ir_table.config ir_table.bin
验证是否成功编译到.bin文件
./ir_bin_create print ir_table.bin
ir_table.bin ——> bootcode
在bootcode中,由 uboot\arch\arm\cpu\armv7\rtd285o\bootparam.c 的 get_factory_ir_table_from_factory()函数来读取 ir_table.bin的地址将其传给kernel
在串口使用cat /proc/cmdline
命令可以看到地址
bootcode ——> kernel
在kernel中 odin2k\kernel\linux\linux-4.14\drivers\rtk_kdriver\ir\ir_table\ir_table_user.c 会去拿这个传过来的地址
static int __init venus_ir_input_table_addr_parse(char *options)
{
unsigned long ir_table_phy_address = 0;
if(options == NULL)
return 0;
if (sscanf(options, "%lx", &ir_table_phy_address) != 1)
return 0;
g_ir_boot_memory_address = ir_table_phy_address;
IR_INFO("g_ir_boot_memory_address == %lx\n", g_ir_boot_memory_address);
return 0;
}
early_param("ir_table", venus_ir_input_table_addr_parse);
之后在 kernel\linux\linux-4.14\drivers\rtk_kdriver\ir\irrc_core.c 文件中
static int examine_ir_avail(uint32_t *which, uint32_t *regValue, uint32_t *irrp2Value, int *dataRepeat)
static int repeat_key_handle(uint32_t which, uint32_t regValue, uint32_t irrp2Value, int dataRepeat)
{
......
keycode = venus_ir_scancode_to_keycode(regValue);
......
}
void venus_ir_input_report_key(uint32_t repkey)
{
......
input_report_key(data->input_dev, data->prev_keycode, 0);
input_sync(data->input_dev);
......
}
kernel——>key映射
这里就说的是linux到Android的映射按键值,这其中有有两个地方需要添加映射分别是.xml和.kl文件,其中xml是自定义的映射
# Power / Mute
key 116 POWER
key 113 VOLUME_MUTE
# Numbers
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
key 7 6
key 8 7
key 9 8
key 10 9
key 11 0
key 551 TV_NUMBER_ENTRY
上述.kl文件中 key 8 7
其中8就是kernel上传上来的值,而7这个标签是映射要继续上传到 fromworks 层由KeyEvent.java来定义其的键值
自定义的全局按键xml映射的映射路径 ir_table.config——>xxxx.xml——>RtkKeyInterceptService.apk
<key scancode="729" label="KEYCODE_APP_LIST" keycode="2013"/>
<key scancode="166" label="KEYCODE_APP_LIST" keycode="2013"/>
<key scancode="712" label="KEYCODE_BLUETOOTH" keycode="2014"/>
<key scancode="708" label="KEYCODE_COLOR_TEMP" keycode="2015"/>
<key scancode="717" label="KEYCODE_CSM_DISPLAY_OFF" keycode="2016"/>
<key scancode="716" label="KEYCODE_CSM_DISPLAY_ON" keycode="2017"/>
<key scancode="724" label="KEYCODE_FACTORY_HOTKEY_OFF" keycode="2018"/>
<key scancode="725" label="KEYCODE_FACTORY_HOTKEY_ON" keycode="2019"/>
<key scancode="718" label="KEYCODE_LIGHT_SENSOR_OFF" keycode="2020"/>
<key scancode="719" label="KEYCODE_LIGHT_SENSOR_ON" keycode="2021"/>
上述.xml文件中 scancode 的值是kernel上传上来的值,映射的是label 其keycode是其上报给 RtkKeyInterceptService.apk 的键值
因此, RtkKeyInterceptService.apk 的接受的keycode由两处获得,分别是 .kl 文件和 xml 文件
key映射——>fromworks
当按键传到 fromworks 我们只需要更改 KeyEvent.java 来完成最后的按键定义,之后就是到 PhoneWindowManager.java 来实现按键功能实现拦截或继续传递。
fromworks——>app
从 PhoneWindowManager.java 之后所有未拦截的按键都将传递到 RtkKeyInterceptService.java ,这里大部分都是发送实现功能的广播,然后可以在这里来选择是否继续向下传递。
RtkKeyInterceptService.apk 中的拦截和继续上报
//return 1代表拦截,不会再发键值去android
//return 0 代表会把值传回给驱动,然后驱动再次上报给 android
拿到一个蓝牙遥控器后,TV先连接蓝牙遥控之后使用命令 getevent
console:/ # getevent
add device 1: /dev/input/event2
name: "RC890"
add device 2: /dev/input/event1
name: "rtk_keypad"
add device 3: /dev/input/event0
name: "IR_tcl_rca"
/dev/input/event2: 0004 0004 000c0223
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0001 00ac 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0004 0004 000c0223
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0001 00ac 00000000
/dev/input/event2: 0000 0000 00000000
RC890蓝牙遥控器的设备号,其所对应的kl文件是RC890.kl ,该次按键上报的值是 0xac
在 /branches/RTK_2851M_TCL/kernel/linux/linux-4.14/drivers/hid/hid-input.c 修改上报蓝牙按键
case 0x055: map_key_clear(0x1f5); break; /* Menu Setting */
case 0x053: map_key_clear(KEY_SMARTZONE); break; /* Menu Smart */
case 0x049: map_key_clear(KEY_SOURCE); break; /* Menu Source */
case 0x050: map_key_clear(KEY_MENU); break; /* Menu */
case 0x052: map_key_clear(KEY_VRKEYBOARD); break; /* Menu VRKEYBOARD*/
case 0x0b7: map_key_clear(KEY_APPS_LIST); break; /* Menu Youtube*/
case 0x058: map_key_clear(KEY_TCL_USB); break; /* Menu TCL_USB*/
case 0x0a6: map_key_clear(KEY_MIC_DETECT); break; /* Menu MIC_DETECT*/
定义路径:
kernel/linux/linux-4.14/include/uapi/linux/input-event-codes.h
kernel/linux/linux-4.14/include/uapi/linux/input-event-custom-codes.h
如何获取遥控器的scancode?
在串口输入如下命令,[irrp=XXXXXXXX] 即为 scancode
echo 8 > /proc/sys/kernel/printk
echo 1 > /sys/venus_ir/ir_decode_debug
如何查看上报的keycode?
在串口输入 getevent
并按下遥控按键 【数字7】 可以看到如下输出
console:/ # getevent
add device 1: /dev/input/event1
name: "rtk_keypad"
add device 2: /dev/input/event0
name: "IR_tcl_rca"
/dev/input/event0: 0001 0008 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0008 00000000
/dev/input/event0: 0000 0000 00000000
以上008即为上报的keycode(注意是16进制)
同时还可以看到使用的设备号为 IR_tcl_rca (遥控器)、rtk_keypad(按键板)
如何查看遥控器使用哪个kl映射文件?
使用 dumpsys input
命令查看
如何用串口输入按键?
使用 input keyevent 20
在KeyEvent.java中查阅相关的键值
如何添加特殊的遥控器头码?
kernel\android\android-10\vendor\realtek\common\ATV\frameworks\native\ExtTv\src\service\ExtFactoryManager.cpp
在上述路径单独添加
如何开启遥控器kernel打印?
echo 8 > /proc/sys/kernel/printk;
echo 1 > /sys/venus_ir/ir_decode_debug
如何用串口切换协议?
echo 8 > /sys/venus_ir/ir_protocol 【RCA协议】
echo 1 > /sys/venus_ir/ir_protocol 【NEC协议】
Debug 如何取消头码匹配?
取消头码匹配,在boot下输入命令 irda_filter disable
开启头码匹配,在boot下输入命令 irda_filter enable
如何查看ini遥控器配置?
在串口中输入 cat /tmp/factory/bin_panel/000BootParam.h
在配置文件ini中修改IR进行头码匹配
[IRFilter]
IR_Filter="00000fff,00000f00,0,0";
#IR_Filter="00000fff,00000f00,0,0-0000ffff,0000c738,0,0";
[IR]
#tcl_kt1752(NEC),tcl_rca(RCA)...
IR_CONFIG="tcl_rca(RCA)";
IR_Filter是遥控器的按键匹配码
如,00000fff 和00000f00之间的是 ‘位&’关系。相当于scancode只保留后三位f00作为头码
如果 scancode 和头码相匹配则按键上报,否则拦截
注:可以采用 - 的方式添加多个头码
Debug验证方法:
facro list
查看文档目录facro delete tmp/factory_ro/ir_table.bin
facro save
go r
cd tmp/factory
cp /mmnt/udisk/xxx/ir_tabl.bin
factory save
reboot