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