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