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