android的设备带全键盘的很少,即使带全键盘的也都是USB HID键盘的居多,我们的设备类似于上网本,需要一个全键盘,但是设备上只有两个USB host口,Wifi用掉一个,剩下的一个USB host被用来做鼠标或者U盘接口用。刚好所用的ARM芯片带的有PS2控制器,所以我们采用PS键盘。linux本身支持PS2协议,如果PS2键盘使用的是标准的第二套键盘扫描码
101 102 和104 键的键盘:
KEY |
MAKE |
BREAK |
KEY |
MAKE |
BREAK |
KEY |
MAKE |
BREAK |
A |
1C |
F0,1C |
9 |
46 |
F0,46 |
[ |
54 |
F0,54 |
B |
32 |
F0,32 |
` |
0E |
F0,0E |
INSERT |
E0,70 |
E0,F0,70 |
C |
21 |
F0,21 |
- |
4E |
F0,4E |
HOME |
E0,6C |
E0,F0,6C |
D |
23 |
F0,23 |
= |
55 |
F0,55 |
PG UP |
E0,7D |
E0,F0,7D |
E |
24 |
F0,24 |
\ |
5D |
F0,5D |
DELETE |
E0,71 |
E0,F0,71 |
F |
2B |
F0,2B |
BKSP |
66 |
F0,66 |
END |
E0,69 |
E0,F0,69 |
G |
34 |
F0,34 |
SPACE |
29 |
F0,29 |
PG DN |
E0,7A |
E0,F0,7A |
H |
33 |
F0,33 |
TAB |
0D |
F0,0D |
U ARROW |
E0,75 |
E0,F0,75 |
I |
43 |
F0,43 |
CAPS |
58 |
F0,58 |
L ARROW |
E0,6B |
E0,F0,6B |
J |
3B |
F0,3B |
L SHFT |
12 |
F0,12 |
D ARROW |
E0,72 |
E0,F0,72 |
K |
42 |
F0,42 |
L CTRL |
14 |
F0,14 |
R ARROW |
E0,74 |
E0,F0,74 |
L |
4B |
F0,4B |
L GUI |
E0,1F |
E0,F0,1F |
NUM |
77 |
F0,77 |
M |
3A |
F0,3A |
L ALT |
11 |
F0,11 |
KP / |
E0,4A |
E0,F0,4A |
N |
31 |
F0,31 |
R SHFT |
59 |
F0,59 |
KP * |
7C |
F0,7C |
O |
44 |
F0,44 |
R CTRL |
E0,14 |
E0,F0,14 |
KP - |
7B |
F0,7B |
P |
4D |
F0,4D |
R GUI |
E0,27 |
E0,F0,27 |
KP + |
79 |
F0,79 |
Q |
15 |
F0,15 |
R ALT |
E0,11 |
E0,F0,11 |
KP EN |
E0,5A |
E0,F0,5A |
R |
2D |
F0,2D |
APPS |
E0,2F |
E0,F0,2F |
KP . |
71 |
F0,71 |
S |
1B |
F0,1B |
ENTER |
5A |
F0,5A |
KP 0 |
70 |
F0,70 |
T |
2C |
F0,2C |
ESC |
76 |
F0,76 |
KP 1 |
69 |
F0,69 |
U |
3C |
F0,3C |
F1 |
05 |
F0,05 |
KP 2 |
72 |
F0,72 |
V |
2A |
F0,2A |
F2 |
06 |
F0,06 |
KP 3 |
7A |
F0,7A |
W |
1D |
F0,1D |
F3 |
04 |
F0,04 |
KP 4 |
6B |
F0,6B |
X |
22 |
F0,22 |
F4 |
0C |
F0,0C |
KP 5 |
73 |
F0,73 |
Y |
35 |
F0,35 |
F5 |
03 |
F0,03 |
KP 6 |
74 |
F0,74 |
Z |
1A |
F0,1A |
F6 |
0B |
F0,0B |
KP 7 |
6C |
F0,6C |
0 |
45 |
F0,45 |
F7 |
83 |
F0,83 |
KP 8 |
75 |
F0,75 |
1 |
16 |
F0,16 |
F8 |
0A |
F0,0A |
KP 9 |
7D |
F0,7D |
2 |
1E |
F0,1E |
F9 |
01 |
F0,01 |
] |
5B |
F0,5B |
3 |
26 |
F0,26 |
F10 |
09 |
F0,09 |
; |
4C |
F0,4C |
4 |
25 |
F0,25 |
F11 |
78 |
F0,78 |
' |
52 |
F0,52 |
5 |
2E |
F0,2E |
F12 |
07 |
F0,07 |
, |
41 |
F0,41 |
6 |
36 |
F0,36 |
PRNT SCRN |
E0,12, E0,7C |
E0,F0,7C, E0,F0,12 |
. |
49 |
F0,49 |
7 |
3D |
F0,3D |
SCROLL |
7E |
F0,7E |
/ |
4A |
F0,4A |
8 |
3E |
F0,3E |
PAUSE |
E1,14,77,E1F0,14,F0,77 |
-NONE |
|
|
|
ACPI扫描码:
Key |
Make Code |
Break Code |
Power |
E0,37 |
E0, F0, 37 |
Sleep |
E0,3F |
E0, F0, 3F |
Wake |
E0,5E |
E0, F0, 5E |
Windows多媒体扫描码:
Key |
Make Code |
Break Cod |
Next Track |
E0, 4D |
E0, F0, 4D |
Previous Track |
E0, 15 |
E0, F0, 15 |
Stop |
E0, 3B |
E0, F0, 3B |
Play/Pause |
E0, 34 |
E0, F0, 34 |
Mute |
E0, 23 |
E0, F0, 23 |
Volume Up |
E0, 32 |
E0, F0, 32 |
Volume Down |
E0, 21 |
E0, F0, 21 |
Media Select |
E0, 50 |
E0, F0, 50 |
|
E0, 48 |
E0, F0, 48 |
Calculator |
E0, 2B |
E0, F0, 2B |
My Computer |
E0, 40 |
E0, F0, 40 |
WWW Search |
E0, 10 |
E0, F0, 10 |
WWW Home |
E0, 3A |
E0, F0, 3A |
WWW Back |
E0, 38 |
E0, F0, 38 |
WWW Forward |
E0, 30 |
E0, F0, 30 |
WWW Stop |
E0, 28 |
E0, F0, 28 |
WWW Refresh |
E0, 20 |
E0, F0, 20 |
WWW Favorites |
E0, 18 |
E0, F0, 18 |
则可以使用linux自带的PS2键盘驱动,由于我的ARM芯片使用的PS2控制器是ARM公司提供的IP核,PS2 控制器的控制寄存器和状态寄存器可以参看ARM网站上的DDI0143.pdf(ARM PrimeCell PS2Keyboard/Mouse Interface (PL050))文档,实际上内核在\kernel\drivers\input\serio\目录下提供了PS2控制器的驱动文件ambakmi.c,没有的话网上也有下载。
/* * linux/drivers/input/serio/ambakmi.c * * Copyright (C) 2000-2003 Deep Blue Solutions Ltd. * Copyright (C) 2002 Russell King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include <linux/module.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/device.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/amba/bus.h> #include <linux/amba/kmi.h> #include <linux/clk.h> #include <linux/gpio.h> #include <asm/io.h> #include <asm/irq.h> #define KMI_BASE (kmi->base) struct amba_kmi_port { struct serio *io; struct clk *clk; void __iomem *base; unsigned int irq; unsigned int divisor; unsigned int open; }; static irqreturn_t amba_kmi_int(int irq, void *dev_id) { struct amba_kmi_port *kmi = dev_id; unsigned int status = readb(KMIIR); int handled = IRQ_NONE; while (status & KMIIR_RXINTR) { serio_interrupt(kmi->io, readb(KMIDATA), 0); status = readb(KMIIR); handled = IRQ_HANDLED; } return handled; } static int amba_kmi_write(struct serio *io, unsigned char val) { struct amba_kmi_port *kmi = io->port_data; unsigned int timeleft = 10000; /* timeout in 100ms */ while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft) udelay(10); if (timeleft) writeb(val, KMIDATA); return timeleft ? 0 : SERIO_TIMEOUT; } static int amba_kmi_open(struct serio *io) { struct amba_kmi_port *kmi = io->port_data; unsigned int divisor; int ret; int gpccon; // ret = clk_enable(kmi->clk); // if (ret) ret = readb(KMICR);//add by zhaojun if (ret & KMICR_EN)//add by zhaojun goto out; // divisor = clk_get_rate(kmi->clk) / 8000000 - 1; divisor = 0xf;//add by zhaojun writeb(divisor, KMICLKDIV); writeb(KMICR_EN, KMICR); // set gpc to pic function add by zhaojun imapx_gpio_setcfg(IMAPX_GPC_RANGE(4, 7), IG_CTRL0, IG_NORMAL); ret = request_irq(kmi->irq, amba_kmi_int, IRQF_DISABLED, "kmi-pl050", kmi); if (ret) { printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq); writeb(0, KMICR); goto clk_disable; } writeb(KMICR_EN | KMICR_RXINTREN, KMICR); return 0; clk_disable: clk_disable(kmi->clk); out: return ret; } static void amba_kmi_close(struct serio *io) { struct amba_kmi_port *kmi = io->port_data; writeb(0, KMICR); free_irq(kmi->irq, kmi); clk_disable(kmi->clk); } static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; int ret; ret = amba_request_regions(dev, NULL); if (ret) return ret; kmi = kzalloc(sizeof(struct amba_kmi_port), GFP_KERNEL); io = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!kmi || !io) { ret = -ENOMEM; goto out; } io->id.type = SERIO_8042; io->write = amba_kmi_write; io->open = amba_kmi_open; io->close = amba_kmi_close; strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name)); strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys)); io->port_data = kmi; io->dev.parent = &dev->dev; kmi->io = io; kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!kmi->base) { ret = -ENOMEM; goto out; } // if (IS_ERR(kmi->clk)) { // ret = PTR_ERR(kmi->clk); // goto unmap; // } kmi->irq = dev->irq[0]; amba_set_drvdata(dev, kmi); serio_register_port(kmi->io); return 0; //unmap: // iounmap(kmi->base); out: kfree(kmi); kfree(io); amba_release_regions(dev); return ret; } static int amba_kmi_remove(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); amba_set_drvdata(dev, NULL); serio_unregister_port(kmi->io); clk_put(kmi->clk); iounmap(kmi->base); kfree(kmi); amba_release_regions(dev); return 0; } static int amba_kmi_resume(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); /* kick the serio layer to rescan this port */ serio_reconnect(kmi->io); return 0; } static struct amba_id amba_kmi_idtable[] = { { .id = 0x00041050, .mask = 0x000fffff, }, { 0, 0 } }; static struct amba_driver ambakmi_driver = { .drv = { .name = "kmi-pl050", }, .id_table = amba_kmi_idtable, .probe = amba_kmi_probe, .remove = amba_kmi_remove, .resume = amba_kmi_resume, }; static int __init amba_kmi_init(void) { return amba_driver_register(&ambakmi_driver); } static void __exit amba_kmi_exit(void) { amba_driver_unregister(&ambakmi_driver); } module_init(amba_kmi_init); module_exit(amba_kmi_exit); MODULE_AUTHOR("Russell King <[email protected]>"); MODULE_DESCRIPTION("AMBA KMI controller driver"); MODULE_LICENSE("GPL");
platform资源如下
struct amba_device imap_ps2_device = { .dev = { .init_name = "kmi-pl050", .coherent_dma_mask = ~0, }, .res = { .start = 0x20E70000, .end = 0x20E71000, .flags = IORESOURCE_MEM, }, .irq = { IRQ_PS2_0, NO_IRQ }, .periphid = 0x00041050, }; EXPORT_SYMBOL(imap_ps2_device);
再用platform_add_devices函数在init_machine时加上这个设备即可。
另外编译时需要选择上
-> Device Drivers
-> Input device support
->keyboards
->AT keyboard
------------------------------------------------------------------------------------
QQ:229425962
------------------------------------------------------------------------------------