]> Joshua Wise's Git repositories - netwatch.git/blame - cs410/keyhelp.c
First pass of 410watch UI code.
[netwatch.git] / cs410 / keyhelp.c
CommitLineData
6093edb5
JW
1/**
2 * The 15-410 reference kernel keyboard handling code.
3 *
4 * @author Steve Muckle <smuckle@andrew.cmu.edu>
5 *
6 * @author Edited by zra for the 2003-2004 season.
7 *
8 * @author Edited by mpa for spring 2004
9 *
10 * @author Rewritten by nwf for spring 2007.
11 *
12 * Functions for turning keyboard scancodes
13 * into chars.
14 *
15 * Notice that we use Scancode Set 1
16 */
17/*@{*/
18
19#include "keyhelp.h"
20
21/**
22 * This is returned as the upper bits of the result of
23 * process_scancode and may be interrogated more readily by
24 * the KH_ macros in keyhelp.h
25 *
26 * WARNING:
27 * The bottom bits overlap with the KH_RESULT_ codes in the
28 * return value.
29 */
30static short key_state = 0;
31
32 /** Currently processing a PRINT SCREEN BREAK sequence */
33#define KH_PRSCR_UP_SCAN 0x0008
34 /** Currently processing a PRINT SCREEN MAKE sequence */
35#define KH_PRSCR_DOWN_SCAN 0x0004
36 /** Currently processing a PAUSE/BREAK (MAKE) sequence */
37#define KH_PAUSE_SCAN 0x0002
38 /** Currently processing an extended sequence (E0 prefix) */
39#define KH_EXTENDED_SCAN 0x0001
40static short key_internal_state = 0;
41
42static int key_sequence = 0;
43
44#define KHS_SHIFT_CORE (key_state & (KH_LSHIFT_KEY | KH_RSHIFT_KEY))
45#define KHS_CTL_CORE (key_state & (KH_LCONTROL_KEY | KH_RCONTROL_KEY))
46
47#define KHS_SHIFT(c,r,s,u) \
48 { c = KHS_SHIFT_CORE ? s : u; r = u; }
49#define KHS_SHIFTCTL(c,r,cc,s,u) \
50 { c = KHS_CTL_CORE ? cc : (KHS_SHIFT_CORE ? s : u); r = u; }
51#define KHS_SHIFTCAPSCTL(c,r,cc,s,u) \
52 { c = KHS_CTL_CORE ? cc : (((KHS_SHIFT_CORE || (key_state & KH_CAPS_LOCK)) && \
53 !(KHS_SHIFT_CORE && (key_state & KH_CAPS_LOCK))) ? s : u) ; r = u; }
54
55/**
56 * This function performs the mapping
57 * from simple scancodes to chars.
58 *
59 * @param scancode a simple scancode.
60 * @param pressed 0 if released, nonzero if pressed.
61 *
62 * @return A partially constructed kh_type.
63 */
64static kh_type
65process_simple_scan(int scancode, int pressed)
66{
67 unsigned char code = 0x80;
68 unsigned char rcode = 0x80;
69 kh_type res = 0;
70
71 switch(scancode & 0x7F)
72 {
73 case 0x1:
74 /* Escape key. */
75 rcode = code = 0x1B;
76 break;
77 case 0x2:
78 /* 1 or ! */
79 KHS_SHIFT(code, rcode, '!', '1');
80 break;
81 case 0x3:
82 /* 2 or @ */
83 KHS_SHIFTCTL(code, rcode, 0x00, '@', '2');
84 break;
85 case 0x4:
86 /* 3 or # */
87 KHS_SHIFT(code, rcode, '#', '3');
88 break;
89 case 0x5:
90 /* 4 or $ */
91 KHS_SHIFT(code, rcode, '$', '4');
92 break;
93 case 0x6:
94 /* 5 or % */
95 KHS_SHIFT(code, rcode, '%', '5');
96 break;
97 case 0x7:
98 /* 6 or ^ */
99 KHS_SHIFTCTL(code, rcode, 0x1E, '^', '6');
100 break;
101 case 0x8:
102 /* 7 or & */
103 KHS_SHIFT(code, rcode, '&', '7');
104 break;
105 case 0x9:
106 /* 8 or * */
107 KHS_SHIFT(code, rcode, '*', '8');
108 break;
109 case 0xA:
110 /* 9 or ( */
111 KHS_SHIFT(code, rcode, '(', '9');
112 break;
113 case 0xB:
114 /* 0 or ) */
115 KHS_SHIFT(code, rcode, ')', '0');
116 break;
117 case 0xC:
118 /* - or _ */
119 KHS_SHIFTCTL(code, rcode, 0x1F, '_', '-');
120 break;
121 case 0xD:
122 /* = or + */
123 KHS_SHIFT(code, rcode, '+', '=');
124 break;
125 case 0xE:
126 /* Backspace key. */
127 rcode = code = '\b';
128 break;
129 case 0xF:
130 /* Tab key. */
131 rcode = code = '\t';
132 break;
133 case 0x10:
134 /* q or Q. */
135 KHS_SHIFTCAPSCTL(code, rcode, 0x11, 'Q', 'q');
136 break;
137 case 0x11:
138 /* w or W. */
139 KHS_SHIFTCAPSCTL(code, rcode, 0x17, 'W', 'w');
140 break;
141 case 0x12:
142 /* e or E. */
143 KHS_SHIFTCAPSCTL(code, rcode, 0x05, 'E', 'e');
144 break;
145 case 0x13:
146 /* r or R. */
147 KHS_SHIFTCAPSCTL(code, rcode, 0x12, 'R', 'r');
148 break;
149 case 0x14:
150 /* t or T. */
151 KHS_SHIFTCAPSCTL(code, rcode, 0x14, 'T', 't');
152 break;
153 case 0x15:
154 /* y or Y. */
155 KHS_SHIFTCAPSCTL(code, rcode, 0x19, 'Y', 'y');
156 break;
157 case 0x16:
158 /* u or U. */
159 KHS_SHIFTCAPSCTL(code, rcode, 0x15, 'U', 'u');
160 break;
161 case 0x17:
162 /* i or I. */
163 KHS_SHIFTCAPSCTL(code, rcode, 0x09, 'I', 'i');
164 break;
165 case 0x18:
166 /* o or O. */
167 KHS_SHIFTCAPSCTL(code, rcode, 0x0F, 'O', 'o');
168 break;
169 case 0x19:
170 /* p or P. */
171 KHS_SHIFTCAPSCTL(code, rcode, 0x10, 'P', 'p');
172 break;
173 case 0x1A:
174 /* [ or {. */
175 KHS_SHIFTCAPSCTL(code, rcode, 0x1B, '{', '[');
176 break;
177 case 0x1B:
178 /* ] or }. */
179 KHS_SHIFTCAPSCTL(code, rcode, 0x1D, '}', ']');
180 break;
181 case 0x1C:
182 /* Enter key. */
183 rcode=code='\n';
184 break;
185 case 0x1D:
186 if((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 0))
187 {
188 /* Stage 1 of a pause sequence */
189 key_sequence++;
190 return 0;
191 } else {
192 key_internal_state &= ~KH_PAUSE_SCAN;
193 key_sequence = 0;
194 }
195 rcode=KHE_LCTL;
196 if(pressed)
197 key_state |= KH_LCONTROL_KEY;
198 else
199 key_state &= ~KH_LCONTROL_KEY;
200 break;
201 case 0x1E:
202 /* a or A. */
203 KHS_SHIFTCAPSCTL(code, rcode, 0x01, 'A', 'a');
204 break;
205 case 0x1F:
206 /* s or S. */
207 KHS_SHIFTCAPSCTL(code, rcode, 0x13, 'S', 's');
208 break;
209 case 0x20:
210 /* d or D. */
211 KHS_SHIFTCAPSCTL(code, rcode, 0x04, 'D', 'd');
212 break;
213 case 0x21:
214 /* f or F. */
215 KHS_SHIFTCAPSCTL(code, rcode, 0x06, 'F', 'f');
216 break;
217 case 0x22:
218 /* g or G. */
219 KHS_SHIFTCAPSCTL(code, rcode, 0x07, 'G', 'g');
220 break;
221 case 0x23:
222 /* h or H. */
223 KHS_SHIFTCAPSCTL(code, rcode, 0x08, 'H', 'h');
224 break;
225 case 0x24:
226 /* j or J. */
227 KHS_SHIFTCAPSCTL(code, rcode, 0x0A, 'J', 'j');
228 break;
229 case 0x25:
230 /* k or K. */
231 KHS_SHIFTCAPSCTL(code, rcode, 0x0B, 'K', 'k');
232 break;
233 case 0x26:
234 /* l or L. */
235 KHS_SHIFTCAPSCTL(code, rcode, 0x0C, 'L', 'l');
236 break;
237 case 0x27:
238 /* ; or :. */
239 KHS_SHIFT(code, rcode, ':', ';');
240 break;
241 case 0x28:
242 /* ' or " */
243 KHS_SHIFT(code, rcode, '\"', '\'');
244 break;
245 case 0x29:
246 KHS_SHIFT(code, rcode, '~', '`');
247 break;
248 case 0x2A:
249 rcode = KHE_LSHIFT;
250 if(pressed)
251 key_state |= KH_LSHIFT_KEY;
252 else
253 key_state &= ~KH_LSHIFT_KEY;
254 break;
255 case 0x2B:
256 /* \ or |. */
257 KHS_SHIFTCTL(code, rcode, 0x1C, '|', '\\');
258 break;
259 case 0x2C:
260 /* z or Z. */
261 KHS_SHIFTCAPSCTL(code, rcode, 0x1A, 'Z', 'z');
262 break;
263 case 0x2D:
264 /* x or X. */
265 KHS_SHIFTCAPSCTL(code, rcode, 0x18, 'X', 'x');
266 break;
267 case 0x2E:
268 /* c or C. */
269 KHS_SHIFTCAPSCTL(code, rcode, 0x03, 'C', 'c');
270 break;
271 case 0x2F:
272 /* v or V. */
273 KHS_SHIFTCAPSCTL(code, rcode, 0x16, 'V', 'v');
274 break;
275 case 0x30:
276 /* b or B. */
277 KHS_SHIFTCAPSCTL(code, rcode, 0x02, 'B', 'b');
278 break;
279 case 0x31:
280 /* n or N. */
281 KHS_SHIFTCAPSCTL(code, rcode, 0x0E, 'N', 'n');
282 break;
283 case 0x32:
284 /* m or M. */
285 KHS_SHIFTCAPSCTL(code, rcode, 0x0D, 'M', 'm');
286 break;
287 case 0x33:
288 /* , or <. */
289 KHS_SHIFT(code, rcode, '<', ',');
290 break;
291 case 0x34:
292 /* . or >. */
293 KHS_SHIFT(code, rcode, '>', '.');
294 break;
295 case 0x35:
296 /* / or ? */
297 KHS_SHIFT(code, rcode, '?', '/');
298 break;
299 case 0x36:
300 rcode = KHE_RSHIFT;
301 if(pressed)
302 key_state |= KH_RSHIFT_KEY;
303 else
304 key_state &= ~KH_RSHIFT_KEY;
305 break;
306 case 0x37:
307 /* NP * */
308 rcode = code = '*';
309 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
310 break;
311 case 0x38:
312 rcode = KHE_LALT;
313 if(pressed)
314 key_state |= KH_LALT_KEY;
315 else
316 key_state &= ~KH_LALT_KEY;
317 break;
318 case 0x39:
319 /* Space bar. */
320 rcode = code =' ';
321 break;
322 case 0x3A:
323 rcode = KHE_CAPSLOCK;
324 if(pressed)
325 {
326 if(key_state & KH_CAPS_LOCK)
327 key_state &= ~KH_CAPS_LOCK;
328 else
329 key_state |= KH_CAPS_LOCK;
330 }
331 break;
332 case 0x3B:
333 /* F1 key. */
334 rcode = code = KHE_F1;
335 break;
336 case 0x3C:
337 /* F2 key. */
338 rcode = code = KHE_F2;
339 break;
340 case 0x3D:
341 /* F3 key. */
342 rcode = code = KHE_F3;
343 break;
344 case 0x3E:
345 /* F4 key. */
346 rcode = code = KHE_F4;
347 break;
348 case 0x3F:
349 /* F5 key. */
350 rcode = code = KHE_F5;
351 break;
352 case 0x40:
353 /* F6 key. */
354 rcode = code = KHE_F6;
355 break;
356 case 0x41:
357 /* F7 key. */
358 rcode = code = KHE_F7;
359 break;
360 case 0x42:
361 /* F8 key. */
362 rcode = code = KHE_F8;
363 break;
364 case 0x43:
365 /* F9 key. */
366 rcode = code = KHE_F9;
367 break;
368 case 0x44:
369 /* F10 key. */
370 rcode = code = KHE_F10;
371 break;
372 case 0x45:
373 if((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 1))
374 {
375 /* Stage 2 of a pause sequence */
376 key_sequence++;
377 return 0;
378 } else {
379 key_internal_state &= ~KH_PAUSE_SCAN;
380 key_sequence = 0;
381 }
382 rcode = KHE_NUMLOCK;
383 if(pressed)
384 {
385 if(key_state & KH_NUM_LOCK)
386 key_state &= ~KH_NUM_LOCK;
387 else
388 key_state |= KH_NUM_LOCK;
389 }
390 break;
391 case 0x47:
392 rcode = code = '7';
393 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
394 break;
395 case 0x48:
396 rcode = code = '8';
397 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
398 break;
399 case 0x49:
400 rcode = code = '9';
401 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
402 break;
403 case 0x4A:
404 rcode = code = '-';
405 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
406 break;
407 case 0x4B:
408 rcode = code = '4';
409 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
410 break;
411 case 0x4C:
412 rcode = code = '5';
413 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
414 break;
415 case 0x4D:
416 rcode = code = '6';
417 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
418 break;
419 case 0x4E:
420 rcode = code = '+';
421 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
422 break;
423 case 0x4F:
424 rcode = code = '1';
425 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
426 break;
427 case 0x50:
428 rcode = code = '2';
429 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
430 break;
431 case 0x51:
432 rcode = code = '3';
433 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
434 break;
435 case 0x52:
436 rcode = code = '0';
437 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
438 break;
439 case 0x53:
440 rcode = code = '.';
441 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
442 break;
443 case 0x57:
444 /* F11 key. */
445 rcode = code = KHE_F11;
446 break;
447 case 0x58:
448 /* F12 key. */
449 rcode = code = KHE_F12;
450 break;
451 case 0xE1 & 0x7F:
452 if(!(key_internal_state & KH_PAUSE_SCAN))
453 {
454 /* Stage 0 of a pause sequence */
455 key_internal_state |= KH_PAUSE_SCAN;
456 key_sequence = 0;
457 return 0;
458 } else if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 2)) {
459 key_sequence++;
460 return 0;
461 } else {
462 key_internal_state &= ~KH_PAUSE_SCAN;
463 key_sequence = 0;
464 }
465 /* FALLTHROUGH */
466 default:
467 rcode = code = KHE_UNDEFINED;
468 break;
469 }
470
471 if ( rcode != KHE_UNDEFINED && code != KHE_UNDEFINED )
472 res |= (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
473 else
474 code = 0x00;
475
476 return res | (code << KH_CHAR_SHIFT)
477 | (rcode << KH_RAWCHAR_SHIFT)
478 | (KH_RESULT_HASRAW << KH_RMODS_SHIFT);
479}
480
481/**
482 * Processes extended scan codes. Notably, this includes
483 * the arrow keys as well as some of the more unusual keys
484 * on the keyboard.
485 *
486 * @param keypress the extended scancode.
487 * @param 0 if released. non-zero if pressed.
488 *
489 * @return A partially constructed kh_type.
490 */
491kh_type
492process_extended_scan(int keypress, int pressed)
493{
494 unsigned char code = 0x80;
495 unsigned char rcode = 0x80;
496 kh_type res = 0;
497
498 /* Intermediate states in multiple byte scancodes should return
499 * zero from this function, rather than returning a RESULT code.
500 */
501
502 switch(keypress & 0x7F)
503 {
504 case 0x1C:
505 /* NP '\n' */
506 rcode = code = '\n';
507 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
508 break;
509 case 0x1D:
510 /* Right control key */
511 rcode = KHE_RCTL;
512 if(pressed)
513 key_state |= KH_RCONTROL_KEY;
514 else
515 key_state &= ~KH_RCONTROL_KEY;
516 break;
517 case 0x2A:
518 /* Stage 0 of PRINT SCREEN MAKE and Stage 1 of PRINT SCREEN BREAK */
519 if(key_internal_state & KH_PRSCR_UP_SCAN)
520 {
521 rcode = code = KHE_PRINT_SCREEN;
522 key_internal_state &= ~KH_PRSCR_UP_SCAN;
523 } else if (!(key_internal_state & KH_PRSCR_UP_SCAN)) {
524 key_internal_state |= KH_PRSCR_DOWN_SCAN;
525 key_internal_state &= ~KH_EXTENDED_SCAN;
526 return 0;
527 } else {
528 rcode = code = KHE_UNDEFINED;
529 }
530 break;
531 case 0x35:
532 /* NP / */
533 rcode = code = '/';
534 res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
535 break;
536 case 0x37:
537 /* Stage 1 of PRINT SCREEN MAKE and Stage 0 of PRINT SCREEN BREAK */
538 if(key_internal_state & KH_PRSCR_DOWN_SCAN)
539 {
540 rcode = code = KHE_PRINT_SCREEN;
541 key_internal_state &= ~KH_PRSCR_DOWN_SCAN;
542 } else if (!(key_internal_state & KH_PRSCR_DOWN_SCAN)) {
543 key_internal_state |= KH_PRSCR_UP_SCAN;
544 key_internal_state &= ~KH_EXTENDED_SCAN;
545 return 0;
546 } else {
547 rcode = code = KHE_UNDEFINED;
548 }
549 break;
550 case 0x38:
551 /* Right alt key */
552 rcode = KHE_RALT;
553 if(pressed)
554 key_state |= KH_RALT_KEY;
555 else
556 key_state &= ~KH_RALT_KEY;
557 break;
558 case 0x48:
559 /* UP */
560 rcode = code=KHE_ARROW_UP;
561 break;
562 case 0x4b:
563 /* LEFT */
564 rcode = code=KHE_ARROW_LEFT;
565 break;
566 case 0x4d:
567 /* RIGHT */
568 rcode = code=KHE_ARROW_RIGHT;
569 break;
570 case 0x50:
571 /* DOWN */
572 rcode = code = KHE_ARROW_DOWN;
573 break;
574 case 0x53:
575 /* DEL */
576 rcode = code = 0x7F;
577 break;
578 default:
579 rcode = code = KHE_UNDEFINED;
580 break;
581 }
582
583 key_internal_state &= ~KH_EXTENDED_SCAN;
584
585 if ( rcode != KHE_UNDEFINED && code != KHE_UNDEFINED )
586 res |= (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
587 else
588 code = 0x00;
589
590 return res | (code << KH_CHAR_SHIFT)
591 | (rcode << KH_RAWCHAR_SHIFT)
592 | (KH_RESULT_HASRAW << KH_RMODS_SHIFT);
593}
594
595 /** The entrypoint to the keyboard processing library.
596 *
597 * @param keypress A raw scancode as returned by the keyboard hardware.
598 * @return A kh_type indicating the keyboard modifier key states, result
599 * modifier bits, and potentially ASCII/410 Upper Code Plane
600 * translations.
601 */
602kh_type process_scancode(int keypress) {
603 kh_type res;
604 int pressed = !(keypress & 0x80);
605 int keycode = keypress & 0x7F;
606
607 if (key_internal_state & KH_EXTENDED_SCAN)
608 res = process_extended_scan(keycode, pressed);
609 else
610 {
611 switch(keypress & 0xFF)
612 {
613 case 0x9D:
614 if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 3))
615 {
616 key_sequence++;
617 return 0;
618 } else {
619 key_internal_state &= ~KH_PAUSE_SCAN;
620 key_sequence = 0;
621 }
622 goto deflt;
623 case 0xC5:
624 if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 4))
625 {
626 key_internal_state &= ~KH_PAUSE_SCAN;
627 /* Pause sequence completed */
628 res = (KHE_PAUSE << KH_CHAR_SHIFT)
629 | (KHE_PAUSE << KH_RAWCHAR_SHIFT)
630 | (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
631 break;
632 }
633 key_internal_state &= ~KH_PAUSE_SCAN;
634 key_sequence = 0;
635 goto deflt;
636 case 0xE0:
637 key_internal_state |= KH_EXTENDED_SCAN;
638 /* Return no result for this intermediate state */
639 return key_state << KH_STATE_SHIFT;
640 default:
641deflt:
642 key_internal_state &= ~(KH_PRSCR_UP_SCAN | KH_PRSCR_DOWN_SCAN);
643 res = process_simple_scan(keycode, pressed);
644 }
645 }
646
647 if(pressed)
648 res |= KH_RESULT_MAKE << KH_RMODS_SHIFT;
649
650 res |= (key_state & KH_STATE_SMASK) << KH_STATE_SHIFT;
651
652 return res;
653}
654
655/*@}*/
This page took 0.072758 seconds and 4 git commands to generate.