通俗易通讲解Android蓝牙键值适配
以下图中tv vod两个按键为例,文章中所涉及到的文件只写文件名,因每个方案的路径各不相同,请自行全局搜索文件。
1.获取按键的扫描码
android设备串口或adb shell下执行getevent -l
(小写的l),然后按下按键(以vod键为例),打印结果如下:
getevent显示结果中的三个有效信息:
- 1)000c006b 前四位000c为键值类型(详情请跳到2与阅读hid.h),后四位为蓝牙键值;
- 2)key_blue 如果在linux_key.h中有此按键的定义,此处就会显示,如果linux_key.h中没有对此键的定义就会显示key_unknown.
- 3)/dev/input/event4: 设备节点,可以通过
dumpsys input
命令查看此节点使用keylayoutfile
(即映射键值的.kl的文件)
console:/ # getevent -l add device 1: /dev/input/event4 name: "语音助手" could not get driver version for /dev/input/mouse2, not a typewriter add device 2: /dev/input/event3 name: "hi keypad" could not get driver version for /dev/input/mouse1, not a typewriter add device 3: /dev/input/event1 name: "hi mouse" could not get driver version for /dev/input/mice, not a typewriter add device 4: /dev/input/event0 name: "hi keyboard" could not get driver version for /dev/input/mouse0, not a typewriter add device 5: /dev/input/event2 name: "qwerty" /dev/input/event4: ev_msc msc_scan 000c006b /dev/input/event4: ev_key key_blue down /dev/input/event4: ev_syn syn_report 00000000 /dev/input/event4: ev_msc msc_scan 000c006b /dev/input/event4: ev_key key_blue up /dev/input/event4: ev_syn syn_report 00000000
2.hid-input.c
从getevent -l时已知vod按键为000c006b,前四位详细定义可以参考kernel下的hid.h,此处只列举几个:
#define hid_up_keyboard 0x00070000 #define hid_up_led 0x00080000 #define hid_up_button 0x00090000 #define hid_up_ordinal 0x000a0000 #define hid_up_telephony 0x000b0000 #define hid_up_consumer 0x000c0000
在hid-input.c中有个函数hidinput_configure_usage,会根据不同的hid执行不同的代码,为0007(hid_up_keyboard)时会处理hid_keyboard[256]的数组,把扫描码转换为10进制后就是该数组的下标,数组下标的数组元素就是linux键值,我的键值前面是000c所以跳过前面说的,case走的是hid_up_consumer,此case下已有对0x6b的处理,意思就是此键在linux中代表的是key_blue。
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { /**省略**/ switch (usage->hid & hid_usage_page) { case hid_up_undefined: goto ignore; /**省略**/ /**省略**/ case hid_up_keyboard: set_bit(ev_rep, input->evbit); if ((usage->hid & hid_usage) < 256) { if (!hid_keyboard[usage->hid & hid_usage]) goto ignore; map_key_clear(hid_keyboard[usage->hid & hid_usage]); } else map_key(key_unknown); break; case hid_up_consumer: /* usb hut v1.12, pages 75-84 */ switch (usage->hid & hid_usage) { case 0x06a: map_key_clear(key_green); break; case 0x06b: map_key_clear(key_blue); break; case 0x06c: map_key_clear(key_yellow); break; case 0x06d: map_key_clear(key_zoom); break; /**省略**/ /**省略**/ }
那key_blue的键值是多少呢?
{"key_blue", 0x191},
我们来查阅linux_key.h,搜索key_blue,我的sdk中key_blue的值为0x191,转换为十进制值为401。
3.keylayoutfile --> .kl
getevent -l时已知设备节点为/dev/input/event4,那我们执行下dumpsys input,结果如下:
5: 语音助手 classes: 0x8000012b path: /dev/input/event4 enabled: true descriptor: e0cab5a5e7db45d100777208b12fb1c21978adca location: controllernumber: 0 uniqueid: 18:11:18:24:33:18 identifier: bus=0x0005, vendor=0x2b54, product=0x1600, version=0x0101 keylayoutfile: /vendor/usr/keylayout/vendor_2b54_product_1600.kl keycharactermapfile: /vendor/usr/keychars/generic.kcm configurationfile: havekeyboardlayoutoverlay: false
结果中可以看出我的蓝牙遥控器的vendor=2b54,product=1600,所以系统优先加载的我自己加到rom中的kl(.kl命名规则与加载优先级请自行百度),有的可能找不到,会加载generic.kl等文件,请根据keylayoutfile:后的路径的文件修改映射关系,如果为默认的generic.kl时,建议不要修改此文件,可以根据vendor与product规则自己新建一个文件。
那我们打开指向的这个kl文件,内容如下:
#key 222 "key_red" # key 400 "key_yellow" key 401 prog_green key 402 channel_up key 403 channel_down
kl文件格式简单解析(详解与其它使用方法自行搜索):
key 可以理解成固定格式
222/401等数字对应的就是linux的键值
prog_green 这里对应的就是android层的键值(此字符串要与inputeventlabels.h中的保持一致,否则会报expected key code label异常,然后就加载其它默认的kl文件了,5.0以前是keycodelabels.h或keycodelabels.h)
既然都理清楚了,那处理按键岂不是很简单了?
已知前面linux_key.h中查询vod的linux键值为401,如果你想让此按键生效,把前面的#号去掉重启设备,使其映射关系生效即可,如果你想改变键值的功能,可以直接在此kl中把401对应的android层的key_blue改为你想要的键就可以了。(当然也可以修改linux的键值,但不提倡这么做.)
总结:
- 1.通过getevent -l获取键值设备节点;
- 2.hid-input.c中添加或修改你的键值;
- 3.通过设备节点找到对应的kl文件;
- 4.添加或修改映射关系;
以上所述是小编给大家介绍的android蓝牙键值适配,希望对大家有所帮助。在此也非常感谢大家对网站的支持!