]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/pm/common/keyboard.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / pm / common / keyboard.c
1 /****************************************************************************
2 *
3 *                   SciTech OS Portability Manager Library
4 *
5 *  ========================================================================
6 *
7 *    The contents of this file are subject to the SciTech MGL Public
8 *    License Version 1.0 (the "License"); you may not use this file
9 *    except in compliance with the License. You may obtain a copy of
10 *    the License at http://www.scitechsoft.com/mgl-license.txt
11 *
12 *    Software distributed under the License is distributed on an
13 *    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 *    implied. See the License for the specific language governing
15 *    rights and limitations under the License.
16 *
17 *    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 *    The Initial Developer of the Original Code is SciTech Software, Inc.
20 *    All Rights Reserved.
21 *
22 *  ========================================================================
23 *
24 * Language:     ANSI C
25 * Environment:  Any
26 *
27 * Description:  Direct keyboard event handling module. This module contains
28 *               code to process raw scan code information, convert it to
29 *               virtual scan codes and do code page translation to ASCII
30 *               for different international keyboard layouts.
31 *
32 ****************************************************************************/
33
34 /*---------------------------- Implementation -----------------------------*/
35
36 /****************************************************************************
37 PARAMETERS:
38 scanCode    - Keyboard scan code to translate
39 table       - Code page table to search
40 count       - Number of entries in the code page table
41
42 REMARKS:
43 This function translates the scan codes from keyboard scan codes to ASCII
44 codes using a binary search on the code page table.
45 ****************************************************************************/
46 static uchar translateScan(
47     uchar scanCode,
48     codepage_entry_t *table,
49     int count)
50 {
51     codepage_entry_t    *test;
52     int                 n,pivot,val;
53
54     for (n = count; n > 0; ) {
55         pivot = n >> 1;
56         test = table + pivot;
57         val = scanCode - test->scanCode;
58         if (val < 0)
59             n = pivot;
60         else if (val == 0)
61             return test->asciiCode;
62         else {
63             table = test + 1;
64             n -= pivot + 1;
65             }
66         }
67     return 0;
68 }
69
70 /****************************************************************************
71 REMARKS:
72 This macro/function is used to converts the scan codes reported by the
73 keyboard to our event libraries normalised format. We only have one scan
74 code for the 'A' key, and use shift modifiers to determine if it is a
75 Ctrl-F1, Alt-F1 etc. The raw scan codes from the keyboard work this way,
76 but the OS gives us 'cooked' scan codes, we have to translate them back
77 to the raw format.
78 {secret}
79 ****************************************************************************/
80 void _EVT_maskKeyCode(
81     event_t *evt)
82 {
83     int ascii,scan = EVT_scanCode(evt->message);
84
85     evt->message &= ~0xFF;
86     if (evt->modifiers & EVT_NUMLOCK) {
87         if ((ascii = translateScan(scan,EVT.codePage->numPad,EVT.codePage->numPadLen)) != 0) {
88             evt->message |= ascii;
89             return;
90             }
91         }
92     if (evt->modifiers & EVT_CTRLSTATE) {
93         evt->message |= translateScan(scan,EVT.codePage->ctrl,EVT.codePage->ctrlLen);
94         return;
95         }
96     if (evt->modifiers & EVT_CAPSLOCK) {
97         if (evt->modifiers & EVT_SHIFTKEY) {
98             if ((ascii = translateScan(scan,EVT.codePage->shiftCaps,EVT.codePage->shiftCapsLen)) != 0) {
99                 evt->message |= ascii;
100                 return;
101                 }
102             }
103         else {
104             if ((ascii = translateScan(scan,EVT.codePage->caps,EVT.codePage->capsLen)) != 0) {
105                 evt->message |= ascii;
106                 return;
107                 }
108             }
109         }
110     if (evt->modifiers & EVT_SHIFTKEY) {
111         if ((ascii = translateScan(scan,EVT.codePage->shift,EVT.codePage->shiftLen)) != 0) {
112             evt->message |= ascii;
113             return;
114             }
115         }
116     evt->message |= translateScan(scan,EVT.codePage->normal,EVT.codePage->normalLen);
117 }
118
119 /****************************************************************************
120 REMARKS:
121 Returns true if the key with the specified scan code is being held down.
122 ****************************************************************************/
123 static ibool _EVT_isKeyDown(
124     uchar scanCode)
125 {
126     if (scanCode > 0x7F)
127         return false;
128     else
129         return EVT.keyTable[scanCode] != 0;
130 }
131
132 /****************************************************************************
133 PARAMETERS:
134 what        - Event code
135 message     - Event message (ASCII code and scan code)
136
137 REMARKS:
138 Adds a new keyboard event to the event queue. This routine is called from
139 within the keyboard interrupt subroutine!
140
141 NOTE:   Interrupts are OFF when this routine is called by the keyboard ISR,
142         and we leave them OFF the entire time.
143 ****************************************************************************/
144 static void addKeyEvent(
145     uint what,
146     uint message)
147 {
148     event_t evt;
149
150     if (EVT.count < EVENTQSIZE) {
151         /* Save information in event record */
152         evt.when = _EVT_getTicks();
153         evt.what = what;
154         evt.message = message | 0x10000UL;
155         evt.where_x = 0;
156         evt.where_y = 0;
157         evt.relative_x = 0;
158         evt.relative_y = 0;
159         evt.modifiers = EVT.keyModifiers;
160         if (evt.what == EVT_KEYREPEAT) {
161             if (EVT.oldKey != -1)
162                 EVT.evtq[EVT.oldKey].message += 0x10000UL;
163             else {
164                 EVT.oldKey = EVT.freeHead;
165                 addEvent(&evt);         /* Add to tail of event queue   */
166                 }
167             }
168         else {
169 #ifdef __QNX__
170             _EVT_maskKeyCode(&evt);
171 #endif
172             addEvent(&evt);             /* Add to tail of event queue   */
173             }
174         EVT.oldMove = -1;
175         }
176 }
177
178 /****************************************************************************
179 REMARKS:
180 This function waits for the keyboard controller to set the ready-for-write
181 bit.
182 ****************************************************************************/
183 static int kbWaitForWriteReady(void)
184 {
185     int timeout = 8192;
186     while ((timeout > 0) && (PM_inpb(0x64) & 0x02))
187         timeout--;
188     return (timeout > 0);
189 }
190
191 /****************************************************************************
192 REMARKS:
193 This function waits for the keyboard controller to set the ready-for-read
194 bit.
195 ****************************************************************************/
196 static int kbWaitForReadReady(void)
197 {
198     int timeout = 8192;
199     while ((timeout > 0) && (!(PM_inpb(0x64) & 0x01)))
200         timeout--;
201     return (timeout > 0);
202 }
203
204 /****************************************************************************
205 PARAMETERS:
206 data    - Data to send to the keyboard
207
208 REMARKS:
209 This function sends a data byte to the keyboard controller.
210 ****************************************************************************/
211 static int kbSendData(
212     uchar data)
213 {
214     int resends = 4;
215     int timeout, temp;
216
217     do {
218         if (!kbWaitForWriteReady())
219             return 0;
220         PM_outpb(0x60,data);
221         timeout = 8192;
222         while (--timeout > 0) {
223             if (!kbWaitForReadReady())
224                 return 0;
225             temp = PM_inpb(0x60);
226             if (temp == 0xFA)
227                 return 1;
228             if (temp == 0xFE)
229                 break;
230             }
231         } while ((resends-- > 0) && (timeout > 0));
232     return 0;
233 }
234
235 /****************************************************************************
236 PARAMETERS:
237 modifiers   - Keyboard modifier flags
238
239 REMARKS:
240 This function re-programs the LED's on the keyboard to the values stored
241 in the passed in modifier flags. If the 'allowLEDS' flag is false, this
242 function does nothing.
243 ****************************************************************************/
244 static void setLEDS(
245     uint modifiers)
246 {
247     if (EVT.allowLEDS) {
248         if (!kbSendData(0xED) || !kbSendData((modifiers>>9) & 7)) {
249             kbSendData(0xF4);
250             }
251         }
252 }
253
254 /****************************************************************************
255 REMARKS:
256 Function to process raw scan codes read from the keyboard controller.
257
258 NOTE:   Interrupts are OFF when this routine is called by the keyboard ISR,
259         and we leave them OFF the entire time.
260 {secret}
261 ****************************************************************************/
262 void processRawScanCode(
263     int scan)
264 {
265     static int  pauseLoop = 0;
266     static int  extended = 0;
267     int         what;
268
269     if (pauseLoop) {
270         /* Skip scan codes until the pause key sequence has been read */
271         pauseLoop--;
272         }
273     else if (scan == 0xE0) {
274         /* This signals the start of an extended scan code sequence */
275         extended = 1;
276         }
277     else if (scan == 0xE1) {
278         /* The Pause key sends a strange scan code sequence, which is:
279          *
280          *  E1 1D 52 E1 9D D2
281          *
282          * However there is never any release code nor any auto-repeat for
283          * this key. For this reason we simply ignore the key and skip the
284          * next 5 scan codes read from the keyboard.
285          */
286         pauseLoop = 5;
287         }
288     else {
289         /* Process the scan code normally (it may be an extended code
290          * however!). Bit 7 means key was released, and bits 0-6 are the
291          * scan code.
292          */
293         what = (scan & 0x80) ? EVT_KEYUP : EVT_KEYDOWN;
294         scan &= 0x7F;
295         if (extended) {
296             extended = 0;
297             if (scan == 0x2A || scan == 0x36) {
298                 /* Ignore these extended scan code sequences. These are
299                  * used by the keyboard controller to wrap around certain
300                  * key sequences for the keypad (and when NUMLOCK is down
301                  * internally).
302                  */
303                 return;
304                 }
305
306             /* Convert extended codes for key sequences that we map to
307              * virtual scan codes so the user can detect them in their
308              * code.
309              */
310             switch (scan) {
311                 case KB_leftCtrl:   scan = KB_rightCtrl;    break;
312                 case KB_leftAlt:    scan = KB_rightAlt;     break;
313                 case KB_divide:     scan = KB_padDivide;    break;
314                 case KB_enter:      scan = KB_padEnter;     break;
315                 case KB_padTimes:   scan = KB_sysReq;       break;
316                 }
317             }
318         else {
319             /* Convert regular scan codes for key sequences that we map to
320              * virtual scan codes so the user can detect them in their
321              * code.
322              */
323             switch (scan) {
324                 case KB_left:       scan = KB_padLeft;      break;
325                 case KB_right:      scan = KB_padRight;     break;
326                 case KB_up:         scan = KB_padUp;        break;
327                 case KB_down:       scan = KB_padDown;      break;
328                 case KB_insert:     scan = KB_padInsert;    break;
329                 case KB_delete:     scan = KB_padDelete;    break;
330                 case KB_home:       scan = KB_padHome;      break;
331                 case KB_end:        scan = KB_padEnd;       break;
332                 case KB_pageUp:     scan = KB_padPageUp;    break;
333                 case KB_pageDown:   scan = KB_padPageDown;  break;
334                 }
335             }
336
337         /* Determine if the key is an UP, DOWN or REPEAT and maintain the
338          * up/down status of all keys in our global key array.
339          */
340         if (what == EVT_KEYDOWN) {
341             if (EVT.keyTable[scan])
342                 what = EVT_KEYREPEAT;
343             else
344                 EVT.keyTable[scan] = scan;
345             }
346         else {
347             EVT.keyTable[scan] = 0;
348             }
349
350         /* Handle shift key modifiers */
351         if (what != EVT_KEYREPEAT) {
352             switch (scan) {
353                 case KB_capsLock:
354                     if (what == EVT_KEYDOWN)
355                         EVT.keyModifiers ^= EVT_CAPSLOCK;
356                     setLEDS(EVT.keyModifiers);
357                     break;
358                 case KB_numLock:
359                     if (what == EVT_KEYDOWN)
360                         EVT.keyModifiers ^= EVT_NUMLOCK;
361                     setLEDS(EVT.keyModifiers);
362                     break;
363                 case KB_scrollLock:
364                     if (what == EVT_KEYDOWN)
365                         EVT.keyModifiers ^= EVT_SCROLLLOCK;
366                     setLEDS(EVT.keyModifiers);
367                     break;
368                 case KB_leftShift:
369                     if (what == EVT_KEYUP)
370                         EVT.keyModifiers &= ~EVT_LEFTSHIFT;
371                     else
372                         EVT.keyModifiers |= EVT_LEFTSHIFT;
373                     break;
374                 case KB_rightShift:
375                     if (what == EVT_KEYUP)
376                         EVT.keyModifiers &= ~EVT_RIGHTSHIFT;
377                     else
378                         EVT.keyModifiers |= EVT_RIGHTSHIFT;
379                     break;
380                 case KB_leftCtrl:
381                     if (what == EVT_KEYUP)
382                         EVT.keyModifiers &= ~EVT_LEFTCTRL;
383                     else
384                         EVT.keyModifiers |= EVT_LEFTCTRL;
385                     break;
386                 case KB_rightCtrl:
387                     if (what == EVT_KEYUP)
388                         EVT.keyModifiers &= ~EVT_RIGHTCTRL;
389                     else
390                         EVT.keyModifiers |= EVT_RIGHTCTRL;
391                     break;
392                 case KB_leftAlt:
393                     if (what == EVT_KEYUP)
394                         EVT.keyModifiers &= ~EVT_LEFTALT;
395                     else
396                         EVT.keyModifiers |= EVT_LEFTALT;
397                     break;
398                 case KB_rightAlt:
399                     if (what == EVT_KEYUP)
400                         EVT.keyModifiers &= ~EVT_RIGHTALT;
401                     else
402                         EVT.keyModifiers |= EVT_RIGHTALT;
403                     break;
404 #ifdef SUPPORT_CTRL_ALT_DEL
405                 case KB_delete:
406                     if ((EVT.keyModifiers & EVT_CTRLSTATE) && (EVT.keyModifiers & EVT_ALTSTATE))
407                         Reboot();
408                     break;
409 #endif
410                 }
411             }
412
413         /* Add the untranslated key code to the event queue. All
414          * translation to ASCII from the key codes occurs when the key
415          * is extracted from the queue, saving time in the low level
416          * interrupt handler.
417          */
418         addKeyEvent(what,scan << 8);
419         }
420 }
421
422 /****************************************************************************
423 DESCRIPTION:
424 Enables/disables the update of the keyboard LED status indicators.
425
426 HEADER:
427 event.h
428
429 PARAMETERS:
430 enable  - True to enable, false to disable
431
432 REMARKS:
433 Enables the update of the keyboard LED status indicators. Sometimes it may
434 be convenient in the application to turn off the updating of the LED
435 status indicators (such as if a game is using the CAPSLOCK key for some
436 function). Passing in a value of FALSE to this function will turn off all
437 the LEDS, and stop updating them when the internal status changes (note
438 however that internally we still keep track of the toggle key status!).
439 ****************************************************************************/
440 void EVTAPI EVT_allowLEDS(
441     ibool enable)
442 {
443     EVT.allowLEDS = true;
444     if (enable)
445         setLEDS(EVT.keyModifiers);
446     else
447         setLEDS(0);
448     EVT.allowLEDS = enable;
449 }
450