]>
Commit | Line | Data |
---|---|---|
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 | */ | |
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 | /*@}*/ |