2019-.4-22补充说明:
这两天又看了一下关于安卓按键的整个处理流程,现总结如下。
首先在linux驱动框架中按键值称为扫描码,而安卓应用中使用的按键值称为KeyCode其也是一个整数值,但是与linux中扫描码不同。linux扫描码需要经过两次转换才能转换为安卓层的KeyCode码,首先在Keylayout(按键布局)文件*.kl文件中把linux扫描码转化为KeycodeLabel字符串,在KEYCODE[]数组中把KeycodeLabel字符串转化为安卓KeyCode码。
frameworks/native/include/android/keycodes.h中定义了KeyCode码
enum {
AKEYCODE_UNKNOWN = 0,
AKEYCODE_SOFT_LEFT = 1,
AKEYCODE_SOFT_RIGHT = 2,
AKEYCODE_HOME = 3,
AKEYCODE_BACK = 4,
... ...
AKEYCODE_VOLUME_UP = 24,
AKEYCODE_VOLUME_DOWN = 25,
... ...
AKEYCODE_MENU = 82,
... ...
AKEYCODE_HELP = 259
};
frameworks/native/include/input/InputEventLabels.h中定义了KeyCode码和KeycodeLabel字符串的对应关系
#define DEFINE_KEYCODE(key) {#key,AKEYCODE_##key}
static const InputEventLabel KEYCODES[] = {
DEFINE_KEYCODE(UNKNOWN), // = {"UNKNOWN",0}
DEFINE_KEYCODE(SOFT_LEFT), // = {"SOFT_LEFT",1}
DEFINE_KEYCODE(SOFT_RIGHT), // = {"SOFT_RIGHT",2}
DEFINE_KEYCODE(HOME), // = {"HOME",3}
DEFINE_KEYCODE(BACK), // = {"BACK",4}
... ...
DEFINE_KEYCODE(VOLUME_UP), // = {"VOLUME_UP",24}
DEFINE_KEYCODE(VOLUME_DOWN), // = {"VOLUME_DOWN",25}
... ...
DEFINE_KEYCODE(MENU), // = {"MENU",82}
... ...
DEFINE_KEYCODE(HELP), // = {HELP",259}
{ NULL, 0 }
};
在按键布局(Keylayout)文件中定义了linux扫描码和 KeycodeLabel字符串的对应关系
如在gpio-keys.kl文件中有
key 115 VOLUME_UP
key 114 VOLUME_DOWN
key 102 HOME
key 528 FOCUS
则linux扫描码115就对应KeycodeLabel字符串“VOLUME_UP”,而“VOLUME_UP”又对应到安卓KeyCode码24,故当linux的按键事件传递给安卓系统115键值最终会转换为安卓的KeyCode码24供安卓APP使用。
在安卓系统存在多个键盘布局文件(Keylayout),则具体某个驱动文件调用哪个kl文件是根据驱动的名字来确定的,如果找不到与驱动名字相同的文件,就会读取默认文件Generic.kl。如名字为gpio-keys的驱动就会读取gpio-keys.kl文件,如果该文件不存在,则读取Generic.kl文件。
2019-04-18 补充说明:
原以为这个东西很简单,像我下面这样设置一下就可以了,今天自己重新编译系统然后烧录进去之后发现除了HOME按键能正常工作之外,MENU+BACk按键都不能正常工作,同样的方法在linux kernel源代码中寻找这三个IO使用区别,但是很遗憾没找到不同的地方,只能想着是安卓上层的原因了,于是看了一下安卓的源代码,发现确实是不一样的,在gpio-keys.kl有下面的代码
key 115 VOLUME_UP
key 114 VOLUME_DOWN
key 102 HOME
key 528 FOCUS
从代码可以看到这个文件中没有设置BACK和MENU按键的值,我想应该把BACK和MENU的值加上去之后就可以了(还没有亲自测试过,待测试之后再把结果告诉大家)。看来要想支持实体按键不仅需要linux源码层支持,还需要安卓层支持,这两者相互合作才能达到目的。
先说一下背景:
新入手了一个开发板,开发板带有BACK+HOME+MENU实体按键,还有两个实体的音量加减按键。但是开机后发现音量键都是可以正常使用的,另外三个按键无法正常使用,在按键没有按下时测量这几个按键的电压发现音量键的电压是1.8V,另外三个按键的电压则是0V。根据电压值可推测,应该是在系统内部没有对这三个IO设置导致这几个IO不能体现其正常的功能。
既然要使用这几个实体按键,就只能老老实实的查看代码把功能添加上去了,这里我先说明一下,其实把按键对应的功能添加上非常容易,但是由于自己第一次做这样的工作,因此记录一下自己的想法和方法。
首先,这5个按键都是通过GPIO和soc链接的,既然音量键能正常工作就看这几个按键和音量键的GPIO设置有哪些区别呗,首先查看dtsi中设备树中这几个GPIO有哪些区别,发现在某个文件中有以下代码。
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
pinctrl-0 = <&gpio_key_active>;
pinctrl-1 = <&gpio_key_suspend>;
vol_up {
label = "volume_up";
gpios = <&msm_gpio 15 0x1>;
linux,input-type = <1>;
linux,code = <115>;
gpio-key,wakeup;
debounce-interval = <15>;
};
vol_down {
label = "volume_down";
gpios = <&msm_gpio 8 0x1>;
linux,input-type = <1>;
linux,code = <114>;
gpio-key,wakeup;
debounce-interval = <15>;
};
};
根据硬件链接可以知道音量“+”使用的时GPIO15,音量“-”使用的是GPIO8刚好和设备树中的gpios对应,故感觉这个就是音量相关的设备树的配置,那就尝试这找driver中的代码吧,看看驱动中是如何使用这些属性的。根据compatible = "gpio-keys"在找到了对应的驱动文件,翻阅了一下驱动文件好像也并没有对vol_up和vol_down做特别的处理,只是读取了设备树的属性,然后根据这些属性进行设置。既然这样,那直接把HOME+MENU+BACK按键的属性添加上去不就大功告成了,这样想着就把BACK+MENU+HOME对应的按键添加到了
gpio_keys {
......
......
vol_up{
......
......
};
vol_down{
......
......
};
home_key {
label = "home_key";
gpios = <&msm_gpio 9 0x1>;
linux,input-type = <1>;
linux,code = <102>;
gpio-key,wakeup;
debounce-interval = <15>;
};
back_button {
label = "back_button";
gpios = <&msm_gpio 10 0x1>;
linux,code = <158>;
linux,input-type = <1>;
gpio-key,wakeup;
debounce-interval = <15>;
};
menu_button {
label = "list_button";
gpios = <&msm_gpio 13 0x1>;
linux,code = <139>;
linux,input-type = <1>;
gpio-key,wakeup;
debounce-interval = <15>;
};
};
然后编译系统,下载进去之后测试,发现另外三个按键不能正常工作,但是不应该啊,因为驱动中没有特别针对音量键,想着是不是设备树中的设置有问题啊,于是又仔细看了一下设备树中gpio_keys的属性,发现有pinctrl-0 = <&gpio_key_active>;
pinctrl-1 = <&gpio_key_suspend>;这两个属性,于是就搜索了一下gpio_key_active和gpio_key_suspend,发现这两个属性在另外一个文件中定义,该文件中代码如下
tlmm_gpio_key {
qcom,pins = <&gp 15>, <&gp 8>;
qcom,pin-func = <0>;
qcom,num-grp-pins = <2>;
label = "tlmm_gpio_key";
gpio_key_active: gpio_key_active {
drive-strength = <2>;
bias-pull-up;
};
gpio_key_suspend: gpio_key_suspend {
drive-strength = <2>;
bias-pull-up;
};
};
看到这里就只有把BACK+MENU+HOME对应的gpio加入到这里了,代码如下
tlmm_gpio_key {
qcom,pins = <&gp 15>, <&gp 8>, <&gp 9>, <&gp 10>, <&gp 13>;
qcom,pin-func = <0>;
qcom,num-grp-pins = <5>;
label = "tlmm_gpio_key";
gpio_key_active: gpio_key_active {
drive-strength = <2>;
bias-pull-up;
};
gpio_key_suspend: gpio_key_suspend {
drive-strength = <2>;
bias-pull-up;
};
};
再次编译,下载。按键就全部可以使用了。
总体上说,做过一次之后这个东西很简单,只是在设备树中添加相应的属性即可。