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 <rmk@arm.linux.org.uk>");
- MODULE_DESCRIPTION("AMBA KMI controller driver");
- MODULE_LICENSE("GPL");
/*
* 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 <rmk@arm.linux.org.uk>");
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);
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