本帖最后由 haolele 于 2011-11-11 21:04 编辑  


Android系统移植之按键移植这一部分主要是移植android的键盘和按键 

(1)Android使用标准的linux输入事件设备(/dev/input目录下)和驱动,按键定义在内核include/linux/input.h文件中, 

按键定义形式如下: 

#define KEY_ESC            1 

#define KEY_1            2 

#define KEY_2            3 


(2)内核中(我的平台是arch/arm/mach-mmp/merlin.c文件)中按键的定义如下形式: 

static struct gpio_keys_button btn_button_table[] = { 

    = { 

        .code            =    KEY_F1, 

        .gpio            =    MFP_PIN_GPIO2, 

        .active_low        =    1,        /* 0 for down 0, up 1; 1 for down 1, up 0 */ 

        .desc            =    "H_BTN button", 

        .type            =    EV_KEY, 

        /* .wakeup            = */ 

        .debounce_interval    =    10,        /* 10 msec jitter elimination */ 

    }, 

    = { 

        .code            =    KEY_F2, 

        .gpio            =    MFP_PIN_GPIO3, 

        .active_low        =    1,        /* 0 for down 0, up 1; 1 for down 1, up 0 */ 

        .desc            =    "O_BTN button", 

        .type            =    EV_KEY, 

        /* .wakeup            = */ 

        .debounce_interval    =    10,        /* 10 msec jitter elimination */ 

    }, 

    = { 

        .code            =    KEY_F4, 

        .gpio            =    MFP_PIN_GPIO1, 

        .active_low        =    1,        /* 0 for down 0, up 1; 1 for down 1, up 0 */ 

        .desc            =    "S_BTN button", 

        .type            =    EV_KEY, 

        /* .wakeup            = */ 

        .debounce_interval    =    10,        /* 10 msec jitter elimination */ 

    }, 

}; 

static struct gpio_keys_platform_data gpio_keys_data = { 

    .buttons  = btn_button_table, 

    .nbuttons = ARRAY_SIZE(btn_button_table), 

}; 


static struct platform_device gpio_keys = { 

    .name = "gpio-keys", 

    .dev  = { 

        .platform_data = &gpio_keys_data, 

    }, 

    .id   = -1, 

}; 

上面定义是将MFP_PIN_GPIO2这个GPIO口的按键映射到Linux的KEY_F1按键,MPF_PIN_GPIO3映射到KEY_F2,MFP_PIN_GPIO1映射到KEY_F4 


(3)上面(2)步实现了从硬件GPIO口到内核标准按键的映射,但是android并没有直接使用映射后的键值,而且对其再进行了一次映射,从内核标准键值 

到android所用键值的映射表定义在android文件系统的/system/usr/keylayout目录下。标准的映射文件为qwerty.kl,定义如下: 

key 399   GRAVE 

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 139   MENU              WAKE_DROPPED 

key 59    MENU              WAKE_DROPPED 

key 127   SEARCH            WAKE_DROPPED 

key 217   SEARCH            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   CAMERA 


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 26    LEFT_BRACKET 

key 27    RIGHT_BRACKET 

key 43    BACKSLASH 


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 39    SEMICOLON 

key 40    APOSTROPHE 

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 53    SLASH 

key 28    ENTER 

         

key 56    ALT_LEFT 

key 100   ALT_RIGHT 

key 42    SHIFT_LEFT 

key 54    SHIFT_RIGHT 

key 15    TAB 

key 57    SPACE 

key 150   EXPLORER 

key 155   ENVELOPE         


key 12    MINUS 

key 13    EQUALS 

key 215   AT 


(4)android对底层按键的处理方法 

android按键的处理是Window Manager负责,主要的映射转换实现在android源代码frameworks/base/libs/ui/EventHub.cpp 

此文件处理来自底层的所有输入事件,并根据来源对事件进行分类处理,对于按键事件,处理过程如下: 

(a)记录驱动名称为 

(b)获取环境变量ANDROID_ROOT为系统路径(默认是/system,定义在android源代码/system/core/rootdir/init.rc文件中) 

(c)查找路径为"系统路径/usr/keylayout/驱动名称.kl"的按键映射文件,如果不存在则默认用路径为"系统路径/usr/keylayout/qwerty.kl" 

这个默认的按键映射文件,映射完成后再把经映射得到的android按键码值发给上层应用程序。 

所以我们可以在内核中定义多个按键设备,然后为每个设备设定不同的按键映射文件,不定义则会默认用qwerty.kl 


