]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
3c72822a6deb7a001adbe962566e03966e59fcf6
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / KeyBoard.c
1 /** @file
2 Helper functions for USB Keyboard Driver.
3
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
9
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.
12
13 **/
14
15 #include "KeyBoard.h"
16
17 //
18 // Default English keyboard layout
19 // Format:<efi key>, <unicode without shift>, <unicode with shift>, <Modifier>, <AffectedAttribute>
20 //
21 // According to Universal Serial Bus HID Usage Tables document ver 1.12,
22 // a Boot Keyboard should support the keycode range from 0x0 to 0x65 and 0xE0 to 0xE7.
23 // 0x0 to 0x3 are reserved for typical keyboard status or keyboard errors, so they are excluded.
24 //
25 UINT8 KeyboardLayoutTable[NUMBER_OF_VALID_USB_KEYCODE][5] = {
26 {EfiKeyC1, 'a', 'A', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x04
27 {EfiKeyB5, 'b', 'B', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x05
28 {EfiKeyB3, 'c', 'C', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x06
29 {EfiKeyC3, 'd', 'D', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x07
30 {EfiKeyD3, 'e', 'E', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x08
31 {EfiKeyC4, 'f', 'F', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x09
32 {EfiKeyC5, 'g', 'G', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0A
33 {EfiKeyC6, 'h', 'H', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0B
34 {EfiKeyD8, 'i', 'I', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0C
35 {EfiKeyC7, 'j', 'J', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0D
36 {EfiKeyC8, 'k', 'K', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0E
37 {EfiKeyC9, 'l', 'L', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x0F
38 {EfiKeyB7, 'm', 'M', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x10
39 {EfiKeyB6, 'n', 'N', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x11
40 {EfiKeyD9, 'o', 'O', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x12
41 {EfiKeyD10, 'p', 'P', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x13
42 {EfiKeyD1, 'q', 'Q', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x14
43 {EfiKeyD4, 'r', 'R', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x15
44 {EfiKeyC2, 's', 'S', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x16
45 {EfiKeyD5, 't', 'T', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x17
46 {EfiKeyD7, 'u', 'U', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x18
47 {EfiKeyB4, 'v', 'V', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x19
48 {EfiKeyD2, 'w', 'W', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x1A
49 {EfiKeyB2, 'x', 'X', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x1B
50 {EfiKeyD6, 'y', 'Y', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x1C
51 {EfiKeyB1, 'z', 'Z', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK}, // 0x1D
52 {EfiKeyE1, '1', '!', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x1E
53 {EfiKeyE2, '2', '@', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x1F
54 {EfiKeyE3, '3', '#', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x20
55 {EfiKeyE4, '4', '$', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x21
56 {EfiKeyE5, '5', '%', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x22
57 {EfiKeyE6, '6', '^', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x23
58 {EfiKeyE7, '7', '&', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x24
59 {EfiKeyE8, '8', '*', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x25
60 {EfiKeyE9, '9', '(', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x26
61 {EfiKeyE10, '0', ')', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x27
62 {EfiKeyEnter, 0x0d, 0x0d, EFI_NULL_MODIFIER, 0}, // 0x28 Enter
63 {EfiKeyEsc, 0x1b, 0x1b, EFI_NULL_MODIFIER, 0}, // 0x29 Esc
64 {EfiKeyBackSpace, 0x08, 0x08, EFI_NULL_MODIFIER, 0}, // 0x2A Backspace
65 {EfiKeyTab, 0x09, 0x09, EFI_NULL_MODIFIER, 0}, // 0x2B Tab
66 {EfiKeySpaceBar, ' ', ' ', EFI_NULL_MODIFIER, 0}, // 0x2C Spacebar
67 {EfiKeyE11, '-', '_', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x2D
68 {EfiKeyE12, '=', '+', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x2E
69 {EfiKeyD11, '[', '{', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x2F
70 {EfiKeyD12, ']', '}', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x30
71 {EfiKeyD13, '\\', '|', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x31
72 {EfiKeyC12, '\\', '|', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x32 Keyboard Non-US # and ~
73 {EfiKeyC10, ';', ':', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x33
74 {EfiKeyC11, '\'', '"', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x34
75 {EfiKeyE0, '`', '~', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x35 Keyboard Grave Accent and Tlide
76 {EfiKeyB8, ',', '<', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x36
77 {EfiKeyB9, '.', '>', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x37
78 {EfiKeyB10, '/', '?', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x38
79 {EfiKeyCapsLock, 0x00, 0x00, EFI_CAPS_LOCK_MODIFIER, 0}, // 0x39 CapsLock
80 {EfiKeyF1, 0x00, 0x00, EFI_FUNCTION_KEY_ONE_MODIFIER, 0}, // 0x3A
81 {EfiKeyF2, 0x00, 0x00, EFI_FUNCTION_KEY_TWO_MODIFIER, 0}, // 0x3B
82 {EfiKeyF3, 0x00, 0x00, EFI_FUNCTION_KEY_THREE_MODIFIER, 0}, // 0x3C
83 {EfiKeyF4, 0x00, 0x00, EFI_FUNCTION_KEY_FOUR_MODIFIER, 0}, // 0x3D
84 {EfiKeyF5, 0x00, 0x00, EFI_FUNCTION_KEY_FIVE_MODIFIER, 0}, // 0x3E
85 {EfiKeyF6, 0x00, 0x00, EFI_FUNCTION_KEY_SIX_MODIFIER, 0}, // 0x3F
86 {EfiKeyF7, 0x00, 0x00, EFI_FUNCTION_KEY_SEVEN_MODIFIER, 0}, // 0x40
87 {EfiKeyF8, 0x00, 0x00, EFI_FUNCTION_KEY_EIGHT_MODIFIER, 0}, // 0x41
88 {EfiKeyF9, 0x00, 0x00, EFI_FUNCTION_KEY_NINE_MODIFIER, 0}, // 0x42
89 {EfiKeyF10, 0x00, 0x00, EFI_FUNCTION_KEY_TEN_MODIFIER, 0}, // 0x43
90 {EfiKeyF11, 0x00, 0x00, EFI_FUNCTION_KEY_ELEVEN_MODIFIER, 0}, // 0x44 F11
91 {EfiKeyF12, 0x00, 0x00, EFI_FUNCTION_KEY_TWELVE_MODIFIER, 0}, // 0x45 F12
92 {EfiKeyPrint, 0x00, 0x00, EFI_PRINT_MODIFIER, 0}, // 0x46 PrintScreen
93 {EfiKeySLck, 0x00, 0x00, EFI_SCROLL_LOCK_MODIFIER, 0}, // 0x47 Scroll Lock
94 {EfiKeyPause, 0x00, 0x00, EFI_PAUSE_MODIFIER, 0}, // 0x48 Pause
95 {EfiKeyIns, 0x00, 0x00, EFI_INSERT_MODIFIER, 0}, // 0x49
96 {EfiKeyHome, 0x00, 0x00, EFI_HOME_MODIFIER, 0}, // 0x4A
97 {EfiKeyPgUp, 0x00, 0x00, EFI_PAGE_UP_MODIFIER, 0}, // 0x4B
98 {EfiKeyDel, 0x00, 0x00, EFI_DELETE_MODIFIER, 0}, // 0x4C
99 {EfiKeyEnd, 0x00, 0x00, EFI_END_MODIFIER, 0}, // 0x4D
100 {EfiKeyPgDn, 0x00, 0x00, EFI_PAGE_DOWN_MODIFIER, 0}, // 0x4E
101 {EfiKeyRightArrow, 0x00, 0x00, EFI_RIGHT_ARROW_MODIFIER, 0}, // 0x4F
102 {EfiKeyLeftArrow, 0x00, 0x00, EFI_LEFT_ARROW_MODIFIER, 0}, // 0x50
103 {EfiKeyDownArrow, 0x00, 0x00, EFI_DOWN_ARROW_MODIFIER, 0}, // 0x51
104 {EfiKeyUpArrow, 0x00, 0x00, EFI_UP_ARROW_MODIFIER, 0}, // 0x52
105 {EfiKeyNLck, 0x00, 0x00, EFI_NUM_LOCK_MODIFIER, 0}, // 0x53 NumLock
106 {EfiKeySlash, '/', '/', EFI_NULL_MODIFIER, 0}, // 0x54
107 {EfiKeyAsterisk, '*', '*', EFI_NULL_MODIFIER, 0}, // 0x55
108 {EfiKeyMinus, '-', '-', EFI_NULL_MODIFIER, 0}, // 0x56
109 {EfiKeyPlus, '+', '+', EFI_NULL_MODIFIER, 0}, // 0x57
110 {EfiKeyEnter, 0x0d, 0x0d, EFI_NULL_MODIFIER, 0}, // 0x58
111 {EfiKeyOne, '1', '1', EFI_END_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x59
112 {EfiKeyTwo, '2', '2', EFI_DOWN_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5A
113 {EfiKeyThree, '3', '3', EFI_PAGE_DOWN_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5B
114 {EfiKeyFour, '4', '4', EFI_LEFT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5C
115 {EfiKeyFive, '5', '5', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5D
116 {EfiKeySix, '6', '6', EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5E
117 {EfiKeySeven, '7', '7', EFI_HOME_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x5F
118 {EfiKeyEight, '8', '8', EFI_UP_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x60
119 {EfiKeyNine, '9', '9', EFI_PAGE_UP_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x61
120 {EfiKeyZero, '0', '0', EFI_INSERT_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x62
121 {EfiKeyPeriod, '.', '.', EFI_DELETE_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK}, // 0x63
122 {EfiKeyB0, '\\', '|', EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x64 Keyboard Non-US \ and |
123 {EfiKeyA4, 0x00, 0x00, EFI_MENU_MODIFIER, 0}, // 0x65 Keyboard Application
124
125 {EfiKeyLCtrl, 0, 0, EFI_LEFT_CONTROL_MODIFIER, 0}, // 0xe0
126 {EfiKeyLShift, 0, 0, EFI_LEFT_SHIFT_MODIFIER, 0}, // 0xe1
127 {EfiKeyLAlt, 0, 0, EFI_LEFT_ALT_MODIFIER, 0}, // 0xe2
128 {EfiKeyA0, 0, 0, EFI_LEFT_LOGO_MODIFIER, 0}, // 0xe3
129 {EfiKeyRCtrl, 0, 0, EFI_RIGHT_CONTROL_MODIFIER, 0}, // 0xe4
130 {EfiKeyRShift, 0, 0, EFI_RIGHT_SHIFT_MODIFIER, 0}, // 0xe5
131 {EfiKeyA2, 0, 0, EFI_RIGHT_ALT_MODIFIER, 0}, // 0xe6
132 {EfiKeyA3, 0, 0, EFI_RIGHT_LOGO_MODIFIER, 0}, // 0xe7
133 };
134
135 //
136 // EFI_KEY to USB Keycode convertion table
137 // EFI_KEY is defined in UEFI spec.
138 // USB Keycode is defined in USB HID Firmware spec.
139 //
140 UINT8 EfiKeyToUsbKeyCodeConvertionTable[] = {
141 0xe0, // EfiKeyLCtrl
142 0xe3, // EfiKeyA0
143 0xe2, // EfiKeyLAlt
144 0x2c, // EfiKeySpaceBar
145 0xe6, // EfiKeyA2
146 0xe7, // EfiKeyA3
147 0x65, // EfiKeyA4
148 0xe4, // EfiKeyRCtrl
149 0x50, // EfiKeyLeftArrow
150 0x51, // EfiKeyDownArrow
151 0x4F, // EfiKeyRightArrow
152 0x62, // EfiKeyZero
153 0x63, // EfiKeyPeriod
154 0x28, // EfiKeyEnter
155 0xe1, // EfiKeyLShift
156 0x64, // EfiKeyB0
157 0x1D, // EfiKeyB1
158 0x1B, // EfiKeyB2
159 0x06, // EfiKeyB3
160 0x19, // EfiKeyB4
161 0x05, // EfiKeyB5
162 0x11, // EfiKeyB6
163 0x10, // EfiKeyB7
164 0x36, // EfiKeyB8
165 0x37, // EfiKeyB9
166 0x38, // EfiKeyB10
167 0xe5, // EfiKeyRShift
168 0x52, // EfiKeyUpArrow
169 0x59, // EfiKeyOne
170 0x5A, // EfiKeyTwo
171 0x5B, // EfiKeyThree
172 0x39, // EfiKeyCapsLock
173 0x04, // EfiKeyC1
174 0x16, // EfiKeyC2
175 0x07, // EfiKeyC3
176 0x09, // EfiKeyC4
177 0x0A, // EfiKeyC5
178 0x0B, // EfiKeyC6
179 0x0D, // EfiKeyC7
180 0x0E, // EfiKeyC8
181 0x0F, // EfiKeyC9
182 0x33, // EfiKeyC10
183 0x34, // EfiKeyC11
184 0x32, // EfiKeyC12
185 0x5C, // EfiKeyFour
186 0x5D, // EfiKeyFive
187 0x5E, // EfiKeySix
188 0x57, // EfiKeyPlus
189 0x2B, // EfiKeyTab
190 0x14, // EfiKeyD1
191 0x1A, // EfiKeyD2
192 0x08, // EfiKeyD3
193 0x15, // EfiKeyD4
194 0x17, // EfiKeyD5
195 0x1C, // EfiKeyD6
196 0x18, // EfiKeyD7
197 0x0C, // EfiKeyD8
198 0x12, // EfiKeyD9
199 0x13, // EfiKeyD10
200 0x2F, // EfiKeyD11
201 0x30, // EfiKeyD12
202 0x31, // EfiKeyD13
203 0x4C, // EfiKeyDel
204 0x4D, // EfiKeyEnd
205 0x4E, // EfiKeyPgDn
206 0x5F, // EfiKeySeven
207 0x60, // EfiKeyEight
208 0x61, // EfiKeyNine
209 0x35, // EfiKeyE0
210 0x1E, // EfiKeyE1
211 0x1F, // EfiKeyE2
212 0x20, // EfiKeyE3
213 0x21, // EfiKeyE4
214 0x22, // EfiKeyE5
215 0x23, // EfiKeyE6
216 0x24, // EfiKeyE7
217 0x25, // EfiKeyE8
218 0x26, // EfiKeyE9
219 0x27, // EfiKeyE10
220 0x2D, // EfiKeyE11
221 0x2E, // EfiKeyE12
222 0x2A, // EfiKeyBackSpace
223 0x49, // EfiKeyIns
224 0x4A, // EfiKeyHome
225 0x4B, // EfiKeyPgUp
226 0x53, // EfiKeyNLck
227 0x54, // EfiKeySlash
228 0x55, // EfiKeyAsterisk
229 0x56, // EfiKeyMinus
230 0x29, // EfiKeyEsc
231 0x3A, // EfiKeyF1
232 0x3B, // EfiKeyF2
233 0x3C, // EfiKeyF3
234 0x3D, // EfiKeyF4
235 0x3E, // EfiKeyF5
236 0x3F, // EfiKeyF6
237 0x40, // EfiKeyF7
238 0x41, // EfiKeyF8
239 0x42, // EfiKeyF9
240 0x43, // EfiKeyF10
241 0x44, // EfiKeyF11
242 0x45, // EfiKeyF12
243 0x46, // EfiKeyPrint
244 0x47, // EfiKeySLck
245 0x48 // EfiKeyPause
246 };
247
248 //
249 // Keyboard modifier value to EFI Scan Code convertion table
250 // EFI Scan Code and the modifier values are defined in UEFI spec.
251 //
252 UINT8 ModifierValueToEfiScanCodeConvertionTable[] = {
253 SCAN_NULL, // EFI_NULL_MODIFIER
254 SCAN_NULL, // EFI_LEFT_CONTROL_MODIFIER
255 SCAN_NULL, // EFI_RIGHT_CONTROL_MODIFIER
256 SCAN_NULL, // EFI_LEFT_ALT_MODIFIER
257 SCAN_NULL, // EFI_RIGHT_ALT_MODIFIER
258 SCAN_NULL, // EFI_ALT_GR_MODIFIER
259 SCAN_INSERT, // EFI_INSERT_MODIFIER
260 SCAN_DELETE, // EFI_DELETE_MODIFIER
261 SCAN_PAGE_DOWN, // EFI_PAGE_DOWN_MODIFIER
262 SCAN_PAGE_UP, // EFI_PAGE_UP_MODIFIER
263 SCAN_HOME, // EFI_HOME_MODIFIER
264 SCAN_END, // EFI_END_MODIFIER
265 SCAN_NULL, // EFI_LEFT_SHIFT_MODIFIER
266 SCAN_NULL, // EFI_RIGHT_SHIFT_MODIFIER
267 SCAN_NULL, // EFI_CAPS_LOCK_MODIFIER
268 SCAN_NULL, // EFI_NUM_LOCK_MODIFIER
269 SCAN_LEFT, // EFI_LEFT_ARROW_MODIFIER
270 SCAN_RIGHT, // EFI_RIGHT_ARROW_MODIFIER
271 SCAN_DOWN, // EFI_DOWN_ARROW_MODIFIER
272 SCAN_UP, // EFI_UP_ARROW_MODIFIER
273 SCAN_NULL, // EFI_NS_KEY_MODIFIER
274 SCAN_NULL, // EFI_NS_KEY_DEPENDENCY_MODIFIER
275 SCAN_F1, // EFI_FUNCTION_KEY_ONE_MODIFIER
276 SCAN_F2, // EFI_FUNCTION_KEY_TWO_MODIFIER
277 SCAN_F3, // EFI_FUNCTION_KEY_THREE_MODIFIER
278 SCAN_F4, // EFI_FUNCTION_KEY_FOUR_MODIFIER
279 SCAN_F5, // EFI_FUNCTION_KEY_FIVE_MODIFIER
280 SCAN_F6, // EFI_FUNCTION_KEY_SIX_MODIFIER
281 SCAN_F7, // EFI_FUNCTION_KEY_SEVEN_MODIFIER
282 SCAN_F8, // EFI_FUNCTION_KEY_EIGHT_MODIFIER
283 SCAN_F9, // EFI_FUNCTION_KEY_NINE_MODIFIER
284 SCAN_F10, // EFI_FUNCTION_KEY_TEN_MODIFIER
285 SCAN_F11, // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
286 SCAN_F12, // EFI_FUNCTION_KEY_TWELVE_MODIFIER
287 };
288
289 EFI_GUID mKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;
290
291 /**
292 Initialize Key Convertion Table by using default keyboard layout.
293
294 @param UsbKeyboardDevice The USB_KB_DEV instance.
295
296 **/
297 VOID
298 EFIAPI
299 LoadDefaultKeyboardLayout (
300 IN OUT USB_KB_DEV *UsbKeyboardDevice
301 )
302 {
303 UINTN Index;
304 EFI_KEY_DESCRIPTOR *KeyDescriptor;
305
306 //
307 // Construct KeyConvertionTable by default keyboard layout
308 //
309 KeyDescriptor = &UsbKeyboardDevice->KeyConvertionTable[0];
310
311 for (Index = 0; Index < (NUMBER_OF_VALID_USB_KEYCODE); Index++) {
312 KeyDescriptor->Key = (EFI_KEY) KeyboardLayoutTable[Index][0];
313 KeyDescriptor->Unicode = KeyboardLayoutTable[Index][1];
314 KeyDescriptor->ShiftedUnicode = KeyboardLayoutTable[Index][2];
315 KeyDescriptor->AltGrUnicode = 0;
316 KeyDescriptor->ShiftedAltGrUnicode = 0;
317 KeyDescriptor->Modifier = KeyboardLayoutTable[Index][3];
318 KeyDescriptor->AffectedAttribute = KeyboardLayoutTable[Index][4];
319
320 KeyDescriptor++;
321 }
322 }
323
324 /**
325 Uses USB I/O to check whether the device is a USB keyboard device.
326
327 @param UsbIo Pointer to a USB I/O protocol instance.
328
329 @retval TRUE Device is a USB keyboard device.
330 @retval FALSE Device is a not USB keyboard device.
331
332 **/
333 BOOLEAN
334 EFIAPI
335 IsUSBKeyboard (
336 IN EFI_USB_IO_PROTOCOL *UsbIo
337 )
338 {
339 EFI_STATUS Status;
340 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
341
342 //
343 // Get the default interface descriptor
344 //
345 Status = UsbIo->UsbGetInterfaceDescriptor (
346 UsbIo,
347 &InterfaceDescriptor
348 );
349
350 if (EFI_ERROR (Status)) {
351 return FALSE;
352 }
353
354 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
355 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
356 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD
357 ) {
358 return TRUE;
359 }
360
361 return FALSE;
362 }
363
364 /**
365 Get current keyboard layout from HII database.
366
367 @return Pointer to HII Keyboard Layout.
368 NULL means failure occurred while trying to get keyboard layout.
369
370 **/
371 EFI_HII_KEYBOARD_LAYOUT *
372 EFIAPI
373 GetCurrentKeyboardLayout (
374 VOID
375 )
376 {
377 EFI_STATUS Status;
378 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
379 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
380 UINT16 Length;
381
382 //
383 // Locate HII Database Protocol
384 //
385 Status = gBS->LocateProtocol (
386 &gEfiHiiDatabaseProtocolGuid,
387 NULL,
388 (VOID **) &HiiDatabase
389 );
390 if (EFI_ERROR (Status)) {
391 return NULL;
392 }
393
394 //
395 // Get current keyboard layout from HII database
396 //
397 Length = 0;
398 KeyboardLayout = NULL;
399 Status = HiiDatabase->GetKeyboardLayout (
400 HiiDatabase,
401 NULL,
402 &Length,
403 KeyboardLayout
404 );
405 if (Status == EFI_BUFFER_TOO_SMALL) {
406 KeyboardLayout = AllocatePool (Length);
407 ASSERT (KeyboardLayout != NULL);
408
409 Status = HiiDatabase->GetKeyboardLayout (
410 HiiDatabase,
411 NULL,
412 &Length,
413 KeyboardLayout
414 );
415 if (EFI_ERROR (Status)) {
416 gBS->FreePool (KeyboardLayout);
417 KeyboardLayout = NULL;
418 }
419 }
420
421 return KeyboardLayout;
422 }
423
424 /**
425 Find Key Descriptor in Key Convertion Table given its USB keycode.
426
427 @param UsbKeyboardDevice The USB_KB_DEV instance.
428 @param KeyCode USB Keycode.
429
430 @return The Key Descriptor in Key Convertion Table.
431 NULL means not found.
432
433 **/
434 EFI_KEY_DESCRIPTOR *
435 EFIAPI
436 GetKeyDescriptor (
437 IN USB_KB_DEV *UsbKeyboardDevice,
438 IN UINT8 KeyCode
439 )
440 {
441 UINT8 Index;
442
443 //
444 // Make sure KeyCode is in the range of [0x4, 0x65] or [0xe0, 0xe7]
445 //
446 if ((!USBKBD_VALID_KEYCODE (KeyCode)) || ((KeyCode > 0x65) && (KeyCode < 0xe0)) || (KeyCode > 0xe7)) {
447 return NULL;
448 }
449
450 //
451 // Calculate the index of Key Descriptor in Key Convertion Table
452 //
453 if (KeyCode <= 0x65) {
454 Index = (UINT8) (KeyCode - 4);
455 } else {
456 Index = (UINT8) (KeyCode - 0xe0 + NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE);
457 }
458
459 return &UsbKeyboardDevice->KeyConvertionTable[Index];
460 }
461
462 /**
463 Find Non-Spacing key for given Key descriptor.
464
465 @param UsbKeyboardDevice The USB_KB_DEV instance.
466 @param KeyDescriptor Key descriptor.
467
468 @return The Non-Spacing key corresponding to KeyDescriptor
469 NULL means not found.
470
471 **/
472 USB_NS_KEY *
473 EFIAPI
474 FindUsbNsKey (
475 IN USB_KB_DEV *UsbKeyboardDevice,
476 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
477 )
478 {
479 LIST_ENTRY *Link;
480 LIST_ENTRY *NsKeyList;
481 USB_NS_KEY *UsbNsKey;
482
483 NsKeyList = &UsbKeyboardDevice->NsKeyList;
484 Link = GetFirstNode (NsKeyList);
485 while (!IsNull (NsKeyList, Link)) {
486 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
487
488 if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {
489 return UsbNsKey;
490 }
491
492 Link = GetNextNode (NsKeyList, Link);
493 }
494
495 return NULL;
496 }
497
498 /**
499 Find physical key definition for a given key descriptor.
500
501 For a specified non-spacing key, there are a list of physical
502 keys following it. This function traverses the list of
503 physical keys and tries to find the physical key matching
504 the KeyDescriptor.
505
506 @param UsbNsKey The non-spacing key information.
507 @param KeyDescriptor The key descriptor.
508
509 @return The physical key definition.
510 If no physical key is found, parameter KeyDescriptor is returned.
511
512 **/
513 EFI_KEY_DESCRIPTOR *
514 EFIAPI
515 FindPhysicalKey (
516 IN USB_NS_KEY *UsbNsKey,
517 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
518 )
519 {
520 UINTN Index;
521 EFI_KEY_DESCRIPTOR *PhysicalKey;
522
523 PhysicalKey = &UsbNsKey->NsKey[1];
524 for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {
525 if (KeyDescriptor->Key == PhysicalKey->Key) {
526 return PhysicalKey;
527 }
528
529 PhysicalKey++;
530 }
531
532 //
533 // No children definition matched, return original key
534 //
535 return KeyDescriptor;
536 }
537
538 /**
539 The notification function for EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID.
540
541 This function is registered to event of EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
542 group type, which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
543 It tries to get curent keyboard layout from HII database.
544
545 @param Event Event being signaled.
546 @param Context Points to USB_KB_DEV instance.
547
548 **/
549 VOID
550 EFIAPI
551 SetKeyboardLayoutEvent (
552 IN EFI_EVENT Event,
553 IN VOID *Context
554 )
555 {
556 USB_KB_DEV *UsbKeyboardDevice;
557 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
558 EFI_KEY_DESCRIPTOR TempKey;
559 EFI_KEY_DESCRIPTOR *KeyDescriptor;
560 EFI_KEY_DESCRIPTOR *TableEntry;
561 EFI_KEY_DESCRIPTOR *NsKey;
562 USB_NS_KEY *UsbNsKey;
563 UINTN Index;
564 UINTN Index2;
565 UINTN KeyCount;
566 UINT8 KeyCode;
567
568 UsbKeyboardDevice = (USB_KB_DEV *) Context;
569
570 //
571 // Try to get current keyboard layout from HII database
572 //
573 KeyboardLayout = GetCurrentKeyboardLayout ();
574 if (KeyboardLayout == NULL) {
575 return;
576 }
577
578 //
579 // Re-allocate resource for KeyConvertionTable
580 //
581 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
582 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
583 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
584
585 //
586 // Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
587 //
588 KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));
589 for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {
590 //
591 // Copy from HII keyboard layout package binary for alignment
592 //
593 CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
594
595 //
596 // Fill the key into KeyConvertionTable, whose index is calculated from USB keycode.
597 //
598 KeyCode = EfiKeyToUsbKeyCodeConvertionTable [(UINT8) (TempKey.Key)];
599 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
600 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
601
602 //
603 // For non-spacing key, create the list with a non-spacing key followed by physical keys.
604 //
605 if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {
606 UsbNsKey = AllocatePool (sizeof (USB_NS_KEY));
607 ASSERT (UsbNsKey != NULL);
608
609 //
610 // Search for sequential children physical key definitions
611 //
612 KeyCount = 0;
613 NsKey = KeyDescriptor + 1;
614 for (Index2 = Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {
615 CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));
616 if (TempKey.Modifier & EFI_NS_KEY_DEPENDENCY_MODIFIER) {
617 KeyCount++;
618 } else {
619 break;
620 }
621 NsKey++;
622 }
623
624 UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;
625 UsbNsKey->KeyCount = KeyCount;
626 UsbNsKey->NsKey = AllocateCopyPool (
627 (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),
628 KeyDescriptor
629 );
630 InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);
631
632 //
633 // Skip over the child physical keys
634 //
635 Index += KeyCount;
636 KeyDescriptor += KeyCount;
637 }
638
639 KeyDescriptor++;
640 }
641
642 //
643 // There are two EfiKeyEnter, duplicate its key descriptor
644 //
645 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);
646 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);
647 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
648
649 FreePool (KeyboardLayout);
650 }
651
652 /**
653 Destroy resources for keyboard layout.
654
655 @param UsbKeyboardDevice The USB_KB_DEV instance.
656
657 **/
658 VOID
659 EFIAPI
660 ReleaseKeyboardLayoutResources (
661 IN OUT USB_KB_DEV *UsbKeyboardDevice
662 )
663 {
664 USB_NS_KEY *UsbNsKey;
665 LIST_ENTRY *Link;
666
667 if (UsbKeyboardDevice->KeyConvertionTable != NULL) {
668 FreePool (UsbKeyboardDevice->KeyConvertionTable);
669 }
670 UsbKeyboardDevice->KeyConvertionTable = NULL;
671
672 while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {
673 Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);
674 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
675 RemoveEntryList (&UsbNsKey->Link);
676
677 FreePool (UsbNsKey->NsKey);
678 FreePool (UsbNsKey);
679 }
680 }
681
682 /**
683 Initialize USB keyboard layout.
684
685 This function initializes Key Convertion Table for the USB keyboard device.
686 It first tries to retrieve layout from HII database. If failed and default
687 layout is enabled, then it just uses the default layout.
688
689 @param UsbKeyboardDevice The USB_KB_DEV instance.
690
691 @retval EFI_SUCCESS Initialization succeeded.
692 @retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII
693 database, and default layout is disabled.
694 @retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.
695
696 **/
697 EFI_STATUS
698 EFIAPI
699 InitKeyboardLayout (
700 OUT USB_KB_DEV *UsbKeyboardDevice
701 )
702 {
703 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
704 EFI_STATUS Status;
705
706 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
707 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
708
709 InitializeListHead (&UsbKeyboardDevice->NsKeyList);
710 UsbKeyboardDevice->CurrentNsKey = NULL;
711 UsbKeyboardDevice->KeyboardLayoutEvent = NULL;
712
713 //
714 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
715 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
716 //
717 Status = gBS->CreateEventEx (
718 EVT_NOTIFY_SIGNAL,
719 TPL_NOTIFY,
720 SetKeyboardLayoutEvent,
721 UsbKeyboardDevice,
722 &mKeyboardLayoutEventGuid,
723 &UsbKeyboardDevice->KeyboardLayoutEvent
724 );
725 if (EFI_ERROR (Status)) {
726 return Status;
727 }
728
729 KeyboardLayout = GetCurrentKeyboardLayout ();
730 if (KeyboardLayout != NULL) {
731 //
732 // If current keyboard layout is successfully retrieved from HII database,
733 // force to initialize the keyboard layout.
734 //
735 gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
736 } else {
737 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {
738 //
739 // If no keyboard layout can be retrieved from HII database, and default layout
740 // is disabled, then return EFI_NOT_READY.
741 //
742 return EFI_NOT_READY;
743 }
744 //
745 // If no keyboard layout can be retrieved from HII database, and default layout
746 // is enabled, then load the default keyboard layout.
747 //
748 LoadDefaultKeyboardLayout (UsbKeyboardDevice);
749 }
750
751 return EFI_SUCCESS;
752 }
753
754
755 /**
756 Initialize USB keyboard device and all private data structures.
757
758 @param UsbKeyboardDevice The USB_KB_DEV instance.
759
760 @retval EFI_SUCCESS Initialization is successful.
761 @retval EFI_DEVICE_ERROR Keyboard initialization failed.
762
763 **/
764 EFI_STATUS
765 EFIAPI
766 InitUSBKeyboard (
767 IN OUT USB_KB_DEV *UsbKeyboardDevice
768 )
769 {
770 UINT8 ConfigValue;
771 UINT8 Protocol;
772 UINT8 ReportId;
773 UINT8 Duration;
774 EFI_STATUS Status;
775 UINT32 TransferResult;
776
777 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
778 EFI_PROGRESS_CODE,
779 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest),
780 UsbKeyboardDevice->DevicePath
781 );
782
783 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
784
785 //
786 // Uses default configuration to configure the USB keyboard device.
787 //
788 ConfigValue = 0x01;
789 Status = UsbSetConfiguration (
790 UsbKeyboardDevice->UsbIo,
791 (UINT16) ConfigValue,
792 &TransferResult
793 );
794 if (EFI_ERROR (Status)) {
795 //
796 // If configuration could not be set here, it means
797 // the keyboard interface has some errors and could
798 // not be initialized
799 //
800 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
801 EFI_ERROR_CODE | EFI_ERROR_MINOR,
802 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError),
803 UsbKeyboardDevice->DevicePath
804 );
805
806 return EFI_DEVICE_ERROR;
807 }
808
809 UsbGetProtocolRequest (
810 UsbKeyboardDevice->UsbIo,
811 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
812 &Protocol
813 );
814 //
815 // Set boot protocol for the USB Keyboard.
816 // This driver only supports boot protocol.
817 // The device that does not support boot protocol is not supported.
818 //
819 if (Protocol != BOOT_PROTOCOL) {
820 UsbSetProtocolRequest (
821 UsbKeyboardDevice->UsbIo,
822 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
823 BOOT_PROTOCOL
824 );
825 }
826
827 //
828 // ReportId is zero, which means the idle rate applies to all input reports.
829 //
830 ReportId = 0;
831 //
832 // Duration is zero, which means the duration is infinite.
833 // so the endpoint will inhibit reporting forever,
834 // and only reporting when a change is detected in the report data.
835 //
836 Duration = 0;
837 UsbSetIdleRequest (
838 UsbKeyboardDevice->UsbIo,
839 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
840 ReportId,
841 Duration
842 );
843
844 UsbKeyboardDevice->CtrlOn = FALSE;
845 UsbKeyboardDevice->AltOn = FALSE;
846 UsbKeyboardDevice->ShiftOn = FALSE;
847 UsbKeyboardDevice->NumLockOn = FALSE;
848 UsbKeyboardDevice->CapsOn = FALSE;
849 UsbKeyboardDevice->ScrollOn = FALSE;
850
851 UsbKeyboardDevice->LeftCtrlOn = FALSE;
852 UsbKeyboardDevice->LeftAltOn = FALSE;
853 UsbKeyboardDevice->LeftShiftOn = FALSE;
854 UsbKeyboardDevice->LeftLogoOn = FALSE;
855 UsbKeyboardDevice->RightCtrlOn = FALSE;
856 UsbKeyboardDevice->RightAltOn = FALSE;
857 UsbKeyboardDevice->RightShiftOn = FALSE;
858 UsbKeyboardDevice->RightLogoOn = FALSE;
859 UsbKeyboardDevice->MenuKeyOn = FALSE;
860 UsbKeyboardDevice->SysReqOn = FALSE;
861
862 UsbKeyboardDevice->AltGrOn = FALSE;
863
864 UsbKeyboardDevice->CurrentNsKey = NULL;
865
866 //
867 // Sync the initial state of lights on keyboard.
868 //
869 SetKeyLED (UsbKeyboardDevice);
870
871 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
872
873 //
874 // Set a timer for repeat keys' generation.
875 //
876 if (UsbKeyboardDevice->RepeatTimer != NULL) {
877 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
878 UsbKeyboardDevice->RepeatTimer = NULL;
879 }
880
881 Status = gBS->CreateEvent (
882 EVT_TIMER | EVT_NOTIFY_SIGNAL,
883 TPL_NOTIFY,
884 USBKeyboardRepeatHandler,
885 UsbKeyboardDevice,
886 &UsbKeyboardDevice->RepeatTimer
887 );
888
889 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
890 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
891 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
892 }
893
894 Status = gBS->CreateEvent (
895 EVT_TIMER | EVT_NOTIFY_SIGNAL,
896 TPL_NOTIFY,
897 USBKeyboardRecoveryHandler,
898 UsbKeyboardDevice,
899 &UsbKeyboardDevice->DelayedRecoveryEvent
900 );
901
902 return EFI_SUCCESS;
903 }
904
905
906 /**
907 Handler function for USB keyboard's asynchronous interrupt transfer.
908
909 This function is the handler function for USB keyboard's asynchronous interrupt transfer
910 to manage the keyboard. It parses the USB keyboard input report, and inserts data to
911 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
912 is also set accordingly.
913
914 @param Data A pointer to a buffer that is filled with key data which is
915 retrieved via asynchronous interrupt transfer.
916 @param DataLength Indicates the size of the data buffer.
917 @param Context Pointing to USB_KB_DEV instance.
918 @param Result Indicates the result of the asynchronous interrupt transfer.
919
920 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
921 @retval EFI_DEVICE_ERROR Hardware error occurs.
922
923 **/
924 EFI_STATUS
925 EFIAPI
926 KeyboardHandler (
927 IN VOID *Data,
928 IN UINTN DataLength,
929 IN VOID *Context,
930 IN UINT32 Result
931 )
932 {
933 USB_KB_DEV *UsbKeyboardDevice;
934 EFI_USB_IO_PROTOCOL *UsbIo;
935 UINT8 *CurKeyCodeBuffer;
936 UINT8 *OldKeyCodeBuffer;
937 UINT8 CurModifierMap;
938 UINT8 OldModifierMap;
939 UINT8 Mask;
940 UINT8 Index;
941 UINT8 Index2;
942 BOOLEAN Down;
943 BOOLEAN KeyRelease;
944 BOOLEAN KeyPress;
945 UINT8 SavedTail;
946 USB_KEY UsbKey;
947 UINT8 NewRepeatKey;
948 UINT32 UsbStatus;
949 EFI_KEY_DESCRIPTOR *KeyDescriptor;
950
951 ASSERT (Context != NULL);
952
953 NewRepeatKey = 0;
954 UsbKeyboardDevice = (USB_KB_DEV *) Context;
955 UsbIo = UsbKeyboardDevice->UsbIo;
956
957 //
958 // Analyzes Result and performs corresponding action.
959 //
960 if (Result != EFI_USB_NOERROR) {
961 //
962 // Some errors happen during the process
963 //
964 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
965 EFI_ERROR_CODE | EFI_ERROR_MINOR,
966 PcdGet32 (PcdStatusCodeValueKeyboardInputError),
967 UsbKeyboardDevice->DevicePath
968 );
969
970 //
971 // Stop the repeat key generation if any
972 //
973 UsbKeyboardDevice->RepeatKey = 0;
974
975 gBS->SetTimer (
976 UsbKeyboardDevice->RepeatTimer,
977 TimerCancel,
978 USBKBD_REPEAT_RATE
979 );
980
981 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
982 UsbClearEndpointHalt (
983 UsbIo,
984 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
985 &UsbStatus
986 );
987 }
988
989 //
990 // Delete & Submit this interrupt again
991 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
992 //
993 UsbIo->UsbAsyncInterruptTransfer (
994 UsbIo,
995 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
996 FALSE,
997 0,
998 0,
999 NULL,
1000 NULL
1001 );
1002 //
1003 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
1004 //
1005 gBS->SetTimer (
1006 UsbKeyboardDevice->DelayedRecoveryEvent,
1007 TimerRelative,
1008 EFI_USB_INTERRUPT_DELAY
1009 );
1010
1011 return EFI_DEVICE_ERROR;
1012 }
1013
1014 //
1015 // If no error and no data, just return EFI_SUCCESS.
1016 //
1017 if (DataLength == 0 || Data == NULL) {
1018 return EFI_SUCCESS;
1019 }
1020
1021 //
1022 // Following code checks current keyboard input report against old key code buffer.
1023 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1024 // Byte 0 is map of Modifier keys.
1025 // Byte 1 is reserved.
1026 // Bytes 2 to 7 are keycodes.
1027 //
1028 CurKeyCodeBuffer = (UINT8 *) Data;
1029 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
1030
1031 //
1032 // Checks for new key stroke.
1033 //
1034 for (Index = 0; Index < 8; Index++) {
1035 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
1036 break;
1037 }
1038 }
1039
1040 //
1041 // If no new key, return EFI_SUCCESS immediately.
1042 //
1043 if (Index == 8) {
1044 return EFI_SUCCESS;
1045 }
1046
1047 //
1048 // Parse the modifier key, which is the first byte of keyboard input report.
1049 //
1050 CurModifierMap = CurKeyCodeBuffer[0];
1051 OldModifierMap = OldKeyCodeBuffer[0];
1052
1053 //
1054 // Handle modifier key's pressing or releasing situation.
1055 // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
1056 // Bit0: Left Control, Keycode: 0xe0
1057 // Bit1: Left Shift, Keycode: 0xe1
1058 // Bit2: Left Alt, Keycode: 0xe2
1059 // Bit3: Left GUI, Keycode: 0xe3
1060 // Bit4: Right Control, Keycode: 0xe4
1061 // Bit5: Right Shift, Keycode: 0xe5
1062 // Bit6: Right Alt, Keycode: 0xe6
1063 // Bit7: Right GUI, Keycode: 0xe7
1064 //
1065 for (Index = 0; Index < 8; Index++) {
1066 Mask = (UINT8) (1 << Index);
1067 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
1068 //
1069 // If current modifier key is up, then CurModifierMap & Mask = 0;
1070 // otherwise it is a non-zero value.
1071 // Insert the changed modifier key into key buffer.
1072 //
1073 Down = (BOOLEAN) ((CurModifierMap & Mask) != 0);
1074 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), (UINT8) (0xe0 + Index), Down);
1075 }
1076 }
1077
1078 //
1079 // Handle normal key's releasing situation
1080 // Bytes 2 to 7 are for normal keycodes
1081 //
1082 KeyRelease = FALSE;
1083 for (Index = 2; Index < 8; Index++) {
1084
1085 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
1086 continue;
1087 }
1088 //
1089 // For any key in old keycode buffer, if it is not in current keycode buffer,
1090 // then it is released. Otherwise, it is not released.
1091 //
1092 KeyRelease = TRUE;
1093 for (Index2 = 2; Index2 < 8; Index2++) {
1094
1095 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
1096 continue;
1097 }
1098
1099 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
1100 KeyRelease = FALSE;
1101 break;
1102 }
1103 }
1104
1105 if (KeyRelease) {
1106 InsertKeyCode (
1107 &(UsbKeyboardDevice->KeyboardBuffer),
1108 OldKeyCodeBuffer[Index],
1109 FALSE
1110 );
1111 //
1112 // The original repeat key is released.
1113 //
1114 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
1115 UsbKeyboardDevice->RepeatKey = 0;
1116 }
1117 }
1118 }
1119
1120 //
1121 // If original repeat key is released, cancel the repeat timer
1122 //
1123 if (UsbKeyboardDevice->RepeatKey == 0) {
1124 gBS->SetTimer (
1125 UsbKeyboardDevice->RepeatTimer,
1126 TimerCancel,
1127 USBKBD_REPEAT_RATE
1128 );
1129 }
1130
1131 //
1132 // Handle normal key's pressing situation
1133 //
1134 KeyPress = FALSE;
1135 for (Index = 2; Index < 8; Index++) {
1136
1137 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
1138 continue;
1139 }
1140 //
1141 // For any key in current keycode buffer, if it is not in old keycode buffer,
1142 // then it is pressed. Otherwise, it is not pressed.
1143 //
1144 KeyPress = TRUE;
1145 for (Index2 = 2; Index2 < 8; Index2++) {
1146
1147 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
1148 continue;
1149 }
1150
1151 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
1152 KeyPress = FALSE;
1153 break;
1154 }
1155 }
1156
1157 if (KeyPress) {
1158 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], TRUE);
1159
1160 //
1161 // Handle repeat key
1162 //
1163 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
1164 ASSERT (KeyDescriptor != NULL);
1165
1166 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
1167 //
1168 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1169 //
1170 UsbKeyboardDevice->RepeatKey = 0;
1171 } else {
1172 //
1173 // Prepare new repeat key, and clear the original one.
1174 //
1175 NewRepeatKey = CurKeyCodeBuffer[Index];
1176 UsbKeyboardDevice->RepeatKey = 0;
1177 }
1178 }
1179 }
1180
1181 //
1182 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
1183 //
1184 for (Index = 0; Index < 8; Index++) {
1185 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
1186 }
1187
1188 //
1189 // Pre-process KeyboardBuffer to check if Ctrl + Alt + Del is pressed.
1190 //
1191 SavedTail = UsbKeyboardDevice->KeyboardBuffer.BufferTail;
1192 Index = UsbKeyboardDevice->KeyboardBuffer.BufferHead;
1193 while (Index != SavedTail) {
1194 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
1195
1196 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1197
1198 switch (KeyDescriptor->Modifier) {
1199
1200 case EFI_LEFT_CONTROL_MODIFIER:
1201 case EFI_RIGHT_CONTROL_MODIFIER:
1202 if (UsbKey.Down) {
1203 UsbKeyboardDevice->CtrlOn = TRUE;
1204 } else {
1205 UsbKeyboardDevice->CtrlOn = FALSE;
1206 }
1207 break;
1208
1209 case EFI_LEFT_ALT_MODIFIER:
1210 case EFI_RIGHT_ALT_MODIFIER:
1211 if (UsbKey.Down) {
1212 UsbKeyboardDevice->AltOn = TRUE;
1213 } else {
1214 UsbKeyboardDevice->AltOn = FALSE;
1215 }
1216 break;
1217
1218 case EFI_ALT_GR_MODIFIER:
1219 if (UsbKey.Down) {
1220 UsbKeyboardDevice->AltGrOn = TRUE;
1221 } else {
1222 UsbKeyboardDevice->AltGrOn = FALSE;
1223 }
1224 break;
1225
1226 //
1227 // For Del Key, check if Ctrl + Alt + Del occurs for reset.
1228 //
1229 case EFI_DELETE_MODIFIER:
1230 if (UsbKey.Down) {
1231 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1232 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1233 }
1234 }
1235 break;
1236
1237 default:
1238 break;
1239 }
1240
1241 //
1242 // Insert the key back to the buffer,
1243 // so the key sequence will not be destroyed.
1244 //
1245 InsertKeyCode (
1246 &(UsbKeyboardDevice->KeyboardBuffer),
1247 UsbKey.KeyCode,
1248 UsbKey.Down
1249 );
1250 Index = UsbKeyboardDevice->KeyboardBuffer.BufferHead;
1251
1252 }
1253 //
1254 // If there is new key pressed, update the RepeatKey value, and set the
1255 // timer to repeate delay timer
1256 //
1257 if (NewRepeatKey != 0) {
1258 //
1259 // Sets trigger time to "Repeat Delay Time",
1260 // to trigger the repeat timer when the key is hold long
1261 // enough time.
1262 //
1263 gBS->SetTimer (
1264 UsbKeyboardDevice->RepeatTimer,
1265 TimerRelative,
1266 USBKBD_REPEAT_DELAY
1267 );
1268 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1269 }
1270
1271 return EFI_SUCCESS;
1272 }
1273
1274
1275 /**
1276 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1277
1278 This function parses keyboard buffer. It updates state of modifier key for
1279 USB_KB_DEV instancem, and returns keycode for output.
1280
1281 @param UsbKeyboardDevice The USB_KB_DEV instance.
1282 @param KeyCode Pointer to the USB keycode for output.
1283
1284 @retval EFI_SUCCESS Keycode successfully parsed.
1285 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1286
1287 **/
1288 EFI_STATUS
1289 EFIAPI
1290 USBParseKey (
1291 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1292 OUT UINT8 *KeyCode
1293 )
1294 {
1295 USB_KEY UsbKey;
1296 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1297
1298 *KeyCode = 0;
1299
1300 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {
1301 //
1302 // Pops one raw data off.
1303 //
1304 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
1305
1306 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1307 ASSERT (KeyDescriptor != NULL);
1308
1309 if (!UsbKey.Down) {
1310 //
1311 // Key is released.
1312 //
1313 switch (KeyDescriptor->Modifier) {
1314
1315 //
1316 // Ctrl release
1317 //
1318 case EFI_LEFT_CONTROL_MODIFIER:
1319 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1320 UsbKeyboardDevice->CtrlOn = FALSE;
1321 break;
1322 case EFI_RIGHT_CONTROL_MODIFIER:
1323 UsbKeyboardDevice->RightCtrlOn = FALSE;
1324 UsbKeyboardDevice->CtrlOn = FALSE;
1325 break;
1326
1327 //
1328 // Shift release
1329 //
1330 case EFI_LEFT_SHIFT_MODIFIER:
1331 UsbKeyboardDevice->LeftShiftOn = FALSE;
1332 UsbKeyboardDevice->ShiftOn = FALSE;
1333 break;
1334 case EFI_RIGHT_SHIFT_MODIFIER:
1335 UsbKeyboardDevice->RightShiftOn = FALSE;
1336 UsbKeyboardDevice->ShiftOn = FALSE;
1337 break;
1338
1339 //
1340 // Alt release
1341 //
1342 case EFI_LEFT_ALT_MODIFIER:
1343 UsbKeyboardDevice->LeftAltOn = FALSE;
1344 UsbKeyboardDevice->AltOn = FALSE;
1345 break;
1346 case EFI_RIGHT_ALT_MODIFIER:
1347 UsbKeyboardDevice->RightAltOn = FALSE;
1348 UsbKeyboardDevice->AltOn = FALSE;
1349 break;
1350
1351 //
1352 // Left Logo release
1353 //
1354 case EFI_LEFT_LOGO_MODIFIER:
1355 UsbKeyboardDevice->LeftLogoOn = FALSE;
1356 break;
1357
1358 //
1359 // Right Logo release
1360 //
1361 case EFI_RIGHT_LOGO_MODIFIER:
1362 UsbKeyboardDevice->RightLogoOn = FALSE;
1363 break;
1364
1365 //
1366 // Menu key release
1367 //
1368 case EFI_MENU_MODIFIER:
1369 UsbKeyboardDevice->MenuKeyOn = FALSE;
1370 break;
1371
1372 //
1373 // SysReq release
1374 //
1375 case EFI_PRINT_MODIFIER:
1376 case EFI_SYS_REQUEST_MODIFIER:
1377 UsbKeyboardDevice->SysReqOn = FALSE;
1378 break;
1379
1380 //
1381 // AltGr release
1382 //
1383 case EFI_ALT_GR_MODIFIER:
1384 UsbKeyboardDevice->AltGrOn = FALSE;
1385 break;
1386
1387 default:
1388 break;
1389 }
1390
1391 continue;
1392 }
1393
1394 //
1395 // Analyzes key pressing situation
1396 //
1397 switch (KeyDescriptor->Modifier) {
1398
1399 //
1400 // Ctrl press
1401 //
1402 case EFI_LEFT_CONTROL_MODIFIER:
1403 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1404 UsbKeyboardDevice->CtrlOn = TRUE;
1405 continue;
1406 break;
1407 case EFI_RIGHT_CONTROL_MODIFIER:
1408 UsbKeyboardDevice->RightCtrlOn = TRUE;
1409 UsbKeyboardDevice->CtrlOn = TRUE;
1410 continue;
1411 break;
1412
1413 //
1414 // Shift press
1415 //
1416 case EFI_LEFT_SHIFT_MODIFIER:
1417 UsbKeyboardDevice->LeftShiftOn = TRUE;
1418 UsbKeyboardDevice->ShiftOn = TRUE;
1419 continue;
1420 break;
1421 case EFI_RIGHT_SHIFT_MODIFIER:
1422 UsbKeyboardDevice->RightShiftOn = TRUE;
1423 UsbKeyboardDevice->ShiftOn = TRUE;
1424 continue;
1425 break;
1426
1427 //
1428 // Alt press
1429 //
1430 case EFI_LEFT_ALT_MODIFIER:
1431 UsbKeyboardDevice->LeftAltOn = TRUE;
1432 UsbKeyboardDevice->AltOn = TRUE;
1433 continue;
1434 break;
1435 case EFI_RIGHT_ALT_MODIFIER:
1436 UsbKeyboardDevice->RightAltOn = TRUE;
1437 UsbKeyboardDevice->AltOn = TRUE;
1438 continue;
1439 break;
1440
1441 //
1442 // Left Logo press
1443 //
1444 case EFI_LEFT_LOGO_MODIFIER:
1445 UsbKeyboardDevice->LeftLogoOn = TRUE;
1446 break;
1447
1448 //
1449 // Right Logo press
1450 //
1451 case EFI_RIGHT_LOGO_MODIFIER:
1452 UsbKeyboardDevice->RightLogoOn = TRUE;
1453 break;
1454
1455 //
1456 // Menu key press
1457 //
1458 case EFI_MENU_MODIFIER:
1459 UsbKeyboardDevice->MenuKeyOn = TRUE;
1460 break;
1461
1462 //
1463 // SysReq press
1464 //
1465 case EFI_PRINT_MODIFIER:
1466 case EFI_SYS_REQUEST_MODIFIER:
1467 UsbKeyboardDevice->SysReqOn = TRUE;
1468 continue;
1469 break;
1470
1471 //
1472 // AltGr press
1473 //
1474 case EFI_ALT_GR_MODIFIER:
1475 UsbKeyboardDevice->AltGrOn = TRUE;
1476 break;
1477
1478 case EFI_NUM_LOCK_MODIFIER:
1479 //
1480 // Toggle NumLock
1481 //
1482 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1483 SetKeyLED (UsbKeyboardDevice);
1484 continue;
1485 break;
1486
1487 case EFI_CAPS_LOCK_MODIFIER:
1488 //
1489 // Toggle CapsLock
1490 //
1491 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1492 SetKeyLED (UsbKeyboardDevice);
1493 continue;
1494 break;
1495
1496 case EFI_SCROLL_LOCK_MODIFIER:
1497 //
1498 // Toggle ScrollLock
1499 //
1500 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1501 SetKeyLED (UsbKeyboardDevice);
1502 continue;
1503 break;
1504
1505 //
1506 // F11, F12, PrintScreen, Pause/Break
1507 // could not be retrieved via SimpleTextInEx protocol
1508 //
1509 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER:
1510 case EFI_FUNCTION_KEY_TWELVE_MODIFIER:
1511 case EFI_PAUSE_MODIFIER:
1512 case EFI_BREAK_MODIFIER:
1513 //
1514 // Fall through
1515 //
1516 continue;
1517 break;
1518
1519 default:
1520 break;
1521 }
1522
1523 //
1524 // When encountering Ctrl + Alt + Del, then warm reset.
1525 //
1526 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1527 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1528 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1529 }
1530 }
1531
1532 *KeyCode = UsbKey.KeyCode;
1533 return EFI_SUCCESS;
1534 }
1535
1536 return EFI_NOT_READY;
1537 }
1538
1539
1540 /**
1541 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1542
1543 @param UsbKeyboardDevice The USB_KB_DEV instance.
1544 @param KeyCode Indicates the key code that will be interpreted.
1545 @param Key A pointer to a buffer that is filled in with
1546 the keystroke information for the key that
1547 was pressed.
1548
1549 @retval EFI_SUCCESS Success.
1550 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1551 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1552 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1553 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1554
1555 **/
1556 EFI_STATUS
1557 EFIAPI
1558 UsbKeyCodeToEfiInputKey (
1559 IN USB_KB_DEV *UsbKeyboardDevice,
1560 IN UINT8 KeyCode,
1561 OUT EFI_INPUT_KEY *Key
1562 )
1563 {
1564 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1565
1566 //
1567 // KeyCode must in the range of 0x4 to 0x65
1568 //
1569 if (!USBKBD_VALID_KEYCODE (KeyCode)) {
1570 return EFI_INVALID_PARAMETER;
1571 }
1572 if ((KeyCode - 4) >= NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE) {
1573 return EFI_INVALID_PARAMETER;
1574 }
1575
1576 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1577 ASSERT (KeyDescriptor != NULL);
1578
1579 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1580 //
1581 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1582 //
1583 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1584 return EFI_NOT_READY;
1585 }
1586
1587 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1588 //
1589 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1590 // physical key.
1591 //
1592 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1593 UsbKeyboardDevice->CurrentNsKey = NULL;
1594 }
1595
1596 //
1597 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1598 //
1599 if (KeyDescriptor->Modifier > EFI_FUNCTION_KEY_TWELVE_MODIFIER) {
1600 return EFI_DEVICE_ERROR;
1601 }
1602
1603 Key->ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1604 Key->UnicodeChar = KeyDescriptor->Unicode;
1605
1606 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1607 if (UsbKeyboardDevice->ShiftOn) {
1608 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1609
1610 //
1611 // Need not return associated shift state if a class of printable characters that
1612 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1613 //
1614 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1615 UsbKeyboardDevice->LeftShiftOn = FALSE;
1616 UsbKeyboardDevice->RightShiftOn = FALSE;
1617 }
1618
1619 if (UsbKeyboardDevice->AltGrOn) {
1620 Key->UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1621 }
1622 } else {
1623 //
1624 // Shift off
1625 //
1626 Key->UnicodeChar = KeyDescriptor->Unicode;
1627
1628 if (UsbKeyboardDevice->AltGrOn) {
1629 Key->UnicodeChar = KeyDescriptor->AltGrUnicode;
1630 }
1631 }
1632 }
1633
1634 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1635 if (UsbKeyboardDevice->CapsOn) {
1636 if (Key->UnicodeChar == KeyDescriptor->Unicode) {
1637 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1638 } else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1639 Key->UnicodeChar = KeyDescriptor->Unicode;
1640 }
1641 }
1642 }
1643
1644 //
1645 // Translate the CTRL-Alpha characters to their corresponding control value
1646 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1647 //
1648 if (UsbKeyboardDevice->CtrlOn) {
1649 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {
1650 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'a' + 1);
1651 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
1652 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'A' + 1);
1653 }
1654 }
1655
1656 if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) {
1657 //
1658 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1659 // normal key, instead of original control key. So the ScanCode should be cleaned.
1660 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1661 //
1662 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1663 Key->ScanCode = SCAN_NULL;
1664 } else {
1665 Key->UnicodeChar = 0x00;
1666 }
1667 }
1668
1669 //
1670 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1671 //
1672 if (Key->UnicodeChar == 0x1B && Key->ScanCode == SCAN_NULL) {
1673 Key->ScanCode = SCAN_ESC;
1674 Key->UnicodeChar = 0x00;
1675 }
1676
1677 //
1678 // Not valid for key without both unicode key code and EFI Scan Code.
1679 //
1680 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
1681 return EFI_NOT_READY;
1682 }
1683
1684
1685 //
1686 // Save Shift/Toggle state
1687 //
1688 if (UsbKeyboardDevice->LeftCtrlOn) {
1689 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1690 }
1691 if (UsbKeyboardDevice->RightCtrlOn) {
1692 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1693 }
1694 if (UsbKeyboardDevice->LeftAltOn) {
1695 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1696 }
1697 if (UsbKeyboardDevice->RightAltOn) {
1698 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1699 }
1700 if (UsbKeyboardDevice->LeftShiftOn) {
1701 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1702 }
1703 if (UsbKeyboardDevice->RightShiftOn) {
1704 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1705 }
1706 if (UsbKeyboardDevice->LeftLogoOn) {
1707 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1708 }
1709 if (UsbKeyboardDevice->RightLogoOn) {
1710 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1711 }
1712 if (UsbKeyboardDevice->MenuKeyOn) {
1713 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1714 }
1715 if (UsbKeyboardDevice->SysReqOn) {
1716 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1717 }
1718
1719 if (UsbKeyboardDevice->ScrollOn) {
1720 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1721 }
1722 if (UsbKeyboardDevice->NumLockOn) {
1723 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1724 }
1725 if (UsbKeyboardDevice->CapsOn) {
1726 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1727 }
1728
1729 return EFI_SUCCESS;
1730
1731 }
1732
1733
1734 /**
1735 Resets USB keyboard buffer.
1736
1737 @param KeyboardBuffer Points to the USB keyboard buffer.
1738
1739 **/
1740 VOID
1741 EFIAPI
1742 InitUSBKeyBuffer (
1743 OUT USB_KB_BUFFER *KeyboardBuffer
1744 )
1745 {
1746 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));
1747
1748 KeyboardBuffer->BufferHead = KeyboardBuffer->BufferTail;
1749 }
1750
1751
1752 /**
1753 Check whether USB keyboard buffer is empty.
1754
1755 @param KeyboardBuffer USB keyboard buffer
1756
1757 @retval TRUE Keyboard buffer is empty.
1758 @retval FALSE Keyboard buffer is not empty.
1759
1760 **/
1761 BOOLEAN
1762 EFIAPI
1763 IsUSBKeyboardBufferEmpty (
1764 IN USB_KB_BUFFER *KeyboardBuffer
1765 )
1766 {
1767 //
1768 // Meet FIFO empty condition
1769 //
1770 return (BOOLEAN) (KeyboardBuffer->BufferHead == KeyboardBuffer->BufferTail);
1771 }
1772
1773
1774 /**
1775 Check whether USB keyboard buffer is full.
1776
1777 @param KeyboardBuffer USB keyboard buffer
1778
1779 @retval TRUE Keyboard buffer is full.
1780 @retval FALSE Keyboard buffer is not full.
1781
1782 **/
1783 BOOLEAN
1784 EFIAPI
1785 IsUSBKeyboardBufferFull (
1786 IN USB_KB_BUFFER *KeyboardBuffer
1787 )
1788 {
1789 return (BOOLEAN)(((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1)) == KeyboardBuffer->BufferHead);
1790 }
1791
1792
1793 /**
1794 Inserts a keycode into keyboard buffer.
1795
1796 @param KeyboardBuffer Points to the USB keyboard buffer.
1797 @param Key Keycode to insert.
1798 @param Down TRUE means key is pressed.
1799 FALSE means key is released.
1800
1801 **/
1802 VOID
1803 EFIAPI
1804 InsertKeyCode (
1805 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1806 IN UINT8 Key,
1807 IN BOOLEAN Down
1808 )
1809 {
1810 USB_KEY UsbKey;
1811
1812 //
1813 // If keyboard buffer is full, throw the
1814 // first key out of the keyboard buffer.
1815 //
1816 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {
1817 RemoveKeyCode (KeyboardBuffer, &UsbKey);
1818 }
1819
1820 ASSERT (KeyboardBuffer->BufferTail <= MAX_KEY_ALLOWED);
1821
1822 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].KeyCode = Key;
1823 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].Down = Down;
1824
1825 //
1826 // Adjust the tail pointer of the FIFO keyboard buffer.
1827 //
1828 KeyboardBuffer->BufferTail = (UINT8) ((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1));
1829 }
1830
1831
1832 /**
1833 Remove a keycode from keyboard buffer and return it.
1834
1835 @param KeyboardBuffer Points to the USB keyboard buffer.
1836 @param UsbKey Points to the buffer that contains keycode for output.
1837
1838 @retval EFI_SUCCESS Keycode successfully removed from keyboard buffer.
1839 @retval EFI_DEVICE_ERROR Keyboard buffer is empty.
1840
1841 **/
1842 EFI_STATUS
1843 EFIAPI
1844 RemoveKeyCode (
1845 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1846 OUT USB_KEY *UsbKey
1847 )
1848 {
1849 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {
1850 return EFI_DEVICE_ERROR;
1851 }
1852
1853 ASSERT (KeyboardBuffer->BufferHead <= MAX_KEY_ALLOWED);
1854
1855 UsbKey->KeyCode = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].KeyCode;
1856 UsbKey->Down = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].Down;
1857
1858 //
1859 // Adjust the head pointer of the FIFO keyboard buffer.
1860 //
1861 KeyboardBuffer->BufferHead = (UINT8) ((KeyboardBuffer->BufferHead + 1) % (MAX_KEY_ALLOWED + 1));
1862
1863 return EFI_SUCCESS;
1864 }
1865
1866
1867 /**
1868 Sets USB keyboard LED state.
1869
1870 @param UsbKeyboardDevice The USB_KB_DEV instance.
1871
1872 **/
1873 VOID
1874 EFIAPI
1875 SetKeyLED (
1876 IN USB_KB_DEV *UsbKeyboardDevice
1877 )
1878 {
1879 LED_MAP Led;
1880 UINT8 ReportId;
1881
1882 //
1883 // Set each field in Led map.
1884 //
1885 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1886 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1887 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1888 Led.Resrvd = 0;
1889
1890 ReportId = 0;
1891 //
1892 // Call Set_Report Request to lighten the LED.
1893 //
1894 UsbSetReportRequest (
1895 UsbKeyboardDevice->UsbIo,
1896 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1897 ReportId,
1898 HID_OUTPUT_REPORT,
1899 1,
1900 (UINT8 *) &Led
1901 );
1902 }
1903
1904
1905 /**
1906 Handler for Repeat Key event.
1907
1908 This function is the handler for Repeat Key event triggered
1909 by timer.
1910 After a repeatable key is pressed, the event would be triggered
1911 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1912 following trigger will come with interval of USBKBD_REPEAT_RATE.
1913
1914 @param Event The Repeat Key event.
1915 @param Context Points to the USB_KB_DEV instance.
1916
1917 **/
1918 VOID
1919 EFIAPI
1920 USBKeyboardRepeatHandler (
1921 IN EFI_EVENT Event,
1922 IN VOID *Context
1923 )
1924 {
1925 USB_KB_DEV *UsbKeyboardDevice;
1926
1927 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1928
1929 //
1930 // Do nothing when there is no repeat key.
1931 //
1932 if (UsbKeyboardDevice->RepeatKey != 0) {
1933 //
1934 // Inserts the repeat key into keyboard buffer,
1935 //
1936 InsertKeyCode (
1937 &(UsbKeyboardDevice->KeyboardBuffer),
1938 UsbKeyboardDevice->RepeatKey,
1939 TRUE
1940 );
1941
1942 //
1943 // Set repeat rate for next repeat key generation.
1944 //
1945 gBS->SetTimer (
1946 UsbKeyboardDevice->RepeatTimer,
1947 TimerRelative,
1948 USBKBD_REPEAT_RATE
1949 );
1950 }
1951 }
1952
1953
1954 /**
1955 Handler for Delayed Recovery event.
1956
1957 This function is the handler for Delayed Recovery event triggered
1958 by timer.
1959 After a device error occurs, the event would be triggered
1960 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1961 is defined in USB standard for error handling.
1962
1963 @param Event The Delayed Recovery event.
1964 @param Context Points to the USB_KB_DEV instance.
1965
1966 **/
1967 VOID
1968 EFIAPI
1969 USBKeyboardRecoveryHandler (
1970 IN EFI_EVENT Event,
1971 IN VOID *Context
1972 )
1973 {
1974
1975 USB_KB_DEV *UsbKeyboardDevice;
1976 EFI_USB_IO_PROTOCOL *UsbIo;
1977 UINT8 PacketSize;
1978
1979 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1980
1981 UsbIo = UsbKeyboardDevice->UsbIo;
1982
1983 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1984
1985 //
1986 // Re-submit Asynchronous Interrupt Transfer for recovery.
1987 //
1988 UsbIo->UsbAsyncInterruptTransfer (
1989 UsbIo,
1990 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1991 TRUE,
1992 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1993 PacketSize,
1994 KeyboardHandler,
1995 UsbKeyboardDevice
1996 );
1997 }