现在的位置: 首页 > 综合 > 正文

ANDROID Porting系列八、Keymaps and Keyboard Input

2013年06月26日 ⁄ 综合 ⁄ 共 10668字 ⁄ 字号 评论关闭

•功能

•关键位置图

•关键字符映射

•实现您自己的驱动程序(驱动程序模板)

•示例实现

    本文档介绍了如何获取键盘输入转化为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, 
KEYCODE_DPAD_CENTER is the center button on the five-way navigation control. Even
though ALT + G generates a "?" character, 
KEYCODE_G is the keycode.

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 definitionsKey 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

Key
Character Map

选择一个Key Character Map

关键字符映射安装在system/usr/keychars and /data/usr/keychars.

对于每一个键盘设备xxx,设置android.keychar.xxx系统属性所希望的keychar文件的完整路径。如果你不指定一个keychar文件,Android 将默认为/system/usr/keychar/qwerty.kl.

文件格式

Key character map都存储在作为二进制资源设备,以减少加载时间。Key character map有以下特点:

Comments:英镑符号(#)表示注释,一行英镑的符号后字符被忽略。

Whitespace:所有的空行被忽略。

Column definitions:列定义,是遵照语法列MODIFIERS [...],
MODIFIERS
定义如下:

 

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

抱歉!评论已关闭.