To fix
[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
5d10269c 96 { SCAN_F11, 0x00, 0x00 }, // 0x44 F11\r
97 { SCAN_F12, 0x00, 0x00 }, // 0x45 F12\r
878ddf1f 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
5d10269c 292 UsbKeyboardDevice->ScrollOn = 0; \r
878ddf1f 293 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);\r
294\r
295 //\r
296 // Set a timer for repeat keys' generation.\r
297 //\r
298 if (UsbKeyboardDevice->RepeatTimer) {\r
299 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
300 UsbKeyboardDevice->RepeatTimer = 0;\r
301 }\r
302\r
303 Status = gBS->CreateEvent (\r
304 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
305 EFI_TPL_NOTIFY,\r
306 USBKeyboardRepeatHandler,\r
307 UsbKeyboardDevice,\r
308 &UsbKeyboardDevice->RepeatTimer\r
309 );\r
310\r
311 if (UsbKeyboardDevice->DelayedRecoveryEvent) {\r
312 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
313 UsbKeyboardDevice->DelayedRecoveryEvent = 0;\r
314 }\r
315\r
316 Status = gBS->CreateEvent (\r
317 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
318 EFI_TPL_NOTIFY,\r
319 USBKeyboardRecoveryHandler,\r
320 UsbKeyboardDevice,\r
321 &UsbKeyboardDevice->DelayedRecoveryEvent\r
322 );\r
323\r
324 return EFI_SUCCESS;\r
325}\r
326\r
327EFI_STATUS\r
328EFIAPI\r
329KeyboardHandler (\r
330 IN VOID *Data,\r
331 IN UINTN DataLength,\r
332 IN VOID *Context,\r
333 IN UINT32 Result\r
334 )\r
335/*++\r
336 \r
337 Routine Description:\r
338 Handler function for USB Keyboard's asynchronous interrupt transfer.\r
339 \r
340 Arguments:\r
341 Data A pointer to a buffer that is filled with key data which is\r
342 retrieved via asynchronous interrupt transfer.\r
343 DataLength Indicates the size of the data buffer.\r
344 Context Pointing to USB_KB_DEV instance.\r
345 Result Indicates the result of the asynchronous interrupt transfer.\r
346 \r
347 Returns:\r
348 EFI_SUCCESS - Success\r
349 EFI_DEVICE_ERROR - Hardware Error\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
878ddf1f 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
878ddf1f 367\r
368 ASSERT (Context);\r
369\r
370 NewRepeatKey = 0;\r
878ddf1f 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 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR)\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
1cc8ee78 410 UsbIo->UsbAsyncInterruptTransfer (\r
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
878ddf1f 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
648EFI_STATUS\r
649USBParseKey (\r
650 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
651 OUT UINT8 *KeyChar\r
652 )\r
653/*++\r
654 \r
655 Routine Description:\r
656 Retrieves a key character after parsing the raw data in keyboard buffer.\r
657 \r
658 Arguments:\r
659 UsbKeyboardDevice The USB_KB_DEV instance.\r
660 KeyChar Points to the Key character after key parsing.\r
661 \r
662 Returns:\r
663 EFI_SUCCESS - Success\r
664 EFI_NOT_READY - Device is not ready \r
665--*/ \r
666{\r
667 USB_KEY UsbKey;\r
668\r
669 *KeyChar = 0;\r
670\r
671 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {\r
672 //\r
673 // pops one raw data off.\r
674 //\r
675 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
676\r
677 if (!UsbKey.Down) {\r
678 switch (UsbKey.KeyCode) {\r
679\r
680 case 0xe0:\r
681 case 0xe4:\r
682 UsbKeyboardDevice->CtrlOn = 0;\r
683 break;\r
684\r
685 case 0xe1:\r
686 case 0xe5:\r
687 UsbKeyboardDevice->ShiftOn = 0;\r
688 break;\r
689\r
690 case 0xe2:\r
691 case 0xe6:\r
692 UsbKeyboardDevice->AltOn = 0;\r
693 break;\r
694\r
695 default:\r
696 break;\r
697 }\r
698\r
699 continue;\r
700 }\r
701 \r
702 //\r
703 // Analyzes key pressing situation\r
704 //\r
705 switch (UsbKey.KeyCode) {\r
706\r
707 case 0xe0:\r
708 case 0xe4:\r
709 UsbKeyboardDevice->CtrlOn = 1;\r
710 continue;\r
711 break;\r
712\r
713 case 0xe1:\r
714 case 0xe5:\r
715 UsbKeyboardDevice->ShiftOn = 1;\r
716 continue;\r
717 break;\r
718\r
719 case 0xe2:\r
720 case 0xe6:\r
721 UsbKeyboardDevice->AltOn = 1;\r
722 continue;\r
723 break;\r
724\r
725 case 0xe3:\r
726 case 0xe7:\r
727 continue;\r
728 break;\r
729\r
730 case 0x53:\r
731 UsbKeyboardDevice->NumLockOn ^= 1;\r
732 SetKeyLED (UsbKeyboardDevice);\r
733 continue;\r
734 break;\r
735\r
736 case 0x39:\r
737 UsbKeyboardDevice->CapsOn ^= 1;\r
738 SetKeyLED (UsbKeyboardDevice);\r
739 continue;\r
740 break;\r
741\r
742 //\r
743 // F11,F12,PrintScreen,ScrollLock,Pause,Application,Power\r
744 // keys are not valid EFI key\r
745 //\r
746 case 0x44:\r
747 //\r
748 // fall through\r
749 //\r
750 case 0x45:\r
751 //\r
752 // fall through\r
753 //\r
754 case 0x46:\r
755 //\r
756 // fall through\r
757 //\r
758 case 0x47:\r
591ee27e 759 //\r
760 // Turn on the ScrollLock light on KB\r
761 //\r
762 UsbKeyboardDevice->ScrollOn ^= 1;\r
763 SetKeyLED (UsbKeyboardDevice);\r
764 continue;\r
765 break; \r
878ddf1f 766 case 0x48:\r
767 //\r
768 // fall through\r
769 //\r
770 case 0x65:\r
771 case 0x66:\r
772 continue;\r
773 break;\r
774\r
775 default:\r
776 break;\r
777 }\r
778 \r
779 //\r
780 // When encountered Del Key...\r
781 //\r
782 if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
783 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
784 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
785 }\r
786 }\r
787\r
788 *KeyChar = UsbKey.KeyCode;\r
789 return EFI_SUCCESS;\r
790 }\r
791\r
792 return EFI_NOT_READY;\r
793\r
794}\r
795\r
796\r
797EFI_STATUS\r
798USBKeyCodeToEFIScanCode (\r
799 IN USB_KB_DEV *UsbKeyboardDevice,\r
800 IN UINT8 KeyChar,\r
801 OUT EFI_INPUT_KEY *Key\r
802 )\r
803/*++\r
804 \r
805 Routine Description:\r
806 Converts USB Keyboard code to EFI Scan Code.\r
807 \r
808 Arguments: \r
809 UsbKeyboardDevice The USB_KB_DEV instance.\r
810 KeyChar Indicates the key code that will be interpreted. \r
811 Key A pointer to a buffer that is filled in with \r
812 the keystroke information for the key that \r
813 was pressed.\r
814 Returns:\r
815 EFI_NOT_READY - Device is not ready\r
816 EFI_SUCCESS - Success\r
817--*/\r
818{\r
819 UINT8 Index;\r
820\r
821 if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
822 return EFI_NOT_READY;\r
823 }\r
824 \r
825 //\r
826 // valid USB Key Code starts from 4\r
827 //\r
828 Index = (UINT8) (KeyChar - 4);\r
829\r
830 if (Index >= USB_KEYCODE_MAX_MAKE) {\r
831 return EFI_NOT_READY;\r
832 }\r
833\r
834 Key->ScanCode = KeyConvertionTable[Index][0];\r
835\r
836 if (UsbKeyboardDevice->ShiftOn) {\r
837\r
838 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
839\r
840 } else {\r
841\r
842 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
843 }\r
844\r
845 if (UsbKeyboardDevice->CapsOn) {\r
846\r
847 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
848\r
849 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
850\r
851 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
852\r
853 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
854\r
855 }\r
856 }\r
857\r
858 if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
859\r
860 if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
861\r
862 Key->ScanCode = SCAN_NULL;\r
863\r
864 } else {\r
865\r
866 Key->UnicodeChar = 0x00;\r
867 }\r
868 }\r
869\r
870 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
871 return EFI_NOT_READY;\r
872 }\r
873\r
874 return EFI_SUCCESS;\r
875\r
876}\r
877\r
878\r
879EFI_STATUS\r
880InitUSBKeyBuffer (\r
881 IN OUT USB_KB_BUFFER *KeyboardBuffer\r
882 )\r
883/*++\r
884 \r
885 Routine Description:\r
886 Resets USB Keyboard Buffer.\r
887 \r
888 Arguments:\r
889 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
890 \r
891 Returns:\r
892 EFI_SUCCESS - Success\r
893--*/ \r
894{\r
895 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));\r
896\r
897 KeyboardBuffer->bHead = KeyboardBuffer->bTail;\r
898\r
899 return EFI_SUCCESS;\r
900}\r
901\r
902BOOLEAN\r
903IsUSBKeyboardBufferEmpty (\r
904 IN USB_KB_BUFFER *KeyboardBuffer\r
905 )\r
906/*++\r
907 \r
908 Routine Description:\r
909 Check whether USB Keyboard buffer is empty.\r
910 \r
911 Arguments:\r
912 KeyboardBuffer - USB Keyboard Buffer.\r
913 \r
914 Returns:\r
915 \r
916--*/\r
917{\r
918 //\r
919 // meet FIFO empty condition\r
920 //\r
921 return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);\r
922}\r
923\r
924\r
925BOOLEAN\r
926IsUSBKeyboardBufferFull (\r
927 IN USB_KB_BUFFER *KeyboardBuffer\r
928 )\r
929/*++\r
930 \r
931 Routine Description:\r
932 Check whether USB Keyboard buffer is full.\r
933 \r
934 Arguments:\r
935 KeyboardBuffer - USB Keyboard Buffer.\r
936 \r
937 Returns:\r
938 \r
939--*/\r
940{\r
941 return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == \r
942 KeyboardBuffer->bHead);\r
943}\r
944\r
945\r
946EFI_STATUS\r
947InsertKeyCode (\r
948 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
949 IN UINT8 Key,\r
950 IN UINT8 Down\r
951 )\r
952/*++\r
953 \r
954 Routine Description:\r
955 Inserts a key code into keyboard buffer.\r
956 \r
957 Arguments:\r
958 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
959 Key - Key code\r
960 Down - Special key\r
961 Returns:\r
962 EFI_SUCCESS - Success\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
986EFI_STATUS\r
987RemoveKeyCode (\r
988 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
989 OUT USB_KEY *UsbKey\r
990 )\r
991/*++\r
992 \r
993 Routine Description:\r
994 Pops a key code off from keyboard buffer.\r
995 \r
996 Arguments:\r
997 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
998 UsbKey - Points to the buffer that contains a usb key code.\r
999 \r
1000 Returns:\r
1001 EFI_SUCCESS - Success\r
1002 EFI_DEVICE_ERROR - Hardware Error\r
1003--*/ \r
1004{\r
1005 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {\r
1006 return EFI_DEVICE_ERROR;\r
1007 }\r
1008\r
1009 UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;\r
1010 UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;\r
1011\r
1012 //\r
1013 // adjust the head pointer of the FIFO keyboard buffer.\r
1014 //\r
1015 KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));\r
1016\r
1017 return EFI_SUCCESS;\r
1018}\r
1019\r
1020EFI_STATUS\r
1021SetKeyLED (\r
1022 IN USB_KB_DEV *UsbKeyboardDevice\r
1023 )\r
1024/*++\r
1025 \r
1026 Routine Description:\r
1027 Sets USB Keyboard LED state.\r
1028 \r
1029 Arguments:\r
1030 UsbKeyboardDevice - The USB_KB_DEV instance.\r
1031 \r
1032 Returns:\r
1033 EFI_SUCCESS - Success\r
1034--*/ \r
1035{\r
1036 LED_MAP Led;\r
1037 UINT8 ReportId;\r
1038\r
1039 //\r
1040 // Set each field in Led map.\r
1041 //\r
1042 Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;\r
1043 Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;\r
591ee27e 1044 Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn; \r
878ddf1f 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