]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbKb / Dxe / keyboard.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Keyboard.c\r
15 \r
16Abstract:\r
17\r
18 Helper functions for USB Keyboard Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "keyboard.h"\r
25\r
26//\r
27// USB Key Code to Efi key mapping table\r
28// Format:<efi scan code>, <unicode without shift>, <unicode with shift>\r
29//\r
30STATIC\r
31UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {\r
32 { SCAN_NULL, 'a', 'A' }, // 0x04\r
33 { SCAN_NULL, 'b', 'B' }, // 0x05\r
34 { SCAN_NULL, 'c', 'C' }, // 0x06\r
35 { SCAN_NULL, 'd', 'D' }, // 0x07\r
36 { SCAN_NULL, 'e', 'E' }, // 0x08\r
37 { SCAN_NULL, 'f', 'F' }, // 0x09\r
38 { SCAN_NULL, 'g', 'G' }, // 0x0A\r
39 { SCAN_NULL, 'h', 'H' }, // 0x0B\r
40 { SCAN_NULL, 'i', 'I' }, // 0x0C\r
41 { SCAN_NULL, 'j', 'J' }, // 0x0D\r
42 { SCAN_NULL, 'k', 'K' }, // 0x0E\r
43 { SCAN_NULL, 'l', 'L' }, // 0x0F\r
44 { SCAN_NULL, 'm', 'M' }, // 0x10\r
45 { SCAN_NULL, 'n', 'N' }, // 0x11\r
46 { SCAN_NULL, 'o', 'O' }, // 0x12\r
47 { SCAN_NULL, 'p', 'P' }, // 0x13\r
48 { SCAN_NULL, 'q', 'Q' }, // 0x14\r
49 { SCAN_NULL, 'r', 'R' }, // 0x15\r
50 { SCAN_NULL, 's', 'S' }, // 0x16\r
51 { SCAN_NULL, 't', 'T' }, // 0x17\r
52 { SCAN_NULL, 'u', 'U' }, // 0x18\r
53 { SCAN_NULL, 'v', 'V' }, // 0x19\r
54 { SCAN_NULL, 'w', 'W' }, // 0x1A\r
55 { SCAN_NULL, 'x', 'X' }, // 0x1B\r
56 { SCAN_NULL, 'y', 'Y' }, // 0x1C\r
57 { SCAN_NULL, 'z', 'Z' }, // 0x1D\r
58 { SCAN_NULL, '1', '!' }, // 0x1E\r
59 { SCAN_NULL, '2', '@' }, // 0x1F\r
60 { SCAN_NULL, '3', '#' }, // 0x20\r
61 { SCAN_NULL, '4', '$' }, // 0x21\r
62 { SCAN_NULL, '5', '%' }, // 0x22\r
63 { SCAN_NULL, '6', '^' }, // 0x23\r
64 { SCAN_NULL, '7', '&' }, // 0x24\r
65 { SCAN_NULL, '8', '*' }, // 0x25\r
66 { SCAN_NULL, '9', '(' }, // 0x26\r
67 { SCAN_NULL, '0', ')' }, // 0x27\r
68 { SCAN_NULL, 0x0d, 0x0d }, // 0x28 Enter\r
69 { SCAN_ESC, 0x00, 0x00 }, // 0x29 Esc\r
70 { SCAN_NULL, 0x08, 0x08 }, // 0x2A Backspace\r
71 { SCAN_NULL, 0x09, 0x09 }, // 0x2B Tab\r
72 { SCAN_NULL, ' ', ' ' }, // 0x2C Spacebar\r
73 { SCAN_NULL, '-', '_' }, // 0x2D\r
74 { SCAN_NULL, '=', '+' }, // 0x2E\r
75 { SCAN_NULL, '[', '{' }, // 0x2F\r
76 { SCAN_NULL, ']', '}' }, // 0x30\r
77 { SCAN_NULL, '\\', '|' }, // 0x31\r
78 { SCAN_NULL, '\\', '|' }, // 0x32 Keyboard US \ and |\r
79 { SCAN_NULL, ';', ':' }, // 0x33\r
80 { SCAN_NULL, '\'', '"' }, // 0x34\r
81 { SCAN_NULL, '`', '~' }, // 0x35 Keyboard Grave Accent and Tlide\r
82 { SCAN_NULL, ',', '<' }, // 0x36\r
83 { SCAN_NULL, '.', '>' }, // 0x37\r
84 { SCAN_NULL, '/', '?' }, // 0x38\r
85 { SCAN_NULL, 0x00, 0x00 }, // 0x39 CapsLock\r
86 { SCAN_F1, 0x00, 0x00 }, // 0x3A\r
87 { SCAN_F2, 0x00, 0x00 }, // 0x3B\r
88 { SCAN_F3, 0x00, 0x00 }, // 0x3C \r
89 { SCAN_F4, 0x00, 0x00 }, // 0x3D \r
90 { SCAN_F5, 0x00, 0x00 }, // 0x3E\r
91 { SCAN_F6, 0x00, 0x00 }, // 0x3F\r
92 { SCAN_F7, 0x00, 0x00 }, // 0x40\r
93 { SCAN_F8, 0x00, 0x00 }, // 0x41\r
94 { SCAN_F9, 0x00, 0x00 }, // 0x42\r
95 { SCAN_F10, 0x00, 0x00 }, // 0x43\r
96 { SCAN_NULL, 0x00, 0x00 }, // 0x44 F11\r
97 { SCAN_NULL, 0x00, 0x00 }, // 0x45 F12\r
98 { SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen\r
99 { SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock\r
100 { SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause\r
101 { SCAN_INSERT, 0x00, 0x00 }, // 0x49\r
102 { SCAN_HOME, 0x00, 0x00 }, // 0x4A\r
103 { SCAN_PAGE_UP, 0x00, 0x00 }, // 0x4B\r
104 { SCAN_DELETE, 0x00, 0x00 }, // 0x4C\r
105 { SCAN_END, 0x00, 0x00 }, // 0x4D\r
106 { SCAN_PAGE_DOWN, 0x00, 0x00 }, // 0x4E\r
107 { SCAN_RIGHT, 0x00, 0x00 }, // 0x4F\r
108 { SCAN_LEFT, 0x00, 0x00 }, // 0x50\r
109 { SCAN_DOWN, 0x00, 0x00 }, // 0x51\r
110 { SCAN_UP, 0x00, 0x00 }, // 0x52\r
111 { SCAN_NULL, 0x00, 0x00 }, // 0x53 NumLock\r
112 { SCAN_NULL, '/', '/' }, // 0x54\r
113 { SCAN_NULL, '*', '*' }, // 0x55\r
114 { SCAN_NULL, '-', '-' }, // 0x56\r
115 { SCAN_NULL, '+', '+' }, // 0x57\r
116 { SCAN_NULL, 0x0d, 0x0d }, // 0x58\r
117 { SCAN_END, '1', '1' }, // 0x59\r
118 { SCAN_DOWN, '2', '2' }, // 0x5A\r
119 { SCAN_PAGE_DOWN, '3', '3' }, // 0x5B\r
120 { SCAN_LEFT, '4', '4' }, // 0x5C\r
121 { SCAN_NULL, '5', '5' }, // 0x5D\r
122 { SCAN_RIGHT, '6', '6' }, // 0x5E\r
123 { SCAN_HOME, '7', '7' }, // 0x5F\r
124 { SCAN_UP, '8', '8' }, // 0x60\r
125 { SCAN_PAGE_UP, '9', '9' }, // 0x61\r
126 { SCAN_INSERT, '0', '0' }, // 0x62\r
127 { SCAN_DELETE, '.', '.' }, // 0x63\r
128 { SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |\r
129 { SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application\r
130 { SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power\r
131 { SCAN_NULL, '=' , '=' } // 0x67 Keypad =\r
132};\r
133\r
134STATIC KB_MODIFIER KB_Mod[8] = {\r
135 { MOD_CONTROL_L, 0xe0 }, // 11100000 \r
136 { MOD_CONTROL_R, 0xe4 }, // 11100100 \r
137 { MOD_SHIFT_L, 0xe1 }, // 11100001 \r
138 { MOD_SHIFT_R, 0xe5 }, // 11100101 \r
139 { MOD_ALT_L, 0xe2 }, // 11100010 \r
140 { MOD_ALT_R, 0xe6 }, // 11100110 \r
141 { MOD_WIN_L, 0xe3 }, // 11100011 \r
142 { MOD_WIN_R, 0xe7 } // 11100111 \r
143};\r
144\r
145\r
146BOOLEAN\r
147IsUSBKeyboard (\r
148 IN EFI_USB_IO_PROTOCOL *UsbIo\r
149 )\r
150/*++\r
151 \r
152 Routine Description:\r
153 Uses USB I/O to check whether the device is a USB Keyboard device.\r
154 \r
155 Arguments:\r
156 UsbIo: Points to a USB I/O protocol instance.\r
157 \r
158 Returns:\r
159 \r
160--*/ \r
161{\r
162 EFI_STATUS Status;\r
163 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
164\r
165 //\r
166 // Get the Default interface descriptor, currently we\r
167 // assume it is interface 1\r
168 //\r
169 Status = UsbIo->UsbGetInterfaceDescriptor (\r
170 UsbIo,\r
171 &InterfaceDescriptor\r
172 );\r
173\r
174 if (EFI_ERROR (Status)) {\r
175 return FALSE;\r
176 }\r
177\r
178 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&\r
179 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&\r
180 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD\r
181 ) {\r
182\r
183 return TRUE;\r
184 }\r
185\r
186 return FALSE;\r
187}\r
188\r
189\r
190EFI_STATUS\r
191InitUSBKeyboard (\r
192 IN USB_KB_DEV *UsbKeyboardDevice\r
193 )\r
194/*++\r
195 \r
196 Routine Description:\r
197 Initialize USB Keyboard device and all private data structures.\r
198 \r
199 Arguments:\r
200 UsbKeyboardDevice The USB_KB_DEV instance.\r
201 \r
202 Returns:\r
203 EFI_SUCCESS - Success\r
204 EFI_DEVICE_ERROR - Hardware Error\r
205--*/\r
206{\r
207 UINT8 ConfigValue;\r
208 UINT8 Protocol;\r
209 UINT8 ReportId;\r
210 UINT8 Duration;\r
211 EFI_STATUS Status;\r
212 UINT32 TransferResult;\r
878ddf1f 213\r
214 KbdReportStatusCode (\r
215 UsbKeyboardDevice->DevicePath,\r
216 EFI_PROGRESS_CODE,\r
217 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST)\r
218 );\r
219\r
220 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
221\r
222 //\r
223 // default configurations\r
224 //\r
225 ConfigValue = 0x01;\r
226\r
227 //\r
228 // Uses default configuration to configure the USB Keyboard device.\r
229 //\r
230 Status = UsbSetDeviceConfiguration (\r
231 UsbKeyboardDevice->UsbIo,\r
232 (UINT16) ConfigValue,\r
233 &TransferResult\r
234 );\r
235 if (EFI_ERROR (Status)) {\r
236 //\r
237 // If configuration could not be set here, it means\r
238 // the keyboard interface has some errors and could\r
239 // not be initialized\r
240 //\r
241 KbdReportStatusCode (\r
242 UsbKeyboardDevice->DevicePath,\r
243 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
244 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR)\r
245 );\r
246\r
247 return EFI_DEVICE_ERROR;\r
248 }\r
249\r
250 UsbGetProtocolRequest (\r
251 UsbKeyboardDevice->UsbIo,\r
252 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
253 &Protocol\r
254 );\r
255 //\r
256 // Sets boot protocol for the USB Keyboard.\r
257 // This driver only supports boot protocol.\r
258 // !!BugBug: How about the device that does not support boot protocol?\r
259 //\r
260 if (Protocol != BOOT_PROTOCOL) {\r
261 UsbSetProtocolRequest (\r
262 UsbKeyboardDevice->UsbIo,\r
263 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
264 BOOT_PROTOCOL\r
265 );\r
266 }\r
267 //\r
268 // the duration is indefinite, so the endpoint will inhibit reporting forever,\r
269 // and only reporting when a change is detected in the report data.\r
270 //\r
271\r
272 //\r
273 // idle value for all report ID\r
274 //\r
275 ReportId = 0;\r
276 //\r
277 // idle forever until there is a key pressed and released.\r
278 //\r
279 Duration = 0;\r
280 UsbSetIdleRequest (\r
281 UsbKeyboardDevice->UsbIo,\r
282 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
283 ReportId,\r
284 Duration\r
285 );\r
286\r
287 UsbKeyboardDevice->CtrlOn = 0;\r
288 UsbKeyboardDevice->AltOn = 0;\r
289 UsbKeyboardDevice->ShiftOn = 0;\r
290 UsbKeyboardDevice->NumLockOn = 0;\r
291 UsbKeyboardDevice->CapsOn = 0;\r
292 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);\r
293\r
294 //\r
295 // Set a timer for repeat keys' generation.\r
296 //\r
297 if (UsbKeyboardDevice->RepeatTimer) {\r
298 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
299 UsbKeyboardDevice->RepeatTimer = 0;\r
300 }\r
301\r
302 Status = gBS->CreateEvent (\r
303 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
304 EFI_TPL_NOTIFY,\r
305 USBKeyboardRepeatHandler,\r
306 UsbKeyboardDevice,\r
307 &UsbKeyboardDevice->RepeatTimer\r
308 );\r
309\r
310 if (UsbKeyboardDevice->DelayedRecoveryEvent) {\r
311 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
312 UsbKeyboardDevice->DelayedRecoveryEvent = 0;\r
313 }\r
314\r
315 Status = gBS->CreateEvent (\r
316 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
317 EFI_TPL_NOTIFY,\r
318 USBKeyboardRecoveryHandler,\r
319 UsbKeyboardDevice,\r
320 &UsbKeyboardDevice->DelayedRecoveryEvent\r
321 );\r
322\r
323 return EFI_SUCCESS;\r
324}\r
325\r
326EFI_STATUS\r
327EFIAPI\r
328KeyboardHandler (\r
329 IN VOID *Data,\r
330 IN UINTN DataLength,\r
331 IN VOID *Context,\r
332 IN UINT32 Result\r
333 )\r
334/*++\r
335 \r
336 Routine Description:\r
337 Handler function for USB Keyboard's asynchronous interrupt transfer.\r
338 \r
339 Arguments:\r
340 Data A pointer to a buffer that is filled with key data which is\r
341 retrieved via asynchronous interrupt transfer.\r
342 DataLength Indicates the size of the data buffer.\r
343 Context Pointing to USB_KB_DEV instance.\r
344 Result Indicates the result of the asynchronous interrupt transfer.\r
345 \r
346 Returns:\r
347 EFI_SUCCESS - Success\r
348 EFI_DEVICE_ERROR - Hardware Error\r
349--*/ \r
350{\r
351 USB_KB_DEV *UsbKeyboardDevice;\r
352 EFI_USB_IO_PROTOCOL *UsbIo;\r
353 UINT8 *CurKeyCodeBuffer;\r
354 UINT8 *OldKeyCodeBuffer;\r
355 UINT8 CurModifierMap;\r
356 UINT8 OldModifierMap;\r
357 UINT8 Index;\r
358 UINT8 Index2;\r
359 BOOLEAN Down;\r
878ddf1f 360 BOOLEAN KeyRelease;\r
361 BOOLEAN KeyPress;\r
362 UINT8 SavedTail;\r
363 USB_KEY UsbKey;\r
364 UINT8 NewRepeatKey;\r
365 UINT32 UsbStatus;\r
878ddf1f 366\r
367 ASSERT (Context);\r
368\r
369 NewRepeatKey = 0;\r
878ddf1f 370 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
371 UsbIo = UsbKeyboardDevice->UsbIo;\r
372\r
373 //\r
374 // Analyzes the Result and performs corresponding action.\r
375 //\r
376 if (Result != EFI_USB_NOERROR) {\r
377 //\r
378 // Some errors happen during the process\r
379 //\r
380 KbdReportStatusCode (\r
381 UsbKeyboardDevice->DevicePath,\r
382 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
383 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR)\r
384 );\r
385\r
386 //\r
387 // stop the repeat key generation if any\r
388 //\r
389 UsbKeyboardDevice->RepeatKey = 0;\r
390\r
391 gBS->SetTimer (\r
392 UsbKeyboardDevice->RepeatTimer,\r
393 TimerCancel,\r
394 USBKBD_REPEAT_RATE\r
395 );\r
396\r
397 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
398 UsbClearEndpointHalt (\r
399 UsbIo,\r
400 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
401 &UsbStatus\r
402 );\r
403 }\r
404 \r
405 //\r
406 // Delete & Submit this interrupt again\r
407 //\r
408 \r
1cc8ee78 409 UsbIo->UsbAsyncInterruptTransfer (\r
410 UsbIo,\r
411 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
412 FALSE,\r
413 0,\r
414 0,\r
415 NULL,\r
416 NULL\r
417 );\r
878ddf1f 418\r
419 gBS->SetTimer (\r
420 UsbKeyboardDevice->DelayedRecoveryEvent,\r
421 TimerRelative,\r
422 EFI_USB_INTERRUPT_DELAY\r
423 );\r
424\r
425 return EFI_DEVICE_ERROR;\r
426 }\r
427\r
428 if (DataLength == 0 || Data == NULL) {\r
429 return EFI_SUCCESS;\r
430 }\r
431\r
432 CurKeyCodeBuffer = (UINT8 *) Data;\r
433 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;\r
434\r
435 //\r
436 // checks for new key stroke.\r
437 // if no new key got, return immediately.\r
438 //\r
439 for (Index = 0; Index < 8; Index++) {\r
440 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {\r
441 break;\r
442 }\r
443 }\r
444\r
445 if (Index == 8) {\r
446 return EFI_SUCCESS;\r
447 }\r
448 \r
449 //\r
450 // Parse the modifier key\r
451 //\r
452 CurModifierMap = CurKeyCodeBuffer[0];\r
453 OldModifierMap = OldKeyCodeBuffer[0];\r
454\r
455 //\r
456 // handle modifier key's pressing or releasing situation.\r
457 //\r
458 for (Index = 0; Index < 8; Index++) {\r
459\r
460 if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) {\r
461 //\r
462 // if current modifier key is up, then\r
463 // CurModifierMap & KB_Mod[Index].Mask = 0;\r
464 // otherwize it is a non-zero value.\r
465 // Inserts the pressed modifier key into key buffer.\r
466 //\r
467 Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask);\r
468 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), KB_Mod[Index].Key, Down);\r
469 }\r
470 }\r
471 \r
472 //\r
473 // handle normal key's releasing situation\r
474 //\r
475 KeyRelease = FALSE;\r
476 for (Index = 2; Index < 8; Index++) {\r
477\r
478 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {\r
479 continue;\r
480 }\r
481\r
482 KeyRelease = TRUE;\r
483 for (Index2 = 2; Index2 < 8; Index2++) {\r
484\r
485 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {\r
486 continue;\r
487 }\r
488\r
489 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {\r
490 KeyRelease = FALSE;\r
491 break;\r
492 }\r
493 }\r
494\r
495 if (KeyRelease) {\r
496 InsertKeyCode (\r
497 &(UsbKeyboardDevice->KeyboardBuffer),\r
498 OldKeyCodeBuffer[Index],\r
499 0\r
500 );\r
501 //\r
502 // the original reapeat key is released.\r
503 //\r
504 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {\r
505 UsbKeyboardDevice->RepeatKey = 0;\r
506 }\r
507 }\r
508 }\r
509 \r
510 //\r
511 // original repeat key is released, cancel the repeat timer\r
512 //\r
513 if (UsbKeyboardDevice->RepeatKey == 0) {\r
514 gBS->SetTimer (\r
515 UsbKeyboardDevice->RepeatTimer,\r
516 TimerCancel,\r
517 USBKBD_REPEAT_RATE\r
518 );\r
519 }\r
520 \r
521 //\r
522 // handle normal key's pressing situation\r
523 //\r
524 KeyPress = FALSE;\r
525 for (Index = 2; Index < 8; Index++) {\r
526\r
527 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {\r
528 continue;\r
529 }\r
530\r
531 KeyPress = TRUE;\r
532 for (Index2 = 2; Index2 < 8; Index2++) {\r
533\r
534 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {\r
535 continue;\r
536 }\r
537\r
538 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {\r
539 KeyPress = FALSE;\r
540 break;\r
541 }\r
542 }\r
543\r
544 if (KeyPress) {\r
545 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], 1);\r
546 //\r
547 // NumLock pressed or CapsLock pressed\r
548 //\r
549 if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) {\r
550 UsbKeyboardDevice->RepeatKey = 0;\r
551 } else {\r
552 NewRepeatKey = CurKeyCodeBuffer[Index];\r
553 //\r
554 // do not repeat the original repeated key\r
555 //\r
556 UsbKeyboardDevice->RepeatKey = 0;\r
557 }\r
558 }\r
559 }\r
560 \r
561 //\r
562 // Update LastKeycodeArray[] buffer in the\r
563 // Usb Keyboard Device data structure.\r
564 //\r
565 for (Index = 0; Index < 8; Index++) {\r
566 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];\r
567 }\r
568 \r
569 //\r
570 // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence\r
571 // and judge whether it will invoke reset event.\r
572 //\r
573 SavedTail = UsbKeyboardDevice->KeyboardBuffer.bTail;\r
574 Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
575 while (Index != SavedTail) {\r
576 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
577\r
578 switch (UsbKey.KeyCode) {\r
579\r
580 case 0xe0:\r
581 case 0xe4:\r
582 if (UsbKey.Down) {\r
583 UsbKeyboardDevice->CtrlOn = 1;\r
584 } else {\r
585 UsbKeyboardDevice->CtrlOn = 0;\r
586 }\r
587 break;\r
588\r
589 case 0xe2:\r
590 case 0xe6:\r
591 if (UsbKey.Down) {\r
592 UsbKeyboardDevice->AltOn = 1;\r
593 } else {\r
594 UsbKeyboardDevice->AltOn = 0;\r
595 }\r
596 break;\r
597\r
598 //\r
599 // Del Key Code\r
600 //\r
601 case 0x4c:\r
602 case 0x63:\r
603 if (UsbKey.Down) {\r
604 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
605 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
606 }\r
607 }\r
608 break;\r
609\r
610 default:\r
611 break;\r
612 }\r
613 \r
614 //\r
615 // insert the key back to the buffer.\r
616 // so the key sequence will not be destroyed.\r
617 //\r
618 InsertKeyCode (\r
619 &(UsbKeyboardDevice->KeyboardBuffer),\r
620 UsbKey.KeyCode,\r
621 UsbKey.Down\r
622 );\r
623 Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
624\r
625 }\r
626 //\r
627 // If have new key pressed, update the RepeatKey value, and set the\r
628 // timer to repeate delay timer\r
629 //\r
630 if (NewRepeatKey != 0) {\r
631 //\r
632 // sets trigger time to "Repeat Delay Time",\r
633 // to trigger the repeat timer when the key is hold long\r
634 // enough time.\r
635 //\r
636 gBS->SetTimer (\r
637 UsbKeyboardDevice->RepeatTimer,\r
638 TimerRelative,\r
639 USBKBD_REPEAT_DELAY\r
640 );\r
641 UsbKeyboardDevice->RepeatKey = NewRepeatKey;\r
642 }\r
643\r
644 return EFI_SUCCESS;\r
645}\r
646\r
647EFI_STATUS\r
648USBParseKey (\r
649 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
650 OUT UINT8 *KeyChar\r
651 )\r
652/*++\r
653 \r
654 Routine Description:\r
655 Retrieves a key character after parsing the raw data in keyboard buffer.\r
656 \r
657 Arguments:\r
658 UsbKeyboardDevice The USB_KB_DEV instance.\r
659 KeyChar Points to the Key character after key parsing.\r
660 \r
661 Returns:\r
662 EFI_SUCCESS - Success\r
663 EFI_NOT_READY - Device is not ready \r
664--*/ \r
665{\r
666 USB_KEY UsbKey;\r
667\r
668 *KeyChar = 0;\r
669\r
670 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {\r
671 //\r
672 // pops one raw data off.\r
673 //\r
674 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
675\r
676 if (!UsbKey.Down) {\r
677 switch (UsbKey.KeyCode) {\r
678\r
679 case 0xe0:\r
680 case 0xe4:\r
681 UsbKeyboardDevice->CtrlOn = 0;\r
682 break;\r
683\r
684 case 0xe1:\r
685 case 0xe5:\r
686 UsbKeyboardDevice->ShiftOn = 0;\r
687 break;\r
688\r
689 case 0xe2:\r
690 case 0xe6:\r
691 UsbKeyboardDevice->AltOn = 0;\r
692 break;\r
693\r
694 default:\r
695 break;\r
696 }\r
697\r
698 continue;\r
699 }\r
700 \r
701 //\r
702 // Analyzes key pressing situation\r
703 //\r
704 switch (UsbKey.KeyCode) {\r
705\r
706 case 0xe0:\r
707 case 0xe4:\r
708 UsbKeyboardDevice->CtrlOn = 1;\r
709 continue;\r
710 break;\r
711\r
712 case 0xe1:\r
713 case 0xe5:\r
714 UsbKeyboardDevice->ShiftOn = 1;\r
715 continue;\r
716 break;\r
717\r
718 case 0xe2:\r
719 case 0xe6:\r
720 UsbKeyboardDevice->AltOn = 1;\r
721 continue;\r
722 break;\r
723\r
724 case 0xe3:\r
725 case 0xe7:\r
726 continue;\r
727 break;\r
728\r
729 case 0x53:\r
730 UsbKeyboardDevice->NumLockOn ^= 1;\r
731 SetKeyLED (UsbKeyboardDevice);\r
732 continue;\r
733 break;\r
734\r
735 case 0x39:\r
736 UsbKeyboardDevice->CapsOn ^= 1;\r
737 SetKeyLED (UsbKeyboardDevice);\r
738 continue;\r
739 break;\r
740\r
741 //\r
742 // F11,F12,PrintScreen,ScrollLock,Pause,Application,Power\r
743 // keys are not valid EFI key\r
744 //\r
745 case 0x44:\r
746 //\r
747 // fall through\r
748 //\r
749 case 0x45:\r
750 //\r
751 // fall through\r
752 //\r
753 case 0x46:\r
754 //\r
755 // fall through\r
756 //\r
757 case 0x47:\r
591ee27e 758 //\r
759 // Turn on the ScrollLock light on KB\r
760 //\r
761 UsbKeyboardDevice->ScrollOn ^= 1;\r
762 SetKeyLED (UsbKeyboardDevice);\r
763 continue;\r
764 break; \r
878ddf1f 765 case 0x48:\r
766 //\r
767 // fall through\r
768 //\r
769 case 0x65:\r
770 case 0x66:\r
771 continue;\r
772 break;\r
773\r
774 default:\r
775 break;\r
776 }\r
777 \r
778 //\r
779 // When encountered Del Key...\r
780 //\r
781 if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
782 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
783 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
784 }\r
785 }\r
786\r
787 *KeyChar = UsbKey.KeyCode;\r
788 return EFI_SUCCESS;\r
789 }\r
790\r
791 return EFI_NOT_READY;\r
792\r
793}\r
794\r
795\r
796EFI_STATUS\r
797USBKeyCodeToEFIScanCode (\r
798 IN USB_KB_DEV *UsbKeyboardDevice,\r
799 IN UINT8 KeyChar,\r
800 OUT EFI_INPUT_KEY *Key\r
801 )\r
802/*++\r
803 \r
804 Routine Description:\r
805 Converts USB Keyboard code to EFI Scan Code.\r
806 \r
807 Arguments: \r
808 UsbKeyboardDevice The USB_KB_DEV instance.\r
809 KeyChar Indicates the key code that will be interpreted. \r
810 Key A pointer to a buffer that is filled in with \r
811 the keystroke information for the key that \r
812 was pressed.\r
813 Returns:\r
814 EFI_NOT_READY - Device is not ready\r
815 EFI_SUCCESS - Success\r
816--*/\r
817{\r
818 UINT8 Index;\r
819\r
820 if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
821 return EFI_NOT_READY;\r
822 }\r
823 \r
824 //\r
825 // valid USB Key Code starts from 4\r
826 //\r
827 Index = (UINT8) (KeyChar - 4);\r
828\r
829 if (Index >= USB_KEYCODE_MAX_MAKE) {\r
830 return EFI_NOT_READY;\r
831 }\r
832\r
833 Key->ScanCode = KeyConvertionTable[Index][0];\r
834\r
835 if (UsbKeyboardDevice->ShiftOn) {\r
836\r
837 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
838\r
839 } else {\r
840\r
841 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
842 }\r
843\r
844 if (UsbKeyboardDevice->CapsOn) {\r
845\r
846 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
847\r
848 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
849\r
850 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
851\r
852 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
853\r
854 }\r
855 }\r
856\r
857 if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
858\r
859 if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
860\r
861 Key->ScanCode = SCAN_NULL;\r
862\r
863 } else {\r
864\r
865 Key->UnicodeChar = 0x00;\r
866 }\r
867 }\r
868\r
869 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
870 return EFI_NOT_READY;\r
871 }\r
872\r
873 return EFI_SUCCESS;\r
874\r
875}\r
876\r
877\r
878EFI_STATUS\r
879InitUSBKeyBuffer (\r
880 IN OUT USB_KB_BUFFER *KeyboardBuffer\r
881 )\r
882/*++\r
883 \r
884 Routine Description:\r
885 Resets USB Keyboard Buffer.\r
886 \r
887 Arguments:\r
888 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
889 \r
890 Returns:\r
891 EFI_SUCCESS - Success\r
892--*/ \r
893{\r
894 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));\r
895\r
896 KeyboardBuffer->bHead = KeyboardBuffer->bTail;\r
897\r
898 return EFI_SUCCESS;\r
899}\r
900\r
901BOOLEAN\r
902IsUSBKeyboardBufferEmpty (\r
903 IN USB_KB_BUFFER *KeyboardBuffer\r
904 )\r
905/*++\r
906 \r
907 Routine Description:\r
908 Check whether USB Keyboard buffer is empty.\r
909 \r
910 Arguments:\r
911 KeyboardBuffer - USB Keyboard Buffer.\r
912 \r
913 Returns:\r
914 \r
915--*/\r
916{\r
917 //\r
918 // meet FIFO empty condition\r
919 //\r
920 return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);\r
921}\r
922\r
923\r
924BOOLEAN\r
925IsUSBKeyboardBufferFull (\r
926 IN USB_KB_BUFFER *KeyboardBuffer\r
927 )\r
928/*++\r
929 \r
930 Routine Description:\r
931 Check whether USB Keyboard buffer is full.\r
932 \r
933 Arguments:\r
934 KeyboardBuffer - USB Keyboard Buffer.\r
935 \r
936 Returns:\r
937 \r
938--*/\r
939{\r
940 return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == \r
941 KeyboardBuffer->bHead);\r
942}\r
943\r
944\r
945EFI_STATUS\r
946InsertKeyCode (\r
947 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
948 IN UINT8 Key,\r
949 IN UINT8 Down\r
950 )\r
951/*++\r
952 \r
953 Routine Description:\r
954 Inserts a key code into keyboard buffer.\r
955 \r
956 Arguments:\r
957 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
958 Key - Key code\r
959 Down - Special key\r
960 Returns:\r
961 EFI_SUCCESS - Success\r
962--*/\r
963{\r
964 USB_KEY UsbKey;\r
965\r
966 //\r
967 // if keyboard buffer is full, throw the\r
968 // first key out of the keyboard buffer.\r
969 //\r
970 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {\r
971 RemoveKeyCode (KeyboardBuffer, &UsbKey);\r
972 }\r
973\r
974 KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;\r
975 KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;\r
976\r
977 //\r
978 // adjust the tail pointer of the FIFO keyboard buffer.\r
979 //\r
980 KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));\r
981\r
982 return EFI_SUCCESS;\r
983}\r
984\r
985EFI_STATUS\r
986RemoveKeyCode (\r
987 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
988 OUT USB_KEY *UsbKey\r
989 )\r
990/*++\r
991 \r
992 Routine Description:\r
993 Pops a key code off from keyboard buffer.\r
994 \r
995 Arguments:\r
996 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
997 UsbKey - Points to the buffer that contains a usb key code.\r
998 \r
999 Returns:\r
1000 EFI_SUCCESS - Success\r
1001 EFI_DEVICE_ERROR - Hardware Error\r
1002--*/ \r
1003{\r
1004 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {\r
1005 return EFI_DEVICE_ERROR;\r
1006 }\r
1007\r
1008 UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;\r
1009 UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;\r
1010\r
1011 //\r
1012 // adjust the head pointer of the FIFO keyboard buffer.\r
1013 //\r
1014 KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));\r
1015\r
1016 return EFI_SUCCESS;\r
1017}\r
1018\r
1019EFI_STATUS\r
1020SetKeyLED (\r
1021 IN USB_KB_DEV *UsbKeyboardDevice\r
1022 )\r
1023/*++\r
1024 \r
1025 Routine Description:\r
1026 Sets USB Keyboard LED state.\r
1027 \r
1028 Arguments:\r
1029 UsbKeyboardDevice - The USB_KB_DEV instance.\r
1030 \r
1031 Returns:\r
1032 EFI_SUCCESS - Success\r
1033--*/ \r
1034{\r
1035 LED_MAP Led;\r
1036 UINT8 ReportId;\r
1037\r
1038 //\r
1039 // Set each field in Led map.\r
1040 //\r
1041 Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;\r
1042 Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;\r
591ee27e 1043 Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn; \r
878ddf1f 1044 Led.Resrvd = 0;\r
1045\r
1046 ReportId = 0;\r
1047 //\r
1048 // call Set Report Request to lighten the LED.\r
1049 //\r
1050 UsbSetReportRequest (\r
1051 UsbKeyboardDevice->UsbIo,\r
1052 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
1053 ReportId,\r
1054 HID_OUTPUT_REPORT,\r
1055 1,\r
1056 (UINT8 *) &Led\r
1057 );\r
1058\r
1059 return EFI_SUCCESS;\r
1060}\r
1061\r
1062VOID\r
1063EFIAPI\r
1064USBKeyboardRepeatHandler (\r
1065 IN EFI_EVENT Event,\r
1066 IN VOID *Context\r
1067 )\r
1068/*++\r
1069 \r
1070 Routine Description:\r
1071 Timer handler for Repeat Key timer.\r
1072 \r
1073 Arguments:\r
1074 Event - The Repeat Key event.\r
1075 Context - Points to the USB_KB_DEV instance.\r
1076 \r
1077 Returns:\r
1078 \r
1079--*/ \r
1080{\r
1081 USB_KB_DEV *UsbKeyboardDevice;\r
1082\r
1083 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1084\r
1085 //\r
1086 // Do nothing when there is no repeat key.\r
1087 //\r
1088 if (UsbKeyboardDevice->RepeatKey != 0) {\r
1089 //\r
1090 // Inserts one Repeat key into keyboard buffer,\r
1091 //\r
1092 InsertKeyCode (\r
1093 &(UsbKeyboardDevice->KeyboardBuffer),\r
1094 UsbKeyboardDevice->RepeatKey,\r
1095 1\r
1096 );\r
1097\r
1098 //\r
1099 // set repeate rate for repeat key generation.\r
1100 //\r
1101 gBS->SetTimer (\r
1102 UsbKeyboardDevice->RepeatTimer,\r
1103 TimerRelative,\r
1104 USBKBD_REPEAT_RATE\r
1105 );\r
1106\r
1107 }\r
1108}\r
1109\r
1110VOID\r
1111EFIAPI\r
1112USBKeyboardRecoveryHandler (\r
1113 IN EFI_EVENT Event,\r
1114 IN VOID *Context\r
1115 )\r
1116/*++\r
1117 \r
1118 Routine Description:\r
1119 Timer handler for Delayed Recovery timer.\r
1120 \r
1121 Arguments:\r
1122 Event - The Delayed Recovery event.\r
1123 Context - Points to the USB_KB_DEV instance.\r
1124 \r
1125 Returns:\r
1126 \r
1127--*/ \r
1128{\r
1129\r
1130 USB_KB_DEV *UsbKeyboardDevice;\r
1131 EFI_USB_IO_PROTOCOL *UsbIo;\r
1132 UINT8 PacketSize;\r
1133\r
1134 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1135\r
1136 UsbIo = UsbKeyboardDevice->UsbIo;\r
1137\r
1138 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
1139\r
1140 UsbIo->UsbAsyncInterruptTransfer (\r
1141 UsbIo,\r
1142 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1143 TRUE,\r
1144 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
1145 PacketSize,\r
1146 KeyboardHandler,\r
1147 UsbKeyboardDevice\r
1148 );\r
1149}\r