3 Helper functions for USB Keyboard Driver.
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/UsbLib.h>
20 // Static English keyboard layout
21 // Format:<efi key>, <unicode without shift>, <unicode with shift>, <Modifier>, <AffectedAttribute>
24 UINT8 KeyboardLayoutTable
[USB_KEYCODE_MAX_MAKE
+ 8][5] = {
25 {EfiKeyC1
, 'a', 'A', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x04
26 {EfiKeyB5
, 'b', 'B', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x05
27 {EfiKeyB3
, 'c', 'C', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x06
28 {EfiKeyC3
, 'd', 'D', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x07
29 {EfiKeyD3
, 'e', 'E', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x08
30 {EfiKeyC4
, 'f', 'F', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x09
31 {EfiKeyC5
, 'g', 'G', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0A
32 {EfiKeyC6
, 'h', 'H', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0B
33 {EfiKeyD8
, 'i', 'I', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0C
34 {EfiKeyC7
, 'j', 'J', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0D
35 {EfiKeyC8
, 'k', 'K', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0E
36 {EfiKeyC9
, 'l', 'L', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x0F
37 {EfiKeyB7
, 'm', 'M', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x10
38 {EfiKeyB6
, 'n', 'N', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x11
39 {EfiKeyD9
, 'o', 'O', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x12
40 {EfiKeyD10
, 'p', 'P', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x13
41 {EfiKeyD1
, 'q', 'Q', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x14
42 {EfiKeyD4
, 'r', 'R', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x15
43 {EfiKeyC2
, 's', 'S', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x16
44 {EfiKeyD5
, 't', 'T', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x17
45 {EfiKeyD7
, 'u', 'U', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x18
46 {EfiKeyB4
, 'v', 'V', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x19
47 {EfiKeyD2
, 'w', 'W', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1A
48 {EfiKeyB2
, 'x', 'X', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1B
49 {EfiKeyD6
, 'y', 'Y', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1C
50 {EfiKeyB1
, 'z', 'Z', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_CAPS_LOCK
}, // 0x1D
51 {EfiKeyE1
, '1', '!', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1E
52 {EfiKeyE2
, '2', '@', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x1F
53 {EfiKeyE3
, '3', '#', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x20
54 {EfiKeyE4
, '4', '$', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x21
55 {EfiKeyE5
, '5', '%', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x22
56 {EfiKeyE6
, '6', '^', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x23
57 {EfiKeyE7
, '7', '&', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x24
58 {EfiKeyE8
, '8', '*', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x25
59 {EfiKeyE9
, '9', '(', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x26
60 {EfiKeyE10
, '0', ')', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x27
61 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x28 Enter
62 {EfiKeyEsc
, 0x1b, 0x1b, EFI_NULL_MODIFIER
, 0}, // 0x29 Esc
63 {EfiKeyBackSpace
, 0x08, 0x08, EFI_NULL_MODIFIER
, 0}, // 0x2A Backspace
64 {EfiKeyTab
, 0x09, 0x09, EFI_NULL_MODIFIER
, 0}, // 0x2B Tab
65 {EfiKeySpaceBar
, ' ', ' ', EFI_NULL_MODIFIER
, 0}, // 0x2C Spacebar
66 {EfiKeyE11
, '-', '_', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2D
67 {EfiKeyE12
, '=', '+', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2E
68 {EfiKeyD11
, '[', '{', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x2F
69 {EfiKeyD12
, ']', '}', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x30
70 {EfiKeyD13
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x31
71 {EfiKeyC12
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x32 Keyboard Non-US # and ~
72 {EfiKeyC10
, ';', ':', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x33
73 {EfiKeyC11
, '\'', '"', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x34
74 {EfiKeyE0
, '`', '~', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x35 Keyboard Grave Accent and Tlide
75 {EfiKeyB8
, ',', '<', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x36
76 {EfiKeyB9
, '.', '>', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x37
77 {EfiKeyB10
, '/', '?', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x38
78 {EfiKeyCapsLock
, 0x00, 0x00, EFI_CAPS_LOCK_MODIFIER
, 0}, // 0x39 CapsLock
79 {EfiKeyF1
, 0x00, 0x00, EFI_FUNCTION_KEY_ONE_MODIFIER
, 0}, // 0x3A
80 {EfiKeyF2
, 0x00, 0x00, EFI_FUNCTION_KEY_TWO_MODIFIER
, 0}, // 0x3B
81 {EfiKeyF3
, 0x00, 0x00, EFI_FUNCTION_KEY_THREE_MODIFIER
, 0}, // 0x3C
82 {EfiKeyF4
, 0x00, 0x00, EFI_FUNCTION_KEY_FOUR_MODIFIER
, 0}, // 0x3D
83 {EfiKeyF5
, 0x00, 0x00, EFI_FUNCTION_KEY_FIVE_MODIFIER
, 0}, // 0x3E
84 {EfiKeyF6
, 0x00, 0x00, EFI_FUNCTION_KEY_SIX_MODIFIER
, 0}, // 0x3F
85 {EfiKeyF7
, 0x00, 0x00, EFI_FUNCTION_KEY_SEVEN_MODIFIER
, 0}, // 0x40
86 {EfiKeyF8
, 0x00, 0x00, EFI_FUNCTION_KEY_EIGHT_MODIFIER
, 0}, // 0x41
87 {EfiKeyF9
, 0x00, 0x00, EFI_FUNCTION_KEY_NINE_MODIFIER
, 0}, // 0x42
88 {EfiKeyF10
, 0x00, 0x00, EFI_FUNCTION_KEY_TEN_MODIFIER
, 0}, // 0x43
89 {EfiKeyF11
, 0x00, 0x00, EFI_FUNCTION_KEY_ELEVEN_MODIFIER
, 0}, // 0x44 F11
90 {EfiKeyF12
, 0x00, 0x00, EFI_FUNCTION_KEY_TWELVE_MODIFIER
, 0}, // 0x45 F12
91 {EfiKeyPrint
, 0x00, 0x00, EFI_PRINT_MODIFIER
, 0}, // 0x46 PrintScreen
92 {EfiKeySLck
, 0x00, 0x00, EFI_SCROLL_LOCK_MODIFIER
, 0}, // 0x47 Scroll Lock
93 {EfiKeyPause
, 0x00, 0x00, EFI_PAUSE_MODIFIER
, 0}, // 0x48 Pause
94 {EfiKeyIns
, 0x00, 0x00, EFI_INSERT_MODIFIER
, 0}, // 0x49
95 {EfiKeyHome
, 0x00, 0x00, EFI_HOME_MODIFIER
, 0}, // 0x4A
96 {EfiKeyPgUp
, 0x00, 0x00, EFI_PAGE_UP_MODIFIER
, 0}, // 0x4B
97 {EfiKeyDel
, 0x00, 0x00, EFI_DELETE_MODIFIER
, 0}, // 0x4C
98 {EfiKeyEnd
, 0x00, 0x00, EFI_END_MODIFIER
, 0}, // 0x4D
99 {EfiKeyPgDn
, 0x00, 0x00, EFI_PAGE_DOWN_MODIFIER
, 0}, // 0x4E
100 {EfiKeyRightArrow
, 0x00, 0x00, EFI_RIGHT_ARROW_MODIFIER
, 0}, // 0x4F
101 {EfiKeyLeftArrow
, 0x00, 0x00, EFI_LEFT_ARROW_MODIFIER
, 0}, // 0x50
102 {EfiKeyDownArrow
, 0x00, 0x00, EFI_DOWN_ARROW_MODIFIER
, 0}, // 0x51
103 {EfiKeyUpArrow
, 0x00, 0x00, EFI_UP_ARROW_MODIFIER
, 0}, // 0x52
104 {EfiKeyNLck
, 0x00, 0x00, EFI_NUM_LOCK_MODIFIER
, 0}, // 0x53 NumLock
105 {EfiKeySlash
, '/', '/', EFI_NULL_MODIFIER
, 0}, // 0x54
106 {EfiKeyAsterisk
, '*', '*', EFI_NULL_MODIFIER
, 0}, // 0x55
107 {EfiKeyMinus
, '-', '-', EFI_NULL_MODIFIER
, 0}, // 0x56
108 {EfiKeyPlus
, '+', '+', EFI_NULL_MODIFIER
, 0}, // 0x57
109 {EfiKeyEnter
, 0x0d, 0x0d, EFI_NULL_MODIFIER
, 0}, // 0x58
110 {EfiKeyOne
, '1', '1', EFI_END_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x59
111 {EfiKeyTwo
, '2', '2', EFI_DOWN_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5A
112 {EfiKeyThree
, '3', '3', EFI_PAGE_DOWN_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5B
113 {EfiKeyFour
, '4', '4', EFI_LEFT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5C
114 {EfiKeyFive
, '5', '5', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5D
115 {EfiKeySix
, '6', '6', EFI_RIGHT_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5E
116 {EfiKeySeven
, '7', '7', EFI_HOME_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x5F
117 {EfiKeyEight
, '8', '8', EFI_UP_ARROW_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x60
118 {EfiKeyNine
, '9', '9', EFI_PAGE_UP_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x61
119 {EfiKeyZero
, '0', '0', EFI_INSERT_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x62
120 {EfiKeyPeriod
, '.', '.', EFI_DELETE_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
| EFI_AFFECTED_BY_NUM_LOCK
}, // 0x63
121 {EfiKeyB0
, '\\', '|', EFI_NULL_MODIFIER
, EFI_AFFECTED_BY_STANDARD_SHIFT
}, // 0x64 Keyboard Non-US \ and |
122 {EfiKeyA4
, 0x00, 0x00, EFI_MENU_MODIFIER
, 0}, // 0x65 Keyboard Application
124 {EfiKeyLCtrl
, 0, 0, EFI_LEFT_CONTROL_MODIFIER
, 0}, // 0xe0
125 {EfiKeyLShift
, 0, 0, EFI_LEFT_SHIFT_MODIFIER
, 0}, // 0xe1
126 {EfiKeyLAlt
, 0, 0, EFI_LEFT_ALT_MODIFIER
, 0}, // 0xe2
127 {EfiKeyA0
, 0, 0, EFI_LEFT_LOGO_MODIFIER
, 0}, // 0xe3
128 {EfiKeyRCtrl
, 0, 0, EFI_RIGHT_CONTROL_MODIFIER
, 0}, // 0xe4
129 {EfiKeyRShift
, 0, 0, EFI_RIGHT_SHIFT_MODIFIER
, 0}, // 0xe5
130 {EfiKeyA2
, 0, 0, EFI_RIGHT_ALT_MODIFIER
, 0}, // 0xe6
131 {EfiKeyA3
, 0, 0, EFI_RIGHT_LOGO_MODIFIER
, 0}, // 0xe7
135 Initialize KeyConvertionTable by using default keyboard layout.
137 @param UsbKeyboardDevice The USB_KB_DEV instance.
143 LoadDefaultKeyboardLayout (
144 IN USB_KB_DEV
*UsbKeyboardDevice
148 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
151 // Construct KeyConvertionTable by default keyboard layout
153 KeyDescriptor
= &UsbKeyboardDevice
->KeyConvertionTable
[0];
155 for (Index
= 0; Index
< (USB_KEYCODE_MAX_MAKE
+ 8); Index
++) {
156 KeyDescriptor
->Key
= (EFI_KEY
) KeyboardLayoutTable
[Index
][0];
157 KeyDescriptor
->Unicode
= KeyboardLayoutTable
[Index
][1];
158 KeyDescriptor
->ShiftedUnicode
= KeyboardLayoutTable
[Index
][2];
159 KeyDescriptor
->AltGrUnicode
= 0;
160 KeyDescriptor
->ShiftedAltGrUnicode
= 0;
161 KeyDescriptor
->Modifier
= KeyboardLayoutTable
[Index
][3];
162 KeyDescriptor
->AffectedAttribute
= KeyboardLayoutTable
[Index
][4];
169 // EFI_KEY to USB Scan Code convertion table
172 UINT8 UsbScanCodeConvertionTable
[] = {
176 0x2c, // EfiKeySpaceBar
181 0x50, // EfiKeyLeftArrow
182 0x51, // EfiKeyDownArrow
183 0x4F, // EfiKeyRightArrow
185 0x63, // EfiKeyPeriod
187 0xe1, // EfiKeyLShift
199 0xe5, // EfiKeyRShift
200 0x52, // EfiKeyUpArrow
204 0x39, // EfiKeyCapsLock
254 0x2A, // EfiKeyBackSpace
260 0x55, // EfiKeyAsterisk
281 // Keyboard Layout Modifier to EFI Scan Code convertion table
284 UINT8 EfiScanCodeConvertionTable
[] = {
285 SCAN_NULL
, // EFI_NULL_MODIFIER
286 SCAN_NULL
, // EFI_LEFT_CONTROL_MODIFIER
287 SCAN_NULL
, // EFI_RIGHT_CONTROL_MODIFIER
288 SCAN_NULL
, // EFI_LEFT_ALT_MODIFIER
289 SCAN_NULL
, // EFI_RIGHT_ALT_MODIFIER
290 SCAN_NULL
, // EFI_ALT_GR_MODIFIER
291 SCAN_INSERT
, // EFI_INSERT_MODIFIER
292 SCAN_DELETE
, // EFI_DELETE_MODIFIER
293 SCAN_PAGE_DOWN
, // EFI_PAGE_DOWN_MODIFIER
294 SCAN_PAGE_UP
, // EFI_PAGE_UP_MODIFIER
295 SCAN_HOME
, // EFI_HOME_MODIFIER
296 SCAN_END
, // EFI_END_MODIFIER
297 SCAN_NULL
, // EFI_LEFT_SHIFT_MODIFIER
298 SCAN_NULL
, // EFI_RIGHT_SHIFT_MODIFIER
299 SCAN_NULL
, // EFI_CAPS_LOCK_MODIFIER
300 SCAN_NULL
, // EFI_NUM_LOCK_MODIFIER
301 SCAN_LEFT
, // EFI_LEFT_ARROW_MODIFIER
302 SCAN_RIGHT
, // EFI_RIGHT_ARROW_MODIFIER
303 SCAN_DOWN
, // EFI_DOWN_ARROW_MODIFIER
304 SCAN_UP
, // EFI_UP_ARROW_MODIFIER
305 SCAN_NULL
, // EFI_NS_KEY_MODIFIER
306 SCAN_NULL
, // EFI_NS_KEY_DEPENDENCY_MODIFIER
307 SCAN_F1
, // EFI_FUNCTION_KEY_ONE_MODIFIER
308 SCAN_F2
, // EFI_FUNCTION_KEY_TWO_MODIFIER
309 SCAN_F3
, // EFI_FUNCTION_KEY_THREE_MODIFIER
310 SCAN_F4
, // EFI_FUNCTION_KEY_FOUR_MODIFIER
311 SCAN_F5
, // EFI_FUNCTION_KEY_FIVE_MODIFIER
312 SCAN_F6
, // EFI_FUNCTION_KEY_SIX_MODIFIER
313 SCAN_F7
, // EFI_FUNCTION_KEY_SEVEN_MODIFIER
314 SCAN_F8
, // EFI_FUNCTION_KEY_EIGHT_MODIFIER
315 SCAN_F9
, // EFI_FUNCTION_KEY_NINE_MODIFIER
316 SCAN_F10
, // EFI_FUNCTION_KEY_TEN_MODIFIER
317 SCAN_F11
, // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
318 SCAN_F12
, // EFI_FUNCTION_KEY_TWELVE_MODIFIER
321 EFI_GUID mKeyboardLayoutEventGuid
= EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
;
324 STATIC KB_MODIFIER KB_Mod
[8] = {
325 { MOD_CONTROL_L
, 0xe0 }, // 11100000
326 { MOD_CONTROL_R
, 0xe4 }, // 11100100
327 { MOD_SHIFT_L
, 0xe1 }, // 11100001
328 { MOD_SHIFT_R
, 0xe5 }, // 11100101
329 { MOD_ALT_L
, 0xe2 }, // 11100010
330 { MOD_ALT_R
, 0xe6 }, // 11100110
331 { MOD_WIN_L
, 0xe3 }, // 11100011
332 { MOD_WIN_R
, 0xe7 }, // 11100111
338 Uses USB I/O to check whether the device is a USB Keyboard device.
340 @param UsbIo Points to a USB I/O protocol instance.
347 IN EFI_USB_IO_PROTOCOL
*UsbIo
351 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
354 // Get the Default interface descriptor, currently we
355 // assume it is interface 1
357 Status
= UsbIo
->UsbGetInterfaceDescriptor (
362 if (EFI_ERROR (Status
)) {
366 if (InterfaceDescriptor
.InterfaceClass
== CLASS_HID
&&
367 InterfaceDescriptor
.InterfaceSubClass
== SUBCLASS_BOOT
&&
368 InterfaceDescriptor
.InterfaceProtocol
== PROTOCOL_KEYBOARD
378 Get current keyboard layout from HII database.
380 @retval Pointer to EFI_HII_KEYBOARD_LAYOUT.
383 EFI_HII_KEYBOARD_LAYOUT
*
385 GetCurrentKeyboardLayout (
390 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
391 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
395 // Locate Hii database protocol
397 Status
= gBS
->LocateProtocol (
398 &gEfiHiiDatabaseProtocolGuid
,
400 (VOID
**) &HiiDatabase
402 if (EFI_ERROR (Status
)) {
407 // Get current keyboard layout from HII database
410 KeyboardLayout
= NULL
;
411 Status
= HiiDatabase
->GetKeyboardLayout (
417 if (Status
== EFI_BUFFER_TOO_SMALL
) {
418 KeyboardLayout
= AllocatePool (Length
);
419 ASSERT (KeyboardLayout
!= NULL
);
421 Status
= HiiDatabase
->GetKeyboardLayout (
427 if (EFI_ERROR (Status
)) {
428 gBS
->FreePool (KeyboardLayout
);
429 KeyboardLayout
= NULL
;
433 return KeyboardLayout
;
437 Find Key Descriptor in KeyConvertionTable given its scan code.
439 @param UsbKeyboardDevice The USB_KB_DEV instance.
440 @param ScanCode USB scan code.
442 @return The Key descriptor in KeyConvertionTable.
448 IN USB_KB_DEV
*UsbKeyboardDevice
,
454 if (((ScanCode
> 0x65) && (ScanCode
< 0xe0)) || (ScanCode
> 0xe7)) {
458 if (ScanCode
<= 0x65) {
459 Index
= (UINT8
) (ScanCode
- 4);
461 Index
= (UINT8
) (ScanCode
- 0xe0 + USB_KEYCODE_MAX_MAKE
);
464 return &UsbKeyboardDevice
->KeyConvertionTable
[Index
];
468 Find Non-Spacing key for given KeyDescriptor.
470 @param UsbKeyboardDevice The USB_KB_DEV instance.
471 @param KeyDescriptor Key descriptor.
473 @retval NULL Key list is empty.
474 @return Other The Non-Spacing key.
480 IN USB_KB_DEV
*UsbKeyboardDevice
,
481 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
485 USB_NS_KEY
*UsbNsKey
;
487 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
488 while (!IsNull (&UsbKeyboardDevice
->NsKeyList
, Link
)) {
489 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
491 if (UsbNsKey
->NsKey
[0].Key
== KeyDescriptor
->Key
) {
495 Link
= GetNextNode (&UsbKeyboardDevice
->NsKeyList
, Link
);
502 Find physical key definition for a given Key stroke.
504 @param UsbNsKey The Non-Spacing key information.
505 @param KeyDescriptor The key stroke.
507 @return The physical key definition.
513 IN USB_NS_KEY
*UsbNsKey
,
514 IN EFI_KEY_DESCRIPTOR
*KeyDescriptor
518 EFI_KEY_DESCRIPTOR
*PhysicalKey
;
520 PhysicalKey
= &UsbNsKey
->NsKey
[1];
521 for (Index
= 0; Index
< UsbNsKey
->KeyCount
; Index
++) {
522 if (KeyDescriptor
->Key
== PhysicalKey
->Key
) {
530 // No children definition matched, return original key
532 return KeyDescriptor
;
536 The notification function for SET_KEYBOARD_LAYOUT_EVENT.
538 @param Event The instance of EFI_EVENT.
539 @param Context passing parameter.
544 SetKeyboardLayoutEvent (
549 USB_KB_DEV
*UsbKeyboardDevice
;
550 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
551 EFI_KEY_DESCRIPTOR TempKey
;
552 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
553 EFI_KEY_DESCRIPTOR
*TableEntry
;
554 EFI_KEY_DESCRIPTOR
*NsKey
;
555 USB_NS_KEY
*UsbNsKey
;
561 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
564 // Try to get current Keyboard Layout from HII database
566 KeyboardLayout
= GetCurrentKeyboardLayout ();
567 if (KeyboardLayout
== NULL
) {
572 // Allocate resource for KeyConvertionTable
574 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
575 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
576 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
578 KeyDescriptor
= (EFI_KEY_DESCRIPTOR
*) (((UINT8
*) KeyboardLayout
) + sizeof (EFI_HII_KEYBOARD_LAYOUT
));
579 for (Index
= 0; Index
< KeyboardLayout
->DescriptorCount
; Index
++) {
581 // Copy from HII keyboard layout package binary for alignment
583 CopyMem (&TempKey
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
586 // Fill the key into KeyConvertionTable (which use USB Scan Code as index)
588 ScanCode
= UsbScanCodeConvertionTable
[(UINT8
) (TempKey
.Key
)];
589 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, ScanCode
);
590 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
592 if (TempKey
.Modifier
== EFI_NS_KEY_MODIFIER
) {
596 UsbNsKey
= AllocatePool (sizeof (USB_NS_KEY
));
597 ASSERT (UsbNsKey
!= NULL
);
600 // Search for sequential children physical key definitions
603 NsKey
= KeyDescriptor
+ 1;
604 for (Index2
= Index
+ 1; Index2
< KeyboardLayout
->DescriptorCount
; Index2
++) {
605 CopyMem (&TempKey
, NsKey
, sizeof (EFI_KEY_DESCRIPTOR
));
606 if (TempKey
.Modifier
& EFI_NS_KEY_DEPENDENCY_MODIFIER
) {
614 UsbNsKey
->Signature
= USB_NS_KEY_SIGNATURE
;
615 UsbNsKey
->KeyCount
= KeyCount
;
616 UsbNsKey
->NsKey
= AllocateCopyPool (
617 (KeyCount
+ 1) * sizeof (EFI_KEY_DESCRIPTOR
),
620 InsertTailList (&UsbKeyboardDevice
->NsKeyList
, &UsbNsKey
->Link
);
623 // Skip over the child physical keys
626 KeyDescriptor
+= KeyCount
;
633 // There are two EfiKeyEnter, duplicate its Key Descriptor
635 TableEntry
= GetKeyDescriptor (UsbKeyboardDevice
, 0x58);
636 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, 0x28);
637 CopyMem (TableEntry
, KeyDescriptor
, sizeof (EFI_KEY_DESCRIPTOR
));
639 gBS
->FreePool (KeyboardLayout
);
643 Destroy resources for Keyboard layout.
645 @param UsbKeyboardDevice The USB_KB_DEV instance.
650 ReleaseKeyboardLayoutResources (
651 IN USB_KB_DEV
*UsbKeyboardDevice
654 USB_NS_KEY
*UsbNsKey
;
657 SafeFreePool (UsbKeyboardDevice
->KeyConvertionTable
);
658 UsbKeyboardDevice
->KeyConvertionTable
= NULL
;
660 while (!IsListEmpty (&UsbKeyboardDevice
->NsKeyList
)) {
661 Link
= GetFirstNode (&UsbKeyboardDevice
->NsKeyList
);
662 UsbNsKey
= USB_NS_KEY_FORM_FROM_LINK (Link
);
663 RemoveEntryList (&UsbNsKey
->Link
);
665 gBS
->FreePool (UsbNsKey
->NsKey
);
666 gBS
->FreePool (UsbNsKey
);
671 Initialize USB Keyboard layout.
673 @param UsbKeyboardDevice The USB_KB_DEV instance.
675 @retval EFI_SUCCESS Initialization Success.
676 @retval Other Keyboard layout initial failed.
682 IN USB_KB_DEV
*UsbKeyboardDevice
685 EFI_HII_KEYBOARD_LAYOUT
*KeyboardLayout
;
688 UsbKeyboardDevice
->KeyConvertionTable
= AllocateZeroPool ((USB_KEYCODE_MAX_MAKE
+ 8) * sizeof (EFI_KEY_DESCRIPTOR
));
689 ASSERT (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
);
691 InitializeListHead (&UsbKeyboardDevice
->NsKeyList
);
692 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
693 UsbKeyboardDevice
->KeyboardLayoutEvent
= NULL
;
696 // Register SET_KEYBOARD_LAYOUT_EVENT notification
698 Status
= gBS
->CreateEventEx (
699 EFI_EVENT_NOTIFY_SIGNAL
,
701 SetKeyboardLayoutEvent
,
703 &mKeyboardLayoutEventGuid
,
704 &UsbKeyboardDevice
->KeyboardLayoutEvent
706 if (EFI_ERROR (Status
)) {
711 // Try to get current keyboard layout from HII database
713 KeyboardLayout
= GetCurrentKeyboardLayout ();
714 if (KeyboardLayout
!= NULL
) {
716 // Force to initialize the keyboard layout
718 gBS
->SignalEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
720 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver
)) {
721 return EFI_NOT_READY
;
725 // Fail to get keyboard layout from HII database,
726 // use default keyboard layout
728 LoadDefaultKeyboardLayout (UsbKeyboardDevice
);
737 Initialize USB Keyboard device and all private data structures.
739 @param UsbKeyboardDevice The USB_KB_DEV instance.
741 @retval EFI_SUCCESS Initialization is successful.
742 @retval EFI_DEVICE_ERROR Configure hardware failed.
748 IN USB_KB_DEV
*UsbKeyboardDevice
756 UINT32 TransferResult
;
758 KbdReportStatusCode (
759 UsbKeyboardDevice
->DevicePath
,
761 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest
)
764 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
767 // default configurations
772 // Uses default configuration to configure the USB Keyboard device.
774 Status
= UsbSetConfiguration (
775 UsbKeyboardDevice
->UsbIo
,
776 (UINT16
) ConfigValue
,
779 if (EFI_ERROR (Status
)) {
781 // If configuration could not be set here, it means
782 // the keyboard interface has some errors and could
783 // not be initialized
785 KbdReportStatusCode (
786 UsbKeyboardDevice
->DevicePath
,
787 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
788 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError
)
791 return EFI_DEVICE_ERROR
;
794 UsbGetProtocolRequest (
795 UsbKeyboardDevice
->UsbIo
,
796 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
800 // Sets boot protocol for the USB Keyboard.
801 // This driver only supports boot protocol.
802 // !!BugBug: How about the device that does not support boot protocol?
804 if (Protocol
!= BOOT_PROTOCOL
) {
805 UsbSetProtocolRequest (
806 UsbKeyboardDevice
->UsbIo
,
807 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
812 // the duration is indefinite, so the endpoint will inhibit reporting forever,
813 // and only reporting when a change is detected in the report data.
817 // idle value for all report ID
821 // idle forever until there is a key pressed and released.
825 UsbKeyboardDevice
->UsbIo
,
826 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
831 UsbKeyboardDevice
->CtrlOn
= 0;
832 UsbKeyboardDevice
->AltOn
= 0;
833 UsbKeyboardDevice
->ShiftOn
= 0;
834 UsbKeyboardDevice
->NumLockOn
= 0;
835 UsbKeyboardDevice
->CapsOn
= 0;
836 UsbKeyboardDevice
->ScrollOn
= 0;
838 UsbKeyboardDevice
->LeftCtrlOn
= 0;
839 UsbKeyboardDevice
->LeftAltOn
= 0;
840 UsbKeyboardDevice
->LeftShiftOn
= 0;
841 UsbKeyboardDevice
->LeftLogoOn
= 0;
842 UsbKeyboardDevice
->RightCtrlOn
= 0;
843 UsbKeyboardDevice
->RightAltOn
= 0;
844 UsbKeyboardDevice
->RightShiftOn
= 0;
845 UsbKeyboardDevice
->RightLogoOn
= 0;
846 UsbKeyboardDevice
->MenuKeyOn
= 0;
847 UsbKeyboardDevice
->SysReqOn
= 0;
849 UsbKeyboardDevice
->AltGrOn
= 0;
851 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
854 // Sync the initial state of lights
856 SetKeyLED (UsbKeyboardDevice
);
858 ZeroMem (UsbKeyboardDevice
->LastKeyCodeArray
, sizeof (UINT8
) * 8);
861 // Set a timer for repeat keys' generation.
863 if (UsbKeyboardDevice
->RepeatTimer
!= NULL
) {
864 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
865 UsbKeyboardDevice
->RepeatTimer
= 0;
868 Status
= gBS
->CreateEvent (
869 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
871 USBKeyboardRepeatHandler
,
873 &UsbKeyboardDevice
->RepeatTimer
876 if (UsbKeyboardDevice
->DelayedRecoveryEvent
!= NULL
) {
877 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
878 UsbKeyboardDevice
->DelayedRecoveryEvent
= 0;
881 Status
= gBS
->CreateEvent (
882 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
884 USBKeyboardRecoveryHandler
,
886 &UsbKeyboardDevice
->DelayedRecoveryEvent
894 Handler function for USB Keyboard's asynchronous interrupt transfer.
896 @param Data A pointer to a buffer that is filled with key data which is
897 retrieved via asynchronous interrupt transfer.
898 @param DataLength Indicates the size of the data buffer.
899 @param Context Pointing to USB_KB_DEV instance.
900 @param Result Indicates the result of the asynchronous interrupt transfer.
902 @retval EFI_SUCCESS Handler is successful.
903 @retval EFI_DEVICE_ERROR Hardware Error
915 USB_KB_DEV
*UsbKeyboardDevice
;
916 EFI_USB_IO_PROTOCOL
*UsbIo
;
917 UINT8
*CurKeyCodeBuffer
;
918 UINT8
*OldKeyCodeBuffer
;
919 UINT8 CurModifierMap
;
920 UINT8 OldModifierMap
;
930 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
935 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
936 UsbIo
= UsbKeyboardDevice
->UsbIo
;
939 // Analyzes the Result and performs corresponding action.
941 if (Result
!= EFI_USB_NOERROR
) {
943 // Some errors happen during the process
945 KbdReportStatusCode (
946 UsbKeyboardDevice
->DevicePath
,
947 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
948 PcdGet32 (PcdStatusCodeValueKeyboardInputError
)
952 // stop the repeat key generation if any
954 UsbKeyboardDevice
->RepeatKey
= 0;
957 UsbKeyboardDevice
->RepeatTimer
,
962 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
963 UsbClearEndpointHalt (
965 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
971 // Delete & Submit this interrupt again
974 UsbIo
->UsbAsyncInterruptTransfer (
976 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
985 UsbKeyboardDevice
->DelayedRecoveryEvent
,
987 EFI_USB_INTERRUPT_DELAY
990 return EFI_DEVICE_ERROR
;
993 if (DataLength
== 0 || Data
== NULL
) {
997 CurKeyCodeBuffer
= (UINT8
*) Data
;
998 OldKeyCodeBuffer
= UsbKeyboardDevice
->LastKeyCodeArray
;
1001 // checks for new key stroke.
1002 // if no new key got, return immediately.
1004 for (Index
= 0; Index
< 8; Index
++) {
1005 if (OldKeyCodeBuffer
[Index
] != CurKeyCodeBuffer
[Index
]) {
1015 // Parse the modifier key
1017 CurModifierMap
= CurKeyCodeBuffer
[0];
1018 OldModifierMap
= OldKeyCodeBuffer
[0];
1021 // handle modifier key's pressing or releasing situation.
1023 for (Index
= 0; Index
< 8; Index
++) {
1025 if ((CurModifierMap
& KB_Mod
[Index
].Mask
) != (OldModifierMap
& KB_Mod
[Index
].Mask
)) {
1027 // if current modifier key is up, then
1028 // CurModifierMap & KB_Mod[Index].Mask = 0;
1029 // otherwize it is a non-zero value.
1030 // Inserts the pressed modifier key into key buffer.
1032 Down
= (UINT8
) (CurModifierMap
& KB_Mod
[Index
].Mask
);
1033 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), KB_Mod
[Index
].Key
, Down
);
1038 // handle normal key's releasing situation
1041 for (Index
= 2; Index
< 8; Index
++) {
1043 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index
])) {
1048 for (Index2
= 2; Index2
< 8; Index2
++) {
1050 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index2
])) {
1054 if (OldKeyCodeBuffer
[Index
] == CurKeyCodeBuffer
[Index2
]) {
1062 &(UsbKeyboardDevice
->KeyboardBuffer
),
1063 OldKeyCodeBuffer
[Index
],
1067 // the original reapeat key is released.
1069 if (OldKeyCodeBuffer
[Index
] == UsbKeyboardDevice
->RepeatKey
) {
1070 UsbKeyboardDevice
->RepeatKey
= 0;
1076 // original repeat key is released, cancel the repeat timer
1078 if (UsbKeyboardDevice
->RepeatKey
== 0) {
1080 UsbKeyboardDevice
->RepeatTimer
,
1087 // handle normal key's pressing situation
1090 for (Index
= 2; Index
< 8; Index
++) {
1092 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer
[Index
])) {
1097 for (Index2
= 2; Index2
< 8; Index2
++) {
1099 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer
[Index2
])) {
1103 if (CurKeyCodeBuffer
[Index
] == OldKeyCodeBuffer
[Index2
]) {
1110 InsertKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), CurKeyCodeBuffer
[Index
], 1);
1112 // NumLock pressed or CapsLock pressed
1114 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, CurKeyCodeBuffer
[Index
]);
1115 if (KeyDescriptor
->Modifier
== EFI_NUM_LOCK_MODIFIER
|| KeyDescriptor
->Modifier
== EFI_CAPS_LOCK_MODIFIER
) {
1116 UsbKeyboardDevice
->RepeatKey
= 0;
1118 NewRepeatKey
= CurKeyCodeBuffer
[Index
];
1120 // do not repeat the original repeated key
1122 UsbKeyboardDevice
->RepeatKey
= 0;
1128 // Update LastKeycodeArray[] buffer in the
1129 // Usb Keyboard Device data structure.
1131 for (Index
= 0; Index
< 8; Index
++) {
1132 UsbKeyboardDevice
->LastKeyCodeArray
[Index
] = CurKeyCodeBuffer
[Index
];
1136 // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence
1137 // and judge whether it will invoke reset event.
1139 SavedTail
= UsbKeyboardDevice
->KeyboardBuffer
.bTail
;
1140 Index
= UsbKeyboardDevice
->KeyboardBuffer
.bHead
;
1141 while (Index
!= SavedTail
) {
1142 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1144 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1146 switch (KeyDescriptor
->Modifier
) {
1148 case EFI_LEFT_CONTROL_MODIFIER
:
1149 case EFI_RIGHT_CONTROL_MODIFIER
:
1150 if (UsbKey
.Down
!= 0) {
1151 UsbKeyboardDevice
->CtrlOn
= 1;
1153 UsbKeyboardDevice
->CtrlOn
= 0;
1157 case EFI_LEFT_ALT_MODIFIER
:
1158 case EFI_RIGHT_ALT_MODIFIER
:
1159 if (UsbKey
.Down
!= 0) {
1160 UsbKeyboardDevice
->AltOn
= 1;
1162 UsbKeyboardDevice
->AltOn
= 0;
1166 case EFI_ALT_GR_MODIFIER
:
1167 if (UsbKey
.Down
!= 0) {
1168 UsbKeyboardDevice
->AltGrOn
= 1;
1170 UsbKeyboardDevice
->AltGrOn
= 0;
1177 case EFI_DELETE_MODIFIER
:
1178 if (UsbKey
.Down
!= 0) {
1179 if ((UsbKeyboardDevice
->CtrlOn
!= 0) && (UsbKeyboardDevice
->AltOn
!= 0)) {
1180 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1190 // insert the key back to the buffer.
1191 // so the key sequence will not be destroyed.
1194 &(UsbKeyboardDevice
->KeyboardBuffer
),
1198 Index
= UsbKeyboardDevice
->KeyboardBuffer
.bHead
;
1202 // If have new key pressed, update the RepeatKey value, and set the
1203 // timer to repeate delay timer
1205 if (NewRepeatKey
!= 0) {
1207 // sets trigger time to "Repeat Delay Time",
1208 // to trigger the repeat timer when the key is hold long
1212 UsbKeyboardDevice
->RepeatTimer
,
1216 UsbKeyboardDevice
->RepeatKey
= NewRepeatKey
;
1224 Retrieves a key character after parsing the raw data in keyboard buffer.
1226 @param UsbKeyboardDevice The USB_KB_DEV instance.
1227 @param KeyChar Points to the Key character after key parsing.
1229 @retval EFI_SUCCESS Parse key is successful.
1230 @retval EFI_NOT_READY Device is not ready.
1236 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
1241 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1245 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice
->KeyboardBuffer
)) {
1247 // pops one raw data off.
1249 RemoveKeyCode (&(UsbKeyboardDevice
->KeyboardBuffer
), &UsbKey
);
1251 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, UsbKey
.KeyCode
);
1252 if (UsbKey
.Down
== 0) {
1253 switch (KeyDescriptor
->Modifier
) {
1258 case EFI_LEFT_CONTROL_MODIFIER
:
1259 UsbKeyboardDevice
->LeftCtrlOn
= 0;
1260 UsbKeyboardDevice
->CtrlOn
= 0;
1262 case EFI_RIGHT_CONTROL_MODIFIER
:
1263 UsbKeyboardDevice
->RightCtrlOn
= 0;
1264 UsbKeyboardDevice
->CtrlOn
= 0;
1270 case EFI_LEFT_SHIFT_MODIFIER
:
1271 UsbKeyboardDevice
->LeftShiftOn
= 0;
1272 UsbKeyboardDevice
->ShiftOn
= 0;
1274 case EFI_RIGHT_SHIFT_MODIFIER
:
1275 UsbKeyboardDevice
->RightShiftOn
= 0;
1276 UsbKeyboardDevice
->ShiftOn
= 0;
1282 case EFI_LEFT_ALT_MODIFIER
:
1283 UsbKeyboardDevice
->LeftAltOn
= 0;
1284 UsbKeyboardDevice
->AltOn
= 0;
1286 case EFI_RIGHT_ALT_MODIFIER
:
1287 UsbKeyboardDevice
->RightAltOn
= 0;
1288 UsbKeyboardDevice
->AltOn
= 0;
1292 // Left Logo release
1294 case EFI_LEFT_LOGO_MODIFIER
:
1295 UsbKeyboardDevice
->LeftLogoOn
= 0;
1299 // Right Logo release
1301 case EFI_RIGHT_LOGO_MODIFIER
:
1302 UsbKeyboardDevice
->RightLogoOn
= 0;
1308 case EFI_MENU_MODIFIER
:
1309 UsbKeyboardDevice
->MenuKeyOn
= 0;
1315 case EFI_PRINT_MODIFIER
:
1316 case EFI_SYS_REQUEST_MODIFIER
:
1317 UsbKeyboardDevice
->SysReqOn
= 0;
1323 case EFI_ALT_GR_MODIFIER
:
1324 UsbKeyboardDevice
->AltGrOn
= 0;
1335 // Analyzes key pressing situation
1337 switch (KeyDescriptor
->Modifier
) {
1342 case EFI_LEFT_CONTROL_MODIFIER
:
1343 UsbKeyboardDevice
->LeftCtrlOn
= 1;
1344 UsbKeyboardDevice
->CtrlOn
= 1;
1347 case EFI_RIGHT_CONTROL_MODIFIER
:
1348 UsbKeyboardDevice
->RightCtrlOn
= 1;
1349 UsbKeyboardDevice
->CtrlOn
= 1;
1356 case EFI_LEFT_SHIFT_MODIFIER
:
1357 UsbKeyboardDevice
->LeftShiftOn
= 1;
1358 UsbKeyboardDevice
->ShiftOn
= 1;
1361 case EFI_RIGHT_SHIFT_MODIFIER
:
1362 UsbKeyboardDevice
->RightShiftOn
= 1;
1363 UsbKeyboardDevice
->ShiftOn
= 1;
1370 case EFI_LEFT_ALT_MODIFIER
:
1371 UsbKeyboardDevice
->LeftAltOn
= 1;
1372 UsbKeyboardDevice
->AltOn
= 1;
1375 case EFI_RIGHT_ALT_MODIFIER
:
1376 UsbKeyboardDevice
->RightAltOn
= 1;
1377 UsbKeyboardDevice
->AltOn
= 1;
1384 case EFI_LEFT_LOGO_MODIFIER
:
1385 UsbKeyboardDevice
->LeftLogoOn
= 1;
1391 case EFI_RIGHT_LOGO_MODIFIER
:
1392 UsbKeyboardDevice
->RightLogoOn
= 1;
1398 case EFI_MENU_MODIFIER
:
1399 UsbKeyboardDevice
->MenuKeyOn
= 1;
1405 case EFI_PRINT_MODIFIER
:
1406 case EFI_SYS_REQUEST_MODIFIER
:
1407 UsbKeyboardDevice
->SysReqOn
= 1;
1414 case EFI_ALT_GR_MODIFIER
:
1415 UsbKeyboardDevice
->AltGrOn
= 1;
1418 case EFI_NUM_LOCK_MODIFIER
:
1419 UsbKeyboardDevice
->NumLockOn
^= 1;
1421 // Turn on the NumLock light on KB
1423 SetKeyLED (UsbKeyboardDevice
);
1427 case EFI_CAPS_LOCK_MODIFIER
:
1428 UsbKeyboardDevice
->CapsOn
^= 1;
1430 // Turn on the CapsLock light on KB
1432 SetKeyLED (UsbKeyboardDevice
);
1436 case EFI_SCROLL_LOCK_MODIFIER
:
1437 UsbKeyboardDevice
->ScrollOn
^= 1;
1439 // Turn on the ScrollLock light on KB
1441 SetKeyLED (UsbKeyboardDevice
);
1446 // F11,F12,PrintScreen,Pause/Break
1447 // could not be retrieved via SimpleTxtInEx protocol
1449 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER
:
1450 case EFI_FUNCTION_KEY_TWELVE_MODIFIER
:
1451 case EFI_PAUSE_MODIFIER
:
1452 case EFI_BREAK_MODIFIER
:
1464 // When encountered Del Key...
1466 if (KeyDescriptor
->Modifier
== EFI_DELETE_MODIFIER
) {
1467 if ((UsbKeyboardDevice
->CtrlOn
!= 0) && (UsbKeyboardDevice
->AltOn
!= 0)) {
1468 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1472 *KeyChar
= UsbKey
.KeyCode
;
1476 return EFI_NOT_READY
;
1481 Converts USB Keyboard code to EFI Scan Code.
1483 @param UsbKeyboardDevice The USB_KB_DEV instance.
1484 @param KeyChar Indicates the key code that will be interpreted.
1485 @param Key A pointer to a buffer that is filled in with
1486 the keystroke information for the key that
1489 @retval EFI_NOT_READY Device is not ready
1490 @retval EFI_SUCCESS Success.
1495 USBKeyCodeToEFIScanCode (
1496 IN USB_KB_DEV
*UsbKeyboardDevice
,
1498 OUT EFI_INPUT_KEY
*Key
1502 EFI_KEY_DESCRIPTOR
*KeyDescriptor
;
1504 if (!USBKBD_VALID_KEYCODE (KeyChar
)) {
1505 return EFI_NOT_READY
;
1509 // valid USB Key Code starts from 4
1511 Index
= (UINT8
) (KeyChar
- 4);
1513 if (Index
>= USB_KEYCODE_MAX_MAKE
) {
1514 return EFI_NOT_READY
;
1517 KeyDescriptor
= GetKeyDescriptor (UsbKeyboardDevice
, KeyChar
);
1520 // Check for Non-spacing key
1522 if (KeyDescriptor
->Modifier
== EFI_NS_KEY_MODIFIER
) {
1523 UsbKeyboardDevice
->CurrentNsKey
= FindUsbNsKey (UsbKeyboardDevice
, KeyDescriptor
);
1524 return EFI_NOT_READY
;
1528 // Check whether this keystroke follows a Non-spacing key
1530 if (UsbKeyboardDevice
->CurrentNsKey
!= NULL
) {
1531 KeyDescriptor
= FindPhysicalKey (UsbKeyboardDevice
->CurrentNsKey
, KeyDescriptor
);
1532 UsbKeyboardDevice
->CurrentNsKey
= NULL
;
1535 Key
->ScanCode
= EfiScanCodeConvertionTable
[KeyDescriptor
->Modifier
];
1536 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1538 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_STANDARD_SHIFT
) {
1539 if (UsbKeyboardDevice
->ShiftOn
!= 0) {
1540 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1543 // Need not return associated shift state if a class of printable characters that
1544 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1546 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) {
1547 UsbKeyboardDevice
->LeftShiftOn
= 0;
1548 UsbKeyboardDevice
->RightShiftOn
= 0;
1551 if (UsbKeyboardDevice
->AltGrOn
!= 0) {
1552 Key
->UnicodeChar
= KeyDescriptor
->ShiftedAltGrUnicode
;
1558 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1560 if (UsbKeyboardDevice
->AltGrOn
!= 0) {
1561 Key
->UnicodeChar
= KeyDescriptor
->AltGrUnicode
;
1566 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_CAPS_LOCK
) {
1567 if (UsbKeyboardDevice
->CapsOn
!= 0) {
1569 if (Key
->UnicodeChar
== KeyDescriptor
->Unicode
) {
1571 Key
->UnicodeChar
= KeyDescriptor
->ShiftedUnicode
;
1573 } else if (Key
->UnicodeChar
== KeyDescriptor
->ShiftedUnicode
) {
1575 Key
->UnicodeChar
= KeyDescriptor
->Unicode
;
1582 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1584 if (UsbKeyboardDevice
->CtrlOn
!= 0) {
1585 if (Key
->UnicodeChar
>= 'a' && Key
->UnicodeChar
<= 'z') {
1586 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'a' + 1);
1587 } else if (Key
->UnicodeChar
>= 'A' && Key
->UnicodeChar
<= 'Z') {
1588 Key
->UnicodeChar
= (UINT8
) (Key
->UnicodeChar
- 'A' + 1);
1592 if (KeyDescriptor
->AffectedAttribute
& EFI_AFFECTED_BY_NUM_LOCK
) {
1594 if ((UsbKeyboardDevice
->NumLockOn
!= 0) && (UsbKeyboardDevice
->ShiftOn
== 0)) {
1596 Key
->ScanCode
= SCAN_NULL
;
1599 Key
->UnicodeChar
= 0x00;
1604 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1606 if (Key
->UnicodeChar
== 0x1B && Key
->ScanCode
== SCAN_NULL
) {
1607 Key
->ScanCode
= SCAN_ESC
;
1608 Key
->UnicodeChar
= 0x00;
1611 if (Key
->UnicodeChar
== 0 && Key
->ScanCode
== SCAN_NULL
) {
1612 return EFI_NOT_READY
;
1617 // Save Shift/Toggle state
1619 if (UsbKeyboardDevice
->LeftCtrlOn
== 1) {
1620 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
1622 if (UsbKeyboardDevice
->RightCtrlOn
== 1) {
1623 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
1625 if (UsbKeyboardDevice
->LeftAltOn
== 1) {
1626 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
1628 if (UsbKeyboardDevice
->RightAltOn
== 1) {
1629 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_ALT_PRESSED
;
1631 if (UsbKeyboardDevice
->LeftShiftOn
== 1) {
1632 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1634 if (UsbKeyboardDevice
->RightShiftOn
== 1) {
1635 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1637 if (UsbKeyboardDevice
->LeftLogoOn
== 1) {
1638 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
1640 if (UsbKeyboardDevice
->RightLogoOn
== 1) {
1641 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
1643 if (UsbKeyboardDevice
->MenuKeyOn
== 1) {
1644 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_MENU_KEY_PRESSED
;
1646 if (UsbKeyboardDevice
->SysReqOn
== 1) {
1647 UsbKeyboardDevice
->KeyState
.KeyShiftState
|= EFI_SYS_REQ_PRESSED
;
1650 if (UsbKeyboardDevice
->ScrollOn
== 1) {
1651 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1653 if (UsbKeyboardDevice
->NumLockOn
== 1) {
1654 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1656 if (UsbKeyboardDevice
->CapsOn
== 1) {
1657 UsbKeyboardDevice
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1666 Resets USB Keyboard Buffer.
1668 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1670 @retval EFI_SUCCESS Init key buffer successfully.
1676 IN OUT USB_KB_BUFFER
*KeyboardBuffer
1679 ZeroMem (KeyboardBuffer
, sizeof (USB_KB_BUFFER
));
1681 KeyboardBuffer
->bHead
= KeyboardBuffer
->bTail
;
1688 Check whether USB Keyboard buffer is empty.
1690 @param KeyboardBuffer USB Keyboard Buffer.
1692 @retval TRUE Key buffer is empty.
1693 @retval FALSE Key buffer is not empty.
1698 IsUSBKeyboardBufferEmpty (
1699 IN USB_KB_BUFFER
*KeyboardBuffer
1703 // meet FIFO empty condition
1705 return (BOOLEAN
) (KeyboardBuffer
->bHead
== KeyboardBuffer
->bTail
);
1710 Check whether USB Keyboard buffer is full.
1712 @param KeyboardBuffer USB Keyboard Buffer.
1714 @retval TRUE Key buffer is full.
1715 @retval FALSE Key buffer is not full.
1720 IsUSBKeyboardBufferFull (
1721 IN USB_KB_BUFFER
*KeyboardBuffer
1724 return (BOOLEAN
)(((KeyboardBuffer
->bTail
+ 1) % (MAX_KEY_ALLOWED
+ 1)) ==
1725 KeyboardBuffer
->bHead
);
1730 Inserts a key code into keyboard buffer.
1732 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1734 @param Down Special key
1736 @retval EFI_SUCCESS Success
1742 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1750 // if keyboard buffer is full, throw the
1751 // first key out of the keyboard buffer.
1753 if (IsUSBKeyboardBufferFull (KeyboardBuffer
)) {
1754 RemoveKeyCode (KeyboardBuffer
, &UsbKey
);
1757 KeyboardBuffer
->buffer
[KeyboardBuffer
->bTail
].KeyCode
= Key
;
1758 KeyboardBuffer
->buffer
[KeyboardBuffer
->bTail
].Down
= Down
;
1761 // adjust the tail pointer of the FIFO keyboard buffer.
1763 KeyboardBuffer
->bTail
= (UINT8
) ((KeyboardBuffer
->bTail
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1770 Pops a key code off from keyboard buffer.
1772 @param KeyboardBuffer Points to the USB Keyboard Buffer.
1773 @param UsbKey Points to the buffer that contains a usb key code.
1775 @retval EFI_SUCCESS Success
1776 @retval EFI_DEVICE_ERROR Hardware Error
1782 IN OUT USB_KB_BUFFER
*KeyboardBuffer
,
1786 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer
)) {
1787 return EFI_DEVICE_ERROR
;
1790 UsbKey
->KeyCode
= KeyboardBuffer
->buffer
[KeyboardBuffer
->bHead
].KeyCode
;
1791 UsbKey
->Down
= KeyboardBuffer
->buffer
[KeyboardBuffer
->bHead
].Down
;
1794 // adjust the head pointer of the FIFO keyboard buffer.
1796 KeyboardBuffer
->bHead
= (UINT8
) ((KeyboardBuffer
->bHead
+ 1) % (MAX_KEY_ALLOWED
+ 1));
1803 Sets USB Keyboard LED state.
1805 @param UsbKeyboardDevice The USB_KB_DEV instance.
1807 @retval EFI_SUCCESS Success
1813 IN USB_KB_DEV
*UsbKeyboardDevice
1820 // Set each field in Led map.
1822 Led
.NumLock
= (UINT8
) UsbKeyboardDevice
->NumLockOn
;
1823 Led
.CapsLock
= (UINT8
) UsbKeyboardDevice
->CapsOn
;
1824 Led
.ScrollLock
= (UINT8
) UsbKeyboardDevice
->ScrollOn
;
1829 // call Set Report Request to lighten the LED.
1831 UsbSetReportRequest (
1832 UsbKeyboardDevice
->UsbIo
,
1833 UsbKeyboardDevice
->InterfaceDescriptor
.InterfaceNumber
,
1845 Timer handler for Repeat Key timer.
1847 @param Event The Repeat Key event.
1848 @param Context Points to the USB_KB_DEV instance.
1854 USBKeyboardRepeatHandler (
1859 USB_KB_DEV
*UsbKeyboardDevice
;
1861 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1864 // Do nothing when there is no repeat key.
1866 if (UsbKeyboardDevice
->RepeatKey
!= 0) {
1868 // Inserts one Repeat key into keyboard buffer,
1871 &(UsbKeyboardDevice
->KeyboardBuffer
),
1872 UsbKeyboardDevice
->RepeatKey
,
1877 // set repeate rate for repeat key generation.
1880 UsbKeyboardDevice
->RepeatTimer
,
1890 Timer handler for Delayed Recovery timer.
1892 @param Event The Delayed Recovery event.
1893 @param Context Points to the USB_KB_DEV instance.
1899 USBKeyboardRecoveryHandler (
1905 USB_KB_DEV
*UsbKeyboardDevice
;
1906 EFI_USB_IO_PROTOCOL
*UsbIo
;
1909 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1911 UsbIo
= UsbKeyboardDevice
->UsbIo
;
1913 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
1915 UsbIo
->UsbAsyncInterruptTransfer (
1917 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
1919 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,