•关键位置图
•关键字符映射
•实现您自己的驱动程序(驱动程序模板)
•示例实现
本文档介绍了如何获取键盘输入转化为Android actions,以及如何可以自定义键的布局和重点字符映射到自己的设备相匹配的需要。
Android使用Linux操作系统的标准输入设备事件(/ dev/event0)和驱动在linuxlinux/input.h内核头文件描述。欲了解更多有关标准的Linux驱动程序的信息输入,请http://kernel.org seeLinux输入驱动。
功能
Android的输入设备是围绕事件中断或轮询例程捕获特定于设备的scancode,并将其转换为标准的形式可以接受的Linux操作系统(如input.h定义),然后input_event()将其传递给内核。
该键盘映射驱动的其他主要功能是建立一个probe功能,设置了中断或轮询功能,处理硬件的初始化,并用input_register_devic()关联输入子系统。
下表描述了所需的步骤,从键盘输入转换为application action:
Step |
Action |
Explanation |
1. |
Window manager reads key event from Linux keyboard driver. |
Events are typically positional. For example, the top-left position on a keypad returns 16 regardless of whether that key is printed with a Q (as on a QWERTY keypad) or an A (as on an AZERTY keypads). This first conversion by the Linux Keyboard Driver yields a scancode (for example, 16). |
2. |
Window manager maps scancode to keycode. |
When the window manager reads a key event out of the driver, it maps the scancode to a keycode using a key layout map file. Typically, the keycode is the primary symbol screen-printed on a key. For example, |
3. |
Window manager sends both the scancode and the keycode to the application. |
Both the scancode and keycode are handled by the view with focus. How the application interprets both depend on the application. |
Key Layout Map
选择一个Key Layout Map
Key Layout是安装在/system/usr/keylayout和/data/usr/keylayout.。
对于每一个键盘设备xxx,设置android.keylayout.xxx系统属性(参见帮助设置系统属性的建立新的Device)。如果你不指定一个keylayout文件,机器人将默认为/system/usr/keylayout/qwerty.kl。
文件格式
Key layout maps都存储在设备的UTF - 8文本文件,并具有以下特点:
•Comments:英镑符号(#)表示注释,一行英镑的符号后字符被忽略。
•Whitespace:所有的空行被忽略。
•Key definitions:Key definitions遵循语法key SCANCODE KEYCODE [FLAGS...], SCANCODE是一个数字,KEYCODE是在特定keylayout文件定义。(android.keylayout.xxx),和潜在的FLAGS 定义如下:
ØSHIFT:在按下时,shift键修饰符设置
Ø ALT:当按下时,Alt键修饰符设置
ØCAPS:在按下时,大写锁定键修饰符设置
ØWAKE:当这个键被按下,而该设备是睡着了,器件将唤醒和key事件被发送到应用程序。
ØWAKE_DROPPED:当这个键被按下,而该设备是睡着了,器件将唤醒和key事件不会得到发送到应用程序。
Key Layout Map的一个范例文件
下面的代码来自android/src/device/product/generic/tuttle2.kl,是一个完整的Key Layout Map示例文件:
# Copyright 2007 Google Inc.
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
key 7 6
key 8 7
key 9 8
key 10 9
key 11 0
key 158 BACK WAKE_DROPPED
key 230 SOFT_RIGHT WAKE
key 60 SOFT_RIGHT WAKE
key 107 ENDCALL WAKE_DROPPED
key 62 ENDCALL WAKE_DROPPED
key 229 MENU WAKE_DROPPED
key 59 MENU WAKE_DROPPED
key 228 POUND
key 227 STAR
key 231 CALL WAKE_DROPPED
key 61 CALL WAKE_DROPPED
key 232 DPAD_CENTER WAKE_DROPPED
key 108 DPAD_DOWN WAKE_DROPPED
key 103 DPAD_UP WAKE_DROPPED
key 102 HOME WAKE
key 105 DPAD_LEFT WAKE_DROPPED
key 106 DPAD_RIGHT WAKE_DROPPED
key 115 VOLUME_UP
key 114 VOLUME_DOWN
key 116 POWER WAKE
key 212 SLASH
key 16 Q
key 17 W
key 18 E
key 19 R
key 20 T
key 21 Y
key 22 U
key 23 I
key 24 O
key 25 P
key 30 A
key 31 S
key 32 D
key 33 F
key 34 G
key 35 H
key 36 J
key 37 K
key 38 L
key 14 DEL
key 44 Z
key 45 X
key 46 C
key 47 V
key 48 B
key 49 N
key 50 M
key 51 COMMA
key 52 PERIOD
key 28 NEWLINE
key 56 ALT_LEFT
key 42 SHIFT_LEFT
key 215 AT
key 57 SPACE
key 53 SLASH
key 127 SYM
key 100 ALT_LEFT
key 399 GRAVE
Character in MODIFIERS |
Corresponding bit in the modifiers |
O |
no modifiers |
S |
MODIFIER_SHIFT |
C |
MODIFIER_CONTROL |
L |
MODIFIER_CAPS_LOCK |
A |
MODIFIER_ALT |
· Key character file: Key definitions有语法 key SCANCODE CHARACTER [...] 其中SCANCODE是一个数字和字符值或者使用UTF - 8的引号字符(for example, "a")或一个数字值,strtol可以解析。
·一个Key Character Map示例文件
·下面的代码来自android/src/device/product/generic/tuttle2.kcm,代表一个完整的key character file:
·该行表示什么类型的键盘类设备实现。可能的类型包括:
· NUMERIC:一个数字(12键)键盘。
· Q14:键盘,其中包括所有的字母,但一键多个字母除外。
· QWERTY键盘:与所有字母和可能的数字键盘。此选项适用于所有完整的键盘配置,如AZERTY。.
# Copyright 2007 Google Inc.
[type=QWERTY]
# keycode base caps fn caps_fn number display_label
A 'a' 'A' '%' 0x00 '%' 'A'
B 'b' 'B' '=' 0x00 '=' 'B'
C 'c' 'C' '8' 0x00E7 '8' 'C'
D 'd' 'D' '5' 0x00 '5' 'D'
E 'e' 'E' '2' 0x0301 '2' 'E'
F 'f' 'F' '6' 0x00A5 '6' 'F'
G 'g' 'G' '-' '_' '-' 'G'
H 'h' 'H' '[' '{' '[' 'H'
I 'i' 'I' '$' 0x0302 '$' 'I'
J 'j' 'J' ']' '}' ']' 'J'
K 'k' 'K' '"' '~' '"' 'K'
L 'l' 'L' ''' '`' ''' 'L'
M 'm' 'M' '>' 0x00 '>' 'M'
N 'n' 'N' '<' 0x0303 '<' 'N'
O 'o' 'O' '(' 0x00 '(' 'O'
P 'p' 'P' ')' 0x00 ')' 'P'
Q 'q' 'Q' '*' 0x0300 '*' 'Q'
R 'r' 'R' '3' 0x20AC '3' 'R'
S 's' 'S' '4' 0x00DF '4' 'S'
T 't' 'T' '+' 0x00A3 '+' 'T'
U 'u' 'U' '&' 0x0308 '&' 'U'
V 'v' 'V' '9' '^' '9' 'V'
W 'w' 'W' '1' 0x00 '1' 'W'
X 'x' 'X' '7' 0xEF00 '7' 'X'
Y 'y' 'Y' '!' 0x00A1 '!' 'Y'
Z 'z' 'Z' '#' 0x00 '#' 'Z'
COMMA ',' ';' ';' '|' ',' ','
PERIOD '.' ':' ':' 0x2026 '.' '.'
AT '@' '0' '0' 0x2022 '0' '@'
SLASH '/' '?' '?' '/' '/' '/'
SPACE 0x20 0x20 0x9 0x9 0x20 0x20
NEWLINE 0xa 0xa 0xa 0xa 0xa 0xa
# on pc keyboards
TAB 0x9 0x9 0x9 0x9 0x9 0x9
0 '0' ')' ')' ')' '0' '0'
1 '1' '!' '!' '!' '1' '1'
2 '2' '@' '@' '@' '2' '2'
3 '3' '#' '#' '#' '3' '3'
4 '4' '$' '$' '$' '4' '4'
5 '5' '%' '%' '%' '5' '5'
6 '6' '^' '^' '^' '6' '6'
7 '7' '&' '&' '&' '7' '7'
8 '8' '*' '*' '*' '8' '8'
9 '9' '(' '(' '(' '9' '9'
GRAVE '`' '~' '`' '~' '`' '`'
MINUS '-' '_' '-' '_' '-' '-'
EQUALS '=' '+' '=' '+' '=' '='
LEFT_BRACKET '[' '{' '[' '{' '[' '['
RIGHT_BRACKET ']' '}' ']' '}' ']' ']'
BACKSLASH '/' '|' '/' '|' '/' '/'
SEMICOLON ';' ':' ';' ':' ';' ';'
APOSTROPHE ''' '"' ''' '"' ''' '''
STAR '*' '*' '*' '*' '*' '*'
POUND '#' '#' '#' '#' '#' '#'
PLUS '+' '+' '+' '+' '+' '+'
资源二进制文件格式
以上文件片断通过makekcharmap工具得到转化并作为build过程的一部分。您可以mmap这个文件,共享约4kB memory,在进程间使用,以尽量减少加载时间.
Offset |
Size (bytes) |
Description |
0x00-0x0b |
|
The ascii value "keycharmap1" including the null character |
0x0c-0x0f |
|
padding |
0x10-0x13 |
|
The number of entries in the modifiers table (COLS) |
0x14-0x17 |
|
The number of entries in the characters table (ROWS) |
0x18-0x1f |
|
padding |
|
4*COLS |
Modifiers table. The modifier mask values that each of the columns in the characters table correspond to. |
|
|
padding to the next 16 byte boundary |
|
4*COLS*ROWS |
Characters table. The modifier mask values that each of the columns correspond to. |
实现自己的驱动程序(驱动程序模板)
以下文件,pguide_events.c,说明如何实现一个Android键盘映射的驱动程序。
/*
* pguide_events.c
*
* ANDROID PORTING GUIDE: INPUT EVENTS DRIVER TEMPLATE
*
* This template is designed to an example of the functionality
* necessary for Android to recieve input events. The PGUIDE_EVENT
* macros are meant as pointers indicating where to implement the
* hardware specific code necessary for the new device. The existence
* of the macros is not meant to trivialize the work required, just as
* an indication of where the work needs to be done.
*
* Copyright 2007, Google Inc.
* Based on goldfish-events.c
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PGUIDE_EVENTS_INTERRUPT do{} while(0)
#define PGUIDE_EVENTS_PROBE do{} while(0)
struct event_dev {
struct input_dev *input;
int irq;
};
static irqreturn_t pguide_events_interrupt(int irq, void *dev_id)
{
struct event_dev *edev = dev_id;
unsigned type=0, code=0, value=0;
/* Set up type, code, and value per input.h
*/
PGUIDE_EVENTS_INTERRUPT;
input_event(edev->input, type, code, value);
return IRQ_HANDLED;
}
static int pguide_events_probe(struct platform_device *pdev)
{
struct input_dev *input_dev;
struct event_dev *edev;
printk("*** pguide events probe ***/n");
edev = kzalloc(sizeof(struct event_dev), GFP_KERNEL);
input_dev = input_allocate_device();
/* Setup edev->irq and do any hardware init */
PGUIDE_EVENTS_PROBE;
if(request_irq(edev->irq, pguide_events_interrupt, 0,
"pguide_events", edev) < 0) {
goto fail;
}
/* indicate that we generate key events */
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_REL, input_dev->evbit);
set_bit(EV_ABS, input_dev->evbit);
/* indicate that we generate *any* key event */
bitmap_fill(input_dev->keybit, KEY_MAX);
bitmap_fill(input_dev->relbit, REL_MAX);
bitmap_fill(input_dev->absbit, ABS_MAX);
platform_set_drvdata(pdev, edev);
input_dev->name = "pguide_events";
input_dev->private = edev;
input_dev->cdev.dev = &pdev->dev;
input_register_device(input_dev);
return 0;
fail:
kfree(edev);
input_free_device(input_dev);
return -EINVAL;
}
static struct platform_driver pguide_events_driver = {
.probe = pguide_events_probe,
.driver = {
.name = "pguide_events",
},
};
static int __devinit pguide_events_init(void)
{
return platform_driver_register(&pguide_events_driver);
}
static void __exit pguide_events_exit(void)
{
}
module_init(pguide_events_init);
module_exit(pguide_events_exit);
MODULE_DESCRIPTION("Pguide Event Device");
MODULE_LICENSE("GPL");
示例实现
以下假设为一个新的键盘设备安装:
android.keylayout.partnerxx_keypad = /system/usr/keylayout/partnerxx_keypad.kl
android.keychar.partnerxx_keypad = /system/usr/keychars/partnerxx.kcm
下面的示例日志文件表明您已正确注册了新的键盘:
I/EventHub( 1548): New device: path=/dev/input/event0 name=partnerxx_keypad id=0x10000 (of 0x1) index=1 fd=30
I/EventHub( 1548): new keyboard input device added, name = partnerxx_keypad
D/WindowManager( 1548): Starting input thread.
D/WindowManager( 1548): Startup complete!
I/EventHub( 1548): New keyboard: name=partnerxx_keypad
keymap=partnerxx_keypad.kl
keymapPath=/system/usr/keychars/partnerxx_keypad.kcm.bin
I/ServiceManager( 1535): ServiceManager: addService(window, 0x13610)
I/EventHub( 1548): Reporting device opened: id=0x10000, name=/dev/input/event0
I/KeyInputQueue( 1548): Device added: id=0x10000, name=partnerxx_keypad, classes=1
I/KeyInputQueue( 1548): Keymap: partnerxx_keypad.kl