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