使用遥控器探索GDK8

1. 功能说明

1.1显示IP地址

F1:显示IP地址的前两位数字(16进制)
F2:显示IP地址的后两位数字(16进制)

例:192.168.8.110
F1:C0 A8

F2:08 6E

1.2 设置USB-2.0端口状态

F3:切换端口模式为OTG / Host
USB设备分为Host主设备和SLAVE从设备,只有当主设备和从设备连接时,才可以实现数据的传输。
Host:只能当作主设备使用
OTG:既可以当作主设备,有可以当作从设备

1.3设置SysRq状态

F4:打开 / 关闭SysRq
SysRq:一种内核调试的方法,只要内核还可以响应中断,SysRq就一直可以使用。

1.4 设置MircoSD插槽状态

F5:切换信号为JTAG / SD
JTAG:主要用于芯片内部测试及对系统进行仿真、调试, JTAG技术是一种嵌入式调试技术,它在芯片内部封装了专门的测试电路 TAP,通过专用的JTAG测试工具对内部节点进行测试。

1.5 自定义按键表

1*Fn 2*Fn 3*Fn 4*Fn 5Fn
1 F1 a k u sysrq
2 F2 b l v 大小写转换
3 F3 c m w Tape
4 F4 d n x =
5 F5 e o y ,
6 F6 f p z Tab
7 F7 g q 空格 $
8 F8 h r / (
9 F9 i s . )
0 F10 j t - ;

2. 添加遥控器按键

在如今这个年头,已经有越来越多的厂商拒绝去开源原本属于Linux开源范围内的东西,理由必然是五花八门,也不能算是理由,只能算是借口;但是GDK8还是本着一种豁达的态度,将内核开源了出来(内核源代码),支持开发者根据自己的喜好和研究目的去定制内核。
【借口解释】
1.以某事为理由(非真正的理由)。例如,不能借口快速施工而降低工程质量。
2.假托理由。例如,别拿忙做借口而放松学习。

2.1 添加现有按键

想要遥控器上面的按键正常工作,首先要获取usercode及键码,然后再在DTS文件做出对应的修改。

获取usercode及键码:
1. 打开键值打印的调试开关
sudo echo 1 > /sys/module/rockchip_pwm_remotectl/parameters/code_print
2. 按下遥控器按键,记录对应的usercode及键码
[ 4265.059916] USERCODE=0xdf00
[ 4265.087021] RMC_GETDATA=e9
3. 在遥控器上逐个按键并记录与之对应的键码;对于同一类型的遥控器而言,其usercode及键码应该都是一样的

需要注意的是DTS文件内usercode不能重复定义,重复定义显然ir_key之间会发生“冲突”,导致遥控器按键无法正常使用。
获取完usercode和键码后,在DTS文件内的&remotectl {}结构中添加下方内容;usercode填写0xdf00,key_table内的去添加相应的按键,格式为<键码 键名>;键名的定义可以在Linux的linux-event-codes.h头文件中去进行查找。

ir_key4 {
    rockchip,usercode = <0xdf00>;
    rockchip,key_table =
        <0xe3 KEY_POWER>,
        <0xe  KEY_POWER>,
        <0xb4 63>,    //youtube
        <0xfe 67>,    //Media Center
        <0xa2 KEY_VOLUMEUP>,
        <0xb0 66>,    //Netflix
        <0xa0 68>,    //SetupWizard
        <0xa3 KEY_VOLUMEDOWN>,

        <0xbd KEY_HOME>,
        <0xf5 KEY_BACK>,

        <0xe5 KEY_UP>,
        <0xb8 KEY_LEFT>,
        <0xf9 KEY_REPLY>,
        <0xf8 KEY_RIGHT>,
        <0xb7 KEY_DOWN>,
        <0xfc KEY_SEARCH>,
        <0xe7 KEY_MENU>,

        <0xab KEY_1>, 
        <0xe9 KEY_2>
        <0xea KEY_3>,
        <0xaf KEY_4>,
        <0xed KEY_5>,
        <0xee KEY_6>,
        <0xb3 KEY_7>,
        <0xf1 KEY_8>,
        <0xf2 KEY_9>,
        <0xbe KEY_FN>,
        <0xf3 KEY_0>,
        <0xef 14>;
};

关于红外遥控器开发更多的内容,请参考文档Rockchip-Developer-Guide-Linux-PWM-CN

2.2 定义其他按键

