]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
Comment unallowed item
[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
209 EFI_USB_IO_PROTOCOL *UsbIo;\r
210\r
211 UsbIo = UsbKeyboardDevice->UsbIo;\r
212\r
213 KbdReportStatusCode (\r
214 UsbKeyboardDevice->DevicePath,\r
215 EFI_PROGRESS_CODE,\r
216 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest)\r
217 );\r
218\r
219 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
220\r
221 //\r
222 // default configurations\r
223 //\r
224 ConfigValue = 0x01;\r
225\r
226 //\r
227 // Uses default configuration to configure the USB Keyboard device.\r
228 //\r
229 Status = UsbSetConfiguration (\r
230 UsbKeyboardDevice->UsbIo,\r
231 (UINT16) ConfigValue,\r
232 &TransferResult\r
233 );\r
234 if (EFI_ERROR (Status)) {\r
235 //\r
236 // If configuration could not be set here, it means\r
237 // the keyboard interface has some errors and could\r
238 // not be initialized\r
239 //\r
240 KbdReportStatusCode (\r
241 UsbKeyboardDevice->DevicePath,\r
242 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
243 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError)\r
244 );\r
245\r
246 return EFI_DEVICE_ERROR;\r
247 }\r
248\r
249 UsbGetProtocolRequest (\r
250 UsbKeyboardDevice->UsbIo,\r
251 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
252 &Protocol\r
253 );\r
254 //\r
255 // Sets boot protocol for the USB Keyboard.\r
256 // This driver only supports boot protocol.\r
257 // !!BugBug: How about the device that does not support boot protocol?\r
258 //\r
259 if (Protocol != BOOT_PROTOCOL) {\r
260 UsbSetProtocolRequest (\r
261 UsbKeyboardDevice->UsbIo,\r
262 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
263 BOOT_PROTOCOL\r
264 );\r
265 }\r
266 //\r
267 // the duration is indefinite, so the endpoint will inhibit reporting forever,\r
268 // and only reporting when a change is detected in the report data.\r
269 //\r
270\r
271 //\r
272 // idle value for all report ID\r
273 //\r
274 ReportId = 0;\r
275 //\r
276 // idle forever until there is a key pressed and released.\r
277 //\r
278 Duration = 0;\r
279 UsbSetIdleRequest (\r
280 UsbKeyboardDevice->UsbIo,\r
281 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
282 ReportId,\r
283 Duration\r
284 );\r
285\r
286 UsbKeyboardDevice->CtrlOn = 0;\r
287 UsbKeyboardDevice->AltOn = 0;\r
288 UsbKeyboardDevice->ShiftOn = 0;\r
289 UsbKeyboardDevice->NumLockOn = 0;\r
290 UsbKeyboardDevice->CapsOn = 0;\r
291 UsbKeyboardDevice->ScrollOn = 0;\r
292\r
293 //\r
294 // Sync the initial state of lights\r
295 //\r
296 SetKeyLED (UsbKeyboardDevice);\r
297\r
298 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);\r
299\r
300 //\r
301 // Set a timer for repeat keys' generation.\r
302 //\r
303 if (UsbKeyboardDevice->RepeatTimer) {\r
304 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
305 UsbKeyboardDevice->RepeatTimer = 0;\r
306 }\r
307\r
308 Status = gBS->CreateEvent (\r
309 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
310 TPL_NOTIFY,\r
311 USBKeyboardRepeatHandler,\r
312 UsbKeyboardDevice,\r
313 &UsbKeyboardDevice->RepeatTimer\r
314 );\r
315\r
316 if (UsbKeyboardDevice->DelayedRecoveryEvent) {\r
317 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
318 UsbKeyboardDevice->DelayedRecoveryEvent = 0;\r
319 }\r
320\r
321 Status = gBS->CreateEvent (\r
322 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
323 TPL_NOTIFY,\r
324 USBKeyboardRecoveryHandler,\r
325 UsbKeyboardDevice,\r
326 &UsbKeyboardDevice->DelayedRecoveryEvent\r
327 );\r
328\r
329 return EFI_SUCCESS;\r
330}\r
331\r
332\r
333/**\r
334 Handler function for USB Keyboard's asynchronous interrupt transfer.\r
335\r
336 Data A pointer to a buffer that is filled with key data which is\r
337 retrieved via asynchronous interrupt transfer.\r
338 DataLength Indicates the size of the data buffer.\r
339 Context Pointing to USB_KB_DEV instance.\r
340 Result Indicates the result of the asynchronous interrupt transfer.\r
341\r
342 @retval EFI_SUCCESS Success\r
343 @retval EFI_DEVICE_ERROR Hardware Error\r
344\r
345**/\r
346EFI_STATUS\r
347EFIAPI\r
348KeyboardHandler (\r
349 IN VOID *Data,\r
350 IN UINTN DataLength,\r
351 IN VOID *Context,\r
352 IN UINT32 Result\r
353 )\r
354{\r
355 USB_KB_DEV *UsbKeyboardDevice;\r
356 EFI_USB_IO_PROTOCOL *UsbIo;\r
357 UINT8 *CurKeyCodeBuffer;\r
358 UINT8 *OldKeyCodeBuffer;\r
359 UINT8 CurModifierMap;\r
360 UINT8 OldModifierMap;\r
361 UINT8 Index;\r
362 UINT8 Index2;\r
363 BOOLEAN Down;\r
364 EFI_STATUS Status;\r
365 BOOLEAN KeyRelease;\r
366 BOOLEAN KeyPress;\r
367 UINT8 SavedTail;\r
368 USB_KEY UsbKey;\r
369 UINT8 NewRepeatKey;\r
370 UINT32 UsbStatus;\r
371 UINT8 *DataPtr;\r
372\r
373 ASSERT (Context);\r
374\r
375 NewRepeatKey = 0;\r
376 DataPtr = (UINT8 *) Data;\r
377 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
378 UsbIo = UsbKeyboardDevice->UsbIo;\r
379\r
380 //\r
381 // Analyzes the Result and performs corresponding action.\r
382 //\r
383 if (Result != EFI_USB_NOERROR) {\r
384 //\r
385 // Some errors happen during the process\r
386 //\r
387 KbdReportStatusCode (\r
388 UsbKeyboardDevice->DevicePath,\r
389 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
390 PcdGet32 (PcdStatusCodeValueKeyboardInputError)\r
391 );\r
392\r
393 //\r
394 // stop the repeat key generation if any\r
395 //\r
396 UsbKeyboardDevice->RepeatKey = 0;\r
397\r
398 gBS->SetTimer (\r
399 UsbKeyboardDevice->RepeatTimer,\r
400 TimerCancel,\r
401 USBKBD_REPEAT_RATE\r
402 );\r
403\r
404 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
405 UsbClearEndpointHalt (\r
406 UsbIo,\r
407 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
408 &UsbStatus\r
409 );\r
410 }\r
411\r
412 //\r
413 // Delete & Submit this interrupt again\r
414 //\r
415\r
416 Status = UsbIo->UsbAsyncInterruptTransfer (\r
417 UsbIo,\r
418 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
419 FALSE,\r
420 0,\r
421 0,\r
422 NULL,\r
423 NULL\r
424 );\r
425\r
426 gBS->SetTimer (\r
427 UsbKeyboardDevice->DelayedRecoveryEvent,\r
428 TimerRelative,\r
429 EFI_USB_INTERRUPT_DELAY\r
430 );\r
431\r
432 return EFI_DEVICE_ERROR;\r
433 }\r
434\r
435 if (DataLength == 0 || Data == NULL) {\r
436 return EFI_SUCCESS;\r
437 }\r
438\r
439 CurKeyCodeBuffer = (UINT8 *) Data;\r
440 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;\r
441\r
442 //\r
443 // checks for new key stroke.\r
444 // if no new key got, return immediately.\r
445 //\r
446 for (Index = 0; Index < 8; Index++) {\r
447 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {\r
448 break;\r
449 }\r
450 }\r
451\r
452 if (Index == 8) {\r
453 return EFI_SUCCESS;\r
454 }\r
455\r
456 //\r
457 // Parse the modifier key\r
458 //\r
459 CurModifierMap = CurKeyCodeBuffer[0];\r
460 OldModifierMap = OldKeyCodeBuffer[0];\r
461\r
462 //\r
463 // handle modifier key's pressing or releasing situation.\r
464 //\r
465 for (Index = 0; Index < 8; Index++) {\r
466\r
467 if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) {\r
468 //\r
469 // if current modifier key is up, then\r
470 // CurModifierMap & KB_Mod[Index].Mask = 0;\r
471 // otherwize it is a non-zero value.\r
472 // Inserts the pressed modifier key into key buffer.\r
473 //\r
474 Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask);\r
475 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), KB_Mod[Index].Key, Down);\r
476 }\r
477 }\r
478\r
479 //\r
480 // handle normal key's releasing situation\r
481 //\r
482 KeyRelease = FALSE;\r
483 for (Index = 2; Index < 8; Index++) {\r
484\r
485 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {\r
486 continue;\r
487 }\r
488\r
489 KeyRelease = TRUE;\r
490 for (Index2 = 2; Index2 < 8; Index2++) {\r
491\r
492 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {\r
493 continue;\r
494 }\r
495\r
496 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {\r
497 KeyRelease = FALSE;\r
498 break;\r
499 }\r
500 }\r
501\r
502 if (KeyRelease) {\r
503 InsertKeyCode (\r
504 &(UsbKeyboardDevice->KeyboardBuffer),\r
505 OldKeyCodeBuffer[Index],\r
506 0\r
507 );\r
508 //\r
509 // the original reapeat key is released.\r
510 //\r
511 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {\r
512 UsbKeyboardDevice->RepeatKey = 0;\r
513 }\r
514 }\r
515 }\r
516\r
517 //\r
518 // original repeat key is released, cancel the repeat timer\r
519 //\r
520 if (UsbKeyboardDevice->RepeatKey == 0) {\r
521 gBS->SetTimer (\r
522 UsbKeyboardDevice->RepeatTimer,\r
523 TimerCancel,\r
524 USBKBD_REPEAT_RATE\r
525 );\r
526 }\r
527\r
528 //\r
529 // handle normal key's pressing situation\r
530 //\r
531 KeyPress = FALSE;\r
532 for (Index = 2; Index < 8; Index++) {\r
533\r
534 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {\r
535 continue;\r
536 }\r
537\r
538 KeyPress = TRUE;\r
539 for (Index2 = 2; Index2 < 8; Index2++) {\r
540\r
541 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {\r
542 continue;\r
543 }\r
544\r
545 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {\r
546 KeyPress = FALSE;\r
547 break;\r
548 }\r
549 }\r
550\r
551 if (KeyPress) {\r
552 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], 1);\r
553 //\r
554 // NumLock pressed or CapsLock pressed\r
555 //\r
556 if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) {\r
557 UsbKeyboardDevice->RepeatKey = 0;\r
558 } else {\r
559 NewRepeatKey = CurKeyCodeBuffer[Index];\r
560 //\r
561 // do not repeat the original repeated key\r
562 //\r
563 UsbKeyboardDevice->RepeatKey = 0;\r
564 }\r
565 }\r
566 }\r
567\r
568 //\r
569 // Update LastKeycodeArray[] buffer in the\r
570 // Usb Keyboard Device data structure.\r
571 //\r
572 for (Index = 0; Index < 8; Index++) {\r
573 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];\r
574 }\r
575\r
576 //\r
577 // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence\r
578 // and judge whether it will invoke reset event.\r
579 //\r
580 SavedTail = UsbKeyboardDevice->KeyboardBuffer.bTail;\r
581 Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
582 while (Index != SavedTail) {\r
583 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
584\r
585 switch (UsbKey.KeyCode) {\r
586\r
587 case 0xe0:\r
588 case 0xe4:\r
589 if (UsbKey.Down) {\r
590 UsbKeyboardDevice->CtrlOn = 1;\r
591 } else {\r
592 UsbKeyboardDevice->CtrlOn = 0;\r
593 }\r
594 break;\r
595\r
596 case 0xe2:\r
597 case 0xe6:\r
598 if (UsbKey.Down) {\r
599 UsbKeyboardDevice->AltOn = 1;\r
600 } else {\r
601 UsbKeyboardDevice->AltOn = 0;\r
602 }\r
603 break;\r
604\r
605 //\r
606 // Del Key Code\r
607 //\r
608 case 0x4c:\r
609 case 0x63:\r
610 if (UsbKey.Down) {\r
611 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
612 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
613 }\r
614 }\r
615 break;\r
616\r
617 default:\r
618 break;\r
619 }\r
620\r
621 //\r
622 // insert the key back to the buffer.\r
623 // so the key sequence will not be destroyed.\r
624 //\r
625 InsertKeyCode (\r
626 &(UsbKeyboardDevice->KeyboardBuffer),\r
627 UsbKey.KeyCode,\r
628 UsbKey.Down\r
629 );\r
630 Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
631\r
632 }\r
633 //\r
634 // If have new key pressed, update the RepeatKey value, and set the\r
635 // timer to repeate delay timer\r
636 //\r
637 if (NewRepeatKey != 0) {\r
638 //\r
639 // sets trigger time to "Repeat Delay Time",\r
640 // to trigger the repeat timer when the key is hold long\r
641 // enough time.\r
642 //\r
643 gBS->SetTimer (\r
644 UsbKeyboardDevice->RepeatTimer,\r
645 TimerRelative,\r
646 USBKBD_REPEAT_DELAY\r
647 );\r
648 UsbKeyboardDevice->RepeatKey = NewRepeatKey;\r
649 }\r
650\r
651 return EFI_SUCCESS;\r
652}\r
653\r
654\r
655/**\r
656 Retrieves a key character after parsing the raw data in keyboard buffer.\r
657\r
658 UsbKeyboardDevice The USB_KB_DEV instance.\r
659 KeyChar Points to the Key character after key parsing.\r
660\r
661 @retval EFI_SUCCESS Success\r
662 @retval EFI_NOT_READY Device is not ready\r
663\r
664**/\r
665EFI_STATUS\r
666USBParseKey (\r
667 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
668 OUT UINT8 *KeyChar\r
669 )\r
670{\r
671 USB_KEY UsbKey;\r
672\r
673 *KeyChar = 0;\r
674\r
675 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {\r
676 //\r
677 // pops one raw data off.\r
678 //\r
679 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
680\r
681 if (!UsbKey.Down) {\r
682 switch (UsbKey.KeyCode) {\r
683\r
684 case 0xe0:\r
685 case 0xe4:\r
686 UsbKeyboardDevice->CtrlOn = 0;\r
687 break;\r
688\r
689 case 0xe1:\r
690 case 0xe5:\r
691 UsbKeyboardDevice->ShiftOn = 0;\r
692 break;\r
693\r
694 case 0xe2:\r
695 case 0xe6:\r
696 UsbKeyboardDevice->AltOn = 0;\r
697 break;\r
698\r
699 default:\r
700 break;\r
701 }\r
702\r
703 continue;\r
704 }\r
705\r
706 //\r
707 // Analyzes key pressing situation\r
708 //\r
709 switch (UsbKey.KeyCode) {\r
710\r
711 case 0xe0:\r
712 case 0xe4:\r
713 UsbKeyboardDevice->CtrlOn = 1;\r
714 continue;\r
715 break;\r
716\r
717 case 0xe1:\r
718 case 0xe5:\r
719 UsbKeyboardDevice->ShiftOn = 1;\r
720 continue;\r
721 break;\r
722\r
723 case 0xe2:\r
724 case 0xe6:\r
725 UsbKeyboardDevice->AltOn = 1;\r
726 continue;\r
727 break;\r
728\r
729 case 0xe3:\r
730 case 0xe7:\r
731 continue;\r
732 break;\r
733\r
734 case 0x53:\r
735 UsbKeyboardDevice->NumLockOn ^= 1;\r
736 //\r
737 // Turn on the NumLock light on KB\r
738 //\r
739 SetKeyLED (UsbKeyboardDevice);\r
740 continue;\r
741 break;\r
742\r
743 case 0x39:\r
744 UsbKeyboardDevice->CapsOn ^= 1;\r
745 //\r
746 // Turn on the CapsLock light on KB\r
747 //\r
748 SetKeyLED (UsbKeyboardDevice);\r
749 continue;\r
750 break;\r
751\r
752 case 0x47:\r
753 UsbKeyboardDevice->ScrollOn ^= 1;\r
754 //\r
755 // Turn on the ScrollLock light on KB\r
756 //\r
757 SetKeyLED (UsbKeyboardDevice);\r
758 continue;\r
759 break;\r
760\r
761 //\r
762 // PrintScreen,Pause,Application,Power\r
763 // keys are not valid EFI key\r
764 //\r
765\r
766 case 0x46:\r
767 //\r
768 // fall through\r
769 //\r
770 case 0x48:\r
771 //\r
772 // fall through\r
773 //\r
774 case 0x65:\r
775 //\r
776 // fall through\r
777 //\r
778 case 0x66:\r
779 //\r
780 // fall through\r
781 //\r
782 continue;\r
783 break;\r
784\r
785 default:\r
786 break;\r
787 }\r
788\r
789 //\r
790 // When encountered Del Key...\r
791 //\r
792 if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
793 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
794 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
795 }\r
796 }\r
797\r
798 *KeyChar = UsbKey.KeyCode;\r
799 return EFI_SUCCESS;\r
800 }\r
801\r
802 return EFI_NOT_READY;\r
803\r
804}\r
805\r
806\r
807\r
808/**\r
809 Converts USB Keyboard code to EFI Scan Code.\r
810\r
811 UsbKeyboardDevice The USB_KB_DEV instance.\r
812 KeyChar Indicates the key code that will be interpreted.\r
813 Key A pointer to a buffer that is filled in with\r
814 the keystroke information for the key that\r
815 was pressed.\r
816\r
817 @retval EFI_NOT_READY Device is not ready\r
818 @retval EFI_SUCCESS Success\r
819\r
820**/\r
821EFI_STATUS\r
822USBKeyCodeToEFIScanCode (\r
823 IN USB_KB_DEV *UsbKeyboardDevice,\r
824 IN UINT8 KeyChar,\r
825 OUT EFI_INPUT_KEY *Key\r
826 )\r
827{\r
828 UINT8 Index;\r
829\r
830 if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
831 return EFI_NOT_READY;\r
832 }\r
833\r
834 //\r
835 // valid USB Key Code starts from 4\r
836 //\r
837 Index = (UINT8) (KeyChar - 4);\r
838\r
839 if (Index >= USB_KEYCODE_MAX_MAKE) {\r
840 return EFI_NOT_READY;\r
841 }\r
842\r
843 Key->ScanCode = KeyConvertionTable[Index][0];\r
844\r
845 if (UsbKeyboardDevice->ShiftOn) {\r
846\r
847 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
848\r
849 } else {\r
850\r
851 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
852 }\r
853\r
854 if (UsbKeyboardDevice->CapsOn) {\r
855\r
856 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
857\r
858 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
859\r
860 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
861\r
862 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
863\r
864 }\r
865 }\r
866\r
867 if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
868\r
869 if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
870\r
871 Key->ScanCode = SCAN_NULL;\r
872\r
873 } else {\r
874\r
875 Key->UnicodeChar = 0x00;\r
876 }\r
877 }\r
878\r
879 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
880 return EFI_NOT_READY;\r
881 }\r
882\r
883 return EFI_SUCCESS;\r
884\r
885}\r
886\r
887\r
888\r
889/**\r
890 Resets USB Keyboard Buffer.\r
891\r
892 @param KeyboardBuffer Points to the USB Keyboard Buffer.\r
893\r
894 @retval EFI_SUCCESS Success\r
895\r
896**/\r
897EFI_STATUS\r
898InitUSBKeyBuffer (\r
899 IN OUT USB_KB_BUFFER *KeyboardBuffer\r
900 )\r
901{\r
902 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));\r
903\r
904 KeyboardBuffer->bHead = KeyboardBuffer->bTail;\r
905\r
906 return EFI_SUCCESS;\r
907}\r
908\r
909\r
910/**\r
911 Check whether USB Keyboard buffer is empty.\r
912\r
913 @param KeyboardBuffer USB Keyboard Buffer.\r
914\r
915\r
916**/\r
917BOOLEAN\r
918IsUSBKeyboardBufferEmpty (\r
919 IN USB_KB_BUFFER *KeyboardBuffer\r
920 )\r
921{\r
922 //\r
923 // meet FIFO empty condition\r
924 //\r
925 return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);\r
926}\r
927\r
928\r
929\r
930/**\r
931 Check whether USB Keyboard buffer is full.\r
932\r
933 @param KeyboardBuffer USB Keyboard Buffer.\r
934\r
935\r
936**/\r
937BOOLEAN\r
938IsUSBKeyboardBufferFull (\r
939 IN USB_KB_BUFFER *KeyboardBuffer\r
940 )\r
941{\r
942 return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) ==\r
943 KeyboardBuffer->bHead);\r
944}\r
945\r
946\r
947\r
948/**\r
949 Inserts a key code into keyboard buffer.\r
950\r
951 @param KeyboardBuffer Points to the USB Keyboard Buffer.\r
952 @param Key Key code\r
953 @param Down Special key\r
954\r
955 @retval EFI_SUCCESS Success\r
956\r
957**/\r
958EFI_STATUS\r
959InsertKeyCode (\r
960 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
961 IN UINT8 Key,\r
962 IN UINT8 Down\r
963 )\r
964{\r
965 USB_KEY UsbKey;\r
966\r
967 //\r
968 // if keyboard buffer is full, throw the\r
969 // first key out of the keyboard buffer.\r
970 //\r
971 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {\r
972 RemoveKeyCode (KeyboardBuffer, &UsbKey);\r
973 }\r
974\r
975 KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;\r
976 KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;\r
977\r
978 //\r
979 // adjust the tail pointer of the FIFO keyboard buffer.\r
980 //\r
981 KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));\r
982\r
983 return EFI_SUCCESS;\r
984}\r
985\r
986\r
987/**\r
988 Pops a key code off from keyboard buffer.\r
989\r
990 @param KeyboardBuffer Points to the USB Keyboard Buffer.\r
991 @param UsbKey Points to the buffer that contains a usb key code.\r
992\r
993 @retval EFI_SUCCESS Success\r
994 @retval EFI_DEVICE_ERROR Hardware Error\r
995\r
996**/\r
997EFI_STATUS\r
998RemoveKeyCode (\r
999 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
1000 OUT USB_KEY *UsbKey\r
1001 )\r
1002{\r
1003 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {\r
1004 return EFI_DEVICE_ERROR;\r
1005 }\r
1006\r
1007 UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;\r
1008 UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;\r
1009\r
1010 //\r
1011 // adjust the head pointer of the FIFO keyboard buffer.\r
1012 //\r
1013 KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));\r
1014\r
1015 return EFI_SUCCESS;\r
1016}\r
1017\r
1018\r
1019/**\r
1020 Sets USB Keyboard LED state.\r
1021\r
1022 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
1023\r
1024 @retval EFI_SUCCESS Success\r
1025\r
1026**/\r
1027EFI_STATUS\r
1028SetKeyLED (\r
1029 IN USB_KB_DEV *UsbKeyboardDevice\r
1030 )\r
1031{\r
1032 LED_MAP Led;\r
1033 UINT8 ReportId;\r
1034\r
1035 //\r
1036 // Set each field in Led map.\r
1037 //\r
1038 Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;\r
1039 Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;\r
1040 Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn;\r
1041 Led.Resrvd = 0;\r
1042\r
1043 ReportId = 0;\r
1044 //\r
1045 // call Set Report Request to lighten the LED.\r
1046 //\r
1047 UsbSetReportRequest (\r
1048 UsbKeyboardDevice->UsbIo,\r
1049 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
1050 ReportId,\r
1051 HID_OUTPUT_REPORT,\r
1052 1,\r
1053 (UINT8 *) &Led\r
1054 );\r
1055\r
1056 return EFI_SUCCESS;\r
1057}\r
1058\r
1059\r
1060/**\r
1061 Timer handler for Repeat Key timer.\r
1062\r
1063 @param Event The Repeat Key event.\r
1064 @param Context Points to the USB_KB_DEV instance.\r
1065\r
1066\r
1067**/\r
1068VOID\r
1069EFIAPI\r
1070USBKeyboardRepeatHandler (\r
1071 IN EFI_EVENT Event,\r
1072 IN VOID *Context\r
1073 )\r
1074{\r
1075 USB_KB_DEV *UsbKeyboardDevice;\r
1076\r
1077 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1078\r
1079 //\r
1080 // Do nothing when there is no repeat key.\r
1081 //\r
1082 if (UsbKeyboardDevice->RepeatKey != 0) {\r
1083 //\r
1084 // Inserts one Repeat key into keyboard buffer,\r
1085 //\r
1086 InsertKeyCode (\r
1087 &(UsbKeyboardDevice->KeyboardBuffer),\r
1088 UsbKeyboardDevice->RepeatKey,\r
1089 1\r
1090 );\r
1091\r
1092 //\r
1093 // set repeate rate for repeat key generation.\r
1094 //\r
1095 gBS->SetTimer (\r
1096 UsbKeyboardDevice->RepeatTimer,\r
1097 TimerRelative,\r
1098 USBKBD_REPEAT_RATE\r
1099 );\r
1100\r
1101 }\r
1102}\r
1103\r
1104\r
1105/**\r
1106 Timer handler for Delayed Recovery timer.\r
1107\r
1108 @param Event The Delayed Recovery event.\r
1109 @param Context Points to the USB_KB_DEV instance.\r
1110\r
1111\r
1112**/\r
1113VOID\r
1114EFIAPI\r
1115USBKeyboardRecoveryHandler (\r
1116 IN EFI_EVENT Event,\r
1117 IN VOID *Context\r
1118 )\r
1119{\r
1120\r
1121 USB_KB_DEV *UsbKeyboardDevice;\r
1122 EFI_USB_IO_PROTOCOL *UsbIo;\r
1123 UINT8 PacketSize;\r
1124\r
1125 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1126\r
1127 UsbIo = UsbKeyboardDevice->UsbIo;\r
1128\r
1129 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
1130\r
1131 UsbIo->UsbAsyncInterruptTransfer (\r
1132 UsbIo,\r
1133 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1134 TRUE,\r
1135 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
1136 PacketSize,\r
1137 KeyboardHandler,\r
1138 UsbKeyboardDevice\r
1139 );\r
1140}\r