]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c
Make MDE package pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbKb / Dxe / keyboard.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Keyboard.c\r
15 \r
16Abstract:\r
17\r
18 Helper functions for USB Keyboard Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "keyboard.h"\r
25\r
26//\r
27// USB Key Code to Efi key mapping table\r
28// Format:<efi scan code>, <unicode without shift>, <unicode with shift>\r
29//\r
30STATIC\r
31UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {\r
32 { SCAN_NULL, 'a', 'A' }, // 0x04\r
33 { SCAN_NULL, 'b', 'B' }, // 0x05\r
34 { SCAN_NULL, 'c', 'C' }, // 0x06\r
35 { SCAN_NULL, 'd', 'D' }, // 0x07\r
36 { SCAN_NULL, 'e', 'E' }, // 0x08\r
37 { SCAN_NULL, 'f', 'F' }, // 0x09\r
38 { SCAN_NULL, 'g', 'G' }, // 0x0A\r
39 { SCAN_NULL, 'h', 'H' }, // 0x0B\r
40 { SCAN_NULL, 'i', 'I' }, // 0x0C\r
41 { SCAN_NULL, 'j', 'J' }, // 0x0D\r
42 { SCAN_NULL, 'k', 'K' }, // 0x0E\r
43 { SCAN_NULL, 'l', 'L' }, // 0x0F\r
44 { SCAN_NULL, 'm', 'M' }, // 0x10\r
45 { SCAN_NULL, 'n', 'N' }, // 0x11\r
46 { SCAN_NULL, 'o', 'O' }, // 0x12\r
47 { SCAN_NULL, 'p', 'P' }, // 0x13\r
48 { SCAN_NULL, 'q', 'Q' }, // 0x14\r
49 { SCAN_NULL, 'r', 'R' }, // 0x15\r
50 { SCAN_NULL, 's', 'S' }, // 0x16\r
51 { SCAN_NULL, 't', 'T' }, // 0x17\r
52 { SCAN_NULL, 'u', 'U' }, // 0x18\r
53 { SCAN_NULL, 'v', 'V' }, // 0x19\r
54 { SCAN_NULL, 'w', 'W' }, // 0x1A\r
55 { SCAN_NULL, 'x', 'X' }, // 0x1B\r
56 { SCAN_NULL, 'y', 'Y' }, // 0x1C\r
57 { SCAN_NULL, 'z', 'Z' }, // 0x1D\r
58 { SCAN_NULL, '1', '!' }, // 0x1E\r
59 { SCAN_NULL, '2', '@' }, // 0x1F\r
60 { SCAN_NULL, '3', '#' }, // 0x20\r
61 { SCAN_NULL, '4', '$' }, // 0x21\r
62 { SCAN_NULL, '5', '%' }, // 0x22\r
63 { SCAN_NULL, '6', '^' }, // 0x23\r
64 { SCAN_NULL, '7', '&' }, // 0x24\r
65 { SCAN_NULL, '8', '*' }, // 0x25\r
66 { SCAN_NULL, '9', '(' }, // 0x26\r
67 { SCAN_NULL, '0', ')' }, // 0x27\r
68 { SCAN_NULL, 0x0d, 0x0d }, // 0x28 Enter\r
69 { SCAN_ESC, 0x00, 0x00 }, // 0x29 Esc\r
70 { SCAN_NULL, 0x08, 0x08 }, // 0x2A Backspace\r
71 { SCAN_NULL, 0x09, 0x09 }, // 0x2B Tab\r
72 { SCAN_NULL, ' ', ' ' }, // 0x2C Spacebar\r
73 { SCAN_NULL, '-', '_' }, // 0x2D\r
74 { SCAN_NULL, '=', '+' }, // 0x2E\r
75 { SCAN_NULL, '[', '{' }, // 0x2F\r
76 { SCAN_NULL, ']', '}' }, // 0x30\r
77 { SCAN_NULL, '\\', '|' }, // 0x31\r
78 { SCAN_NULL, '\\', '|' }, // 0x32 Keyboard US \ and |\r
79 { SCAN_NULL, ';', ':' }, // 0x33\r
80 { SCAN_NULL, '\'', '"' }, // 0x34\r
81 { SCAN_NULL, '`', '~' }, // 0x35 Keyboard Grave Accent and Tlide\r
82 { SCAN_NULL, ',', '<' }, // 0x36\r
83 { SCAN_NULL, '.', '>' }, // 0x37\r
84 { SCAN_NULL, '/', '?' }, // 0x38\r
85 { SCAN_NULL, 0x00, 0x00 }, // 0x39 CapsLock\r
86 { SCAN_F1, 0x00, 0x00 }, // 0x3A\r
87 { SCAN_F2, 0x00, 0x00 }, // 0x3B\r
88 { SCAN_F3, 0x00, 0x00 }, // 0x3C \r
89 { SCAN_F4, 0x00, 0x00 }, // 0x3D \r
90 { SCAN_F5, 0x00, 0x00 }, // 0x3E\r
91 { SCAN_F6, 0x00, 0x00 }, // 0x3F\r
92 { SCAN_F7, 0x00, 0x00 }, // 0x40\r
93 { SCAN_F8, 0x00, 0x00 }, // 0x41\r
94 { SCAN_F9, 0x00, 0x00 }, // 0x42\r
95 { SCAN_F10, 0x00, 0x00 }, // 0x43\r
96 { SCAN_NULL, 0x00, 0x00 }, // 0x44 F11\r
97 { SCAN_NULL, 0x00, 0x00 }, // 0x45 F12\r
98 { SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen\r
99 { SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock\r
100 { SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause\r
101 { SCAN_INSERT, 0x00, 0x00 }, // 0x49\r
102 { SCAN_HOME, 0x00, 0x00 }, // 0x4A\r
103 { SCAN_PAGE_UP, 0x00, 0x00 }, // 0x4B\r
104 { SCAN_DELETE, 0x00, 0x00 }, // 0x4C\r
105 { SCAN_END, 0x00, 0x00 }, // 0x4D\r
106 { SCAN_PAGE_DOWN, 0x00, 0x00 }, // 0x4E\r
107 { SCAN_RIGHT, 0x00, 0x00 }, // 0x4F\r
108 { SCAN_LEFT, 0x00, 0x00 }, // 0x50\r
109 { SCAN_DOWN, 0x00, 0x00 }, // 0x51\r
110 { SCAN_UP, 0x00, 0x00 }, // 0x52\r
111 { SCAN_NULL, 0x00, 0x00 }, // 0x53 NumLock\r
112 { SCAN_NULL, '/', '/' }, // 0x54\r
113 { SCAN_NULL, '*', '*' }, // 0x55\r
114 { SCAN_NULL, '-', '-' }, // 0x56\r
115 { SCAN_NULL, '+', '+' }, // 0x57\r
116 { SCAN_NULL, 0x0d, 0x0d }, // 0x58\r
117 { SCAN_END, '1', '1' }, // 0x59\r
118 { SCAN_DOWN, '2', '2' }, // 0x5A\r
119 { SCAN_PAGE_DOWN, '3', '3' }, // 0x5B\r
120 { SCAN_LEFT, '4', '4' }, // 0x5C\r
121 { SCAN_NULL, '5', '5' }, // 0x5D\r
122 { SCAN_RIGHT, '6', '6' }, // 0x5E\r
123 { SCAN_HOME, '7', '7' }, // 0x5F\r
124 { SCAN_UP, '8', '8' }, // 0x60\r
125 { SCAN_PAGE_UP, '9', '9' }, // 0x61\r
126 { SCAN_INSERT, '0', '0' }, // 0x62\r
127 { SCAN_DELETE, '.', '.' }, // 0x63\r
128 { SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |\r
129 { SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application\r
130 { SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power\r
131 { SCAN_NULL, '=' , '=' } // 0x67 Keypad =\r
132};\r
133\r
134STATIC KB_MODIFIER KB_Mod[8] = {\r
135 { MOD_CONTROL_L, 0xe0 }, // 11100000 \r
136 { MOD_CONTROL_R, 0xe4 }, // 11100100 \r
137 { MOD_SHIFT_L, 0xe1 }, // 11100001 \r
138 { MOD_SHIFT_R, 0xe5 }, // 11100101 \r
139 { MOD_ALT_L, 0xe2 }, // 11100010 \r
140 { MOD_ALT_R, 0xe6 }, // 11100110 \r
141 { MOD_WIN_L, 0xe3 }, // 11100011 \r
142 { MOD_WIN_R, 0xe7 } // 11100111 \r
143};\r
144\r
145\r
146BOOLEAN\r
147IsUSBKeyboard (\r
148 IN EFI_USB_IO_PROTOCOL *UsbIo\r
149 )\r
150/*++\r
151 \r
152 Routine Description:\r
153 Uses USB I/O to check whether the device is a USB Keyboard device.\r
154 \r
155 Arguments:\r
156 UsbIo: Points to a USB I/O protocol instance.\r
157 \r
158 Returns:\r
159 \r
160--*/ \r
161{\r
162 EFI_STATUS Status;\r
163 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
164\r
165 //\r
166 // Get the Default interface descriptor, currently we\r
167 // assume it is interface 1\r
168 //\r
169 Status = UsbIo->UsbGetInterfaceDescriptor (\r
170 UsbIo,\r
171 &InterfaceDescriptor\r
172 );\r
173\r
174 if (EFI_ERROR (Status)) {\r
175 return FALSE;\r
176 }\r
177\r
178 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&\r
179 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&\r
180 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD\r
181 ) {\r
182\r
183 return TRUE;\r
184 }\r
185\r
186 return FALSE;\r
187}\r
188\r
189\r
190EFI_STATUS\r
191InitUSBKeyboard (\r
192 IN USB_KB_DEV *UsbKeyboardDevice\r
193 )\r
194/*++\r
195 \r
196 Routine Description:\r
197 Initialize USB Keyboard device and all private data structures.\r
198 \r
199 Arguments:\r
200 UsbKeyboardDevice The USB_KB_DEV instance.\r
201 \r
202 Returns:\r
203 EFI_SUCCESS - Success\r
204 EFI_DEVICE_ERROR - Hardware Error\r
205--*/\r
206{\r
207 UINT8 ConfigValue;\r
208 UINT8 Protocol;\r
209 UINT8 ReportId;\r
210 UINT8 Duration;\r
211 EFI_STATUS Status;\r
212 UINT32 TransferResult;\r
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
591ee27e 764 //\r
765 // Turn on the ScrollLock light on KB\r
766 //\r
767 UsbKeyboardDevice->ScrollOn ^= 1;\r
768 SetKeyLED (UsbKeyboardDevice);\r
769 continue;\r
770 break; \r
878ddf1f 771 case 0x48:\r
772 //\r
773 // fall through\r
774 //\r
775 case 0x65:\r
776 case 0x66:\r
777 continue;\r
778 break;\r
779\r
780 default:\r
781 break;\r
782 }\r
783 \r
784 //\r
785 // When encountered Del Key...\r
786 //\r
787 if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
788 if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
789 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
790 }\r
791 }\r
792\r
793 *KeyChar = UsbKey.KeyCode;\r
794 return EFI_SUCCESS;\r
795 }\r
796\r
797 return EFI_NOT_READY;\r
798\r
799}\r
800\r
801\r
802EFI_STATUS\r
803USBKeyCodeToEFIScanCode (\r
804 IN USB_KB_DEV *UsbKeyboardDevice,\r
805 IN UINT8 KeyChar,\r
806 OUT EFI_INPUT_KEY *Key\r
807 )\r
808/*++\r
809 \r
810 Routine Description:\r
811 Converts USB Keyboard code to EFI Scan Code.\r
812 \r
813 Arguments: \r
814 UsbKeyboardDevice The USB_KB_DEV instance.\r
815 KeyChar Indicates the key code that will be interpreted. \r
816 Key A pointer to a buffer that is filled in with \r
817 the keystroke information for the key that \r
818 was pressed.\r
819 Returns:\r
820 EFI_NOT_READY - Device is not ready\r
821 EFI_SUCCESS - Success\r
822--*/\r
823{\r
824 UINT8 Index;\r
825\r
826 if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
827 return EFI_NOT_READY;\r
828 }\r
829 \r
830 //\r
831 // valid USB Key Code starts from 4\r
832 //\r
833 Index = (UINT8) (KeyChar - 4);\r
834\r
835 if (Index >= USB_KEYCODE_MAX_MAKE) {\r
836 return EFI_NOT_READY;\r
837 }\r
838\r
839 Key->ScanCode = KeyConvertionTable[Index][0];\r
840\r
841 if (UsbKeyboardDevice->ShiftOn) {\r
842\r
843 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
844\r
845 } else {\r
846\r
847 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
848 }\r
849\r
850 if (UsbKeyboardDevice->CapsOn) {\r
851\r
852 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
853\r
854 Key->UnicodeChar = KeyConvertionTable[Index][2];\r
855\r
856 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
857\r
858 Key->UnicodeChar = KeyConvertionTable[Index][1];\r
859\r
860 }\r
861 }\r
862\r
863 if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
864\r
865 if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
866\r
867 Key->ScanCode = SCAN_NULL;\r
868\r
869 } else {\r
870\r
871 Key->UnicodeChar = 0x00;\r
872 }\r
873 }\r
874\r
875 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
876 return EFI_NOT_READY;\r
877 }\r
878\r
879 return EFI_SUCCESS;\r
880\r
881}\r
882\r
883\r
884EFI_STATUS\r
885InitUSBKeyBuffer (\r
886 IN OUT USB_KB_BUFFER *KeyboardBuffer\r
887 )\r
888/*++\r
889 \r
890 Routine Description:\r
891 Resets USB Keyboard Buffer.\r
892 \r
893 Arguments:\r
894 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
895 \r
896 Returns:\r
897 EFI_SUCCESS - Success\r
898--*/ \r
899{\r
900 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));\r
901\r
902 KeyboardBuffer->bHead = KeyboardBuffer->bTail;\r
903\r
904 return EFI_SUCCESS;\r
905}\r
906\r
907BOOLEAN\r
908IsUSBKeyboardBufferEmpty (\r
909 IN USB_KB_BUFFER *KeyboardBuffer\r
910 )\r
911/*++\r
912 \r
913 Routine Description:\r
914 Check whether USB Keyboard buffer is empty.\r
915 \r
916 Arguments:\r
917 KeyboardBuffer - USB Keyboard Buffer.\r
918 \r
919 Returns:\r
920 \r
921--*/\r
922{\r
923 //\r
924 // meet FIFO empty condition\r
925 //\r
926 return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);\r
927}\r
928\r
929\r
930BOOLEAN\r
931IsUSBKeyboardBufferFull (\r
932 IN USB_KB_BUFFER *KeyboardBuffer\r
933 )\r
934/*++\r
935 \r
936 Routine Description:\r
937 Check whether USB Keyboard buffer is full.\r
938 \r
939 Arguments:\r
940 KeyboardBuffer - USB Keyboard Buffer.\r
941 \r
942 Returns:\r
943 \r
944--*/\r
945{\r
946 return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == \r
947 KeyboardBuffer->bHead);\r
948}\r
949\r
950\r
951EFI_STATUS\r
952InsertKeyCode (\r
953 IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
954 IN UINT8 Key,\r
955 IN UINT8 Down\r
956 )\r
957/*++\r
958 \r
959 Routine Description:\r
960 Inserts a key code into keyboard buffer.\r
961 \r
962 Arguments:\r
963 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
964 Key - Key code\r
965 Down - Special key\r
966 Returns:\r
967 EFI_SUCCESS - Success\r
968--*/\r
969{\r
970 USB_KEY UsbKey;\r
971\r
972 //\r
973 // if keyboard buffer is full, throw the\r
974 // first key out of the keyboard buffer.\r
975 //\r
976 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {\r
977 RemoveKeyCode (KeyboardBuffer, &UsbKey);\r
978 }\r
979\r
980 KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;\r
981 KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;\r
982\r
983 //\r
984 // adjust the tail pointer of the FIFO keyboard buffer.\r
985 //\r
986 KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));\r
987\r
988 return EFI_SUCCESS;\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 \r
998 Routine Description:\r
999 Pops a key code off from keyboard buffer.\r
1000 \r
1001 Arguments:\r
1002 KeyboardBuffer - Points to the USB Keyboard Buffer.\r
1003 UsbKey - Points to the buffer that contains a usb key code.\r
1004 \r
1005 Returns:\r
1006 EFI_SUCCESS - Success\r
1007 EFI_DEVICE_ERROR - Hardware Error\r
1008--*/ \r
1009{\r
1010 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {\r
1011 return EFI_DEVICE_ERROR;\r
1012 }\r
1013\r
1014 UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;\r
1015 UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;\r
1016\r
1017 //\r
1018 // adjust the head pointer of the FIFO keyboard buffer.\r
1019 //\r
1020 KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));\r
1021\r
1022 return EFI_SUCCESS;\r
1023}\r
1024\r
1025EFI_STATUS\r
1026SetKeyLED (\r
1027 IN USB_KB_DEV *UsbKeyboardDevice\r
1028 )\r
1029/*++\r
1030 \r
1031 Routine Description:\r
1032 Sets USB Keyboard LED state.\r
1033 \r
1034 Arguments:\r
1035 UsbKeyboardDevice - The USB_KB_DEV instance.\r
1036 \r
1037 Returns:\r
1038 EFI_SUCCESS - Success\r
1039--*/ \r
1040{\r
1041 LED_MAP Led;\r
1042 UINT8 ReportId;\r
1043\r
1044 //\r
1045 // Set each field in Led map.\r
1046 //\r
1047 Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;\r
1048 Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;\r
591ee27e 1049 Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn; \r
878ddf1f 1050 Led.Resrvd = 0;\r
1051\r
1052 ReportId = 0;\r
1053 //\r
1054 // call Set Report Request to lighten the LED.\r
1055 //\r
1056 UsbSetReportRequest (\r
1057 UsbKeyboardDevice->UsbIo,\r
1058 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
1059 ReportId,\r
1060 HID_OUTPUT_REPORT,\r
1061 1,\r
1062 (UINT8 *) &Led\r
1063 );\r
1064\r
1065 return EFI_SUCCESS;\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 \r
1076 Routine Description:\r
1077 Timer handler for Repeat Key timer.\r
1078 \r
1079 Arguments:\r
1080 Event - The Repeat Key event.\r
1081 Context - Points to the USB_KB_DEV instance.\r
1082 \r
1083 Returns:\r
1084 \r
1085--*/ \r
1086{\r
1087 USB_KB_DEV *UsbKeyboardDevice;\r
1088\r
1089 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1090\r
1091 //\r
1092 // Do nothing when there is no repeat key.\r
1093 //\r
1094 if (UsbKeyboardDevice->RepeatKey != 0) {\r
1095 //\r
1096 // Inserts one Repeat key into keyboard buffer,\r
1097 //\r
1098 InsertKeyCode (\r
1099 &(UsbKeyboardDevice->KeyboardBuffer),\r
1100 UsbKeyboardDevice->RepeatKey,\r
1101 1\r
1102 );\r
1103\r
1104 //\r
1105 // set repeate rate for repeat key generation.\r
1106 //\r
1107 gBS->SetTimer (\r
1108 UsbKeyboardDevice->RepeatTimer,\r
1109 TimerRelative,\r
1110 USBKBD_REPEAT_RATE\r
1111 );\r
1112\r
1113 }\r
1114}\r
1115\r
1116VOID\r
1117EFIAPI\r
1118USBKeyboardRecoveryHandler (\r
1119 IN EFI_EVENT Event,\r
1120 IN VOID *Context\r
1121 )\r
1122/*++\r
1123 \r
1124 Routine Description:\r
1125 Timer handler for Delayed Recovery timer.\r
1126 \r
1127 Arguments:\r
1128 Event - The Delayed Recovery event.\r
1129 Context - Points to the USB_KB_DEV instance.\r
1130 \r
1131 Returns:\r
1132 \r
1133--*/ \r
1134{\r
1135\r
1136 USB_KB_DEV *UsbKeyboardDevice;\r
1137 EFI_USB_IO_PROTOCOL *UsbIo;\r
1138 UINT8 PacketSize;\r
1139\r
1140 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1141\r
1142 UsbIo = UsbKeyboardDevice->UsbIo;\r
1143\r
1144 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
1145\r
1146 UsbIo->UsbAsyncInterruptTransfer (\r
1147 UsbIo,\r
1148 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1149 TRUE,\r
1150 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
1151 PacketSize,\r
1152 KeyboardHandler,\r
1153 UsbKeyboardDevice\r
1154 );\r
1155}\r