遥控器上面的按键数量比较有限(毕竟还不是键盘嘛);但当我们需要使用其他按键的时候,由于没有对应的键码的缘故,不能在DTS文件内添加按键,所以可以考虑使用组合键去对应我们想要的按键。
当然啊,硬去设置DTS文件也不是不行;例如将<0xf3 KEY_0>改为<0xf3 KEY_F1>后,再去按遥控器上面的0键,这是时候GDK8拿到的肯定就不是0,而是变成F1了;但是此举实为下下策,属于拆了东墙补西墙,漏风漏雨的地方是换了,但是现状并没有改变;因此我们把“墙”给补上,才是“正道”!

2.2.1 自定义按键并进行转换

GDK8使用Fn键和数字键作为组合键(具体的自定义按键表描述见上方);自定义按键表在GDX_ALT_KEY_TABLE内去进行设置,我们通过gdx_fn_count去判断是否需要转换按键,如果需要转换按键,就去GDX_ALT_KEY_TABLE内找到对应的按键,并将该按键传给keycode。

static int gdx_fn_count = 0;
static int GDX_ALT_KEY_TABLE[][10] = {
    {KEY_F1,KEY_F2, KEY_F3, KEY_F4, KEY_F5,
        KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10},
    {KEY_A, KEY_B, KEY_C,KEY_D, KEY_E, 
        KEY_F, KEY_G, KEY_H, KEY_I, KEY_J},
    {KEY_K, KEY_L, KEY_M,KEY_N, KEY_O, 
        KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T},
    {KEY_U, KEY_V, KEY_W,KEY_X, KEY_Y, 
        KEY_Z, KEY_SPACE, KEY_SLASH, KEY_DOT, KEY_MINUS},
    {KEY_SYSRQ, KEY_CAPSLOCK, KEY_TAPE, KEY_EQUAL, KEY_COMMA,
        KEY_TAB, KEY_DOLLAR, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_SEMICOLON},
};

static int dump_ket_table(struct rkxx_remotectl_drvdata *ddata)
{
  int i;

  for(i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++){
    printk("remotectl_button[ddata->keynum].key_table[i].keycode: %d\n",
      remotectl_button[ddata->keynum].key_table[i].keycode);
  }

  return 0;
}

static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)
{
    int i, cur_key= 0, alt_key = 0;
    unsigned char keydata = (unsigned char)((ddata->scandata >> 8) & 0xff);

#ifdef GDX_DBG
    dump_ket_table(ddata);
#endif

    for (i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++) {
        if (remotectl_button[ddata->keynum].key_table[i].scancode == keydata) {
            cur_key = remotectl_button[ddata->keynum].key_table[i].keycode;
            if(cur_key == KEY_FN) {
                gdx_fn_count++;
                return 0;
            }
            else {
                if(gdx_fn_count > 0 && (cur_key >= KEY_1 && cur_key <= KEY_0)) {
                    gdx_fn_count = (gdx_fn_count > 5) ? 5 : gdx_fn_count;
                    alt_key = GDX_ALT_KEY_TABLE[gdx_fn_count-1][cur_key - KEY_1];
                }
                gdx_fn_count = 0;
            }
            printk("GDX: remapped key %d to key %d , Fn Count: %d\n", cur_key, alt_key, gdx_fn_count-1);
            ddata->keycode = (alt_key != 0) ? alt_key : cur_key;
            DBG("GDX: %s keycode %d \n", __func__, ddata->keycode);
            return 1;
        }
    }
    return 0;
}

2.2.2 上报自定义按键

完成自定义按键的转换之后,还需要上报自定义按键,让设备知道你所做出的更改,不上报按键的话,设备不知道按键的存在,当然也就没办法输出按键;正如下方代码所示,我们需要使用input_set_capability函数,将自定义按键逐个上报。

for (j = 0; j < alt_table_num; j++){
    DBG("GDIRD: remotectl probe j = 0x%x\n", j);
    for (i = 0; i < gird_key_num; i++){
        input_set_capability(input, EV_KEY, GDX_ALT_KEY_TABLE[j][i]);
    }
}

2.3 编译内核

编译命令
1. 移动到内核目录下
2. make ARCH=arm64 rockchip_linux_defconfig
3. make ARCH=arm64 gdk850.img -j8 LOCALVERSION=-yanzi
如果生成的内核版本号带有dirty后缀,可以在内核目录下,创建名为.scmversion的空文件,来避免dirty后缀的生成。

生成新的内核后,可以使用dd命令将boot.img烧录到GDK8当中(可以参考文章更新内核