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