]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
Minor refinement for USB modules.
[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 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 //
818 if (Protocol != BOOT_PROTOCOL) {
819 UsbSetProtocolRequest (
820 UsbKeyboardDevice->UsbIo,
821 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
822 BOOT_PROTOCOL
823 );
824 }
825
826 //
827 // ReportId is zero, which means the idle rate applies to all input reports.
828 //
829 ReportId = 0;
830 //
831 // Duration is zero, which means the duration is infinite.
832 // so the endpoint will inhibit reporting forever,
833 // and only reporting when a change is detected in the report data.
834 //
835 Duration = 0;
836 UsbSetIdleRequest (
837 UsbKeyboardDevice->UsbIo,
838 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
839 ReportId,
840 Duration
841 );
842
843 UsbKeyboardDevice->CtrlOn = FALSE;
844 UsbKeyboardDevice->AltOn = FALSE;
845 UsbKeyboardDevice->ShiftOn = FALSE;
846 UsbKeyboardDevice->NumLockOn = FALSE;
847 UsbKeyboardDevice->CapsOn = FALSE;
848 UsbKeyboardDevice->ScrollOn = FALSE;
849
850 UsbKeyboardDevice->LeftCtrlOn = FALSE;
851 UsbKeyboardDevice->LeftAltOn = FALSE;
852 UsbKeyboardDevice->LeftShiftOn = FALSE;
853 UsbKeyboardDevice->LeftLogoOn = FALSE;
854 UsbKeyboardDevice->RightCtrlOn = FALSE;
855 UsbKeyboardDevice->RightAltOn = FALSE;
856 UsbKeyboardDevice->RightShiftOn = FALSE;
857 UsbKeyboardDevice->RightLogoOn = FALSE;
858 UsbKeyboardDevice->MenuKeyOn = FALSE;
859 UsbKeyboardDevice->SysReqOn = FALSE;
860
861 UsbKeyboardDevice->AltGrOn = FALSE;
862
863 UsbKeyboardDevice->CurrentNsKey = NULL;
864
865 //
866 // Sync the initial state of lights on keyboard.
867 //
868 SetKeyLED (UsbKeyboardDevice);
869
870 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
871
872 //
873 // Create event for repeat keys' generation.
874 //
875 if (UsbKeyboardDevice->RepeatTimer != NULL) {
876 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
877 UsbKeyboardDevice->RepeatTimer = NULL;
878 }
879
880 gBS->CreateEvent (
881 EVT_TIMER | EVT_NOTIFY_SIGNAL,
882 TPL_NOTIFY,
883 USBKeyboardRepeatHandler,
884 UsbKeyboardDevice,
885 &UsbKeyboardDevice->RepeatTimer
886 );
887
888 //
889 // Create event for delayed recovery, which deals with device error.
890 //
891 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
892 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
893 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
894 }
895
896 gBS->CreateEvent (
897 EVT_TIMER | EVT_NOTIFY_SIGNAL,
898 TPL_NOTIFY,
899 USBKeyboardRecoveryHandler,
900 UsbKeyboardDevice,
901 &UsbKeyboardDevice->DelayedRecoveryEvent
902 );
903
904 return EFI_SUCCESS;
905 }
906
907
908 /**
909 Handler function for USB keyboard's asynchronous interrupt transfer.
910
911 This function is the handler function for USB keyboard's asynchronous interrupt transfer
912 to manage the keyboard. It parses the USB keyboard input report, and inserts data to
913 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
914 is also set accordingly.
915
916 @param Data A pointer to a buffer that is filled with key data which is
917 retrieved via asynchronous interrupt transfer.
918 @param DataLength Indicates the size of the data buffer.
919 @param Context Pointing to USB_KB_DEV instance.
920 @param Result Indicates the result of the asynchronous interrupt transfer.
921
922 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
923 @retval EFI_DEVICE_ERROR Hardware error occurs.
924
925 **/
926 EFI_STATUS
927 EFIAPI
928 KeyboardHandler (
929 IN VOID *Data,
930 IN UINTN DataLength,
931 IN VOID *Context,
932 IN UINT32 Result
933 )
934 {
935 USB_KB_DEV *UsbKeyboardDevice;
936 EFI_USB_IO_PROTOCOL *UsbIo;
937 UINT8 *CurKeyCodeBuffer;
938 UINT8 *OldKeyCodeBuffer;
939 UINT8 CurModifierMap;
940 UINT8 OldModifierMap;
941 UINT8 Mask;
942 UINT8 Index;
943 UINT8 Index2;
944 BOOLEAN Down;
945 BOOLEAN KeyRelease;
946 BOOLEAN KeyPress;
947 UINT8 SavedTail;
948 USB_KEY UsbKey;
949 UINT8 NewRepeatKey;
950 UINT32 UsbStatus;
951 EFI_KEY_DESCRIPTOR *KeyDescriptor;
952
953 ASSERT (Context != NULL);
954
955 NewRepeatKey = 0;
956 UsbKeyboardDevice = (USB_KB_DEV *) Context;
957 UsbIo = UsbKeyboardDevice->UsbIo;
958
959 //
960 // Analyzes Result and performs corresponding action.
961 //
962 if (Result != EFI_USB_NOERROR) {
963 //
964 // Some errors happen during the process
965 //
966 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
967 EFI_ERROR_CODE | EFI_ERROR_MINOR,
968 PcdGet32 (PcdStatusCodeValueKeyboardInputError),
969 UsbKeyboardDevice->DevicePath
970 );
971
972 //
973 // Stop the repeat key generation if any
974 //
975 UsbKeyboardDevice->RepeatKey = 0;
976
977 gBS->SetTimer (
978 UsbKeyboardDevice->RepeatTimer,
979 TimerCancel,
980 USBKBD_REPEAT_RATE
981 );
982
983 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
984 UsbClearEndpointHalt (
985 UsbIo,
986 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
987 &UsbStatus
988 );
989 }
990
991 //
992 // Delete & Submit this interrupt again
993 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
994 //
995 UsbIo->UsbAsyncInterruptTransfer (
996 UsbIo,
997 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
998 FALSE,
999 0,
1000 0,
1001 NULL,
1002 NULL
1003 );
1004 //
1005 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
1006 //
1007 gBS->SetTimer (
1008 UsbKeyboardDevice->DelayedRecoveryEvent,
1009 TimerRelative,
1010 EFI_USB_INTERRUPT_DELAY
1011 );
1012
1013 return EFI_DEVICE_ERROR;
1014 }
1015
1016 //
1017 // If no error and no data, just return EFI_SUCCESS.
1018 //
1019 if (DataLength == 0 || Data == NULL) {
1020 return EFI_SUCCESS;
1021 }
1022
1023 //
1024 // Following code checks current keyboard input report against old key code buffer.
1025 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1026 // Byte 0 is map of Modifier keys.
1027 // Byte 1 is reserved.
1028 // Bytes 2 to 7 are keycodes.
1029 //
1030 CurKeyCodeBuffer = (UINT8 *) Data;
1031 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
1032
1033 //
1034 // Checks for new key stroke.
1035 //
1036 for (Index = 0; Index < 8; Index++) {
1037 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
1038 break;
1039 }
1040 }
1041
1042 //
1043 // If no new key, return EFI_SUCCESS immediately.
1044 //
1045 if (Index == 8) {
1046 return EFI_SUCCESS;
1047 }
1048
1049 //
1050 // Parse the modifier key, which is the first byte of keyboard input report.
1051 //
1052 CurModifierMap = CurKeyCodeBuffer[0];
1053 OldModifierMap = OldKeyCodeBuffer[0];
1054
1055 //
1056 // Handle modifier key's pressing or releasing situation.
1057 // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
1058 // Bit0: Left Control, Keycode: 0xe0
1059 // Bit1: Left Shift, Keycode: 0xe1
1060 // Bit2: Left Alt, Keycode: 0xe2
1061 // Bit3: Left GUI, Keycode: 0xe3
1062 // Bit4: Right Control, Keycode: 0xe4
1063 // Bit5: Right Shift, Keycode: 0xe5
1064 // Bit6: Right Alt, Keycode: 0xe6
1065 // Bit7: Right GUI, Keycode: 0xe7
1066 //
1067 for (Index = 0; Index < 8; Index++) {
1068 Mask = (UINT8) (1 << Index);
1069 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
1070 //
1071 // If current modifier key is up, then CurModifierMap & Mask = 0;
1072 // otherwise it is a non-zero value.
1073 // Insert the changed modifier key into key buffer.
1074 //
1075 Down = (BOOLEAN) ((CurModifierMap & Mask) != 0);
1076 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), (UINT8) (0xe0 + Index), Down);
1077 }
1078 }
1079
1080 //
1081 // Handle normal key's releasing situation
1082 // Bytes 2 to 7 are for normal keycodes
1083 //
1084 KeyRelease = FALSE;
1085 for (Index = 2; Index < 8; Index++) {
1086
1087 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
1088 continue;
1089 }
1090 //
1091 // For any key in old keycode buffer, if it is not in current keycode buffer,
1092 // then it is released. Otherwise, it is not released.
1093 //
1094 KeyRelease = TRUE;
1095 for (Index2 = 2; Index2 < 8; Index2++) {
1096
1097 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
1098 continue;
1099 }
1100
1101 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
1102 KeyRelease = FALSE;
1103 break;
1104 }
1105 }
1106
1107 if (KeyRelease) {
1108 InsertKeyCode (
1109 &(UsbKeyboardDevice->KeyboardBuffer),
1110 OldKeyCodeBuffer[Index],
1111 FALSE
1112 );
1113 //
1114 // The original repeat key is released.
1115 //
1116 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
1117 UsbKeyboardDevice->RepeatKey = 0;
1118 }
1119 }
1120 }
1121
1122 //
1123 // If original repeat key is released, cancel the repeat timer
1124 //
1125 if (UsbKeyboardDevice->RepeatKey == 0) {
1126 gBS->SetTimer (
1127 UsbKeyboardDevice->RepeatTimer,
1128 TimerCancel,
1129 USBKBD_REPEAT_RATE
1130 );
1131 }
1132
1133 //
1134 // Handle normal key's pressing situation
1135 //
1136 KeyPress = FALSE;
1137 for (Index = 2; Index < 8; Index++) {
1138
1139 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
1140 continue;
1141 }
1142 //
1143 // For any key in current keycode buffer, if it is not in old keycode buffer,
1144 // then it is pressed. Otherwise, it is not pressed.
1145 //
1146 KeyPress = TRUE;
1147 for (Index2 = 2; Index2 < 8; Index2++) {
1148
1149 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
1150 continue;
1151 }
1152
1153 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
1154 KeyPress = FALSE;
1155 break;
1156 }
1157 }
1158
1159 if (KeyPress) {
1160 InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], TRUE);
1161
1162 //
1163 // Handle repeat key
1164 //
1165 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
1166 ASSERT (KeyDescriptor != NULL);
1167
1168 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
1169 //
1170 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1171 //
1172 UsbKeyboardDevice->RepeatKey = 0;
1173 } else {
1174 //
1175 // Prepare new repeat key, and clear the original one.
1176 //
1177 NewRepeatKey = CurKeyCodeBuffer[Index];
1178 UsbKeyboardDevice->RepeatKey = 0;
1179 }
1180 }
1181 }
1182
1183 //
1184 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
1185 //
1186 for (Index = 0; Index < 8; Index++) {
1187 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
1188 }
1189
1190 //
1191 // Pre-process KeyboardBuffer to check if Ctrl + Alt + Del is pressed.
1192 //
1193 SavedTail = UsbKeyboardDevice->KeyboardBuffer.BufferTail;
1194 Index = UsbKeyboardDevice->KeyboardBuffer.BufferHead;
1195 while (Index != SavedTail) {
1196 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
1197
1198 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1199
1200 switch (KeyDescriptor->Modifier) {
1201
1202 case EFI_LEFT_CONTROL_MODIFIER:
1203 case EFI_RIGHT_CONTROL_MODIFIER:
1204 if (UsbKey.Down) {
1205 UsbKeyboardDevice->CtrlOn = TRUE;
1206 } else {
1207 UsbKeyboardDevice->CtrlOn = FALSE;
1208 }
1209 break;
1210
1211 case EFI_LEFT_ALT_MODIFIER:
1212 case EFI_RIGHT_ALT_MODIFIER:
1213 if (UsbKey.Down) {
1214 UsbKeyboardDevice->AltOn = TRUE;
1215 } else {
1216 UsbKeyboardDevice->AltOn = FALSE;
1217 }
1218 break;
1219
1220 case EFI_ALT_GR_MODIFIER:
1221 if (UsbKey.Down) {
1222 UsbKeyboardDevice->AltGrOn = TRUE;
1223 } else {
1224 UsbKeyboardDevice->AltGrOn = FALSE;
1225 }
1226 break;
1227
1228 //
1229 // For Del Key, check if Ctrl + Alt + Del occurs for reset.
1230 //
1231 case EFI_DELETE_MODIFIER:
1232 if (UsbKey.Down) {
1233 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1234 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1235 }
1236 }
1237 break;
1238
1239 default:
1240 break;
1241 }
1242
1243 //
1244 // Insert the key back to the buffer,
1245 // so the key sequence will not be destroyed.
1246 //
1247 InsertKeyCode (
1248 &(UsbKeyboardDevice->KeyboardBuffer),
1249 UsbKey.KeyCode,
1250 UsbKey.Down
1251 );
1252 Index = UsbKeyboardDevice->KeyboardBuffer.BufferHead;
1253
1254 }
1255 //
1256 // If there is new key pressed, update the RepeatKey value, and set the
1257 // timer to repeate delay timer
1258 //
1259 if (NewRepeatKey != 0) {
1260 //
1261 // Sets trigger time to "Repeat Delay Time",
1262 // to trigger the repeat timer when the key is hold long
1263 // enough time.
1264 //
1265 gBS->SetTimer (
1266 UsbKeyboardDevice->RepeatTimer,
1267 TimerRelative,
1268 USBKBD_REPEAT_DELAY
1269 );
1270 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1271 }
1272
1273 return EFI_SUCCESS;
1274 }
1275
1276
1277 /**
1278 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1279
1280 This function parses keyboard buffer. It updates state of modifier key for
1281 USB_KB_DEV instancem, and returns keycode for output.
1282
1283 @param UsbKeyboardDevice The USB_KB_DEV instance.
1284 @param KeyCode Pointer to the USB keycode for output.
1285
1286 @retval EFI_SUCCESS Keycode successfully parsed.
1287 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1288
1289 **/
1290 EFI_STATUS
1291 EFIAPI
1292 USBParseKey (
1293 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1294 OUT UINT8 *KeyCode
1295 )
1296 {
1297 USB_KEY UsbKey;
1298 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1299
1300 *KeyCode = 0;
1301
1302 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {
1303 //
1304 // Pops one raw data off.
1305 //
1306 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
1307
1308 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1309 ASSERT (KeyDescriptor != NULL);
1310
1311 if (!UsbKey.Down) {
1312 //
1313 // Key is released.
1314 //
1315 switch (KeyDescriptor->Modifier) {
1316
1317 //
1318 // Ctrl release
1319 //
1320 case EFI_LEFT_CONTROL_MODIFIER:
1321 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1322 UsbKeyboardDevice->CtrlOn = FALSE;
1323 break;
1324 case EFI_RIGHT_CONTROL_MODIFIER:
1325 UsbKeyboardDevice->RightCtrlOn = FALSE;
1326 UsbKeyboardDevice->CtrlOn = FALSE;
1327 break;
1328
1329 //
1330 // Shift release
1331 //
1332 case EFI_LEFT_SHIFT_MODIFIER:
1333 UsbKeyboardDevice->LeftShiftOn = FALSE;
1334 UsbKeyboardDevice->ShiftOn = FALSE;
1335 break;
1336 case EFI_RIGHT_SHIFT_MODIFIER:
1337 UsbKeyboardDevice->RightShiftOn = FALSE;
1338 UsbKeyboardDevice->ShiftOn = FALSE;
1339 break;
1340
1341 //
1342 // Alt release
1343 //
1344 case EFI_LEFT_ALT_MODIFIER:
1345 UsbKeyboardDevice->LeftAltOn = FALSE;
1346 UsbKeyboardDevice->AltOn = FALSE;
1347 break;
1348 case EFI_RIGHT_ALT_MODIFIER:
1349 UsbKeyboardDevice->RightAltOn = FALSE;
1350 UsbKeyboardDevice->AltOn = FALSE;
1351 break;
1352
1353 //
1354 // Left Logo release
1355 //
1356 case EFI_LEFT_LOGO_MODIFIER:
1357 UsbKeyboardDevice->LeftLogoOn = FALSE;
1358 break;
1359
1360 //
1361 // Right Logo release
1362 //
1363 case EFI_RIGHT_LOGO_MODIFIER:
1364 UsbKeyboardDevice->RightLogoOn = FALSE;
1365 break;
1366
1367 //
1368 // Menu key release
1369 //
1370 case EFI_MENU_MODIFIER:
1371 UsbKeyboardDevice->MenuKeyOn = FALSE;
1372 break;
1373
1374 //
1375 // SysReq release
1376 //
1377 case EFI_PRINT_MODIFIER:
1378 case EFI_SYS_REQUEST_MODIFIER:
1379 UsbKeyboardDevice->SysReqOn = FALSE;
1380 break;
1381
1382 //
1383 // AltGr release
1384 //
1385 case EFI_ALT_GR_MODIFIER:
1386 UsbKeyboardDevice->AltGrOn = FALSE;
1387 break;
1388
1389 default:
1390 break;
1391 }
1392
1393 continue;
1394 }
1395
1396 //
1397 // Analyzes key pressing situation
1398 //
1399 switch (KeyDescriptor->Modifier) {
1400
1401 //
1402 // Ctrl press
1403 //
1404 case EFI_LEFT_CONTROL_MODIFIER:
1405 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1406 UsbKeyboardDevice->CtrlOn = TRUE;
1407 continue;
1408 break;
1409 case EFI_RIGHT_CONTROL_MODIFIER:
1410 UsbKeyboardDevice->RightCtrlOn = TRUE;
1411 UsbKeyboardDevice->CtrlOn = TRUE;
1412 continue;
1413 break;
1414
1415 //
1416 // Shift press
1417 //
1418 case EFI_LEFT_SHIFT_MODIFIER:
1419 UsbKeyboardDevice->LeftShiftOn = TRUE;
1420 UsbKeyboardDevice->ShiftOn = TRUE;
1421 continue;
1422 break;
1423 case EFI_RIGHT_SHIFT_MODIFIER:
1424 UsbKeyboardDevice->RightShiftOn = TRUE;
1425 UsbKeyboardDevice->ShiftOn = TRUE;
1426 continue;
1427 break;
1428
1429 //
1430 // Alt press
1431 //
1432 case EFI_LEFT_ALT_MODIFIER:
1433 UsbKeyboardDevice->LeftAltOn = TRUE;
1434 UsbKeyboardDevice->AltOn = TRUE;
1435 continue;
1436 break;
1437 case EFI_RIGHT_ALT_MODIFIER:
1438 UsbKeyboardDevice->RightAltOn = TRUE;
1439 UsbKeyboardDevice->AltOn = TRUE;
1440 continue;
1441 break;
1442
1443 //
1444 // Left Logo press
1445 //
1446 case EFI_LEFT_LOGO_MODIFIER:
1447 UsbKeyboardDevice->LeftLogoOn = TRUE;
1448 break;
1449
1450 //
1451 // Right Logo press
1452 //
1453 case EFI_RIGHT_LOGO_MODIFIER:
1454 UsbKeyboardDevice->RightLogoOn = TRUE;
1455 break;
1456
1457 //
1458 // Menu key press
1459 //
1460 case EFI_MENU_MODIFIER:
1461 UsbKeyboardDevice->MenuKeyOn = TRUE;
1462 break;
1463
1464 //
1465 // SysReq press
1466 //
1467 case EFI_PRINT_MODIFIER:
1468 case EFI_SYS_REQUEST_MODIFIER:
1469 UsbKeyboardDevice->SysReqOn = TRUE;
1470 continue;
1471 break;
1472
1473 //
1474 // AltGr press
1475 //
1476 case EFI_ALT_GR_MODIFIER:
1477 UsbKeyboardDevice->AltGrOn = TRUE;
1478 break;
1479
1480 case EFI_NUM_LOCK_MODIFIER:
1481 //
1482 // Toggle NumLock
1483 //
1484 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1485 SetKeyLED (UsbKeyboardDevice);
1486 continue;
1487 break;
1488
1489 case EFI_CAPS_LOCK_MODIFIER:
1490 //
1491 // Toggle CapsLock
1492 //
1493 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1494 SetKeyLED (UsbKeyboardDevice);
1495 continue;
1496 break;
1497
1498 case EFI_SCROLL_LOCK_MODIFIER:
1499 //
1500 // Toggle ScrollLock
1501 //
1502 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1503 SetKeyLED (UsbKeyboardDevice);
1504 continue;
1505 break;
1506
1507 //
1508 // F11, F12, PrintScreen, Pause/Break
1509 // could not be retrieved via SimpleTextInEx protocol
1510 //
1511 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER:
1512 case EFI_FUNCTION_KEY_TWELVE_MODIFIER:
1513 case EFI_PAUSE_MODIFIER:
1514 case EFI_BREAK_MODIFIER:
1515 //
1516 // Fall through
1517 //
1518 continue;
1519 break;
1520
1521 default:
1522 break;
1523 }
1524
1525 //
1526 // When encountering Ctrl + Alt + Del, then warm reset.
1527 //
1528 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1529 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1530 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1531 }
1532 }
1533
1534 *KeyCode = UsbKey.KeyCode;
1535 return EFI_SUCCESS;
1536 }
1537
1538 return EFI_NOT_READY;
1539 }
1540
1541
1542 /**
1543 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1544
1545 @param UsbKeyboardDevice The USB_KB_DEV instance.
1546 @param KeyCode Indicates the key code that will be interpreted.
1547 @param Key A pointer to a buffer that is filled in with
1548 the keystroke information for the key that
1549 was pressed.
1550
1551 @retval EFI_SUCCESS Success.
1552 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1553 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1554 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1555 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1556
1557 **/
1558 EFI_STATUS
1559 EFIAPI
1560 UsbKeyCodeToEfiInputKey (
1561 IN USB_KB_DEV *UsbKeyboardDevice,
1562 IN UINT8 KeyCode,
1563 OUT EFI_INPUT_KEY *Key
1564 )
1565 {
1566 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1567
1568 //
1569 // KeyCode must in the range of 0x4 to 0x65
1570 //
1571 if (!USBKBD_VALID_KEYCODE (KeyCode)) {
1572 return EFI_INVALID_PARAMETER;
1573 }
1574 if ((KeyCode - 4) >= NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE) {
1575 return EFI_INVALID_PARAMETER;
1576 }
1577
1578 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1579 ASSERT (KeyDescriptor != NULL);
1580
1581 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1582 //
1583 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1584 //
1585 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1586 return EFI_NOT_READY;
1587 }
1588
1589 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1590 //
1591 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1592 // physical key.
1593 //
1594 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1595 UsbKeyboardDevice->CurrentNsKey = NULL;
1596 }
1597
1598 //
1599 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1600 //
1601 if (KeyDescriptor->Modifier > EFI_FUNCTION_KEY_TWELVE_MODIFIER) {
1602 return EFI_DEVICE_ERROR;
1603 }
1604
1605 Key->ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1606 Key->UnicodeChar = KeyDescriptor->Unicode;
1607
1608 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1609 if (UsbKeyboardDevice->ShiftOn) {
1610 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1611
1612 //
1613 // Need not return associated shift state if a class of printable characters that
1614 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1615 //
1616 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1617 UsbKeyboardDevice->LeftShiftOn = FALSE;
1618 UsbKeyboardDevice->RightShiftOn = FALSE;
1619 }
1620
1621 if (UsbKeyboardDevice->AltGrOn) {
1622 Key->UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1623 }
1624 } else {
1625 //
1626 // Shift off
1627 //
1628 Key->UnicodeChar = KeyDescriptor->Unicode;
1629
1630 if (UsbKeyboardDevice->AltGrOn) {
1631 Key->UnicodeChar = KeyDescriptor->AltGrUnicode;
1632 }
1633 }
1634 }
1635
1636 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1637 if (UsbKeyboardDevice->CapsOn) {
1638 if (Key->UnicodeChar == KeyDescriptor->Unicode) {
1639 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1640 } else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1641 Key->UnicodeChar = KeyDescriptor->Unicode;
1642 }
1643 }
1644 }
1645
1646 //
1647 // Translate the CTRL-Alpha characters to their corresponding control value
1648 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1649 //
1650 if (UsbKeyboardDevice->CtrlOn) {
1651 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {
1652 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'a' + 1);
1653 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
1654 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'A' + 1);
1655 }
1656 }
1657
1658 if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) {
1659 //
1660 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1661 // normal key, instead of original control key. So the ScanCode should be cleaned.
1662 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1663 //
1664 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1665 Key->ScanCode = SCAN_NULL;
1666 } else {
1667 Key->UnicodeChar = 0x00;
1668 }
1669 }
1670
1671 //
1672 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1673 //
1674 if (Key->UnicodeChar == 0x1B && Key->ScanCode == SCAN_NULL) {
1675 Key->ScanCode = SCAN_ESC;
1676 Key->UnicodeChar = 0x00;
1677 }
1678
1679 //
1680 // Not valid for key without both unicode key code and EFI Scan Code.
1681 //
1682 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
1683 return EFI_NOT_READY;
1684 }
1685
1686
1687 //
1688 // Save Shift/Toggle state
1689 //
1690 if (UsbKeyboardDevice->LeftCtrlOn) {
1691 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1692 }
1693 if (UsbKeyboardDevice->RightCtrlOn) {
1694 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1695 }
1696 if (UsbKeyboardDevice->LeftAltOn) {
1697 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1698 }
1699 if (UsbKeyboardDevice->RightAltOn) {
1700 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1701 }
1702 if (UsbKeyboardDevice->LeftShiftOn) {
1703 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1704 }
1705 if (UsbKeyboardDevice->RightShiftOn) {
1706 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1707 }
1708 if (UsbKeyboardDevice->LeftLogoOn) {
1709 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1710 }
1711 if (UsbKeyboardDevice->RightLogoOn) {
1712 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1713 }
1714 if (UsbKeyboardDevice->MenuKeyOn) {
1715 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1716 }
1717 if (UsbKeyboardDevice->SysReqOn) {
1718 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1719 }
1720
1721 if (UsbKeyboardDevice->ScrollOn) {
1722 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1723 }
1724 if (UsbKeyboardDevice->NumLockOn) {
1725 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1726 }
1727 if (UsbKeyboardDevice->CapsOn) {
1728 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1729 }
1730
1731 return EFI_SUCCESS;
1732
1733 }
1734
1735
1736 /**
1737 Resets USB keyboard buffer.
1738
1739 @param KeyboardBuffer Points to the USB keyboard buffer.
1740
1741 **/
1742 VOID
1743 EFIAPI
1744 InitUSBKeyBuffer (
1745 OUT USB_KB_BUFFER *KeyboardBuffer
1746 )
1747 {
1748 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));
1749
1750 KeyboardBuffer->BufferHead = KeyboardBuffer->BufferTail;
1751 }
1752
1753
1754 /**
1755 Check whether USB keyboard buffer is empty.
1756
1757 @param KeyboardBuffer USB keyboard buffer
1758
1759 @retval TRUE Keyboard buffer is empty.
1760 @retval FALSE Keyboard buffer is not empty.
1761
1762 **/
1763 BOOLEAN
1764 EFIAPI
1765 IsUSBKeyboardBufferEmpty (
1766 IN USB_KB_BUFFER *KeyboardBuffer
1767 )
1768 {
1769 //
1770 // Meet FIFO empty condition
1771 //
1772 return (BOOLEAN) (KeyboardBuffer->BufferHead == KeyboardBuffer->BufferTail);
1773 }
1774
1775
1776 /**
1777 Check whether USB keyboard buffer is full.
1778
1779 @param KeyboardBuffer USB keyboard buffer
1780
1781 @retval TRUE Keyboard buffer is full.
1782 @retval FALSE Keyboard buffer is not full.
1783
1784 **/
1785 BOOLEAN
1786 EFIAPI
1787 IsUSBKeyboardBufferFull (
1788 IN USB_KB_BUFFER *KeyboardBuffer
1789 )
1790 {
1791 return (BOOLEAN)(((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1)) == KeyboardBuffer->BufferHead);
1792 }
1793
1794
1795 /**
1796 Inserts a keycode into keyboard buffer.
1797
1798 @param KeyboardBuffer Points to the USB keyboard buffer.
1799 @param Key Keycode to insert.
1800 @param Down TRUE means key is pressed.
1801 FALSE means key is released.
1802
1803 **/
1804 VOID
1805 EFIAPI
1806 InsertKeyCode (
1807 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1808 IN UINT8 Key,
1809 IN BOOLEAN Down
1810 )
1811 {
1812 USB_KEY UsbKey;
1813
1814 //
1815 // If keyboard buffer is full, throw the
1816 // first key out of the keyboard buffer.
1817 //
1818 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {
1819 RemoveKeyCode (KeyboardBuffer, &UsbKey);
1820 }
1821
1822 ASSERT (KeyboardBuffer->BufferTail <= MAX_KEY_ALLOWED);
1823
1824 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].KeyCode = Key;
1825 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].Down = Down;
1826
1827 //
1828 // Adjust the tail pointer of the FIFO keyboard buffer.
1829 //
1830 KeyboardBuffer->BufferTail = (UINT8) ((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1));
1831 }
1832
1833
1834 /**
1835 Remove a keycode from keyboard buffer and return it.
1836
1837 @param KeyboardBuffer Points to the USB keyboard buffer.
1838 @param UsbKey Points to the buffer that contains keycode for output.
1839
1840 @retval EFI_SUCCESS Keycode successfully removed from keyboard buffer.
1841 @retval EFI_DEVICE_ERROR Keyboard buffer is empty.
1842
1843 **/
1844 EFI_STATUS
1845 EFIAPI
1846 RemoveKeyCode (
1847 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1848 OUT USB_KEY *UsbKey
1849 )
1850 {
1851 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {
1852 return EFI_DEVICE_ERROR;
1853 }
1854
1855 ASSERT (KeyboardBuffer->BufferHead <= MAX_KEY_ALLOWED);
1856
1857 UsbKey->KeyCode = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].KeyCode;
1858 UsbKey->Down = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].Down;
1859
1860 //
1861 // Adjust the head pointer of the FIFO keyboard buffer.
1862 //
1863 KeyboardBuffer->BufferHead = (UINT8) ((KeyboardBuffer->BufferHead + 1) % (MAX_KEY_ALLOWED + 1));
1864
1865 return EFI_SUCCESS;
1866 }
1867
1868
1869 /**
1870 Sets USB keyboard LED state.
1871
1872 @param UsbKeyboardDevice The USB_KB_DEV instance.
1873
1874 **/
1875 VOID
1876 EFIAPI
1877 SetKeyLED (
1878 IN USB_KB_DEV *UsbKeyboardDevice
1879 )
1880 {
1881 LED_MAP Led;
1882 UINT8 ReportId;
1883
1884 //
1885 // Set each field in Led map.
1886 //
1887 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1888 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1889 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1890 Led.Resrvd = 0;
1891
1892 ReportId = 0;
1893 //
1894 // Call Set_Report Request to lighten the LED.
1895 //
1896 UsbSetReportRequest (
1897 UsbKeyboardDevice->UsbIo,
1898 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1899 ReportId,
1900 HID_OUTPUT_REPORT,
1901 1,
1902 (UINT8 *) &Led
1903 );
1904 }
1905
1906
1907 /**
1908 Handler for Repeat Key event.
1909
1910 This function is the handler for Repeat Key event triggered
1911 by timer.
1912 After a repeatable key is pressed, the event would be triggered
1913 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1914 following trigger will come with interval of USBKBD_REPEAT_RATE.
1915
1916 @param Event The Repeat Key event.
1917 @param Context Points to the USB_KB_DEV instance.
1918
1919 **/
1920 VOID
1921 EFIAPI
1922 USBKeyboardRepeatHandler (
1923 IN EFI_EVENT Event,
1924 IN VOID *Context
1925 )
1926 {
1927 USB_KB_DEV *UsbKeyboardDevice;
1928
1929 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1930
1931 //
1932 // Do nothing when there is no repeat key.
1933 //
1934 if (UsbKeyboardDevice->RepeatKey != 0) {
1935 //
1936 // Inserts the repeat key into keyboard buffer,
1937 //
1938 InsertKeyCode (
1939 &(UsbKeyboardDevice->KeyboardBuffer),
1940 UsbKeyboardDevice->RepeatKey,
1941 TRUE
1942 );
1943
1944 //
1945 // Set repeat rate for next repeat key generation.
1946 //
1947 gBS->SetTimer (
1948 UsbKeyboardDevice->RepeatTimer,
1949 TimerRelative,
1950 USBKBD_REPEAT_RATE
1951 );
1952 }
1953 }
1954
1955
1956 /**
1957 Handler for Delayed Recovery event.
1958
1959 This function is the handler for Delayed Recovery event triggered
1960 by timer.
1961 After a device error occurs, the event would be triggered
1962 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1963 is defined in USB standard for error handling.
1964
1965 @param Event The Delayed Recovery event.
1966 @param Context Points to the USB_KB_DEV instance.
1967
1968 **/
1969 VOID
1970 EFIAPI
1971 USBKeyboardRecoveryHandler (
1972 IN EFI_EVENT Event,
1973 IN VOID *Context
1974 )
1975 {
1976
1977 USB_KB_DEV *UsbKeyboardDevice;
1978 EFI_USB_IO_PROTOCOL *UsbIo;
1979 UINT8 PacketSize;
1980
1981 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1982
1983 UsbIo = UsbKeyboardDevice->UsbIo;
1984
1985 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1986
1987 //
1988 // Re-submit Asynchronous Interrupt Transfer for recovery.
1989 //
1990 UsbIo->UsbAsyncInterruptTransfer (
1991 UsbIo,
1992 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1993 TRUE,
1994 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1995 PacketSize,
1996 KeyboardHandler,
1997 UsbKeyboardDevice
1998 );
1999 }