4 * Open Hack'Ware BIOS PC keyboard driver.
6 * Copyright (c) 2005 Jocelyn Mayer
8 * This code is a rework (mostly simplification) from code
9 * proposed by Matthew Wood <mwood@realmsys.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License V2
13 * as published by the Free Software Foundation
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #define PCKBD_IO_BASE 0x60
31 #define PCKBD_COMMAND_OFFSET 0x4
32 #define PCKBD_STATUS_OFFSET 0x4
34 /* Indexes for keyboard state */
45 /* XXX: missing capslock */
46 /* XXX: TODO: add keypad/numlock ... (pc105 kbd) */
48 typedef struct kbdmap_t kbdmap_t;
53 typedef struct pckbd_t pckbd_t;
61 /* XXX: should not be here cause it's locale dependent */
62 static kbdmap_t pc_map_us[] = {
64 { { -1, -1, -1, -1, -1, -1, -1, -1, }, },
65 { { 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, }, },
66 { { '1', '!', -1, -1, '1', '!', -1, -1, }, },
67 { { '2', '\'', '\'', -1, -1, '2', '\'', '\'', }, },
68 { { '3', '#', -1, -1, '3', '#', -1, -1, }, },
69 { { '4', '$', -1, -1, '4', '$', -1, -1, }, },
70 { { '5', '%', -1, -1, '5', '%', -1, -1, }, },
71 { { '6', '^', -1, -1, '6', '^', -1, -1, }, },
73 { { '7', '&', -1, -1, '7', '&', -1, -1, }, },
74 { { '8', '*', -1, -1, '8', '*', -1, -1, }, },
75 { { '9', '(', -1, -1, '9', '(', -1, -1, }, },
76 { { '0', ')', -1, -1, '0', ')', -1, -1, }, },
77 { { '-', '_', -1, -1, '-', '_', -1, -1, }, },
78 { { '=', '+', -1, -1, '=', '+', -1, -1, }, },
79 { { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }, },
80 { { 0x2a, -1, -1, -1, 0x2a, -1, -1, -1, }, },
82 { { 'q', 'Q', -1, -1, 'q', 'Q', -1, -1, }, },
83 { { 'w', 'W', -1, -1, 'w', 'W', -1, -1, }, },
84 { { 'e', 'E', -1, -1, 'e', 'E', -1, -1, }, },
85 { { 'r', 'R', -1, -1, 'r', 'R', -1, -1, }, },
86 { { 't', 'T', -1, -1, 't', 'T', -1, -1, }, },
87 { { 'y', 'Y', -1, -1, 'y', 'Y', -1, -1, }, },
88 { { 'u', 'U', -1, -1, 'u', 'U', -1, -1, }, },
89 { { 'i', 'I', -1, -1, 'i', 'I', -1, -1, }, },
91 { { 'o', 'O', -1, -1, 'o', 'O', -1, -1, }, },
92 { { 'p', 'P', -1, -1, 'p', 'P', -1, -1, }, },
93 { { '[', '{', 0x1b, 0x1b, '[', '{', 0x1b, 0x1b, }, },
94 { { ']', '}', -1, -1, ']', '}', -1, -1, }, },
95 { { 0x0d, 0x0d, '\r', '\r', 0x0d, 0x0d, '\r', '\r', }, },
96 { { -1, -1, -1, -1, -1, -1, -1, -1, }, },
97 { { 'a', 'A', -1, -1, 'a', 'A', -1, -1, }, },
98 { { 's', 'S', -1, -1, 's', 'S', -1, -1, }, },
100 { { 'd', 'D', -1, -1, 'd', 'D', -1, -1, }, },
101 { { 'f', 'F', -1, -1, 'f', 'F', -1, -1, }, },
102 { { 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, }, },
103 { { 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, }, },
104 { { 'j', 'J', '\r', '\r', 'j', 'J', '\r', '\r', }, },
105 { { 'k', 'K', -1, -1, 'k', 'K', -1, -1, }, },
106 { { 'l', 'L', -1, -1, 'l', 'L', -1, -1, }, },
107 { { ';', ':', -1, -1, ';', ':', -1, -1, }, },
109 { { '\'', '"', -1, -1, '\'', '"', -1, -1, }, },
110 { { '`', '~', -1, -1, '`', '~', -1, -1, }, },
111 { { 0x02, -1, -1, -1, -1, -1, -1, -1, }, },
112 { { '\\', '|', -1, -1, '\\', '|', -1, -1, }, },
113 { { 'z', 'Z', -1, -1, 'z', 'Z', -1, -1, }, },
114 { { 'x', 'X', -1, -1, 'x', 'X', -1, -1, }, },
115 { { 'c', 'C', -1, -1, 'c', 'C', -1, -1, }, },
116 { { 'v', 'V', 0x16, 0x16, 'v', 'V', -1, -1, }, },
118 { { 'b', 'B', -1, -1, 'b', 'B', -1, -1, }, },
119 { { 'n', 'N', -1, -1, 'n', 'N', -1, -1, }, },
120 { { 'm', 'M', 0x0d, 0x0d, 'm', 'M', 0x0d, 0x0d, }, },
121 { { ',', '<', -1, -1, ',', '<', -1, -1, }, },
122 { { '.', '>', -1, -1, '.', '>', -1, -1, }, },
123 { { '/', '?', -1, -1, '/', '?', -1, -1, }, },
124 { { -1, -1, -1, -1, -1, -1, -1, -1, }, },
125 { { '*', '*', -1, -1, '*', '*', -1, -1, }, },
127 { { -1, -1, -1, -1, -1, -1, -1, -1, }, },
128 { { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, },
131 static int pckbd_open (unused void *private)
136 static int pckbd_close (unused void *private)
141 static int pckbd_readb (void *private)
143 pckbd_t *kbd = private;
144 int status, key, up, mod;
147 for (ret = -1; ret < 0; ) {
148 status = inb(kbd->io_base + PCKBD_STATUS_OFFSET);
150 /* No more data available */
153 key = inb(kbd->io_base);
154 up = (key & 0x80) != 0;
167 #if 0 /* XXX: missing definition */
173 kbd->modifiers &= ~mod;
175 kbd->modifiers |= mod;
178 /* We don't care about up events or unknown keys */
179 if (!up && key < kbd->maplen)
180 ret = kbd->map[key].translate[kbd->modifiers];
188 static cops_t pckbd_ops = {
195 int pckbd_register (void)
199 kbd = malloc(sizeof(pckbd_t));
202 memset(kbd, 0, sizeof(pckbd_t));
204 /* XXX: should be a parameter... */
205 kbd->io_base = PCKBD_IO_BASE;
206 /* Set default keymap */
207 kbd->map = pc_map_us;
208 kbd->maplen = sizeof(pc_map_us) / sizeof(kbdmap_t);
209 /* Reset modifiers state */
210 kbd->modifiers = 0x00;
211 chardev_register(CHARDEV_KBD, &pckbd_ops, kbd);