75df174d205833af75dc2e9bee1e6d6e6161e07e
[reactos.git] / reactos / ntoskrnl / dbg / kdb_keyboard.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/dbg/kdb_keyboard.c
22 * PURPOSE: Keyboard driver
23 * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
24 * Jason Filby (jasonfilby@yahoo.com)
25 */
26
27 /* INCLUDES ****************************************************************/
28
29 #include <ddk/ntddk.h>
30 #include <string.h>
31 #include <ntos/keyboard.h>
32 #include <ntos/minmax.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 #if 1
38
39 #define KBD_STATUS_REG 0x64
40 #define KBD_CNTL_REG 0x64
41 #define KBD_DATA_REG 0x60
42
43 #define KBD_DISABLE_MOUSE 0xA7
44 #define KBD_ENABLE_MOUSE 0xA8
45
46 #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
47
48 #define kbd_write_command(cmd) WRITE_PORT_UCHAR((PUCHAR)KBD_STATUS_REG,cmd)
49 #define kbd_read_input() READ_PORT_UCHAR((PUCHAR)KBD_DATA_REG)
50 #define kbd_read_status() READ_PORT_UCHAR((PUCHAR)KBD_STATUS_REG)
51
52 static unsigned char keyb_layout[2][128] =
53 {
54 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
55 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
56 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
57 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
58 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
59 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
60 "\r\000/" /* 0x60 - 0x6f */
61 ,
62 "\000\033!@#$%^&*()_+\177\t" /* 0x00 - 0x0f */
63 "QWERTYUIOP{}\r\000AS" /* 0x10 - 0x1f */
64 "DFGHJKL:\"`\000\\ZXCV" /* 0x20 - 0x2f */
65 "BNM<>?\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
66 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
67 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
68 "\r\000/" /* 0x60 - 0x6f */
69 };
70
71 typedef BYTE byte_t;
72
73 VOID KbdEnableMouse()
74 {
75 kbd_write_command(KBD_ENABLE_MOUSE);
76 }
77
78 VOID KbdDisableMouse()
79 {
80 kbd_write_command(KBD_DISABLE_MOUSE);
81 }
82
83 CHAR
84 KdbTryGetCharKeyboard(PULONG ScanCode)
85 {
86 static byte_t last_key = 0;
87 static byte_t shift = 0;
88 char c;
89 while(1) {
90 unsigned char status = kbd_read_status();
91 while (status & KBD_STAT_OBF) {
92 byte_t scancode;
93 scancode = kbd_read_input();
94 /* check for SHIFT-keys */
95 if (((scancode & 0x7F) == 42) || ((scancode & 0x7F) == 54))
96 {
97 shift = !(scancode & 0x80);
98 continue;
99 }
100 /* ignore all other RELEASED-codes */
101 if (scancode & 0x80)
102 last_key = 0;
103 else if (last_key != scancode)
104 {
105 //printf("kbd: %d, %d, %c\n", scancode, last_key, keyb_layout[shift][scancode]);
106 last_key = scancode;
107 c = keyb_layout[shift][scancode];
108 *ScanCode = scancode;
109 if (c > 0) return c;
110 }
111 }
112 }
113 }
114
115 #endif
116
117 #if 0
118
119 /* GLOBALS *******************************************************************/
120
121 /*
122 * Keyboard I/O ports.
123 */
124 #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
125 #define K_STATUS 0x64 /* keybd status (read-only) */
126 #define K_CMD 0x64 /* keybd ctlr command (write-only) */
127
128 /*
129 * Bit definitions for K_STATUS port.
130 */
131 #define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */
132 #define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */
133 #define K_SYSFLAG 0x04 /* "System Flag" */
134 #define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */
135 #define K_KBD_INHIBIT 0x10 /* 0 if keyboard inhibited */
136 #define K_AUX_OBUF_FUL 0x20 /* 1 = obuf holds aux device data */
137 #define K_TIMEOUT 0x40 /* timout error flag */
138 #define K_PARITY_ERROR 0x80 /* parity error flag */
139
140 /*
141 * Keyboard controller commands (sent to K_CMD port).
142 */
143 #define KC_CMD_READ 0x20 /* read controller command byte */
144 #define KC_CMD_WRITE 0x60 /* write controller command byte */
145 #define KC_CMD_DIS_AUX 0xa7 /* disable auxiliary device */
146 #define KC_CMD_ENB_AUX 0xa8 /* enable auxiliary device */
147 #define KC_CMD_TEST_AUX 0xa9 /* test auxiliary device interface */
148 #define KC_CMD_SELFTEST 0xaa /* keyboard controller self-test */
149 #define KC_CMD_TEST 0xab /* test keyboard interface */
150 #define KC_CMD_DUMP 0xac /* diagnostic dump */
151 #define KC_CMD_DISABLE 0xad /* disable keyboard */
152 #define KC_CMD_ENABLE 0xae /* enable keyboard */
153 #define KC_CMD_RDKBD 0xc4 /* read keyboard ID */
154 #define KC_CMD_WIN 0xd0 /* read output port */
155 #define KC_CMD_WOUT 0xd1 /* write output port */
156 #define KC_CMD_ECHO 0xee /* used for diagnostic testing */
157 #define KC_CMD_PULSE 0xff /* pulse bits 3-0 based on low nybble */
158
159 /*
160 * Keyboard commands (send to K_RDWR).
161 */
162 #define K_CMD_LEDS 0xed /* set status LEDs (caps lock, etc.) */
163 #define K_CMD_TYPEMATIC 0xf3 /* set key repeat and delay */
164
165 /*
166 * Bit definitions for controller command byte (sent following
167 * KC_CMD_WRITE command).
168 *
169 * Bits 0x02 and 0x80 unused, always set to 0.
170 */
171 #define K_CB_ENBLIRQ 0x01 /* enable data-ready intrpt */
172 #define K_CB_SETSYSF 0x04 /* Set System Flag */
173 #define K_CB_INHBOVR 0x08 /* Inhibit Override */
174 #define K_CB_DISBLE 0x10 /* disable keyboard */
175 #define K_CB_IGNPARITY 0x20 /* ignore parity from keyboard */
176 #define K_CB_SCAN 0x40 /* standard scan conversion */
177
178 /*
179 * Bit definitions for "Indicator Status Byte" (sent after a
180 * K_CMD_LEDS command). If the bit is on, the LED is on. Undefined
181 * bit positions must be 0.
182 */
183 #define K_LED_SCRLLK 0x1 /* scroll lock */
184 #define K_LED_NUMLK 0x2 /* num lock */
185 #define K_LED_CAPSLK 0x4 /* caps lock */
186
187 /*
188 * Bit definitions for "Miscellaneous port B" (K_PORTB).
189 */
190 /* read/write */
191 #define K_ENABLETMR2 0x01 /* enable output from timer 2 */
192 #define K_SPKRDATA 0x02 /* direct input to speaker */
193 #define K_ENABLEPRTB 0x04 /* "enable" port B */
194 #define K_EIOPRTB 0x08 /* enable NMI on parity error */
195 /* read-only */
196 #define K_REFRESHB 0x10 /* refresh flag from INLTCONT PAL */
197 #define K_OUT2B 0x20 /* timer 2 output */
198 #define K_ICKB 0x40 /* I/O channel check (parity error) */
199
200 /*
201 * Bit definitions for the keyboard controller's output port.
202 */
203 #define KO_SYSRESET 0x01 /* processor reset */
204 #define KO_GATE20 0x02 /* A20 address line enable */
205 #define KO_AUX_DATA_OUT 0x04 /* output data to auxiliary device */
206 #define KO_AUX_CLOCK 0x08 /* auxiliary device clock */
207 #define KO_OBUF_FUL 0x10 /* keyboard output buffer full */
208 #define KO_AUX_OBUF_FUL 0x20 /* aux device output buffer full */
209 #define KO_CLOCK 0x40 /* keyboard clock */
210 #define KO_DATA_OUT 0x80 /* output data to keyboard */
211
212 /*
213 * Keyboard return codes.
214 */
215 #define K_RET_RESET_DONE 0xaa /* BAT complete */
216 #define K_RET_ECHO 0xee /* echo after echo command */
217 #define K_RET_ACK 0xfa /* ack */
218 #define K_RET_RESET_FAIL 0xfc /* BAT error */
219 #define K_RET_RESEND 0xfe /* resend request */
220
221 #define SHIFT -1
222 #define CTRL -2
223 #define META -3
224
225 static char keymap[128][2] = {
226 {0}, /* 0 */
227 {27, 27}, /* 1 - ESC */
228 {'1', '!'}, /* 2 */
229 {'2', '@'},
230 {'3', '#'},
231 {'4', '$'},
232 {'5', '%'},
233 {'6', '^'},
234 {'7', '&'},
235 {'8', '*'},
236 {'9', '('},
237 {'0', ')'},
238 {'-', '_'},
239 {'=', '+'},
240 {8, 8}, /* 14 - Backspace */
241 {'\t', '\t'}, /* 15 */
242 {'q', 'Q'},
243 {'w', 'W'},
244 {'e', 'E'},
245 {'r', 'R'},
246 {'t', 'T'},
247 {'y', 'Y'},
248 {'u', 'U'},
249 {'i', 'I'},
250 {'o', 'O'},
251 {'p', 'P'},
252 {'[', '{'},
253 {']', '}'}, /* 27 */
254 {'\r', '\r'}, /* 28 - Enter */
255 {CTRL, CTRL}, /* 29 - Ctrl */
256 {'a', 'A'}, /* 30 */
257 {'s', 'S'},
258 {'d', 'D'},
259 {'f', 'F'},
260 {'g', 'G'},
261 {'h', 'H'},
262 {'j', 'J'},
263 {'k', 'K'},
264 {'l', 'L'},
265 {';', ':'},
266 {'\'', '"'}, /* 40 */
267 {'`', '~'}, /* 41 */
268 {SHIFT, SHIFT}, /* 42 - Left Shift */
269 {'\\', '|'}, /* 43 */
270 {'z', 'Z'}, /* 44 */
271 {'x', 'X'},
272 {'c', 'C'},
273 {'v', 'V'},
274 {'b', 'B'},
275 {'n', 'N'},
276 {'m', 'M'},
277 {',', '<'},
278 {'.', '>'},
279 {'/', '?'}, /* 53 */
280 {SHIFT, SHIFT}, /* 54 - Right Shift */
281 {0, 0}, /* 55 - Print Screen */
282 {META, META}, /* 56 - Alt */
283 {' ', ' '}, /* 57 - Space bar */
284 {0, 0}, /* 58 - Caps Lock */
285 {0, 0}, /* 59 - F1 */
286 {0, 0}, /* 60 - F2 */
287 {0, 0}, /* 61 - F3 */
288 {0, 0}, /* 62 - F4 */
289 {0, 0}, /* 63 - F5 */
290 {0, 0}, /* 64 - F6 */
291 {0, 0}, /* 65 - F7 */
292 {0, 0}, /* 66 - F8 */
293 {0, 0}, /* 67 - F9 */
294 {0, 0}, /* 68 - F10 */
295 {0, 0}, /* 69 - Num Lock */
296 {0, 0}, /* 70 - Scroll Lock */
297 {'7', '7'}, /* 71 - Numeric keypad 7 */
298 {'8', '8'}, /* 72 - Numeric keypad 8 */
299 {'9', '9'}, /* 73 - Numeric keypad 9 */
300 {'-', '-'}, /* 74 - Numeric keypad '-' */
301 {'4', '4'}, /* 75 - Numeric keypad 4 */
302 {'5', '5'}, /* 76 - Numeric keypad 5 */
303 {'6', '6'}, /* 77 - Numeric keypad 6 */
304 {'+', '+'}, /* 78 - Numeric keypad '+' */
305 {'1', '1'}, /* 79 - Numeric keypad 1 */
306 {'2', '2'}, /* 80 - Numeric keypad 2 */
307 {'3', '3'}, /* 81 - Numeric keypad 3 */
308 {'0', '0'}, /* 82 - Numeric keypad 0 */
309 {'.', '.'}, /* 83 - Numeric keypad '.' */
310 };
311
312 /* FUNCTIONS *****************************************************************/
313
314 /*
315 * Quick poll for a pending input character.
316 * Returns a character if available, -1 otherwise. This routine can return
317 * false negatives in the following cases:
318 *
319 * - a valid character is in transit from the keyboard when called
320 * - a key release is received (from a previous key press)
321 * - a SHIFT key press is received (shift state is recorded however)
322 * - a key press for a multi-character sequence is received
323 *
324 * Yes, this is horrible.
325 */
326 ULONG
327 KdbTryGetCharKeyboard(VOID)
328 {
329 static unsigned shift_state, ctrl_state, meta_state;
330 unsigned scan_code, ch;
331
332 /* See if a scan code is ready, returning if none. */
333 if ((READ_PORT_UCHAR((PUCHAR)K_STATUS) & K_OBUF_FUL) == 0) {
334 return -1;
335 }
336 scan_code = READ_PORT_UCHAR((PUCHAR)K_RDWR);
337
338 /* Handle key releases - only release of SHIFT is important. */
339 if (scan_code & 0x80) {
340 scan_code &= 0x7f;
341 if (keymap[scan_code][0] == SHIFT)
342 shift_state = 0;
343 else if (keymap[scan_code][0] == CTRL)
344 ctrl_state = 0;
345 else if (keymap[scan_code][0] == META)
346 meta_state = 0;
347 ch = -1;
348 } else {
349 /* Translate the character through the keymap. */
350 ch = keymap[scan_code][shift_state] | meta_state;
351 if (ch == SHIFT) {
352 shift_state = 1;
353 ch = -1;
354 } else if (ch == CTRL) {
355 ctrl_state = 1;
356 ch = -1;
357 } else if (ch == META) {
358 meta_state = 0200;
359 ch = -1;
360 } else if (ch == 0)
361 ch = -1;
362 else if (ctrl_state)
363 ch = (keymap[scan_code][1] - '@') | meta_state;
364 }
365
366 return ch;
367 }
368
369 #endif