3 Copyright (c) 2004 - 2008, 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
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.
18 Helper functions for USB Keyboard Driver
26 #include <Library/UsbLib.h>
29 // Static English keyboard layout
30 // Format:<efi key>, <unicode without shift>, <unicode with shift>, <Modifier>, <AffectedAttribute>
33 UINT8 KeyboardLayoutTable
[USB_KEYCODE_MAX_MAKE
+ 8][5] = {
34 {EfiKeyC1
, 'a', 'A', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x04
35 {EfiKeyB5
, 'b', 'B', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x05
36 {EfiKeyB3
, 'c', 'C', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x06
37 {EfiKeyC3
, 'd', 'D', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x07
38 {EfiKeyD3
, 'e', 'E', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x08
39 {EfiKeyC4
, 'f', 'F', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x09
40 {EfiKeyC5
, 'g', 'G', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0A
41 {EfiKeyC6
, 'h', 'H', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0B
42 {EfiKeyD8
, 'i', 'I', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0C
43 {EfiKeyC7
, 'j', 'J', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0D
44 {EfiKeyC8
, 'k', 'K', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0E
45 {EfiKeyC9
, 'l', 'L', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0F
46 {EfiKeyB7
, 'm', 'M', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x10
47 {EfiKeyB6
, 'n', 'N', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x11
48 {EfiKeyD9
, 'o', 'O', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x12
49 {EfiKeyD10
, 'p', 'P', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x13
50 {EfiKeyD1
, 'q', 'Q', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x14
51 {EfiKeyD4
, 'r', 'R', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x15
52 {EfiKeyC2
, 's', 'S', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x16
53 {EfiKeyD5
, 't', 'T', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x17
54 {EfiKeyD7
, 'u', 'U', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x18
55 {EfiKeyB4
, 'v', 'V', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x19
56 {EfiKeyD2
, 'w', 'W', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1A
57 {EfiKeyB2
, 'x', 'X', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1B
58 {EfiKeyD6
, 'y', 'Y', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1C
59 {EfiKeyB1
, 'z', 'Z', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1D
60 {EfiKeyE1
, '1', '!', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1E
61 {EfiKeyE2
, '2', '@', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1F
62 {EfiKeyE3
, '3', '#', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x20
63 {EfiKeyE4
, '4', '$', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x21
64 {EfiKeyE5
, '5', '%', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x22
65 {EfiKeyE6
, '6', '^', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x23
66 {EfiKeyE7
, '7', '&', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x24
67 {EfiKeyE8
, '8', '*', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x25
68 {EfiKeyE9
, '9', '(', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x26
69 {EfiKeyE10
, '0', ')', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x27
70 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x28 Enter
71 {EfiKeyEsc
, 0x1b, 0x1b, EFI_NULL_MODIFIER
, 0}, // 0x29 Esc
72 {EfiKeyBackSpace
, 0x08, 0x08, EFI_NULL_MODIFIER
, 0}, // 0x2A Backspace
73 {EfiKeyTab
, 0x09, 0x09, EFI_NULL_MODIFIER
, 0}, // 0x2B Tab
74 {EfiKeySpaceBar
, ' ', ' ', EFI_NULL_MODIFIER
, 0}, // 0x2C Spacebar
75 {EfiKeyE11
, '-', '_', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2D
76 {EfiKeyE12
, '=', '+', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2E
77 {EfiKeyD11
, '[', '{', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2F
78 {EfiKeyD12
, ']', '}', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x30
79 {EfiKeyD13
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x31
80 {EfiKeyC12
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x32 Keyboard Non-US # and ~
81 {EfiKeyC10
, ';', ':', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x33
82 {EfiKeyC11
, '\'', '"', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x34
83 {EfiKeyE0
, '`', '~', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x35 Keyboard Grave Accent and Tlide
84 {EfiKeyB8
, ',', '<', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x36
85 {EfiKeyB9
, '.', '>', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x37
86 {EfiKeyB10
, '/', '?', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x38
87 {EfiKeyCapsLock
, 0x00, 0x00, EFI_CAPS_LOCK_MODIFIER
, 0}, // 0x39 CapsLock
88 {EfiKeyF1
, 0x00, 0x00, EFI_FUNCTION_KEY_ONE_MODIFIER
, 0}, // 0x3A
89 {EfiKeyF2
, 0x00, 0x00, EFI_FUNCTION_KEY_TWO_MODIFIER
, 0}, // 0x3B
90 {EfiKeyF3
, 0x00, 0x00, EFI_FUNCTION_KEY_THREE_MODIFIER
, 0}, // 0x3C
91 {EfiKeyF4
, 0x00, 0x00, EFI_FUNCTION_KEY_FOUR_MODIFIER
, 0}, // 0x3D
92 {EfiKeyF5
, 0x00, 0x00, EFI_FUNCTION_KEY_FIVE_MODIFIER
, 0}, // 0x3E
93 {EfiKeyF6
, 0x00, 0x00, EFI_FUNCTION_KEY_SIX_MODIFIER
, 0}, // 0x3F
94 {EfiKeyF7
, 0x00, 0x00, EFI_FUNCTION_KEY_SEVEN_MODIFIER
, 0}, // 0x40
95 {EfiKeyF8
, 0x00, 0x00, EFI_FUNCTION_KEY_EIGHT_MODIFIER
, 0}, // 0x41
96 {EfiKeyF9
, 0x00, 0x00, EFI_FUNCTION_KEY_NINE_MODIFIER
, 0}, // 0x42
97 {EfiKeyF10
, 0x00, 0x00, EFI_FUNCTION_KEY_TEN_MODIFIER
, 0}, // 0x43
98 {EfiKeyF11
, 0x00, 0x00, EFI_FUNCTION_KEY_ELEVEN_MODIFIER
, 0}, // 0x44 F11
99 {EfiKeyF12
, 0x00, 0x00, EFI_FUNCTION_KEY_TWELVE_MODIFIER
, 0}, // 0x45 F12
100 {EfiKeyPrint
, 0x00, 0x00, EFI_PRINT_MODIFIER
, 0}, // 0x46 PrintScreen
101 {EfiKeySLck
, 0x00, 0x00, EFI_SCROLL_LOCK_MODIFIER
, 0}, // 0x47 Scroll Lock
102 {EfiKeyPause
, 0x00, 0x00, EFI_PAUSE_MODIFIER
, 0}, // 0x48 Pause
103 {EfiKeyIns
, 0x00, 0x00, EFI_INSERT_MODIFIER
, 0}, // 0x49
104 {EfiKeyHome
, 0x00, 0x00, EFI_HOME_MODIFIER
, 0}, // 0x4A
105 {EfiKeyPgUp
, 0x00, 0x00, EFI_PAGE_UP_MODIFIER
, 0}, // 0x4B
106 {EfiKeyDel
, 0x00, 0x00, EFI_DELETE_MODIFIER
, 0}, // 0x4C
107 {EfiKeyEnd
, 0x00, 0x00, EFI_END_MODIFIER
, 0}, // 0x4D
108 {EfiKeyPgDn
, 0x00, 0x00, EFI_PAGE_DOWN_MODIFIER
, 0}, // 0x4E
109 {EfiKeyRightArrow
, 0x00, 0x00, EFI_RIGHT_ARROW_MODIFIER
, 0}, // 0x4F
110 {EfiKeyLeftArrow
, 0x00, 0x00, EFI_LEFT_ARROW_MODIFIER
, 0}, // 0x50
111 {EfiKeyDownArrow
, 0x00, 0x00, EFI_DOWN_ARROW_MODIFIER
, 0}, // 0x51
112 {EfiKeyUpArrow
, 0x00, 0x00, EFI_UP_ARROW_MODIFIER
, 0}, // 0x52
113 {EfiKeyNLck
, 0x00, 0x00, EFI_NUM_LOCK_MODIFIER
, 0}, // 0x53 NumLock
114 {EfiKeySlash
, '/', '/', EFI_NULL_MODIFIER
, 0}, // 0x54
115 {EfiKeyAsterisk
, '*', '*', EFI_NULL_MODIFIER
, 0}, // 0x55
116 {EfiKeyMinus
, '-', '-', EFI_NULL_MODIFIER
, 0}, // 0x56
117 {EfiKeyPlus
, '+', '+', EFI_NULL_MODIFIER
, 0}, // 0x57
118 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x58
119 {EfiKeyOne
, '1', '1', EFI_END_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x59
120 {EfiKeyTwo
, '2', '2', EFI_DOWN_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5A
121 {EfiKeyThree
, '3', '3', EFI_PAGE_DOWN_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5B
122 {EfiKeyFour
, '4', '4', EFI_LEFT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5C
123 {EfiKeyFive
, '5', '5', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5D
124 {EfiKeySix
, '6', '6', EFI_RIGHT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5E
125 {EfiKeySeven
, '7', '7', EFI_HOME_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5F
126 {EfiKeyEight
, '8', '8', EFI_UP_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x60
127 {EfiKeyNine
, '9', '9', EFI_PAGE_UP_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x61
128 {EfiKeyZero
, '0', '0', EFI_INSERT_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x62
129 {EfiKeyPeriod
, '.', '.', EFI_DELETE_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x63
130 {EfiKeyB0
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x64 Keyboard Non-US \ and |
131 {EfiKeyA4
, 0x00, 0x00, EFI_MENU_MODIFIER
, 0}, // 0x65 Keyboard Application
133 {EfiKeyLCtrl
, 0, 0, EFI_LEFT_CONTROL_MODIFIER
, 0}, // 0xe0
134 {EfiKeyLShift
, 0, 0, EFI_LEFT_SHIFT_MODIFIER
, 0}, // 0xe1
135 {EfiKeyLAlt
, 0, 0, EFI_LEFT_ALT_MODIFIER
, 0}, // 0xe2
136 {EfiKeyA0
, 0, 0, EFI_LEFT_LOGO_MODIFIER
, 0}, // 0xe3
137 {EfiKeyRCtrl
, 0, 0, EFI_RIGHT_CONTROL_MODIFIER
, 0}, // 0xe4
138 {EfiKeyRShift
, 0, 0, EFI_RIGHT_SHIFT_MODIFIER
, 0}, // 0xe5
139 {EfiKeyA2
, 0, 0, EFI_RIGHT_ALT_MODIFIER
, 0}, // 0xe6
140 {EfiKeyA3
, 0, 0, EFI_RIGHT_LOGO_MODIFIER
, 0}, // 0xe7
144 LoadDefaultKeyboardLayout (
145 IN USB_KB_DEV
*UsbKeyboardDevice
150 Initialize KeyConvertionTable by using default keyboard layout.
153 UsbKeyboardDevice The USB_KB_DEV instance.
161 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
164 // Construct KeyConvertionTable by default keyboard layout
166 KeyDescriptor
= &UsbKeyboardDevice
->KeyConvertionTable
[0];
168 for (Index
= 0; Index
< (USB_KEYCODE_MAX_MAKE
+ 8); Index
++) {
169 KeyDescriptor
->Key
= (EFI_KEY
) KeyboardLayoutTable
[Index
][0];
170 KeyDescriptor
->Unicode
= KeyboardLayoutTable
[Index
][1];
171 KeyDescriptor
->ShiftedUnicode
= KeyboardLayoutTable
[Index
][2];
172 KeyDescriptor
->AltGrUnicode
= 0;
173 KeyDescriptor
->ShiftedAltGrUnicode
= 0;
174 KeyDescriptor
->Modifier
= KeyboardLayoutTable
[Index
][3];
175 KeyDescriptor
->AffectedAttribute
= KeyboardLayoutTable
[Index
][4];
182 // EFI_KEY to USB Scan Code convertion table
185 UINT8 UsbScanCodeConvertionTable
[] = {
189 0x2c, // EfiKeySpaceBar
194 0x50, // EfiKeyLeftArrow
195 0x51, // EfiKeyDownArrow
196 0x4F, // EfiKeyRightArrow
198 0x63, // EfiKeyPeriod
200 0xe1, // EfiKeyLShift
212 0xe5, // EfiKeyRShift
213 0x52, // EfiKeyUpArrow
217 0x39, // EfiKeyCapsLock
267 0x2A, // EfiKeyBackSpace
273 0x55, // EfiKeyAsterisk
294 // Keyboard Layout Modifier to EFI Scan Code convertion table
297 UINT8 EfiScanCodeConvertionTable
[] = {
298 SCAN_NULL
, // EFI_NULL_MODIFIER
299 SCAN_NULL
, // EFI_LEFT_CONTROL_MODIFIER
300 SCAN_NULL
, // EFI_RIGHT_CONTROL_MODIFIER
301 SCAN_NULL
, // EFI_LEFT_ALT_MODIFIER
302 SCAN_NULL
, // EFI_RIGHT_ALT_MODIFIER
303 SCAN_NULL
, // EFI_ALT_GR_MODIFIER
304 SCAN_INSERT
, // EFI_INSERT_MODIFIER
305 SCAN_DELETE
, // EFI_DELETE_MODIFIER
306 SCAN_PAGE_DOWN
, // EFI_PAGE_DOWN_MODIFIER
307 SCAN_PAGE_UP
, // EFI_PAGE_UP_MODIFIER
308 SCAN_HOME
, // EFI_HOME_MODIFIER
309 SCAN_END
, // EFI_END_MODIFIER
310 SCAN_NULL
, // EFI_LEFT_SHIFT_MODIFIER
311 SCAN_NULL
, // EFI_RIGHT_SHIFT_MODIFIER
312 SCAN_NULL
, // EFI_CAPS_LOCK_MODIFIER
313 SCAN_NULL
, // EFI_NUM_LOCK_MODIFIER
314 SCAN_LEFT
, // EFI_LEFT_ARROW_MODIFIER
315 SCAN_RIGHT
, // EFI_RIGHT_ARROW_MODIFIER
316 SCAN_DOWN
, // EFI_DOWN_ARROW_MODIFIER
317 SCAN_UP
, // EFI_UP_ARROW_MODIFIER
318 SCAN_NULL
, // EFI_NS_KEY_MODIFIER
319 SCAN_NULL
, // EFI_NS_KEY_DEPENDENCY_MODIFIER
320 SCAN_F1
, // EFI_FUNCTION_KEY_ONE_MODIFIER
321 SCAN_F2
, // EFI_FUNCTION_KEY_TWO_MODIFIER
322 SCAN_F3
, // EFI_FUNCTION_KEY_THREE_MODIFIER
323 SCAN_F4
, // EFI_FUNCTION_KEY_FOUR_MODIFIER
324 SCAN_F5
, // EFI_FUNCTION_KEY_FIVE_MODIFIER
325 SCAN_F6
, // EFI_FUNCTION_KEY_SIX_MODIFIER
326 SCAN_F7
, // EFI_FUNCTION_KEY_SEVEN_MODIFIER
327 SCAN_F8
, // EFI_FUNCTION_KEY_EIGHT_MODIFIER
328 SCAN_F9
, // EFI_FUNCTION_KEY_NINE_MODIFIER
329 SCAN_F10
, // EFI_FUNCTION_KEY_TEN_MODIFIER
330 SCAN_F11
, // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
331 SCAN_F12
, // EFI_FUNCTION_KEY_TWELVE_MODIFIER
334 EFI_GUID mKeyboardLayoutEventGuid
= EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
;
337 STATIC KB_MODIFIER KB_Mod
[8] = {
338 { MOD_CONTROL_L
, 0xe0 }, // 11100000
339 { MOD_CONTROL_R
, 0xe4 }, // 11100100
340 { MOD_SHIFT_L
, 0xe1 }, // 11100001
341 { MOD_SHIFT_R
, 0xe5 }, // 11100101
342 { MOD_ALT_L
, 0xe2 }, // 11100010
343 { MOD_ALT_R
, 0xe6 }, // 11100110
344 { MOD_WIN_L
, 0xe3 }, // 11100011
345 { MOD_WIN_R
, 0xe7 }, // 11100111
351 Uses USB I/O to check whether the device is a USB Keyboard device.
353 UsbIo: Points to a USB I/O protocol instance.
359 IN EFI_USB_IO_PROTOCOL
*UsbIo
363 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
366 // Get the Default interface descriptor, currently we
367 // assume it is interface 1
369 Status
= UsbIo
->UsbGetInterfaceDescriptor (
374 if (EFI_ERROR (Status
)) {
378 if (InterfaceDescriptor
.InterfaceClass
== CLASS_HID
&&
379 InterfaceDescriptor
.InterfaceSubClass
== SUBCLASS_BOOT
&&
380 InterfaceDescriptor
.InterfaceProtocol
== PROTOCOL_KEYBOARD
390 EFI_HII_KEYBOARD_LAYOUT
*
391 GetCurrentKeyboardLayout (
397 Get current keyboard layout from HII database.
403 Pointer to EFI_HII_KEYBOARD_LAYOUT.
408 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
409 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
413 // Locate Hii database protocol
415 Status
= gBS
->LocateProtocol (
416 &gEfiHiiDatabaseProtocolGuid
,
418 (VOID
**) &HiiDatabase
420 if (EFI_ERROR (Status
)) {
425 // Get current keyboard layout from HII database
428 KeyboardLayout
= NULL
;
429 Status
= HiiDatabase
->GetKeyboardLayout (
435 if (Status
== EFI_BUFFER_TOO_SMALL
) {
436 KeyboardLayout
= AllocatePool (Length
);
437 ASSERT (KeyboardLayout
!= NULL
);
439 Status
= HiiDatabase
->GetKeyboardLayout (
445 if (EFI_ERROR (Status
)) {
446 gBS
->FreePool (KeyboardLayout
);
447 KeyboardLayout
= NULL
;
451 return KeyboardLayout
;
456 IN USB_KB_DEV
*UsbKeyboardDevice
,
462 Find Key Descriptor in KeyConvertionTable given its scan code.
465 UsbKeyboardDevice - The USB_KB_DEV instance.
466 ScanCode - USB scan code.
469 The Key descriptor in KeyConvertionTable.
475 if (((ScanCode
> 0x65) && (ScanCode
< 0xe0)) || (ScanCode
> 0xe7)) {
479 if (ScanCode
<= 0x65) {
480 Index
= (UINT8
) (ScanCode
- 4);
482 Index
= (UINT8
) (ScanCode
- 0xe0 + USB_KEYCODE_MAX_MAKE
);
485 return &UsbKeyboardDevice
->KeyConvertionTable
[Index
];
490 IN USB_KB_DEV
*UsbKeyboardDevice
,
491 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
496 Find Non-Spacing key for given KeyDescriptor.
499 UsbKeyboardDevice - The USB_KB_DEV instance.
500 KeyDescriptor - Key descriptor.
508 USB_NS_KEY
*UsbNsKey
;
510 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
511 while (!IsNull (&UsbKeyboardDevice
->NsKeyList
, Link
)) {
512 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
514 if (UsbNsKey
->NsKey
[0].Key
== KeyDescriptor
->Key
) {
518 Link
= GetNextNode (&UsbKeyboardDevice
->NsKeyList
, Link
);
526 IN USB_NS_KEY
*UsbNsKey
,
527 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
532 Find physical key definition for a given Key stroke.
535 UsbNsKey - The Non-Spacing key information.
536 KeyDescriptor - The key stroke.
539 The physical key definition.
544 EFI_KEY_DESCRIPTOR
*PhysicalKey
;
546 PhysicalKey
= &UsbNsKey
->NsKey
[1];
547 for (Index
= 0; Index
< UsbNsKey
->KeyCount
; Index
++) {
548 if (KeyDescriptor
->Key
== PhysicalKey
->Key
) {
556 // No children definition matched, return original key
558 return KeyDescriptor
;
563 SetKeyboardLayoutEvent (
570 The notification function for SET_KEYBOARD_LAYOUT_EVENT.
578 USB_KB_DEV
*UsbKeyboardDevice
;
579 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
580 EFI_KEY_DESCRIPTOR TempKey
;
581 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
582 EFI_KEY_DESCRIPTOR
*TableEntry
;
583 EFI_KEY_DESCRIPTOR
*NsKey
;
584 USB_NS_KEY
*UsbNsKey
;
590 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
593 // Try to get current Keyboard Layout from HII database
595 KeyboardLayout
= GetCurrentKeyboardLayout ();
596 if (KeyboardLayout
== NULL
) {
601 // Allocate resource for KeyConvertionTable
603 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
604 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
605 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
607 KeyDescriptor
= (EFI_KEY_DESCRIPTOR
*) (((UINT8
*) KeyboardLayout
) + sizeof (EFI_HII_KEYBOARD_LAYOUT
));
608 for (Index
= 0; Index
< KeyboardLayout
->DescriptorCount
; Index
++) {
610 // Copy from HII keyboard layout package binary for alignment
612 CopyMem (&TempKey
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
615 // Fill the key into KeyConvertionTable (which use USB Scan Code as index)
617 ScanCode
= UsbScanCodeConvertionTable
[(UINT8
) (TempKey
.Key
)];
618 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, ScanCode
);
619 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
621 if (TempKey
.Modifier
== EFI_NS_KEY_MODIFIER
) {
625 UsbNsKey
= AllocatePool (sizeof (USB_NS_KEY
));
626 ASSERT (UsbNsKey
!= NULL
);
629 // Search for sequential children physical key definitions
632 NsKey
= KeyDescriptor
+ 1;
633 for (Index2
= Index
+ 1; Index2
< KeyboardLayout
->DescriptorCount
; Index2
++) {
634 CopyMem (&TempKey
, NsKey
, sizeof (EFI_KEY_DESCRIPTOR
));
635 if (TempKey
.Modifier
& EFI_NS_KEY_DEPENDENCY_MODIFIER
) {
643 UsbNsKey
->Signature
= USB_NS_KEY_SIGNATURE
;
644 UsbNsKey
->KeyCount
= KeyCount
;
645 UsbNsKey
->NsKey
= AllocateCopyPool (
646 (KeyCount
+ 1) * sizeof (EFI_KEY_DESCRIPTOR
),
649 InsertTailList (&UsbKeyboardDevice
->NsKeyList
, &UsbNsKey
->Link
);
652 // Skip over the child physical keys
655 KeyDescriptor
+= KeyCount
;
662 // There are two EfiKeyEnter, duplicate its Key Descriptor
664 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, 0x58);
665 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, 0x28);
666 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
668 gBS
->FreePool (KeyboardLayout
);
672 ReleaseKeyboardLayoutResources (
673 IN USB_KB_DEV
*UsbKeyboardDevice
678 Destroy resources for Keyboard layout.
681 UsbKeyboardDevice - The USB_KB_DEV instance.
688 USB_NS_KEY
*UsbNsKey
;
691 SafeFreePool (UsbKeyboardDevice
->KeyConvertionTable
);
692 UsbKeyboardDevice
->KeyConvertionTable
= NULL
;
694 while (!IsListEmpty (&UsbKeyboardDevice
->NsKeyList
)) {
695 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
696 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
697 RemoveEntryList (&UsbNsKey
->Link
);
699 gBS
->FreePool (UsbNsKey
->NsKey
);
700 gBS
->FreePool (UsbNsKey
);
706 IN USB_KB_DEV
*UsbKeyboardDevice
711 Initialize USB Keyboard layout.
714 UsbKeyboardDevice The USB_KB_DEV instance.
717 EFI_SUCCESS - Success
718 Other - Keyboard layout initial failed.
721 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
724 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
725 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
727 InitializeListHead (&UsbKeyboardDevice
->NsKeyList
);
728 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
729 UsbKeyboardDevice
->KeyboardLayoutEvent
= NULL
;
732 // Register SET_KEYBOARD_LAYOUT_EVENT notification
734 Status
= gBS
->CreateEventEx (
735 EFI_EVENT_NOTIFY_SIGNAL
,
737 SetKeyboardLayoutEvent
,
739 &mKeyboardLayoutEventGuid
,
740 &UsbKeyboardDevice
->KeyboardLayoutEvent
742 if (EFI_ERROR (Status
)) {
747 // Try to get current keyboard layout from HII database
749 KeyboardLayout
= GetCurrentKeyboardLayout ();
750 if (KeyboardLayout
!= NULL
) {
752 // Force to initialize the keyboard layout
754 gBS
->SignalEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
756 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver
)) {
757 return EFI_NOT_READY
;
761 // Fail to get keyboard layout from HII database,
762 // use default keyboard layout
764 LoadDefaultKeyboardLayout (UsbKeyboardDevice
);
773 Initialize USB Keyboard device and all private data structures.
775 UsbKeyboardDevice The USB_KB_DEV instance.
777 @retval EFI_SUCCESS Success
778 @retval EFI_DEVICE_ERROR Hardware Error
783 IN USB_KB_DEV
*UsbKeyboardDevice
791 UINT32 TransferResult
;
793 KbdReportStatusCode (
794 UsbKeyboardDevice
->DevicePath
,
796 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest
)
799 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
802 // default configurations
807 // Uses default configuration to configure the USB Keyboard device.
809 Status
= UsbSetConfiguration (
810 UsbKeyboardDevice
->UsbIo
,
811 (UINT16
) ConfigValue
,
814 if (EFI_ERROR (Status
)) {
816 // If configuration could not be set here, it means
817 // the keyboard interface has some errors and could
818 // not be initialized
820 KbdReportStatusCode (
821 UsbKeyboardDevice
->DevicePath
,
822 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
823 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError
)
826 return EFI_DEVICE_ERROR
;
829 UsbGetProtocolRequest (
830 UsbKeyboardDevice
->UsbIo
,
831 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
835 // Sets boot protocol for the USB Keyboard.
836 // This driver only supports boot protocol.
837 // !!BugBug: How about the device that does not support boot protocol?
839 if (Protocol
!= BOOT_PROTOCOL
) {
840 UsbSetProtocolRequest (
841 UsbKeyboardDevice
->UsbIo
,
842 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
847 // the duration is indefinite, so the endpoint will inhibit reporting forever,
848 // and only reporting when a change is detected in the report data.
852 // idle value for all report ID
856 // idle forever until there is a key pressed and released.
860 UsbKeyboardDevice
->UsbIo
,
861 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
866 UsbKeyboardDevice
->CtrlOn
= 0;
867 UsbKeyboardDevice
->AltOn
= 0;
868 UsbKeyboardDevice
->ShiftOn
= 0;
869 UsbKeyboardDevice
->NumLockOn
= 0;
870 UsbKeyboardDevice
->CapsOn
= 0;
871 UsbKeyboardDevice
->ScrollOn
= 0;
873 UsbKeyboardDevice
->LeftCtrlOn
= 0;
874 UsbKeyboardDevice
->LeftAltOn
= 0;
875 UsbKeyboardDevice
->LeftShiftOn
= 0;
876 UsbKeyboardDevice
->LeftLogoOn
= 0;
877 UsbKeyboardDevice
->RightCtrlOn
= 0;
878 UsbKeyboardDevice
->RightAltOn
= 0;
879 UsbKeyboardDevice
->RightShiftOn
= 0;
880 UsbKeyboardDevice
->RightLogoOn
= 0;
881 UsbKeyboardDevice
->MenuKeyOn
= 0;
882 UsbKeyboardDevice
->SysReqOn
= 0;
884 UsbKeyboardDevice
->AltGrOn
= 0;
886 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
889 // Sync the initial state of lights
891 SetKeyLED (UsbKeyboardDevice
);
893 ZeroMem (UsbKeyboardDevice
->LastKeyCodeArray
, sizeof (UINT8
) * 8);
896 // Set a timer for repeat keys' generation.
898 if (UsbKeyboardDevice
->RepeatTimer
) {
899 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
900 UsbKeyboardDevice
->RepeatTimer
= 0;
903 Status
= gBS
->CreateEvent (
904 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
906 USBKeyboardRepeatHandler
,
908 &UsbKeyboardDevice
->RepeatTimer
911 if (UsbKeyboardDevice
->DelayedRecoveryEvent
) {
912 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
913 UsbKeyboardDevice
->DelayedRecoveryEvent
= 0;
916 Status
= gBS
->CreateEvent (
917 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
919 USBKeyboardRecoveryHandler
,
921 &UsbKeyboardDevice
->DelayedRecoveryEvent
929 Handler function for USB Keyboard's asynchronous interrupt transfer.
931 Data A pointer to a buffer that is filled with key data which is
932 retrieved via asynchronous interrupt transfer.
933 DataLength Indicates the size of the data buffer.
934 Context Pointing to USB_KB_DEV instance.
935 Result Indicates the result of the asynchronous interrupt transfer.
937 @retval EFI_SUCCESS Success
938 @retval EFI_DEVICE_ERROR Hardware Error
950 USB_KB_DEV
*UsbKeyboardDevice
;
951 EFI_USB_IO_PROTOCOL
*UsbIo
;
952 UINT8
*CurKeyCodeBuffer
;
953 UINT8
*OldKeyCodeBuffer
;
954 UINT8 CurModifierMap
;
955 UINT8 OldModifierMap
;
965 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
970 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
971 UsbIo
= UsbKeyboardDevice
->UsbIo
;
974 // Analyzes the Result and performs corresponding action.
976 if (Result
!= EFI_USB_NOERROR
) {
978 // Some errors happen during the process
980 KbdReportStatusCode (
981 UsbKeyboardDevice
->DevicePath
,
982 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
983 PcdGet32 (PcdStatusCodeValueKeyboardInputError
)
987 // stop the repeat key generation if any
989 UsbKeyboardDevice
->RepeatKey
= 0;
992 UsbKeyboardDevice
->RepeatTimer
,
997 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
998 UsbClearEndpointHalt (
1000 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
1006 // Delete & Submit this interrupt again
1009 UsbIo
->UsbAsyncInterruptTransfer (
1011 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
1020 UsbKeyboardDevice
->DelayedRecoveryEvent
,
1022 EFI_USB_INTERRUPT_DELAY
1025 return EFI_DEVICE_ERROR
;
1028 if (DataLength
== 0 || Data
== NULL
) {
1032 CurKeyCodeBuffer
= (UINT8
*) Data
;
1033 OldKeyCodeBuffer
= UsbKeyboardDevice
->LastKeyCodeArray
;
1036 // checks for new key stroke.
1037 // if no new key got, return immediately.
1039 for (Index
= 0; Index
< 8; Index
++) {
1040 if (OldKeyCodeBuffer
[Index
] != CurKeyCodeBuffer
[Index
]) {
1050 // Parse the modifier key
1052 CurModifierMap
= CurKeyCodeBuffer
[0];
1053 OldModifierMap
= OldKeyCodeBuffer
[0];
1056 // handle modifier key's pressing or releasing situation.
1058 for (Index
= 0; Index
< 8; Index
++) {
1060 if ((CurModifierMap
& KB_Mod
[Index
].Mask
) != (OldModifierMap
& KB_Mod
[Index
].Mask
)) {
1062 // if current modifier key is up, then
1063 // CurModifierMap & KB_Mod[Index].Mask = 0;
1064 // otherwize it is a non-zero value.
1065 // Inserts the pressed modifier key into key buffer.
1067 Down
= (UINT8
) (CurModifierMap
& KB_Mod
[Index
].Mask
);
1068 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), KB_Mod
[Index
].Key
, Down
);
1073 // handle normal key's releasing situation
1076 for (Index
= 2; Index
< 8; Index
++) {
1078 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index
])) {
1083 for (Index2
= 2; Index2
< 8; Index2
++) {
1085 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index2
])) {
1089 if (OldKeyCodeBuffer
[Index
] == CurKeyCodeBuffer
[Index2
]) {
1097 &(UsbKeyboardDevice
->KeyboardBuffer
),
1098 OldKeyCodeBuffer
[Index
],
1102 // the original reapeat key is released.
1104 if (OldKeyCodeBuffer
[Index
] == UsbKeyboardDevice
->RepeatKey
) {
1105 UsbKeyboardDevice
->RepeatKey
= 0;
1111 // original repeat key is released, cancel the repeat timer
1113 if (UsbKeyboardDevice
->RepeatKey
== 0) {
1115 UsbKeyboardDevice
->RepeatTimer
,
1122 // handle normal key's pressing situation
1125 for (Index
= 2; Index
< 8; Index
++) {
1127 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index
])) {
1132 for (Index2
= 2; Index2
< 8; Index2
++) {
1134 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index2
])) {
1138 if (CurKeyCodeBuffer
[Index
] == OldKeyCodeBuffer
[Index2
]) {
1145 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), CurKeyCodeBuffer
[Index
], 1);
1147 // NumLock pressed or CapsLock pressed
1149 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, CurKeyCodeBuffer
[Index
]);
1150 if (KeyDescriptor
->Modifier
== EFI_NUM_LOCK_MODIFIER
|| KeyDescriptor
->Modifier
== EFI_CAPS_LOCK_MODIFIER
) {
1151 UsbKeyboardDevice
->RepeatKey
= 0;
1153 NewRepeatKey
= CurKeyCodeBuffer
[Index
];
1155 // do not repeat the original repeated key
1157 UsbKeyboardDevice
->RepeatKey
= 0;
1163 // Update LastKeycodeArray[] buffer in the
1164 // Usb Keyboard Device data structure.
1166 for (Index
= 0; Index
< 8; Index
++) {
1167 UsbKeyboardDevice
->LastKeyCodeArray
[Index
] = CurKeyCodeBuffer
[Index
];
1171 // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence
1172 // and judge whether it will invoke reset event.
1174 SavedTail
= UsbKeyboardDevice
->KeyboardBuffer
.bTail
;
1175 Index
= UsbKeyboardDevice
->KeyboardBuffer
.bHead
;
1176 while (Index
!= SavedTail
) {
1177 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1179 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1181 switch (KeyDescriptor
->Modifier
) {
1183 case EFI_LEFT_CONTROL_MODIFIER
:
1184 case EFI_RIGHT_CONTROL_MODIFIER
:
1186 UsbKeyboardDevice
->CtrlOn
= 1;
1188 UsbKeyboardDevice
->CtrlOn
= 0;
1192 case EFI_LEFT_ALT_MODIFIER
:
1193 case EFI_RIGHT_ALT_MODIFIER
:
1195 UsbKeyboardDevice
->AltOn
= 1;
1197 UsbKeyboardDevice
->AltOn
= 0;
1201 case EFI_ALT_GR_MODIFIER
:
1203 UsbKeyboardDevice
->AltGrOn
= 1;
1205 UsbKeyboardDevice
->AltGrOn
= 0;
1212 case EFI_DELETE_MODIFIER
:
1214 if (UsbKeyboardDevice
->CtrlOn
&& UsbKeyboardDevice
->AltOn
) {
1215 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1225 // insert the key back to the buffer.
1226 // so the key sequence will not be destroyed.
1229 &(UsbKeyboardDevice
->KeyboardBuffer
),
1233 Index
= UsbKeyboardDevice
->KeyboardBuffer
.bHead
;
1237 // If have new key pressed, update the RepeatKey value, and set the
1238 // timer to repeate delay timer
1240 if (NewRepeatKey
!= 0) {
1242 // sets trigger time to "Repeat Delay Time",
1243 // to trigger the repeat timer when the key is hold long
1247 UsbKeyboardDevice
->RepeatTimer
,
1251 UsbKeyboardDevice
->RepeatKey
= NewRepeatKey
;
1259 Retrieves a key character after parsing the raw data in keyboard buffer.
1261 UsbKeyboardDevice The USB_KB_DEV instance.
1262 KeyChar Points to the Key character after key parsing.
1264 @retval EFI_SUCCESS Success
1265 @retval EFI_NOT_READY Device is not ready
1270 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
1275 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1279 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice
->KeyboardBuffer
)) {
1281 // pops one raw data off.
1283 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1285 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1287 switch (KeyDescriptor
->Modifier
) {
1292 case EFI_LEFT_CONTROL_MODIFIER
:
1293 UsbKeyboardDevice
->LeftCtrlOn
= 0;
1294 UsbKeyboardDevice
->CtrlOn
= 0;
1296 case EFI_RIGHT_CONTROL_MODIFIER
:
1297 UsbKeyboardDevice
->RightCtrlOn
= 0;
1298 UsbKeyboardDevice
->CtrlOn
= 0;
1304 case EFI_LEFT_SHIFT_MODIFIER
:
1305 UsbKeyboardDevice
->LeftShiftOn
= 0;
1306 UsbKeyboardDevice
->ShiftOn
= 0;
1308 case EFI_RIGHT_SHIFT_MODIFIER
:
1309 UsbKeyboardDevice
->RightShiftOn
= 0;
1310 UsbKeyboardDevice
->ShiftOn
= 0;
1316 case EFI_LEFT_ALT_MODIFIER
:
1317 UsbKeyboardDevice
->LeftAltOn
= 0;
1318 UsbKeyboardDevice
->AltOn
= 0;
1320 case EFI_RIGHT_ALT_MODIFIER
:
1321 UsbKeyboardDevice
->RightAltOn
= 0;
1322 UsbKeyboardDevice
->AltOn
= 0;
1326 // Left Logo release
1328 case EFI_LEFT_LOGO_MODIFIER
:
1329 UsbKeyboardDevice
->LeftLogoOn
= 0;
1333 // Right Logo release
1335 case EFI_RIGHT_LOGO_MODIFIER
:
1336 UsbKeyboardDevice
->RightLogoOn
= 0;
1342 case EFI_MENU_MODIFIER
:
1343 UsbKeyboardDevice
->MenuKeyOn
= 0;
1349 case EFI_PRINT_MODIFIER
:
1350 case EFI_SYS_REQUEST_MODIFIER
:
1351 UsbKeyboardDevice
->SysReqOn
= 0;
1357 case EFI_ALT_GR_MODIFIER
:
1358 UsbKeyboardDevice
->AltGrOn
= 0;
1369 // Analyzes key pressing situation
1371 switch (KeyDescriptor
->Modifier
) {
1376 case EFI_LEFT_CONTROL_MODIFIER
:
1377 UsbKeyboardDevice
->LeftCtrlOn
= 1;
1378 UsbKeyboardDevice
->CtrlOn
= 1;
1381 case EFI_RIGHT_CONTROL_MODIFIER
:
1382 UsbKeyboardDevice
->RightCtrlOn
= 1;
1383 UsbKeyboardDevice
->CtrlOn
= 1;
1390 case EFI_LEFT_SHIFT_MODIFIER
:
1391 UsbKeyboardDevice
->LeftShiftOn
= 1;
1392 UsbKeyboardDevice
->ShiftOn
= 1;
1395 case EFI_RIGHT_SHIFT_MODIFIER
:
1396 UsbKeyboardDevice
->RightShiftOn
= 1;
1397 UsbKeyboardDevice
->ShiftOn
= 1;
1404 case EFI_LEFT_ALT_MODIFIER
:
1405 UsbKeyboardDevice
->LeftAltOn
= 1;
1406 UsbKeyboardDevice
->AltOn
= 1;
1409 case EFI_RIGHT_ALT_MODIFIER
:
1410 UsbKeyboardDevice
->RightAltOn
= 1;
1411 UsbKeyboardDevice
->AltOn
= 1;
1418 case EFI_LEFT_LOGO_MODIFIER
:
1419 UsbKeyboardDevice
->LeftLogoOn
= 1;
1425 case EFI_RIGHT_LOGO_MODIFIER
:
1426 UsbKeyboardDevice
->RightLogoOn
= 1;
1432 case EFI_MENU_MODIFIER
:
1433 UsbKeyboardDevice
->MenuKeyOn
= 1;
1439 case EFI_PRINT_MODIFIER
:
1440 case EFI_SYS_REQUEST_MODIFIER
:
1441 UsbKeyboardDevice
->SysReqOn
= 1;
1448 case EFI_ALT_GR_MODIFIER
:
1449 UsbKeyboardDevice
->AltGrOn
= 1;
1452 case EFI_NUM_LOCK_MODIFIER
:
1453 UsbKeyboardDevice
->NumLockOn
^= 1;
1455 // Turn on the NumLock light on KB
1457 SetKeyLED (UsbKeyboardDevice
);
1461 case EFI_CAPS_LOCK_MODIFIER
:
1462 UsbKeyboardDevice
->CapsOn
^= 1;
1464 // Turn on the CapsLock light on KB
1466 SetKeyLED (UsbKeyboardDevice
);
1470 case EFI_SCROLL_LOCK_MODIFIER
:
1471 UsbKeyboardDevice
->ScrollOn
^= 1;
1473 // Turn on the ScrollLock light on KB
1475 SetKeyLED (UsbKeyboardDevice
);
1480 // F11,F12,PrintScreen,Pause/Break
1481 // could not be retrieved via SimpleTxtInEx protocol
1483 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER
:
1484 case EFI_FUNCTION_KEY_TWELVE_MODIFIER
:
1485 case EFI_PAUSE_MODIFIER
:
1486 case EFI_BREAK_MODIFIER
:
1498 // When encountered Del Key...
1500 if (KeyDescriptor
->Modifier
== EFI_DELETE_MODIFIER
) {
1501 if (UsbKeyboardDevice
->CtrlOn
&& UsbKeyboardDevice
->AltOn
) {
1502 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1506 *KeyChar
= UsbKey
.KeyCode
;
1510 return EFI_NOT_READY
;
1516 Converts USB Keyboard code to EFI Scan Code.
1518 UsbKeyboardDevice The USB_KB_DEV instance.
1519 KeyChar Indicates the key code that will be interpreted.
1520 Key A pointer to a buffer that is filled in with
1521 the keystroke information for the key that
1524 @retval EFI_NOT_READY Device is not ready
1525 @retval EFI_SUCCESS Success
1529 USBKeyCodeToEFIScanCode (
1530 IN USB_KB_DEV
*UsbKeyboardDevice
,
1532 OUT EFI_INPUT_KEY
*Key
1536 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1538 if (!USBKBD_VALID_KEYCODE (KeyChar
)) {
1539 return EFI_NOT_READY
;
1543 // valid USB Key Code starts from 4
1545 Index
= (UINT8
) (KeyChar
- 4);
1547 if (Index
>= USB_KEYCODE_MAX_MAKE
) {
1548 return EFI_NOT_READY
;
1551 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, KeyChar
);
1554 // Check for Non-spacing key
1556 if (KeyDescriptor
->Modifier
== EFI_NS_KEY_MODIFIER
) {
1557 UsbKeyboardDevice
->CurrentNsKey
= FindUsbNsKey (UsbKeyboardDevice
, KeyDescriptor
);
1558 return EFI_NOT_READY
;
1562 // Check whether this keystroke follows a Non-spacing key
1564 if (UsbKeyboardDevice
->CurrentNsKey
!= NULL
) {
1565 KeyDescriptor
= FindPhysicalKey (UsbKeyboardDevice
->CurrentNsKey
, KeyDescriptor
);
1566 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
1569 Key
->ScanCode
= EfiScanCodeConvertionTable
[KeyDescriptor
->Modifier
];
1570 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1572 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_STANDARD_SHIFT
) {
1573 if (UsbKeyboardDevice
->ShiftOn
) {
1574 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1577 // Need not return associated shift state if a class of printable characters that
1578 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1580 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) {
1581 UsbKeyboardDevice
->LeftShiftOn
= 0;
1582 UsbKeyboardDevice
->RightShiftOn
= 0;
1585 if (UsbKeyboardDevice
->AltGrOn
) {
1586 Key
->UnicodeChar
= KeyDescriptor
->ShiftedAltGrUnicode
;
1592 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1594 if (UsbKeyboardDevice
->AltGrOn
) {
1595 Key
->UnicodeChar
= KeyDescriptor
->AltGrUnicode
;
1600 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) {
1601 if (UsbKeyboardDevice
->CapsOn
) {
1603 if (Key
->UnicodeChar
== KeyDescriptor
->Unicode
) {
1605 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1607 } else if (Key
->UnicodeChar
== KeyDescriptor
->ShiftedUnicode
) {
1609 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1616 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1618 if (UsbKeyboardDevice
->CtrlOn
) {
1619 if (Key
->UnicodeChar
>= 'a' && Key
->UnicodeChar
<= 'z') {
1620 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'a' + 1);
1621 } else if (Key
->UnicodeChar
>= 'A' && Key
->UnicodeChar
<= 'Z') {
1622 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'A' + 1);
1626 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_NUM_LOCK
) {
1628 if (UsbKeyboardDevice
->NumLockOn
&& !UsbKeyboardDevice
->ShiftOn
) {
1630 Key
->ScanCode
= SCAN_NULL
;
1633 Key
->UnicodeChar
= 0x00;
1638 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1640 if (Key
->UnicodeChar
== 0x1B && Key
->ScanCode
== SCAN_NULL
) {
1641 Key
->ScanCode
= SCAN_ESC
;
1642 Key
->UnicodeChar
= 0x00;
1645 if (Key
->UnicodeChar
== 0 && Key
->ScanCode
== SCAN_NULL
) {
1646 return EFI_NOT_READY
;
1651 // Save Shift/Toggle state
1653 if (UsbKeyboardDevice
->LeftCtrlOn
== 1) {
1654 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
1656 if (UsbKeyboardDevice
->RightCtrlOn
== 1) {
1657 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
1659 if (UsbKeyboardDevice
->LeftAltOn
== 1) {
1660 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
1662 if (UsbKeyboardDevice
->RightAltOn
== 1) {
1663 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_ALT_PRESSED
;
1665 if (UsbKeyboardDevice
->LeftShiftOn
== 1) {
1666 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1668 if (UsbKeyboardDevice
->RightShiftOn
== 1) {
1669 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1671 if (UsbKeyboardDevice
->LeftLogoOn
== 1) {
1672 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
1674 if (UsbKeyboardDevice
->RightLogoOn
== 1) {
1675 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
1677 if (UsbKeyboardDevice
->MenuKeyOn
== 1) {
1678 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_MENU_KEY_PRESSED
;
1680 if (UsbKeyboardDevice
->SysReqOn
== 1) {
1681 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_SYS_REQ_PRESSED
;
1684 if (UsbKeyboardDevice
->ScrollOn
== 1) {
1685 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1687 if (UsbKeyboardDevice
->NumLockOn
== 1) {
1688 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1690 if (UsbKeyboardDevice
->CapsOn
== 1) {
1691 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1701 Resets USB Keyboard Buffer.
1703 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1705 @retval EFI_SUCCESS Success
1710 IN OUT USB_KB_BUFFER
*KeyboardBuffer
1713 ZeroMem (KeyboardBuffer
, sizeof (USB_KB_BUFFER
));
1715 KeyboardBuffer
->bHead
= KeyboardBuffer
->bTail
;
1722 Check whether USB Keyboard buffer is empty.
1724 @param KeyboardBuffer USB Keyboard Buffer.
1729 IsUSBKeyboardBufferEmpty (
1730 IN USB_KB_BUFFER
*KeyboardBuffer
1734 // meet FIFO empty condition
1736 return (BOOLEAN
) (KeyboardBuffer
->bHead
== KeyboardBuffer
->bTail
);
1742 Check whether USB Keyboard buffer is full.
1744 @param KeyboardBuffer USB Keyboard Buffer.
1749 IsUSBKeyboardBufferFull (
1750 IN USB_KB_BUFFER
*KeyboardBuffer
1753 return (BOOLEAN
)(((KeyboardBuffer
->bTail
+ 1) % (MAX_KEY_ALLOWED
+ 1)) ==
1754 KeyboardBuffer
->bHead
);
1760 Inserts a key code into keyboard buffer.
1762 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1764 @param Down Special key
1766 @retval EFI_SUCCESS Success
1771 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1779 // if keyboard buffer is full, throw the
1780 // first key out of the keyboard buffer.
1782 if (IsUSBKeyboardBufferFull (KeyboardBuffer
)) {
1783 RemoveKeyCode (KeyboardBuffer
, &UsbKey
);
1786 KeyboardBuffer
->buffer
[KeyboardBuffer
->bTail
].KeyCode
= Key
;
1787 KeyboardBuffer
->buffer
[KeyboardBuffer
->bTail
].Down
= Down
;
1790 // adjust the tail pointer of the FIFO keyboard buffer.
1792 KeyboardBuffer
->bTail
= (UINT8
) ((KeyboardBuffer
->bTail
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1799 Pops a key code off from keyboard buffer.
1801 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1802 @param UsbKey Points to the buffer that contains a usb key code.
1804 @retval EFI_SUCCESS Success
1805 @retval EFI_DEVICE_ERROR Hardware Error
1810 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1814 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer
)) {
1815 return EFI_DEVICE_ERROR
;
1818 UsbKey
->KeyCode
= KeyboardBuffer
->buffer
[KeyboardBuffer
->bHead
].KeyCode
;
1819 UsbKey
->Down
= KeyboardBuffer
->buffer
[KeyboardBuffer
->bHead
].Down
;
1822 // adjust the head pointer of the FIFO keyboard buffer.
1824 KeyboardBuffer
->bHead
= (UINT8
) ((KeyboardBuffer
->bHead
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1831 Sets USB Keyboard LED state.
1833 @param UsbKeyboardDevice The USB_KB_DEV instance.
1835 @retval EFI_SUCCESS Success
1840 IN USB_KB_DEV
*UsbKeyboardDevice
1847 // Set each field in Led map.
1849 Led
.NumLock
= (UINT8
) UsbKeyboardDevice
->NumLockOn
;
1850 Led
.CapsLock
= (UINT8
) UsbKeyboardDevice
->CapsOn
;
1851 Led
.ScrollLock
= (UINT8
) UsbKeyboardDevice
->ScrollOn
;
1856 // call Set Report Request to lighten the LED.
1858 UsbSetReportRequest (
1859 UsbKeyboardDevice
->UsbIo
,
1860 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
1872 Timer handler for Repeat Key timer.
1874 @param Event The Repeat Key event.
1875 @param Context Points to the USB_KB_DEV instance.
1881 USBKeyboardRepeatHandler (
1886 USB_KB_DEV
*UsbKeyboardDevice
;
1888 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1891 // Do nothing when there is no repeat key.
1893 if (UsbKeyboardDevice
->RepeatKey
!= 0) {
1895 // Inserts one Repeat key into keyboard buffer,
1898 &(UsbKeyboardDevice
->KeyboardBuffer
),
1899 UsbKeyboardDevice
->RepeatKey
,
1904 // set repeate rate for repeat key generation.
1907 UsbKeyboardDevice
->RepeatTimer
,
1917 Timer handler for Delayed Recovery timer.
1919 @param Event The Delayed Recovery event.
1920 @param Context Points to the USB_KB_DEV instance.
1926 USBKeyboardRecoveryHandler (
1932 USB_KB_DEV
*UsbKeyboardDevice
;
1933 EFI_USB_IO_PROTOCOL
*UsbIo
;
1936 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1938 UsbIo
= UsbKeyboardDevice
->UsbIo
;
1940 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
1942 UsbIo
->UsbAsyncInterruptTransfer (
1944 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
1946 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,