(5)举例 

上面(2)步我们在内核中声明了一个名为"gpio-keys"的按键设备,此设备定义在内核drivers/input/keyboard/gpio_keys.c文件中 

然后我们在内核启动过程中注册此设备:  platform_device_register(&gpio_keys); 

然后我们可以自己定义一个名为gpio-keys.kl的android按键映射文件,此文件的定义可以参考querty.kl的内容,比如说我们想将MPF_PIN_GPIO3 

对应的按键作android中的MENU键用,首先我们在内核中将MPF_PIN_GPIO3映射到KEY_F2,在内核include/linux/input.h中查找KEY_F2发现 

#define KEY_F2            60 

参照KEY_F2的值我们在gpio-keys.kl中加入如下映射即可 

key 60    MENU              WAKE 

其它按键也照此添加,完成后将按键表放置到/system/usr/keylayout目录下即可。 

补充: 

(1)android按键设备的映射关系可以在logcat开机日志中找的到(查找EventHub即可) 

(2)android按键设备由Window Manager负责,Window Manager从按键驱动读取内核按键码,然后将内核按键码转换成android按键码,转换完成 

后Window Manager会将内核按键码和android按键码一起发给应用程序来使用,这一点一定要注意。Android系统开发小知识-在android产品开 发中添加新的编译模块 Android开发中用户内容定义在vendor目录下,而用户产品的内容都定义在vendor/<company_name> /<board_name>目录下 

如果需要添加新的内容,可以在该目录下新建子目录,同时修改AndroidBoard.mk文件即可。比如说要添加一个按键映射文件: 

(1)在vendor/<company_name>/<board_name>目录下建立一个keymaps子目录 

(2)将我们需要的按键映射文件gpio-keys.kl和power-button.kl复制到keymaps目录下 

(3)在keymaps目录下新建一个Mdroid.mk文件,内容如下: 

LOCAL_PATH:= $(call my-dir) 

include $(CLEAR_VARS) 


file := $(TARGET_OUT_KEYLAYOUT)/gpio-keys.kl 

ALL_PREBUILT += $(file) 

$(file): $(LOCAL_PATH)/gpio-keys.kl | $(ACP) 

    $(transform-prebuilt-to-target) 


file := $(TARGET_OUT_KEYLAYOUT)/power-button.kl 

ALL_PREBUILT += $(file) 

$(file): $(LOCAL_PATH)/power-button.kl | $(ACP) 

    $(transform-prebuilt-to-target) 

(4)在vendor/<company_name>/<board_name>目录下的AndroidBoard.mk添加如下内容: 

include $(LOCAL_PATH)/keymaps/Mdroid.mk 

 haolele 发表于 2011-11-11 21:04:44
 Android系统移植之按键字符表
 
本帖最后由 haolele 于 2011-11-11 21:05 编辑  


Android系统移植之按键字符表 


上节讲android的Window Manager将内核按键码通过按键映射表转换成android按键码, 

这节讲的是android按键码向android字符的转换,转换也是通过Window Manager来完成的 

(1)原始按键字符表,我们知道一个按键是可以显示多个字符的,决定显示字符的是CAPS(大小写),FN,NUNMBER等按键 

举例如下: 

                                            

                                                         

# keycode       display number  base    caps    fn      caps_fn 

                                                         

A               'A'     '2'     'a'     'A'     '#'     0x00 

B               'B'     '2'     'b'     'B'     '<'     0x00 

C               'C'     '2'     'c'     'C'     '9'     0x00E7 

D               'D'     '3'     'd'     'D'     '5'     0x00 

E               'E'     '3'     'e'     'E'     '2'     0x0301 

F               'F'     '3'     'f'     'F'     '6'     0x00A5 

G               'G'     '4'     'g'     'G'     '-'     '_' 

H               'H'     '4'     'h'     'H'     '['     '{' 

I               'I'     '4'     'i'     'I'     '$'     0x0302 

J               'J'     '5'     'j'     'J'     ']'     '}' 

K               'K'     '5'     'k'     'K'     '"'     '~' 

