【笔记分享】Android TV 红外&蓝牙遥控器添加

记录RTK平台上适配红外&蓝牙遥控器,以便以后查看。

红外遥控器

遥控器流程图
【笔记分享】Android TV 红外&蓝牙遥控器添加_第1张图片

物理按键的定义是在ir_table.config
如:【笔记分享】Android TV 红外&蓝牙遥控器添加_第2张图片
NEC编码: 1
RCA编码: 8
0xE31CC738 :scancode
KEY_POWER : keycode

其中三个头文件分别对解析 scancode 进行了转换,路径如下:

  1. kernel\system\lib\develop\ir_bin_create\input-event-custom-codes.h
  2. kernel\linux\linux-4.14\include\uapi\linux\input-event-custom-codes.h
  3. kernel\linux\linux-4.14\include\uapi\linux\input-event-codes.h

由上述编译文件进行编译,生成对应的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 文件中

  1. 判断协议是否正确,并解析出 scancode
static int examine_ir_avail(uint32_t *which, uint32_t *regValue, uint32_t *irrp2Value, int *dataRepeat)
  1. 根据 scancode 去找keycode
 static int repeat_key_handle(uint32_t which, uint32_t regValue, uint32_t irrp2Value, int dataRepeat)
{
	......
 	keycode = venus_ir_scancode_to_keycode(regValue);
 	......
}
  1. 在 kernel\linux\linux-4.14\drivers\rtk_kdriver\ir\ir_input.c 上报keycode键值
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

A&Q

  1. 如何获取遥控器的scancode?
    在串口输入如下命令,[irrp=XXXXXXXX] 即为 scancode

    echo 8 > /proc/sys/kernel/printk
    echo 1 > /sys/venus_ir/ir_decode_debug
    
  2. 如何查看上报的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(按键板)

  3. 如何查看遥控器使用哪个kl映射文件?
    使用 dumpsys input 命令查看

  4. 如何用串口输入按键?
    使用 input keyevent 20 在KeyEvent.java中查阅相关的键值

  5. 如何添加特殊的遥控器头码?
    kernel\android\android-10\vendor\realtek\common\ATV\frameworks\native\ExtTv\src\service\ExtFactoryManager.cpp
    在上述路径单独添加

  6. 如何开启遥控器kernel打印?

     echo 8 > /proc/sys/kernel/printk;
     echo 1 > /sys/venus_ir/ir_decode_debug
    
  7. 如何用串口切换协议?

    echo 8 > /sys/venus_ir/ir_protocol  【RCA协议】
    echo 1 > /sys/venus_ir/ir_protocol  【NEC协议】
    
  8. Debug 如何取消头码匹配?
    取消头码匹配,在boot下输入命令 irda_filter disable
    开启头码匹配,在boot下输入命令 irda_filter enable

  9. 如何查看ini遥控器配置?
    在串口中输入 cat /tmp/factory/bin_panel/000BootParam.h

  10. 在配置文件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 和头码相匹配则按键上报,否则拦截
    注:可以采用 - 的方式添加多个头码

  11. Debug验证方法:

    1. 先编译出ir_table.bin文件
    2. 进入boot模式,命令 facro list 查看文档目录
    3. 删除ir_table.bin文件命令 facro delete tmp/factory_ro/ir_table.bin
    4. 保存命令 facro save
    5. 进入rescue模式(不要插U盘) 命令 go r
    6. 之后分别执行命令 cd tmp/factory cp /mmnt/udisk/xxx/ir_tabl.bin
    7. 保存退出 factory save reboot

你可能感兴趣的:(Android,Tv,遥控器,android,tv)