您的位置:首页 > 移动开发 > Android开发

Android按键事件——上层与驱动的映射

2014-10-13 14:11 429 查看
http://blog.csdn.net/zengdaquan007/article/details/8686431

首先查看android对上层按键事件的定义,在头文件<KeycodeLabels.h>中:

[cpp]
view plaincopy

static const KeycodeLabel KEYCODES[] = {
{ "SOFT_LEFT", 1 },
{ "SOFT_RIGHT", 2 },
{ "HOME", 3 },
{ "BACK", 4 },
{ "CALL", 5 },
{ "ENDCALL", 6 },
{ "0", 7 },
{ "1", 8 },
{ "2", 9 },
{ "3", 10 },
{ "4", 11 },
{ "5", 12 },
{ "6", 13 },
{ "7", 14 },
{ "8", 15 },
{ "9", 16 },
{ "STAR", 17 },
{ "POUND", 18 },
{ "DPAD_UP", 19 },
{ "DPAD_DOWN", 20 },
{ "DPAD_LEFT", 21 },
{ "DPAD_RIGHT", 22 },
{ "DPAD_CENTER", 23 },
{ "VOLUME_UP", 24 },
{ "VOLUME_DOWN", 25 },
{ "POWER", 26 },
{ "CAMERA", 27 },
{ "CLEAR", 28 },
{ "A", 29 },
{ "B", 30 },
{ "C", 31 },
{ "D", 32 },
{ "E", 33 },
{ "F", 34 },
{ "G", 35 },
{ "H", 36 },
{ "I", 37 },
{ "J", 38 },
{ "K", 39 },
{ "L", 40 },
{ "M", 41 },
{ "N", 42 },
{ "O", 43 },
{ "P", 44 },
{ "Q", 45 },
{ "R", 46 },
{ "S", 47 },
{ "T", 48 },
...
{ "BUTTON_14", 201 },
{ "BUTTON_15", 202 },
{ "BUTTON_16", 203 },
{ "LANGUAGE_SWITCH", 204 },
{ "MANNER_MODE", 205 },
{ "3D_MODE", 206 },
{ "CONTACTS", 207 },
{ "CALENDAR", 208 },
{ "MUSIC", 209 },
{ "CALCULATOR", 210 },
{ "ZENKAKU_HANKAKU", 211 },
{ "EISU", 212 },
{ "MUHENKAN", 213 },
{ "HENKAN", 214 },
{ "KATAKANA_HIRAGANA", 215 },
{ "YEN", 216 },
{ "RO", 217 },
{ "KANA", 218 },
{ "ASSIST", 219 },

// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.

{ NULL, 0 }
};

</span>

左边是事件的名称,根据字面意思非常容易了解其作用;右边是对应的事件号,比如我们在终端敲入"input keyevent 4"命令,就可以产生BACK的效果。上层按键事件的定义个人建议不要修改,如果增加了一个新的按键事件的定义,也要到KeyEvent.java里面作相应的修改。
按键的底层驱动事件是驱动开发人员自行定义的,这里我们只关心它上报的事件和对应的按键号。假如设备现在有6个按键,其对应的按键事件为:

按键 事件

key 1 0x01

key 2 0x02

key 3 0x03

key 4 0x04

key 5 0x05

key 6 0x06

目前的情况是,android上层已经有按键事件的定义了,底层驱动也有按键事件上报。但是缺少了中间的对接层,也就是说哪个按键对应哪种事件还不清楚。所以,需要为它们加入一个布局文件。按键的布局文件存放在frameworks/base/data/keyboards目录下,以.kl为后缀的文件都是键盘的布局文件,ls一下:

[cpp]
view plaincopy

android-4.2_r1/frameworks/base/data/keyboards$ ls
Android.mk
Generic.kcm
qwerty2.kcm qwerty.kl
Vendor_046d_Product_c294.kl
Vendor_054c_Product_0268.kl
Virtual.kcm
AVRCP.kl
Generic.kl
keyboards.mk
qwerty.idc
Vendor_045e_Product_028e.kl
Vendor_046d_Product_c299.kl
Vendor_05ac_Product_0239.kl
common.mk
qwerty2.idc
qwerty.kcm
Vendor_046d_Product_c216.kl
Vendor_046d_Product_c532.kl
Vendor_22b8_Product_093d.kl
</span>