L               'L'     '5'     'l'     'L'     '''     '`' 

M               'M'     '6'     'm'     'M'     '!'     0x00 

N               'N'     '6'     'n'     'N'     '>'     0x0303 

O               'O'     '6'     'o'     'O'     '('     0x00 

P               'P'     '7'     'p'     'P'     ')'     0x00 

Q               'Q'     '7'     'q'     'Q'     '*'     0x0300 

R               'R'     '7'     'r'     'R'     '3'     0x20AC 

S               'S'     '7'     's'     'S'     '4'     0x00DF 

T               'T'     '8'     't'     'T'     '+'     0x00A3 

U               'U'     '8'     'u'     'U'     '&'     0x0308 

V               'V'     '8'     'v'     'V'     '='     '^' 

W               'W'     '9'     'w'     'W'     '1'     0x00 

X               'X'     '9'     'x'     'X'     '8'     0xEF00 

Y               'Y'     '9'     'y'     'Y'     '%'     0x00A1 

Z               'Z'     '9'     'z'     'Z'     '7'     0x00 

                                                         

# on pc keyboards 

COMMA           ','     ','     ','     ';'     ';'     '|' 

PERIOD          '.'     '.'     '.'     ':'     ':'     0x2026 

AT              '@'     '0'     '@'     '0'     '0'     0x2022 

SLASH           '/'     '/'     '/'     '?'     '?'     '\' 

                                                         

SPACE           0x20    0x20    0x20    0x20    0xEF01  0xEF01 

ENTER         0xa     0xa     0xa     0xa     0xa     0xa 

                                                         

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            '+'     '+'     '+'     '+'     '+'     '+' 


(2)android为了减少载入时间,并没有使用原始按键表文件,而是将其转换成二进制文件 

转换的工具源代码在android源代码build/tools/kcm目录下,android在编译过程中会 

首先编译转换工具,然后利用转换工具将android源代码sdk/emulator/keymaps目录下 

的qwerty.kcm和qwerty2.kcm文件分别转换成qwerty.kcm.bin和qwerty2.kcm.bin 

转换后的二进制文件复制到out/target/product/<board_name>/system/usr/keychars 

目录下,也就是目标平台的/system/usr/keychars目录中。 


(3)Window Manager对按键的处理在android源代码frameworks/base/libs/ui/EventHub.cpp文件中 

Window Manager从内核接收到一个按键输入事件后会首先调用按键映射表将内核按键码映射成android按键码(这部分上节已讲),然后会 

将android按键码转换成字符,具体过程如下: 

(a)设置系统系统属性hw.keyboards.设备号.devname的值为设备名 

以上节的gpio-keys设备为例,会设置系统属性hw.keyboards.65539.devname的值为gpio-keys 

(b)载入按键字符表,首先载入/system/usr/keychars目录下的设备名.kcm.bin文件(此例即gpio-keys.kcm.bin文件),如果载入失败 

则载入该目录下的querty.kcm.bin. 

(c)利用载入的按键字符表将android按键转换成按键字符发给上层应用程序。 


(4)一般情况下一个控制按键是不需要作按键字符表的,系统会调用默认的去处理,但是如果要开发一个全功能键盘(包含了字母和数字),那可能就需要 

自己作一个专用的按键字符表了。android系统开发小问题-启动过程中android字符没有显示出来 android目标平台可以正常启动,但是启动过程中的android字符没有显示出来,这个是linux内核配置的问题 

打开内核framebuffer控制台即可。 

(1)make menuconifg后选择Device Drivers->Graphics support->Console display driver support->Framebuffer Console support 

然后打开相关的几个配置选项即可。 

(2)直接修改内核配置文件,如下: 

CONFIG_FRAMEBUFFER_CONSOLE=y 

CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y 

# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set 

CONFIG_FONTS=y 

CONFIG_FONT_8x8=y 

CONFIG_FONT_8x16=y 

CONFIG_FONT_6x11=y 

# CONFIG_FONT_7x14 is not set 

# CONFIG_FONT_PEARL_8x8 is not set 

# CONFIG_FONT_ACORN_8x8 is not set 

# CONFIG_FONT_MINI_4x6 is not set 

# CONFIG_FONT_SUN8x16 is not set 

# CONFIG_FONT_SUN12x22 is not set 

# CONFIG_FONT_10x18 is not set 

(3)android启动过程中的android字符显示在源代码的system/core/init.c中,如下: 

    if( load_565rle_image(INIT_IMAGE_FILE) ) { 

    fd = open("/dev/tty0", O_WRONLY); 

    if (fd >= 0) { 

        const char *msg; 

            msg = "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n"  // console is 40 cols x 30 lines 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "\n" 

        "             A N D R O I D "; 

        write(fd, msg, strlen(msg)); 

        close(fd); 

    } 

    }  

 haolele 发表于 2011-11-11 21:06:22