]> Joshua Wise's Git repositories - netwatch.git/blob - cs410/keyhelp.c
First pass of 410watch UI code.
[netwatch.git] / cs410 / keyhelp.c
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  */
30 static 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
40 static short key_internal_state = 0;
41
42 static 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  */
64 static kh_type
65 process_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  */
491 kh_type
492 process_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    */
602 kh_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:
641 deflt:
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.056609 seconds and 4 git commands to generate.