2 Helper functions for USB Keyboard Driver.
4 Copyright (c) 2004 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Static English keyboard layout
19 // Format:<efi key>, <unicode without shift>, <unicode with shift>, <Modifier>, <AffectedAttribute>
21 UINT8 KeyboardLayoutTable
[USB_KEYCODE_MAX_MAKE
+ 8][5] = {
22 {EfiKeyC1
, 'a', 'A', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x04
23 {EfiKeyB5
, 'b', 'B', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x05
24 {EfiKeyB3
, 'c', 'C', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x06
25 {EfiKeyC3
, 'd', 'D', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x07
26 {EfiKeyD3
, 'e', 'E', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x08
27 {EfiKeyC4
, 'f', 'F', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x09
28 {EfiKeyC5
, 'g', 'G', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0A
29 {EfiKeyC6
, 'h', 'H', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0B
30 {EfiKeyD8
, 'i', 'I', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0C
31 {EfiKeyC7
, 'j', 'J', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0D
32 {EfiKeyC8
, 'k', 'K', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0E
33 {EfiKeyC9
, 'l', 'L', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0F
34 {EfiKeyB7
, 'm', 'M', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x10
35 {EfiKeyB6
, 'n', 'N', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x11
36 {EfiKeyD9
, 'o', 'O', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x12
37 {EfiKeyD10
, 'p', 'P', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x13
38 {EfiKeyD1
, 'q', 'Q', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x14
39 {EfiKeyD4
, 'r', 'R', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x15
40 {EfiKeyC2
, 's', 'S', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x16
41 {EfiKeyD5
, 't', 'T', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x17
42 {EfiKeyD7
, 'u', 'U', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x18
43 {EfiKeyB4
, 'v', 'V', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x19
44 {EfiKeyD2
, 'w', 'W', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1A
45 {EfiKeyB2
, 'x', 'X', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1B
46 {EfiKeyD6
, 'y', 'Y', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1C
47 {EfiKeyB1
, 'z', 'Z', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1D
48 {EfiKeyE1
, '1', '!', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1E
49 {EfiKeyE2
, '2', '@', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1F
50 {EfiKeyE3
, '3', '#', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x20
51 {EfiKeyE4
, '4', '$', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x21
52 {EfiKeyE5
, '5', '%', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x22
53 {EfiKeyE6
, '6', '^', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x23
54 {EfiKeyE7
, '7', '&', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x24
55 {EfiKeyE8
, '8', '*', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x25
56 {EfiKeyE9
, '9', '(', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x26
57 {EfiKeyE10
, '0', ')', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x27
58 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x28 Enter
59 {EfiKeyEsc
, 0x1b, 0x1b, EFI_NULL_MODIFIER
, 0}, // 0x29 Esc
60 {EfiKeyBackSpace
, 0x08, 0x08, EFI_NULL_MODIFIER
, 0}, // 0x2A Backspace
61 {EfiKeyTab
, 0x09, 0x09, EFI_NULL_MODIFIER
, 0}, // 0x2B Tab
62 {EfiKeySpaceBar
, ' ', ' ', EFI_NULL_MODIFIER
, 0}, // 0x2C Spacebar
63 {EfiKeyE11
, '-', '_', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2D
64 {EfiKeyE12
, '=', '+', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2E
65 {EfiKeyD11
, '[', '{', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2F
66 {EfiKeyD12
, ']', '}', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x30
67 {EfiKeyD13
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x31
68 {EfiKeyC12
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x32 Keyboard Non-US # and ~
69 {EfiKeyC10
, ';', ':', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x33
70 {EfiKeyC11
, '\'', '"', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x34
71 {EfiKeyE0
, '`', '~', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x35 Keyboard Grave Accent and Tlide
72 {EfiKeyB8
, ',', '<', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x36
73 {EfiKeyB9
, '.', '>', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x37
74 {EfiKeyB10
, '/', '?', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x38
75 {EfiKeyCapsLock
, 0x00, 0x00, EFI_CAPS_LOCK_MODIFIER
, 0}, // 0x39 CapsLock
76 {EfiKeyF1
, 0x00, 0x00, EFI_FUNCTION_KEY_ONE_MODIFIER
, 0}, // 0x3A
77 {EfiKeyF2
, 0x00, 0x00, EFI_FUNCTION_KEY_TWO_MODIFIER
, 0}, // 0x3B
78 {EfiKeyF3
, 0x00, 0x00, EFI_FUNCTION_KEY_THREE_MODIFIER
, 0}, // 0x3C
79 {EfiKeyF4
, 0x00, 0x00, EFI_FUNCTION_KEY_FOUR_MODIFIER
, 0}, // 0x3D
80 {EfiKeyF5
, 0x00, 0x00, EFI_FUNCTION_KEY_FIVE_MODIFIER
, 0}, // 0x3E
81 {EfiKeyF6
, 0x00, 0x00, EFI_FUNCTION_KEY_SIX_MODIFIER
, 0}, // 0x3F
82 {EfiKeyF7
, 0x00, 0x00, EFI_FUNCTION_KEY_SEVEN_MODIFIER
, 0}, // 0x40
83 {EfiKeyF8
, 0x00, 0x00, EFI_FUNCTION_KEY_EIGHT_MODIFIER
, 0}, // 0x41
84 {EfiKeyF9
, 0x00, 0x00, EFI_FUNCTION_KEY_NINE_MODIFIER
, 0}, // 0x42
85 {EfiKeyF10
, 0x00, 0x00, EFI_FUNCTION_KEY_TEN_MODIFIER
, 0}, // 0x43
86 {EfiKeyF11
, 0x00, 0x00, EFI_FUNCTION_KEY_ELEVEN_MODIFIER
, 0}, // 0x44 F11
87 {EfiKeyF12
, 0x00, 0x00, EFI_FUNCTION_KEY_TWELVE_MODIFIER
, 0}, // 0x45 F12
88 {EfiKeyPrint
, 0x00, 0x00, EFI_PRINT_MODIFIER
, 0}, // 0x46 PrintScreen
89 {EfiKeySLck
, 0x00, 0x00, EFI_SCROLL_LOCK_MODIFIER
, 0}, // 0x47 Scroll Lock
90 {EfiKeyPause
, 0x00, 0x00, EFI_PAUSE_MODIFIER
, 0}, // 0x48 Pause
91 {EfiKeyIns
, 0x00, 0x00, EFI_INSERT_MODIFIER
, 0}, // 0x49
92 {EfiKeyHome
, 0x00, 0x00, EFI_HOME_MODIFIER
, 0}, // 0x4A
93 {EfiKeyPgUp
, 0x00, 0x00, EFI_PAGE_UP_MODIFIER
, 0}, // 0x4B
94 {EfiKeyDel
, 0x00, 0x00, EFI_DELETE_MODIFIER
, 0}, // 0x4C
95 {EfiKeyEnd
, 0x00, 0x00, EFI_END_MODIFIER
, 0}, // 0x4D
96 {EfiKeyPgDn
, 0x00, 0x00, EFI_PAGE_DOWN_MODIFIER
, 0}, // 0x4E
97 {EfiKeyRightArrow
, 0x00, 0x00, EFI_RIGHT_ARROW_MODIFIER
, 0}, // 0x4F
98 {EfiKeyLeftArrow
, 0x00, 0x00, EFI_LEFT_ARROW_MODIFIER
, 0}, // 0x50
99 {EfiKeyDownArrow
, 0x00, 0x00, EFI_DOWN_ARROW_MODIFIER
, 0}, // 0x51
100 {EfiKeyUpArrow
, 0x00, 0x00, EFI_UP_ARROW_MODIFIER
, 0}, // 0x52
101 {EfiKeyNLck
, 0x00, 0x00, EFI_NUM_LOCK_MODIFIER
, 0}, // 0x53 NumLock
102 {EfiKeySlash
, '/', '/', EFI_NULL_MODIFIER
, 0}, // 0x54
103 {EfiKeyAsterisk
, '*', '*', EFI_NULL_MODIFIER
, 0}, // 0x55
104 {EfiKeyMinus
, '-', '-', EFI_NULL_MODIFIER
, 0}, // 0x56
105 {EfiKeyPlus
, '+', '+', EFI_NULL_MODIFIER
, 0}, // 0x57
106 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x58
107 {EfiKeyOne
, '1', '1', EFI_END_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x59
108 {EfiKeyTwo
, '2', '2', EFI_DOWN_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5A
109 {EfiKeyThree
, '3', '3', EFI_PAGE_DOWN_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5B
110 {EfiKeyFour
, '4', '4', EFI_LEFT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5C
111 {EfiKeyFive
, '5', '5', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5D
112 {EfiKeySix
, '6', '6', EFI_RIGHT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5E
113 {EfiKeySeven
, '7', '7', EFI_HOME_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5F
114 {EfiKeyEight
, '8', '8', EFI_UP_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x60
115 {EfiKeyNine
, '9', '9', EFI_PAGE_UP_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x61
116 {EfiKeyZero
, '0', '0', EFI_INSERT_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x62
117 {EfiKeyPeriod
, '.', '.', EFI_DELETE_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x63
118 {EfiKeyB0
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x64 Keyboard Non-US \ and |
119 {EfiKeyA4
, 0x00, 0x00, EFI_MENU_MODIFIER
, 0}, // 0x65 Keyboard Application
121 {EfiKeyLCtrl
, 0, 0, EFI_LEFT_CONTROL_MODIFIER
, 0}, // 0xe0
122 {EfiKeyLShift
, 0, 0, EFI_LEFT_SHIFT_MODIFIER
, 0}, // 0xe1
123 {EfiKeyLAlt
, 0, 0, EFI_LEFT_ALT_MODIFIER
, 0}, // 0xe2
124 {EfiKeyA0
, 0, 0, EFI_LEFT_LOGO_MODIFIER
, 0}, // 0xe3
125 {EfiKeyRCtrl
, 0, 0, EFI_RIGHT_CONTROL_MODIFIER
, 0}, // 0xe4
126 {EfiKeyRShift
, 0, 0, EFI_RIGHT_SHIFT_MODIFIER
, 0}, // 0xe5
127 {EfiKeyA2
, 0, 0, EFI_RIGHT_ALT_MODIFIER
, 0}, // 0xe6
128 {EfiKeyA3
, 0, 0, EFI_RIGHT_LOGO_MODIFIER
, 0}, // 0xe7
132 // EFI_KEY to USB Scan Code convertion table
134 UINT8 UsbScanCodeConvertionTable
[] = {
138 0x2c, // EfiKeySpaceBar
143 0x50, // EfiKeyLeftArrow
144 0x51, // EfiKeyDownArrow
145 0x4F, // EfiKeyRightArrow
147 0x63, // EfiKeyPeriod
149 0xe1, // EfiKeyLShift
161 0xe5, // EfiKeyRShift
162 0x52, // EfiKeyUpArrow
166 0x39, // EfiKeyCapsLock
216 0x2A, // EfiKeyBackSpace
222 0x55, // EfiKeyAsterisk
243 // Keyboard Layout Modifier to EFI Scan Code convertion table
245 UINT8 EfiScanCodeConvertionTable
[] = {
246 SCAN_NULL
, // EFI_NULL_MODIFIER
247 SCAN_NULL
, // EFI_LEFT_CONTROL_MODIFIER
248 SCAN_NULL
, // EFI_RIGHT_CONTROL_MODIFIER
249 SCAN_NULL
, // EFI_LEFT_ALT_MODIFIER
250 SCAN_NULL
, // EFI_RIGHT_ALT_MODIFIER
251 SCAN_NULL
, // EFI_ALT_GR_MODIFIER
252 SCAN_INSERT
, // EFI_INSERT_MODIFIER
253 SCAN_DELETE
, // EFI_DELETE_MODIFIER
254 SCAN_PAGE_DOWN
, // EFI_PAGE_DOWN_MODIFIER
255 SCAN_PAGE_UP
, // EFI_PAGE_UP_MODIFIER
256 SCAN_HOME
, // EFI_HOME_MODIFIER
257 SCAN_END
, // EFI_END_MODIFIER
258 SCAN_NULL
, // EFI_LEFT_SHIFT_MODIFIER
259 SCAN_NULL
, // EFI_RIGHT_SHIFT_MODIFIER
260 SCAN_NULL
, // EFI_CAPS_LOCK_MODIFIER
261 SCAN_NULL
, // EFI_NUM_LOCK_MODIFIER
262 SCAN_LEFT
, // EFI_LEFT_ARROW_MODIFIER
263 SCAN_RIGHT
, // EFI_RIGHT_ARROW_MODIFIER
264 SCAN_DOWN
, // EFI_DOWN_ARROW_MODIFIER
265 SCAN_UP
, // EFI_UP_ARROW_MODIFIER
266 SCAN_NULL
, // EFI_NS_KEY_MODIFIER
267 SCAN_NULL
, // EFI_NS_KEY_DEPENDENCY_MODIFIER
268 SCAN_F1
, // EFI_FUNCTION_KEY_ONE_MODIFIER
269 SCAN_F2
, // EFI_FUNCTION_KEY_TWO_MODIFIER
270 SCAN_F3
, // EFI_FUNCTION_KEY_THREE_MODIFIER
271 SCAN_F4
, // EFI_FUNCTION_KEY_FOUR_MODIFIER
272 SCAN_F5
, // EFI_FUNCTION_KEY_FIVE_MODIFIER
273 SCAN_F6
, // EFI_FUNCTION_KEY_SIX_MODIFIER
274 SCAN_F7
, // EFI_FUNCTION_KEY_SEVEN_MODIFIER
275 SCAN_F8
, // EFI_FUNCTION_KEY_EIGHT_MODIFIER
276 SCAN_F9
, // EFI_FUNCTION_KEY_NINE_MODIFIER
277 SCAN_F10
, // EFI_FUNCTION_KEY_TEN_MODIFIER
278 SCAN_F11
, // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
279 SCAN_F12
, // EFI_FUNCTION_KEY_TWELVE_MODIFIER
282 EFI_GUID mKeyboardLayoutEventGuid
= EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
;
285 KB_MODIFIER KB_Mod
[8] = {
286 { MOD_CONTROL_L
, 0xe0 }, // 11100000
287 { MOD_CONTROL_R
, 0xe4 }, // 11100100
288 { MOD_SHIFT_L
, 0xe1 }, // 11100001
289 { MOD_SHIFT_R
, 0xe5 }, // 11100101
290 { MOD_ALT_L
, 0xe2 }, // 11100010
291 { MOD_ALT_R
, 0xe6 }, // 11100110
292 { MOD_WIN_L
, 0xe3 }, // 11100011
293 { MOD_WIN_R
, 0xe7 }, // 11100111
297 Initialize KeyConvertionTable by using default keyboard layout.
299 @param UsbKeyboardDevice The USB_KB_DEV instance.
304 LoadDefaultKeyboardLayout (
305 IN USB_KB_DEV
*UsbKeyboardDevice
309 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
312 // Construct KeyConvertionTable by default keyboard layout
314 KeyDescriptor
= &UsbKeyboardDevice
->KeyConvertionTable
[0];
316 for (Index
= 0; Index
< (USB_KEYCODE_MAX_MAKE
+ 8); Index
++) {
317 KeyDescriptor
->Key
= (EFI_KEY
) KeyboardLayoutTable
[Index
][0];
318 KeyDescriptor
->Unicode
= KeyboardLayoutTable
[Index
][1];
319 KeyDescriptor
->ShiftedUnicode
= KeyboardLayoutTable
[Index
][2];
320 KeyDescriptor
->AltGrUnicode
= 0;
321 KeyDescriptor
->ShiftedAltGrUnicode
= 0;
322 KeyDescriptor
->Modifier
= KeyboardLayoutTable
[Index
][3];
323 KeyDescriptor
->AffectedAttribute
= KeyboardLayoutTable
[Index
][4];
330 Uses USB I/O to check whether the device is a USB Keyboard device.
332 @param UsbIo Points to a USB I/O protocol instance.
338 IN EFI_USB_IO_PROTOCOL
*UsbIo
342 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
345 // Get the Default interface descriptor, currently we
346 // assume it is interface 1
348 Status
= UsbIo
->UsbGetInterfaceDescriptor (
353 if (EFI_ERROR (Status
)) {
357 if (InterfaceDescriptor
.InterfaceClass
== CLASS_HID
&&
358 InterfaceDescriptor
.InterfaceSubClass
== SUBCLASS_BOOT
&&
359 InterfaceDescriptor
.InterfaceProtocol
== PROTOCOL_KEYBOARD
369 Get current keyboard layout from HII database.
371 @return Pointer to EFI_HII_KEYBOARD_LAYOUT.
374 EFI_HII_KEYBOARD_LAYOUT
*
376 GetCurrentKeyboardLayout (
381 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
382 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
386 // Locate Hii database protocol
388 Status
= gBS
->LocateProtocol (
389 &gEfiHiiDatabaseProtocolGuid
,
391 (VOID
**) &HiiDatabase
393 if (EFI_ERROR (Status
)) {
398 // Get current keyboard layout from HII database
401 KeyboardLayout
= NULL
;
402 Status
= HiiDatabase
->GetKeyboardLayout (
408 if (Status
== EFI_BUFFER_TOO_SMALL
) {
409 KeyboardLayout
= AllocatePool (Length
);
410 ASSERT (KeyboardLayout
!= NULL
);
412 Status
= HiiDatabase
->GetKeyboardLayout (
418 if (EFI_ERROR (Status
)) {
419 gBS
->FreePool (KeyboardLayout
);
420 KeyboardLayout
= NULL
;
424 return KeyboardLayout
;
428 Find Key Descriptor in KeyConvertionTable given its scan code.
430 @param UsbKeyboardDevice The USB_KB_DEV instance.
431 @param ScanCode USB scan code.
433 @return The Key descriptor in KeyConvertionTable.
434 NULL means not found.
440 IN USB_KB_DEV
*UsbKeyboardDevice
,
446 if (((ScanCode
> 0x65) && (ScanCode
< 0xe0)) || (ScanCode
> 0xe7)) {
450 if (ScanCode
<= 0x65) {
451 Index
= (UINT8
) (ScanCode
- 4);
453 Index
= (UINT8
) (ScanCode
- 0xe0 + USB_KEYCODE_MAX_MAKE
);
456 return &UsbKeyboardDevice
->KeyConvertionTable
[Index
];
460 Find Non-Spacing key for given KeyDescriptor.
462 @param UsbKeyboardDevice The USB_KB_DEV instance.
463 @param KeyDescriptor Key descriptor.
465 @return The Non-Spacing key corresponding to KeyDescriptor
466 NULL means not found.
472 IN USB_KB_DEV
*UsbKeyboardDevice
,
473 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
477 USB_NS_KEY
*UsbNsKey
;
479 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
480 while (!IsNull (&UsbKeyboardDevice
->NsKeyList
, Link
)) {
481 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
483 if (UsbNsKey
->NsKey
[0].Key
== KeyDescriptor
->Key
) {
487 Link
= GetNextNode (&UsbKeyboardDevice
->NsKeyList
, Link
);
494 Find physical key definition for a given Key stroke.
496 @param UsbNsKey The Non-Spacing key information.
497 @param KeyDescriptor The key stroke.
499 @return The physical key definition.
505 IN USB_NS_KEY
*UsbNsKey
,
506 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
510 EFI_KEY_DESCRIPTOR
*PhysicalKey
;
512 PhysicalKey
= &UsbNsKey
->NsKey
[1];
513 for (Index
= 0; Index
< UsbNsKey
->KeyCount
; Index
++) {
514 if (KeyDescriptor
->Key
== PhysicalKey
->Key
) {
522 // No children definition matched, return original key
524 return KeyDescriptor
;
528 The notification function for SET_KEYBOARD_LAYOUT_EVENT.
530 @param Event The instance of EFI_EVENT.
531 @param Context passing parameter.
536 SetKeyboardLayoutEvent (
541 USB_KB_DEV
*UsbKeyboardDevice
;
542 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
543 EFI_KEY_DESCRIPTOR TempKey
;
544 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
545 EFI_KEY_DESCRIPTOR
*TableEntry
;
546 EFI_KEY_DESCRIPTOR
*NsKey
;
547 USB_NS_KEY
*UsbNsKey
;
553 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
556 // Try to get current Keyboard Layout from HII database
558 KeyboardLayout
= GetCurrentKeyboardLayout ();
559 if (KeyboardLayout
== NULL
) {
564 // Re-allocate resource for KeyConvertionTable
566 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
567 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
568 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
571 // Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
573 KeyDescriptor
= (EFI_KEY_DESCRIPTOR
*) (((UINT8
*) KeyboardLayout
) + sizeof (EFI_HII_KEYBOARD_LAYOUT
));
574 for (Index
= 0; Index
< KeyboardLayout
->DescriptorCount
; Index
++) {
576 // Copy from HII keyboard layout package binary for alignment
578 CopyMem (&TempKey
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
581 // Fill the key into KeyConvertionTable, whose index is calculated from USB scan code.
583 ScanCode
= UsbScanCodeConvertionTable
[(UINT8
) (TempKey
.Key
)];
584 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, ScanCode
);
585 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
587 if (TempKey
.Modifier
== EFI_NS_KEY_MODIFIER
) {
589 // For non-spacing key, create the list with a non-spacing key followed by physical keys.
591 UsbNsKey
= AllocatePool (sizeof (USB_NS_KEY
));
592 ASSERT (UsbNsKey
!= NULL
);
595 // Search for sequential children physical key definitions
598 NsKey
= KeyDescriptor
+ 1;
599 for (Index2
= Index
+ 1; Index2
< KeyboardLayout
->DescriptorCount
; Index2
++) {
600 CopyMem (&TempKey
, NsKey
, sizeof (EFI_KEY_DESCRIPTOR
));
601 if (TempKey
.Modifier
& EFI_NS_KEY_DEPENDENCY_MODIFIER
) {
609 UsbNsKey
->Signature
= USB_NS_KEY_SIGNATURE
;
610 UsbNsKey
->KeyCount
= KeyCount
;
611 UsbNsKey
->NsKey
= AllocateCopyPool (
612 (KeyCount
+ 1) * sizeof (EFI_KEY_DESCRIPTOR
),
615 InsertTailList (&UsbKeyboardDevice
->NsKeyList
, &UsbNsKey
->Link
);
618 // Skip over the child physical keys
621 KeyDescriptor
+= KeyCount
;
628 // There are two EfiKeyEnter, duplicate its Key Descriptor
630 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, 0x58);
631 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, 0x28);
632 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
634 gBS
->FreePool (KeyboardLayout
);
638 Destroy resources for Keyboard layout.
640 @param UsbKeyboardDevice The USB_KB_DEV instance.
645 ReleaseKeyboardLayoutResources (
646 IN USB_KB_DEV
*UsbKeyboardDevice
649 USB_NS_KEY
*UsbNsKey
;
652 if (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
) {
653 FreePool (UsbKeyboardDevice
->KeyConvertionTable
);
655 UsbKeyboardDevice
->KeyConvertionTable
= NULL
;
657 while (!IsListEmpty (&UsbKeyboardDevice
->NsKeyList
)) {
658 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
659 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
660 RemoveEntryList (&UsbNsKey
->Link
);
662 FreePool (UsbNsKey
->NsKey
);
668 Initialize USB Keyboard layout.
670 @param UsbKeyboardDevice The USB_KB_DEV instance.
672 @retval EFI_SUCCESS Initialization Success.
673 @retval Other Keyboard layout initial failed.
679 IN USB_KB_DEV
*UsbKeyboardDevice
682 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
685 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
686 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
688 InitializeListHead (&UsbKeyboardDevice
->NsKeyList
);
689 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
690 UsbKeyboardDevice
->KeyboardLayoutEvent
= NULL
;
693 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
694 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout.
696 Status
= gBS
->CreateEventEx (
699 SetKeyboardLayoutEvent
,
701 &mKeyboardLayoutEventGuid
,
702 &UsbKeyboardDevice
->KeyboardLayoutEvent
704 if (EFI_ERROR (Status
)) {
708 KeyboardLayout
= GetCurrentKeyboardLayout ();
709 if (KeyboardLayout
!= NULL
) {
711 // If current keyboard layout is successfully retrieved from HII database,
712 // force to initialize the keyboard layout.
714 gBS
->SignalEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
716 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver
)) {
718 // If no keyboard layout can be retrieved from HII database, and default layout
719 // is disabled, then return EFI_NOT_READY.
721 return EFI_NOT_READY
;
724 // If no keyboard layout can be retrieved from HII database, and default layout
725 // is enabled, then load the default keyboard layout.
727 LoadDefaultKeyboardLayout (UsbKeyboardDevice
);
735 Initialize USB Keyboard device and all private data structures.
737 @param UsbKeyboardDevice The USB_KB_DEV instance.
739 @retval EFI_SUCCESS Initialization is successful.
740 @retval EFI_DEVICE_ERROR Configure hardware failed.
746 IN USB_KB_DEV
*UsbKeyboardDevice
754 UINT32 TransferResult
;
756 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
758 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest
),
759 UsbKeyboardDevice
->DevicePath
762 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
765 // default configurations
770 // Uses default configuration to configure the USB Keyboard device.
772 Status
= UsbSetConfiguration (
773 UsbKeyboardDevice
->UsbIo
,
774 (UINT16
) ConfigValue
,
777 if (EFI_ERROR (Status
)) {
779 // If configuration could not be set here, it means
780 // the keyboard interface has some errors and could
781 // not be initialized
783 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
784 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
785 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError
),
786 UsbKeyboardDevice
->DevicePath
789 return EFI_DEVICE_ERROR
;
792 UsbGetProtocolRequest (
793 UsbKeyboardDevice
->UsbIo
,
794 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
798 // Set boot protocol for the USB Keyboard.
799 // This driver only supports boot protocol.
800 // The device that does not support boot protocol is not supported.
802 if (Protocol
!= BOOT_PROTOCOL
) {
803 UsbSetProtocolRequest (
804 UsbKeyboardDevice
->UsbIo
,
805 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
811 // ReportId is zero, which means the idle rate applies to all input reports.
815 // Duration is zero, which means the duration is indefinite.
816 // so the endpoint will inhibit reporting forever,
817 // and only reporting when a change is detected in the report data.
821 UsbKeyboardDevice
->UsbIo
,
822 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
827 UsbKeyboardDevice
->CtrlOn
= 0;
828 UsbKeyboardDevice
->AltOn
= 0;
829 UsbKeyboardDevice
->ShiftOn
= 0;
830 UsbKeyboardDevice
->NumLockOn
= 0;
831 UsbKeyboardDevice
->CapsOn
= 0;
832 UsbKeyboardDevice
->ScrollOn
= 0;
834 UsbKeyboardDevice
->LeftCtrlOn
= 0;
835 UsbKeyboardDevice
->LeftAltOn
= 0;
836 UsbKeyboardDevice
->LeftShiftOn
= 0;
837 UsbKeyboardDevice
->LeftLogoOn
= 0;
838 UsbKeyboardDevice
->RightCtrlOn
= 0;
839 UsbKeyboardDevice
->RightAltOn
= 0;
840 UsbKeyboardDevice
->RightShiftOn
= 0;
841 UsbKeyboardDevice
->RightLogoOn
= 0;
842 UsbKeyboardDevice
->MenuKeyOn
= 0;
843 UsbKeyboardDevice
->SysReqOn
= 0;
845 UsbKeyboardDevice
->AltGrOn
= 0;
847 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
850 // Sync the initial state of lights
852 SetKeyLED (UsbKeyboardDevice
);
854 ZeroMem (UsbKeyboardDevice
->LastKeyCodeArray
, sizeof (UINT8
) * 8);
857 // Set a timer for repeat keys' generation.
859 if (UsbKeyboardDevice
->RepeatTimer
!= NULL
) {
860 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
861 UsbKeyboardDevice
->RepeatTimer
= NULL
;
864 Status
= gBS
->CreateEvent (
865 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
867 USBKeyboardRepeatHandler
,
869 &UsbKeyboardDevice
->RepeatTimer
872 if (UsbKeyboardDevice
->DelayedRecoveryEvent
!= NULL
) {
873 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
874 UsbKeyboardDevice
->DelayedRecoveryEvent
= NULL
;
877 Status
= gBS
->CreateEvent (
878 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
880 USBKeyboardRecoveryHandler
,
882 &UsbKeyboardDevice
->DelayedRecoveryEvent
890 Handler function for USB Keyboard's asynchronous interrupt transfer.
892 @param Data A pointer to a buffer that is filled with key data which is
893 retrieved via asynchronous interrupt transfer.
894 @param DataLength Indicates the size of the data buffer.
895 @param Context Pointing to USB_KB_DEV instance.
896 @param Result Indicates the result of the asynchronous interrupt transfer.
898 @retval EFI_SUCCESS Handler is successful.
899 @retval EFI_DEVICE_ERROR Hardware Error
911 USB_KB_DEV
*UsbKeyboardDevice
;
912 EFI_USB_IO_PROTOCOL
*UsbIo
;
913 UINT8
*CurKeyCodeBuffer
;
914 UINT8
*OldKeyCodeBuffer
;
915 UINT8 CurModifierMap
;
916 UINT8 OldModifierMap
;
926 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
928 ASSERT (Context
!= NULL
);
931 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
932 UsbIo
= UsbKeyboardDevice
->UsbIo
;
935 // Analyzes the Result and performs corresponding action.
937 if (Result
!= EFI_USB_NOERROR
) {
939 // Some errors happen during the process
941 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
942 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
943 PcdGet32 (PcdStatusCodeValueKeyboardInputError
),
944 UsbKeyboardDevice
->DevicePath
948 // stop the repeat key generation if any
950 UsbKeyboardDevice
->RepeatKey
= 0;
953 UsbKeyboardDevice
->RepeatTimer
,
958 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
959 UsbClearEndpointHalt (
961 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
967 // Delete & Submit this interrupt again
968 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
970 UsbIo
->UsbAsyncInterruptTransfer (
972 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
980 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling
983 UsbKeyboardDevice
->DelayedRecoveryEvent
,
985 EFI_USB_INTERRUPT_DELAY
988 return EFI_DEVICE_ERROR
;
992 // If no error and no data, just return EFI_SUCCESS.
994 if (DataLength
== 0 || Data
== NULL
) {
999 // Following code checks current keyboard input report against old key code buffer.
1000 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1001 // Byte 0 is map of Modifier keys.
1002 // Byte 1 is reserved.
1003 // Bytes 2 to 7 are keycodes.
1005 CurKeyCodeBuffer
= (UINT8
*) Data
;
1006 OldKeyCodeBuffer
= UsbKeyboardDevice
->LastKeyCodeArray
;
1009 // Checks for new key stroke.
1011 for (Index
= 0; Index
< 8; Index
++) {
1012 if (OldKeyCodeBuffer
[Index
] != CurKeyCodeBuffer
[Index
]) {
1018 // If no new key, return EFI_SUCCESS immediately.
1025 // Parse the modifier key, which is the first byte of keyboard input report.
1027 CurModifierMap
= CurKeyCodeBuffer
[0];
1028 OldModifierMap
= OldKeyCodeBuffer
[0];
1031 // Handle modifier key's pressing or releasing situation.
1033 for (Index
= 0; Index
< 8; Index
++) {
1035 if ((CurModifierMap
& KB_Mod
[Index
].Mask
) != (OldModifierMap
& KB_Mod
[Index
].Mask
)) {
1037 // If current modifier key is up, then
1038 // CurModifierMap & KB_Mod[Index].Mask = 0;
1039 // otherwise it is a non-zero value.
1040 // Inserts the pressed modifier key into key buffer.
1042 Down
= (UINT8
) (CurModifierMap
& KB_Mod
[Index
].Mask
);
1043 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), KB_Mod
[Index
].Key
, Down
);
1048 // Handle normal key's releasing situation
1049 // Bytes 2 to 7 are normal keycodes
1052 for (Index
= 2; Index
< 8; Index
++) {
1054 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index
])) {
1058 // For any key in old keycode buffer, if it is not in current keycode buffer,
1059 // then it is released. Otherwise, it is not released.
1062 for (Index2
= 2; Index2
< 8; Index2
++) {
1064 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index2
])) {
1068 if (OldKeyCodeBuffer
[Index
] == CurKeyCodeBuffer
[Index2
]) {
1076 &(UsbKeyboardDevice
->KeyboardBuffer
),
1077 OldKeyCodeBuffer
[Index
],
1081 // The original repeat key is released.
1083 if (OldKeyCodeBuffer
[Index
] == UsbKeyboardDevice
->RepeatKey
) {
1084 UsbKeyboardDevice
->RepeatKey
= 0;
1090 // If original repeat key is released, cancel the repeat timer
1092 if (UsbKeyboardDevice
->RepeatKey
== 0) {
1094 UsbKeyboardDevice
->RepeatTimer
,
1101 // Handle normal key's pressing situation
1104 for (Index
= 2; Index
< 8; Index
++) {
1106 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index
])) {
1110 // For any key in current keycode buffer, if it is not in old keycode buffer,
1111 // then it is pressed. Otherwise, it is not pressed.
1114 for (Index2
= 2; Index2
< 8; Index2
++) {
1116 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index2
])) {
1120 if (CurKeyCodeBuffer
[Index
] == OldKeyCodeBuffer
[Index2
]) {
1127 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), CurKeyCodeBuffer
[Index
], 1);
1130 // Handle repeat key
1132 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, CurKeyCodeBuffer
[Index
]);
1133 if (KeyDescriptor
->Modifier
== EFI_NUM_LOCK_MODIFIER
|| KeyDescriptor
->Modifier
== EFI_CAPS_LOCK_MODIFIER
) {
1135 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1137 UsbKeyboardDevice
->RepeatKey
= 0;
1140 // Prepare new repeat key, and clear the original one.
1142 NewRepeatKey
= CurKeyCodeBuffer
[Index
];
1143 UsbKeyboardDevice
->RepeatKey
= 0;
1149 // Update LastKeycodeArray[] buffer in the
1150 // Usb Keyboard Device data structure.
1152 for (Index
= 0; Index
< 8; Index
++) {
1153 UsbKeyboardDevice
->LastKeyCodeArray
[Index
] = CurKeyCodeBuffer
[Index
];
1157 // Pre-process KeyboardBuffer. Pop out the Ctrl, Alt, Del key in sequence
1158 // and judge whether it will invoke reset event.
1160 SavedTail
= UsbKeyboardDevice
->KeyboardBuffer
.BufferTail
;
1161 Index
= UsbKeyboardDevice
->KeyboardBuffer
.BufferHead
;
1162 while (Index
!= SavedTail
) {
1163 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1165 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1167 switch (KeyDescriptor
->Modifier
) {
1169 case EFI_LEFT_CONTROL_MODIFIER
:
1170 case EFI_RIGHT_CONTROL_MODIFIER
:
1171 if (UsbKey
.Down
!= 0) {
1172 UsbKeyboardDevice
->CtrlOn
= 1;
1174 UsbKeyboardDevice
->CtrlOn
= 0;
1178 case EFI_LEFT_ALT_MODIFIER
:
1179 case EFI_RIGHT_ALT_MODIFIER
:
1180 if (UsbKey
.Down
!= 0) {
1181 UsbKeyboardDevice
->AltOn
= 1;
1183 UsbKeyboardDevice
->AltOn
= 0;
1187 case EFI_ALT_GR_MODIFIER
:
1188 if (UsbKey
.Down
!= 0) {
1189 UsbKeyboardDevice
->AltGrOn
= 1;
1191 UsbKeyboardDevice
->AltGrOn
= 0;
1196 // For Del Key, check if Ctrl + Alt + Del occurs for reset.
1198 case EFI_DELETE_MODIFIER
:
1199 if (UsbKey
.Down
!= 0) {
1200 if ((UsbKeyboardDevice
->CtrlOn
!= 0) && (UsbKeyboardDevice
->AltOn
!= 0)) {
1201 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1211 // Insert the key back to the buffer,
1212 // so the key sequence will not be destroyed.
1215 &(UsbKeyboardDevice
->KeyboardBuffer
),
1219 Index
= UsbKeyboardDevice
->KeyboardBuffer
.BufferHead
;
1223 // If have new key pressed, update the RepeatKey value, and set the
1224 // timer to repeate delay timer
1226 if (NewRepeatKey
!= 0) {
1228 // Sets trigger time to "Repeat Delay Time",
1229 // to trigger the repeat timer when the key is hold long
1233 UsbKeyboardDevice
->RepeatTimer
,
1237 UsbKeyboardDevice
->RepeatKey
= NewRepeatKey
;
1245 Retrieves a key character after parsing the raw data in keyboard buffer.
1247 @param UsbKeyboardDevice The USB_KB_DEV instance.
1248 @param KeyChar Points to the Key character after key parsing.
1250 @retval EFI_SUCCESS Parse key is successful.
1251 @retval EFI_NOT_READY Device is not ready.
1257 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
1262 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1266 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice
->KeyboardBuffer
)) {
1268 // Pops one raw data off.
1270 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1272 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1273 if (UsbKey
.Down
== 0) {
1277 switch (KeyDescriptor
->Modifier
) {
1282 case EFI_LEFT_CONTROL_MODIFIER
:
1283 UsbKeyboardDevice
->LeftCtrlOn
= 0;
1284 UsbKeyboardDevice
->CtrlOn
= 0;
1286 case EFI_RIGHT_CONTROL_MODIFIER
:
1287 UsbKeyboardDevice
->RightCtrlOn
= 0;
1288 UsbKeyboardDevice
->CtrlOn
= 0;
1294 case EFI_LEFT_SHIFT_MODIFIER
:
1295 UsbKeyboardDevice
->LeftShiftOn
= 0;
1296 UsbKeyboardDevice
->ShiftOn
= 0;
1298 case EFI_RIGHT_SHIFT_MODIFIER
:
1299 UsbKeyboardDevice
->RightShiftOn
= 0;
1300 UsbKeyboardDevice
->ShiftOn
= 0;
1306 case EFI_LEFT_ALT_MODIFIER
:
1307 UsbKeyboardDevice
->LeftAltOn
= 0;
1308 UsbKeyboardDevice
->AltOn
= 0;
1310 case EFI_RIGHT_ALT_MODIFIER
:
1311 UsbKeyboardDevice
->RightAltOn
= 0;
1312 UsbKeyboardDevice
->AltOn
= 0;
1316 // Left Logo release
1318 case EFI_LEFT_LOGO_MODIFIER
:
1319 UsbKeyboardDevice
->LeftLogoOn
= 0;
1323 // Right Logo release
1325 case EFI_RIGHT_LOGO_MODIFIER
:
1326 UsbKeyboardDevice
->RightLogoOn
= 0;
1332 case EFI_MENU_MODIFIER
:
1333 UsbKeyboardDevice
->MenuKeyOn
= 0;
1339 case EFI_PRINT_MODIFIER
:
1340 case EFI_SYS_REQUEST_MODIFIER
:
1341 UsbKeyboardDevice
->SysReqOn
= 0;
1347 case EFI_ALT_GR_MODIFIER
:
1348 UsbKeyboardDevice
->AltGrOn
= 0;
1359 // Analyzes key pressing situation
1361 switch (KeyDescriptor
->Modifier
) {
1366 case EFI_LEFT_CONTROL_MODIFIER
:
1367 UsbKeyboardDevice
->LeftCtrlOn
= 1;
1368 UsbKeyboardDevice
->CtrlOn
= 1;
1371 case EFI_RIGHT_CONTROL_MODIFIER
:
1372 UsbKeyboardDevice
->RightCtrlOn
= 1;
1373 UsbKeyboardDevice
->CtrlOn
= 1;
1380 case EFI_LEFT_SHIFT_MODIFIER
:
1381 UsbKeyboardDevice
->LeftShiftOn
= 1;
1382 UsbKeyboardDevice
->ShiftOn
= 1;
1385 case EFI_RIGHT_SHIFT_MODIFIER
:
1386 UsbKeyboardDevice
->RightShiftOn
= 1;
1387 UsbKeyboardDevice
->ShiftOn
= 1;
1394 case EFI_LEFT_ALT_MODIFIER
:
1395 UsbKeyboardDevice
->LeftAltOn
= 1;
1396 UsbKeyboardDevice
->AltOn
= 1;
1399 case EFI_RIGHT_ALT_MODIFIER
:
1400 UsbKeyboardDevice
->RightAltOn
= 1;
1401 UsbKeyboardDevice
->AltOn
= 1;
1408 case EFI_LEFT_LOGO_MODIFIER
:
1409 UsbKeyboardDevice
->LeftLogoOn
= 1;
1415 case EFI_RIGHT_LOGO_MODIFIER
:
1416 UsbKeyboardDevice
->RightLogoOn
= 1;
1422 case EFI_MENU_MODIFIER
:
1423 UsbKeyboardDevice
->MenuKeyOn
= 1;
1429 case EFI_PRINT_MODIFIER
:
1430 case EFI_SYS_REQUEST_MODIFIER
:
1431 UsbKeyboardDevice
->SysReqOn
= 1;
1438 case EFI_ALT_GR_MODIFIER
:
1439 UsbKeyboardDevice
->AltGrOn
= 1;
1442 case EFI_NUM_LOCK_MODIFIER
:
1443 UsbKeyboardDevice
->NumLockOn
^= 1;
1445 // Set the NumLock light on keyboard
1447 SetKeyLED (UsbKeyboardDevice
);
1451 case EFI_CAPS_LOCK_MODIFIER
:
1452 UsbKeyboardDevice
->CapsOn
^= 1;
1454 // Set the CapsLock light on keyboard
1456 SetKeyLED (UsbKeyboardDevice
);
1460 case EFI_SCROLL_LOCK_MODIFIER
:
1461 UsbKeyboardDevice
->ScrollOn
^= 1;
1463 // Set the ScrollLock light on keyboard
1465 SetKeyLED (UsbKeyboardDevice
);
1470 // F11, F12, PrintScreen, Pause/Break
1471 // could not be retrieved via SimpleTextInEx protocol
1473 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER
:
1474 case EFI_FUNCTION_KEY_TWELVE_MODIFIER
:
1475 case EFI_PAUSE_MODIFIER
:
1476 case EFI_BREAK_MODIFIER
:
1488 // When encountering Ctrl + Alt + Del, then warm reset.
1490 if (KeyDescriptor
->Modifier
== EFI_DELETE_MODIFIER
) {
1491 if ((UsbKeyboardDevice
->CtrlOn
!= 0) && (UsbKeyboardDevice
->AltOn
!= 0)) {
1492 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1496 *KeyChar
= UsbKey
.KeyCode
;
1500 return EFI_NOT_READY
;
1505 Converts USB Keyboard code to EFI_INPUT_KEY.
1507 @param UsbKeyboardDevice The USB_KB_DEV instance.
1508 @param KeyChar Indicates the key code that will be interpreted.
1509 @param Key A pointer to a buffer that is filled in with
1510 the keystroke information for the key that
1513 @retval EFI_NOT_READY Device is not ready
1514 @retval EFI_SUCCESS Success.
1519 UsbKeyCodeToEfiInputKey (
1520 IN USB_KB_DEV
*UsbKeyboardDevice
,
1522 OUT EFI_INPUT_KEY
*Key
1526 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1528 if (!USBKBD_VALID_KEYCODE (KeyChar
)) {
1529 return EFI_NOT_READY
;
1533 // Valid USB Key Code starts from 4, so it's safe to minus 4.
1535 Index
= (UINT8
) (KeyChar
- 4);
1537 if (Index
>= USB_KEYCODE_MAX_MAKE
) {
1538 return EFI_NOT_READY
;
1541 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, KeyChar
);
1543 if (KeyDescriptor
->Modifier
== EFI_NS_KEY_MODIFIER
) {
1545 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1547 UsbKeyboardDevice
->CurrentNsKey
= FindUsbNsKey (UsbKeyboardDevice
, KeyDescriptor
);
1548 return EFI_NOT_READY
;
1551 if (UsbKeyboardDevice
->CurrentNsKey
!= NULL
) {
1553 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1556 KeyDescriptor
= FindPhysicalKey (UsbKeyboardDevice
->CurrentNsKey
, KeyDescriptor
);
1557 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
1560 Key
->ScanCode
= EfiScanCodeConvertionTable
[KeyDescriptor
->Modifier
];
1561 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1563 if ((KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_STANDARD_SHIFT
)!= 0) {
1564 if (UsbKeyboardDevice
->ShiftOn
!= 0) {
1565 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1568 // Need not return associated shift state if a class of printable characters that
1569 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1571 if ((KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) != 0) {
1572 UsbKeyboardDevice
->LeftShiftOn
= 0;
1573 UsbKeyboardDevice
->RightShiftOn
= 0;
1576 if (UsbKeyboardDevice
->AltGrOn
!= 0) {
1577 Key
->UnicodeChar
= KeyDescriptor
->ShiftedAltGrUnicode
;
1583 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1585 if (UsbKeyboardDevice
->AltGrOn
!= 0) {
1586 Key
->UnicodeChar
= KeyDescriptor
->AltGrUnicode
;
1591 if ((KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) != 0) {
1592 if (UsbKeyboardDevice
->CapsOn
!= 0) {
1594 if (Key
->UnicodeChar
== KeyDescriptor
->Unicode
) {
1596 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1598 } else if (Key
->UnicodeChar
== KeyDescriptor
->ShiftedUnicode
) {
1600 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1607 // Translate the CTRL-Alpha characters to their corresponding control value
1608 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1610 if (UsbKeyboardDevice
->CtrlOn
!= 0) {
1611 if (Key
->UnicodeChar
>= 'a' && Key
->UnicodeChar
<= 'z') {
1612 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'a' + 1);
1613 } else if (Key
->UnicodeChar
>= 'A' && Key
->UnicodeChar
<= 'Z') {
1614 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'A' + 1);
1618 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_NUM_LOCK
) {
1620 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1621 // normal key, instead of original control key. So the ScanCode should be cleaned.
1622 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1624 if ((UsbKeyboardDevice
->NumLockOn
!= 0) && (UsbKeyboardDevice
->ShiftOn
== 0)) {
1625 Key
->ScanCode
= SCAN_NULL
;
1627 Key
->UnicodeChar
= 0x00;
1632 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1634 if (Key
->UnicodeChar
== 0x1B && Key
->ScanCode
== SCAN_NULL
) {
1635 Key
->ScanCode
= SCAN_ESC
;
1636 Key
->UnicodeChar
= 0x00;
1640 // Not valid for key without both unicode key code and EFI Scan Code.
1642 if (Key
->UnicodeChar
== 0 && Key
->ScanCode
== SCAN_NULL
) {
1643 return EFI_NOT_READY
;
1648 // Save Shift/Toggle state
1650 if (UsbKeyboardDevice
->LeftCtrlOn
== 1) {
1651 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
1653 if (UsbKeyboardDevice
->RightCtrlOn
== 1) {
1654 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
1656 if (UsbKeyboardDevice
->LeftAltOn
== 1) {
1657 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
1659 if (UsbKeyboardDevice
->RightAltOn
== 1) {
1660 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_ALT_PRESSED
;
1662 if (UsbKeyboardDevice
->LeftShiftOn
== 1) {
1663 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1665 if (UsbKeyboardDevice
->RightShiftOn
== 1) {
1666 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1668 if (UsbKeyboardDevice
->LeftLogoOn
== 1) {
1669 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
1671 if (UsbKeyboardDevice
->RightLogoOn
== 1) {
1672 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
1674 if (UsbKeyboardDevice
->MenuKeyOn
== 1) {
1675 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_MENU_KEY_PRESSED
;
1677 if (UsbKeyboardDevice
->SysReqOn
== 1) {
1678 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_SYS_REQ_PRESSED
;
1681 if (UsbKeyboardDevice
->ScrollOn
== 1) {
1682 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1684 if (UsbKeyboardDevice
->NumLockOn
== 1) {
1685 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1687 if (UsbKeyboardDevice
->CapsOn
== 1) {
1688 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1697 Resets USB Keyboard Buffer.
1699 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1705 IN OUT USB_KB_BUFFER
*KeyboardBuffer
1708 ZeroMem (KeyboardBuffer
, sizeof (USB_KB_BUFFER
));
1710 KeyboardBuffer
->BufferHead
= KeyboardBuffer
->BufferTail
;
1715 Check whether USB Keyboard buffer is empty.
1717 @param KeyboardBuffer USB Keyboard Buffer.
1719 @retval TRUE Key buffer is empty.
1720 @retval FALSE Key buffer is not empty.
1725 IsUSBKeyboardBufferEmpty (
1726 IN USB_KB_BUFFER
*KeyboardBuffer
1730 // meet FIFO empty condition
1732 return (BOOLEAN
) (KeyboardBuffer
->BufferHead
== KeyboardBuffer
->BufferTail
);
1737 Check whether USB Keyboard buffer is full.
1739 @param KeyboardBuffer USB Keyboard Buffer.
1741 @retval TRUE Key buffer is full.
1742 @retval FALSE Key buffer is not full.
1747 IsUSBKeyboardBufferFull (
1748 IN USB_KB_BUFFER
*KeyboardBuffer
1751 return (BOOLEAN
)(((KeyboardBuffer
->BufferTail
+ 1) % (MAX_KEY_ALLOWED
+ 1)) == KeyboardBuffer
->BufferHead
);
1756 Inserts a key code into keyboard buffer.
1758 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1760 @param Down Special key
1766 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1774 // if keyboard buffer is full, throw the
1775 // first key out of the keyboard buffer.
1777 if (IsUSBKeyboardBufferFull (KeyboardBuffer
)) {
1778 RemoveKeyCode (KeyboardBuffer
, &UsbKey
);
1781 KeyboardBuffer
->Buffer
[KeyboardBuffer
->BufferTail
].KeyCode
= Key
;
1782 KeyboardBuffer
->Buffer
[KeyboardBuffer
->BufferTail
].Down
= Down
;
1785 // Adjust the tail pointer of the FIFO keyboard buffer.
1787 KeyboardBuffer
->BufferTail
= (UINT8
) ((KeyboardBuffer
->BufferTail
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1792 Pops a key code off from keyboard buffer.
1794 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1795 @param UsbKey Points to the buffer that contains a usb key code.
1797 @retval EFI_SUCCESS Key code Successfully poped from keyboard buffer.
1798 @retval EFI_DEVICE_ERROR Keyboard buffer is empty.
1804 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1808 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer
)) {
1809 return EFI_DEVICE_ERROR
;
1812 UsbKey
->KeyCode
= KeyboardBuffer
->Buffer
[KeyboardBuffer
->BufferHead
].KeyCode
;
1813 UsbKey
->Down
= KeyboardBuffer
->Buffer
[KeyboardBuffer
->BufferHead
].Down
;
1816 // Adjust the head pointer of the FIFO keyboard buffer.
1818 KeyboardBuffer
->BufferHead
= (UINT8
) ((KeyboardBuffer
->BufferHead
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1825 Sets USB Keyboard LED state.
1827 @param UsbKeyboardDevice The USB_KB_DEV instance.
1833 IN USB_KB_DEV
*UsbKeyboardDevice
1840 // Set each field in Led map.
1842 Led
.NumLock
= (UINT8
) UsbKeyboardDevice
->NumLockOn
;
1843 Led
.CapsLock
= (UINT8
) UsbKeyboardDevice
->CapsOn
;
1844 Led
.ScrollLock
= (UINT8
) UsbKeyboardDevice
->ScrollOn
;
1849 // Call Set_Report Request to lighten the LED.
1851 UsbSetReportRequest (
1852 UsbKeyboardDevice
->UsbIo
,
1853 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
1863 Timer handler for Repeat Key timer.
1865 @param Event The Repeat Key event.
1866 @param Context Points to the USB_KB_DEV instance.
1871 USBKeyboardRepeatHandler (
1876 USB_KB_DEV
*UsbKeyboardDevice
;
1878 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1881 // Do nothing when there is no repeat key.
1883 if (UsbKeyboardDevice
->RepeatKey
!= 0) {
1885 // Inserts one Repeat key into keyboard buffer,
1888 &(UsbKeyboardDevice
->KeyboardBuffer
),
1889 UsbKeyboardDevice
->RepeatKey
,
1894 // Set repeate rate for next repeat key generation.
1897 UsbKeyboardDevice
->RepeatTimer
,
1906 Timer handler for Delayed Recovery timer.
1908 @param Event The Delayed Recovery event.
1909 @param Context Points to the USB_KB_DEV instance.
1914 USBKeyboardRecoveryHandler (
1920 USB_KB_DEV
*UsbKeyboardDevice
;
1921 EFI_USB_IO_PROTOCOL
*UsbIo
;
1924 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1926 UsbIo
= UsbKeyboardDevice
->UsbIo
;
1928 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
1931 // Re-submit Asynchronous Interrupt Transfer for recovery.
1933 UsbIo
->UsbAsyncInterruptTransfer (
1935 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
1937 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,