遥控器按键设置原理
1. 添加遥控器按键
在如今这个年头,已经有越来越多的厂商拒绝去开源原本属于Linux开源范围内的东西,理由必然是五花八门,也不能算是理由,只能算是借口;但是GDK8还是本着一种豁达的态度,将内核开源了出来(内核源代码),支持开发者根据自己的喜好和研究目的去定制内核。
【借口解释】
1.以某事为理由(非真正的理由)。例如,不能借口快速施工而降低工程质量。
2.假托理由。例如,别拿忙做借口而放松学习。
1.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
1.2 定义其他按键
遥控器上面的按键数量比较有限(毕竟还不是键盘嘛);但当我们需要使用其他按键的时候,由于没有对应的键码的缘故,不能在DTS文件内添加按键,所以可以考虑使用组合键去对应我们想要的按键。
当然啊,硬去设置DTS文件也不是不行;例如将<0xf3 KEY_0>改为<0xf3 KEY_F1>后,再去按遥控器上面的0键,这是时候GDK8拿到的肯定就不是0,而是变成F1了;但是此举实为下下策,属于拆了东墙补西墙,漏风漏雨的地方是换了,但是现状并没有改变;因此我们把“墙”给补上,才是“正道”!
1.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;
}
1.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]);
}
}
1.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当中(可以参考文章更新内核)
2. 使用遥控器控制GDK8
如果想要了解遥控器的基本用法,请查看文章()。