具体读取哪个布局文件是根据驱动的名字来确定的,如果找不到与驱动名字相同的文件,就会读取默认文件Generic.kl。现在我们假设键盘在驱动层的名字为“my_keypad”,所以需要创建一个名为“my_keypad,kl”的布局文件。文件的内容是什么呢,不急。目前还有一点不明确,上面提到的6个按键的作用我们还没有定义。假设定义如下:

按键 作用

key 1 确定

key 2 返回

key 3 菜单

key 4 主解面

key 5 左移

key 6 右移

对应的布局文件“my_keypad,kl”的内容就应该为:

[cpp]
view plaincopy

<span style="font-size:14px;">key 0x1 ENTER
key 0x2 BACK
key 0x3 MENU
key 0x4 HOME
key 0x5 DPAD_LEFT
key 0x6 DPAD_RIGHT</span>

把布局文件编译进系统,在当前目录的common.mk中,在keylayouts变量的末尾加入: my_keypad.kl\

到这里,android键盘的底层驱动事件跟上层定义的按键事件就对应起来了。

************************************************************************************************************

我的实际工作经验,增加audio jack 的button的映射关系

1. @device/somc/yukon/AndroidBoard.mk中添加

include $(CLEAR_VARS)

LOCAL_MODULE := msm8226-tapan-snd-card_Button_Jack.kl

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE_CLASS := ETC

LOCAL_SRC_FILES := $(LOCAL_MODULE)

LOCAL_MODULE_PATH := $(TARGET_OUT_KEYLAYOUT)

include $(BUILD_PREBUILT)

则会在手机 system/usr/keylayout 目录下增加文件 msm8226-tapan-snd-card_Button_Jack.kl

2. @device/somc/yukon/platform.mk中增加

PRODUCT_PACKAGES += \

msm8226-tapan-snd-card_Button_Jack.kl

3. @device/somc/yukon目录下增加文件msm8226-tapan-snd-card_Button_Jack.kl

4. 特别注意 msm8226-tapan-snd-card_Button_Jack.kl的文件名不是随意写的。

status_t KeyMap::load@frameworks/base/libs/androidfw/keyboard.cpp

{

if (deviceConfiguration) {

String8 keyLayoutName;

if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),

....

}

// Try searching by device identifier.

if (probeKeyMap(deviceIdenfifier, String8::empty())) {

return OK;

}

// Fall back on the Generic key map.

// TODO Apply some additional heuristics here to figure out what kind of

// generic key map to use (US English, etc.) for typical external keyboards.

if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {

return OK;

}

// Try the Virtual key map as a last resort.

if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {

return OK;

}

}

#getevent -i

add device 2: /dev/input/event7

bus: 0000

vendor 0000

product 0000

version 0000

name: "msm8226-tapan-snd-card Button Jack"

location: "ALSA"

id: ""

version: 1.0.1

events:

KEY (0001): 00e2 0101 0102 0103 0104 0105 0106 0107

input props:

<none>

读取*.kl的名字组合顺序为

a. 首先查看 props中是否有keyboard.layout的参数,如果有则读取该名字的kl文件

b. 如果 该设备的vendor,product和version都不全为0,则通过它们的组合成 kl的文件名

Vendor_%04x_Product_%04x_Version_%04x.kl

Vendor_%04x_Product_%04x.kl

最终形成文件路径system/usr/keylayout/Vendor_xxxx_Product_xxxx.kl或system/usr/keylayout/Vendor_xxxx_Product_xxxx_Version_xxxx.kl

c. 如果vendor,product,version都为0,则通过该设备的name: "msm8226-tapan-snd-card Button Jack"来组合kl文件名

appendInputDeviceConfigurationFileRelativePath中会把其中的空格转换成'_'

最终形成文件路径system/usr/keylayout/msm8226-tapan-snd-card_Button_Jack.kl

5.还可以直接用 snd_jack_set_key 映射

ret = snd_jack_set_key(button_jack.jack,SND_JACK_BTN_0,KEY_MEDIA);

*********************************************************************************************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: