]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
Pass ECC check.
[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 /**
290 Initialize Key Convertion Table by using default keyboard layout.
291
292 @param UsbKeyboardDevice The USB_KB_DEV instance.
293
294 **/
295 VOID
296 EFIAPI
297 LoadDefaultKeyboardLayout (
298 IN OUT USB_KB_DEV *UsbKeyboardDevice
299 )
300 {
301 UINTN Index;
302 EFI_KEY_DESCRIPTOR *KeyDescriptor;
303
304 //
305 // Construct KeyConvertionTable by default keyboard layout
306 //
307 KeyDescriptor = &UsbKeyboardDevice->KeyConvertionTable[0];
308
309 for (Index = 0; Index < (NUMBER_OF_VALID_USB_KEYCODE); Index++) {
310 KeyDescriptor->Key = (EFI_KEY) KeyboardLayoutTable[Index][0];
311 KeyDescriptor->Unicode = KeyboardLayoutTable[Index][1];
312 KeyDescriptor->ShiftedUnicode = KeyboardLayoutTable[Index][2];
313 KeyDescriptor->AltGrUnicode = 0;
314 KeyDescriptor->ShiftedAltGrUnicode = 0;
315 KeyDescriptor->Modifier = KeyboardLayoutTable[Index][3];
316 KeyDescriptor->AffectedAttribute = KeyboardLayoutTable[Index][4];
317
318 KeyDescriptor++;
319 }
320 }
321
322 /**
323 Uses USB I/O to check whether the device is a USB keyboard device.
324
325 @param UsbIo Pointer to a USB I/O protocol instance.
326
327 @retval TRUE Device is a USB keyboard device.
328 @retval FALSE Device is a not USB keyboard device.
329
330 **/
331 BOOLEAN
332 EFIAPI
333 IsUSBKeyboard (
334 IN EFI_USB_IO_PROTOCOL *UsbIo
335 )
336 {
337 EFI_STATUS Status;
338 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
339
340 //
341 // Get the default interface descriptor
342 //
343 Status = UsbIo->UsbGetInterfaceDescriptor (
344 UsbIo,
345 &InterfaceDescriptor
346 );
347
348 if (EFI_ERROR (Status)) {
349 return FALSE;
350 }
351
352 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
353 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
354 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD
355 ) {
356 return TRUE;
357 }
358
359 return FALSE;
360 }
361
362 /**
363 Get current keyboard layout from HII database.
364
365 @return Pointer to HII Keyboard Layout.
366 NULL means failure occurred while trying to get keyboard layout.
367
368 **/
369 EFI_HII_KEYBOARD_LAYOUT *
370 EFIAPI
371 GetCurrentKeyboardLayout (
372 VOID
373 )
374 {
375 EFI_STATUS Status;
376 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
377 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
378 UINT16 Length;
379
380 //
381 // Locate HII Database Protocol
382 //
383 Status = gBS->LocateProtocol (
384 &gEfiHiiDatabaseProtocolGuid,
385 NULL,
386 (VOID **) &HiiDatabase
387 );
388 if (EFI_ERROR (Status)) {
389 return NULL;
390 }
391
392 //
393 // Get current keyboard layout from HII database
394 //
395 Length = 0;
396 KeyboardLayout = NULL;
397 Status = HiiDatabase->GetKeyboardLayout (
398 HiiDatabase,
399 NULL,
400 &Length,
401 KeyboardLayout
402 );
403 if (Status == EFI_BUFFER_TOO_SMALL) {
404 KeyboardLayout = AllocatePool (Length);
405 ASSERT (KeyboardLayout != NULL);
406
407 Status = HiiDatabase->GetKeyboardLayout (
408 HiiDatabase,
409 NULL,
410 &Length,
411 KeyboardLayout
412 );
413 if (EFI_ERROR (Status)) {
414 FreePool (KeyboardLayout);
415 KeyboardLayout = NULL;
416 }
417 }
418
419 return KeyboardLayout;
420 }
421
422 /**
423 Find Key Descriptor in Key Convertion Table given its USB keycode.
424
425 @param UsbKeyboardDevice The USB_KB_DEV instance.
426 @param KeyCode USB Keycode.
427
428 @return The Key Descriptor in Key Convertion Table.
429 NULL means not found.
430
431 **/
432 EFI_KEY_DESCRIPTOR *
433 EFIAPI
434 GetKeyDescriptor (
435 IN USB_KB_DEV *UsbKeyboardDevice,
436 IN UINT8 KeyCode
437 )
438 {
439 UINT8 Index;
440
441 //
442 // Make sure KeyCode is in the range of [0x4, 0x65] or [0xe0, 0xe7]
443 //
444 if ((!USBKBD_VALID_KEYCODE (KeyCode)) || ((KeyCode > 0x65) && (KeyCode < 0xe0)) || (KeyCode > 0xe7)) {
445 return NULL;
446 }
447
448 //
449 // Calculate the index of Key Descriptor in Key Convertion Table
450 //
451 if (KeyCode <= 0x65) {
452 Index = (UINT8) (KeyCode - 4);
453 } else {
454 Index = (UINT8) (KeyCode - 0xe0 + NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE);
455 }
456
457 return &UsbKeyboardDevice->KeyConvertionTable[Index];
458 }
459
460 /**
461 Find Non-Spacing key for given Key descriptor.
462
463 @param UsbKeyboardDevice The USB_KB_DEV instance.
464 @param KeyDescriptor Key descriptor.
465
466 @return The Non-Spacing key corresponding to KeyDescriptor
467 NULL means not found.
468
469 **/
470 USB_NS_KEY *
471 EFIAPI
472 FindUsbNsKey (
473 IN USB_KB_DEV *UsbKeyboardDevice,
474 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
475 )
476 {
477 LIST_ENTRY *Link;
478 LIST_ENTRY *NsKeyList;
479 USB_NS_KEY *UsbNsKey;
480
481 NsKeyList = &UsbKeyboardDevice->NsKeyList;
482 Link = GetFirstNode (NsKeyList);
483 while (!IsNull (NsKeyList, Link)) {
484 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
485
486 if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {
487 return UsbNsKey;
488 }
489
490 Link = GetNextNode (NsKeyList, Link);
491 }
492
493 return NULL;
494 }
495
496 /**
497 Find physical key definition for a given key descriptor.
498
499 For a specified non-spacing key, there are a list of physical
500 keys following it. This function traverses the list of
501 physical keys and tries to find the physical key matching
502 the KeyDescriptor.
503
504 @param UsbNsKey The non-spacing key information.
505 @param KeyDescriptor The key descriptor.
506
507 @return The physical key definition.
508 If no physical key is found, parameter KeyDescriptor is returned.
509
510 **/
511 EFI_KEY_DESCRIPTOR *
512 EFIAPI
513 FindPhysicalKey (
514 IN USB_NS_KEY *UsbNsKey,
515 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
516 )
517 {
518 UINTN Index;
519 EFI_KEY_DESCRIPTOR *PhysicalKey;
520
521 PhysicalKey = &UsbNsKey->NsKey[1];
522 for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {
523 if (KeyDescriptor->Key == PhysicalKey->Key) {
524 return PhysicalKey;
525 }
526
527 PhysicalKey++;
528 }
529
530 //
531 // No children definition matched, return original key
532 //
533 return KeyDescriptor;
534 }
535
536 /**
537 The notification function for EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID.
538
539 This function is registered to event of EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
540 group type, which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
541 It tries to get curent keyboard layout from HII database.
542
543 @param Event Event being signaled.
544 @param Context Points to USB_KB_DEV instance.
545
546 **/
547 VOID
548 EFIAPI
549 SetKeyboardLayoutEvent (
550 IN EFI_EVENT Event,
551 IN VOID *Context
552 )
553 {
554 USB_KB_DEV *UsbKeyboardDevice;
555 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
556 EFI_KEY_DESCRIPTOR TempKey;
557 EFI_KEY_DESCRIPTOR *KeyDescriptor;
558 EFI_KEY_DESCRIPTOR *TableEntry;
559 EFI_KEY_DESCRIPTOR *NsKey;
560 USB_NS_KEY *UsbNsKey;
561 UINTN Index;
562 UINTN Index2;
563 UINTN KeyCount;
564 UINT8 KeyCode;
565
566 UsbKeyboardDevice = (USB_KB_DEV *) Context;
567
568 //
569 // Try to get current keyboard layout from HII database
570 //
571 KeyboardLayout = GetCurrentKeyboardLayout ();
572 if (KeyboardLayout == NULL) {
573 return;
574 }
575
576 //
577 // Re-allocate resource for KeyConvertionTable
578 //
579 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
580 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
581 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
582
583 //
584 // Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
585 //
586 KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));
587 for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {
588 //
589 // Copy from HII keyboard layout package binary for alignment
590 //
591 CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
592
593 //
594 // Fill the key into KeyConvertionTable, whose index is calculated from USB keycode.
595 //
596 KeyCode = EfiKeyToUsbKeyCodeConvertionTable [(UINT8) (TempKey.Key)];
597 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
598 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
599
600 //
601 // For non-spacing key, create the list with a non-spacing key followed by physical keys.
602 //
603 if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {
604 UsbNsKey = AllocatePool (sizeof (USB_NS_KEY));
605 ASSERT (UsbNsKey != NULL);
606
607 //
608 // Search for sequential children physical key definitions
609 //
610 KeyCount = 0;
611 NsKey = KeyDescriptor + 1;
612 for (Index2 = Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {
613 CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));
614 if (TempKey.Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER) {
615 KeyCount++;
616 } else {
617 break;
618 }
619 NsKey++;
620 }
621
622 UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;
623 UsbNsKey->KeyCount = KeyCount;
624 UsbNsKey->NsKey = AllocateCopyPool (
625 (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),
626 KeyDescriptor
627 );
628 InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);
629
630 //
631 // Skip over the child physical keys
632 //
633 Index += KeyCount;
634 KeyDescriptor += KeyCount;
635 }
636
637 KeyDescriptor++;
638 }
639
640 //
641 // There are two EfiKeyEnter, duplicate its key descriptor
642 //
643 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);
644 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);
645 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
646
647 FreePool (KeyboardLayout);
648 }
649
650 /**
651 Destroy resources for keyboard layout.
652
653 @param UsbKeyboardDevice The USB_KB_DEV instance.
654
655 **/
656 VOID
657 EFIAPI
658 ReleaseKeyboardLayoutResources (
659 IN OUT USB_KB_DEV *UsbKeyboardDevice
660 )
661 {
662 USB_NS_KEY *UsbNsKey;
663 LIST_ENTRY *Link;
664
665 if (UsbKeyboardDevice->KeyConvertionTable != NULL) {
666 FreePool (UsbKeyboardDevice->KeyConvertionTable);
667 }
668 UsbKeyboardDevice->KeyConvertionTable = NULL;
669
670 while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {
671 Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);
672 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
673 RemoveEntryList (&UsbNsKey->Link);
674
675 FreePool (UsbNsKey->NsKey);
676 FreePool (UsbNsKey);
677 }
678 }
679
680 /**
681 Initialize USB keyboard layout.
682
683 This function initializes Key Convertion Table for the USB keyboard device.
684 It first tries to retrieve layout from HII database. If failed and default
685 layout is enabled, then it just uses the default layout.
686
687 @param UsbKeyboardDevice The USB_KB_DEV instance.
688
689 @retval EFI_SUCCESS Initialization succeeded.
690 @retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII
691 database, and default layout is disabled.
692 @retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.
693
694 **/
695 EFI_STATUS
696 EFIAPI
697 InitKeyboardLayout (
698 OUT USB_KB_DEV *UsbKeyboardDevice
699 )
700 {
701 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
702 EFI_STATUS Status;
703
704 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
705 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
706
707 InitializeListHead (&UsbKeyboardDevice->NsKeyList);
708 UsbKeyboardDevice->CurrentNsKey = NULL;
709 UsbKeyboardDevice->KeyboardLayoutEvent = NULL;
710
711 //
712 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
713 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
714 //
715 Status = gBS->CreateEventEx (
716 EVT_NOTIFY_SIGNAL,
717 TPL_NOTIFY,
718 SetKeyboardLayoutEvent,
719 UsbKeyboardDevice,
720 &gEfiHiiKeyBoardLayoutGuid,
721 &UsbKeyboardDevice->KeyboardLayoutEvent
722 );
723 if (EFI_ERROR (Status)) {
724 return Status;
725 }
726
727 KeyboardLayout = GetCurrentKeyboardLayout ();
728 if (KeyboardLayout != NULL) {
729 //
730 // If current keyboard layout is successfully retrieved from HII database,
731 // force to initialize the keyboard layout.
732 //
733 gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
734 } else {
735 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {
736 //
737 // If no keyboard layout can be retrieved from HII database, and default layout
738 // is disabled, then return EFI_NOT_READY.
739 //
740 return EFI_NOT_READY;
741 }
742 //
743 // If no keyboard layout can be retrieved from HII database, and default layout
744 // is enabled, then load the default keyboard layout.
745 //
746 LoadDefaultKeyboardLayout (UsbKeyboardDevice);
747 }
748
749 return EFI_SUCCESS;
750 }
751
752
753 /**
754 Initialize USB keyboard device and all private data structures.
755
756 @param UsbKeyboardDevice The USB_KB_DEV instance.
757
758 @retval EFI_SUCCESS Initialization is successful.
759 @retval EFI_DEVICE_ERROR Keyboard initialization failed.
760
761 **/
762 EFI_STATUS
763 EFIAPI
764 InitUSBKeyboard (
765 IN OUT USB_KB_DEV *UsbKeyboardDevice
766 )
767 {
768 UINT8 ConfigValue;
769 UINT8 Protocol;
770 UINT8 ReportId;
771 UINT8 Duration;
772 EFI_STATUS Status;
773 UINT32 TransferResult;
774
775 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
776 EFI_PROGRESS_CODE,
777 PcdGet32 (PcdStatusCodeValueKeyboardSelfTest),
778 UsbKeyboardDevice->DevicePath
779 );
780
781 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
782
783 //
784 // Uses default configuration to configure the USB keyboard device.
785 //
786 ConfigValue = 0x01;
787 Status = UsbSetConfiguration (
788 UsbKeyboardDevice->UsbIo,
789 (UINT16) ConfigValue,
790 &TransferResult
791 );
792 if (EFI_ERROR (Status)) {
793 //
794 // If configuration could not be set here, it means
795 // the keyboard interface has some errors and could
796 // not be initialized
797 //
798 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
799 EFI_ERROR_CODE | EFI_ERROR_MINOR,
800 PcdGet32 (PcdStatusCodeValueKeyboardInterfaceError),
801 UsbKeyboardDevice->DevicePath
802 );
803
804 return EFI_DEVICE_ERROR;
805 }
806
807 UsbGetProtocolRequest (
808 UsbKeyboardDevice->UsbIo,
809 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
810 &Protocol
811 );
812 //
813 // Set boot protocol for the USB Keyboard.
814 // This driver only supports boot protocol.
815 //
816 if (Protocol != BOOT_PROTOCOL) {
817 UsbSetProtocolRequest (
818 UsbKeyboardDevice->UsbIo,
819 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
820 BOOT_PROTOCOL
821 );
822 }
823
824 //
825 // ReportId is zero, which means the idle rate applies to all input reports.
826 //
827 ReportId = 0;
828 //
829 // Duration is zero, which means the duration is infinite.
830 // so the endpoint will inhibit reporting forever,
831 // and only reporting when a change is detected in the report data.
832 //
833 Duration = 0;
834 UsbSetIdleRequest (
835 UsbKeyboardDevice->UsbIo,
836 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
837 ReportId,
838 Duration
839 );
840
841 UsbKeyboardDevice->CtrlOn = FALSE;
842 UsbKeyboardDevice->AltOn = FALSE;
843 UsbKeyboardDevice->ShiftOn = FALSE;
844 UsbKeyboardDevice->NumLockOn = FALSE;
845 UsbKeyboardDevice->CapsOn = FALSE;
846 UsbKeyboardDevice->ScrollOn = FALSE;
847
848 UsbKeyboardDevice->LeftCtrlOn = FALSE;
849 UsbKeyboardDevice->LeftAltOn = FALSE;
850 UsbKeyboardDevice->LeftShiftOn = FALSE;
851 UsbKeyboardDevice->LeftLogoOn = FALSE;
852 UsbKeyboardDevice->RightCtrlOn = FALSE;
853 UsbKeyboardDevice->RightAltOn = FALSE;
854 UsbKeyboardDevice->RightShiftOn = FALSE;
855 UsbKeyboardDevice->RightLogoOn = FALSE;
856 UsbKeyboardDevice->MenuKeyOn = FALSE;
857 UsbKeyboardDevice->SysReqOn = FALSE;
858
859 UsbKeyboardDevice->AltGrOn = FALSE;
860
861 UsbKeyboardDevice->CurrentNsKey = NULL;
862
863 //
864 // Sync the initial state of lights on keyboard.
865 //
866 SetKeyLED (UsbKeyboardDevice);
867
868 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
869
870 //
871 // Create event for repeat keys' generation.
872 //
873 if (UsbKeyboardDevice->RepeatTimer != NULL) {
874 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
875 UsbKeyboardDevice->RepeatTimer = NULL;
876 }
877
878 gBS->CreateEvent (
879 EVT_TIMER | EVT_NOTIFY_SIGNAL,
880 TPL_NOTIFY,
881 USBKeyboardRepeatHandler,
882 UsbKeyboardDevice,
883 &UsbKeyboardDevice->RepeatTimer
884 );
885
886 //
887 // Create event for delayed recovery, which deals with device error.
888 //
889 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
890 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
891 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
892 }
893
894 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 ASSERT (KeyDescriptor != NULL);
1198
1199 switch (KeyDescriptor->Modifier) {
1200
1201 case EFI_LEFT_CONTROL_MODIFIER:
1202 case EFI_RIGHT_CONTROL_MODIFIER:
1203 if (UsbKey.Down) {
1204 UsbKeyboardDevice->CtrlOn = TRUE;
1205 } else {
1206 UsbKeyboardDevice->CtrlOn = FALSE;
1207 }
1208 break;
1209
1210 case EFI_LEFT_ALT_MODIFIER:
1211 case EFI_RIGHT_ALT_MODIFIER:
1212 if (UsbKey.Down) {
1213 UsbKeyboardDevice->AltOn = TRUE;
1214 } else {
1215 UsbKeyboardDevice->AltOn = FALSE;
1216 }
1217 break;
1218
1219 case EFI_ALT_GR_MODIFIER:
1220 if (UsbKey.Down) {
1221 UsbKeyboardDevice->AltGrOn = TRUE;
1222 } else {
1223 UsbKeyboardDevice->AltGrOn = FALSE;
1224 }
1225 break;
1226
1227 //
1228 // For Del Key, check if Ctrl + Alt + Del occurs for reset.
1229 //
1230 case EFI_DELETE_MODIFIER:
1231 if (UsbKey.Down) {
1232 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1233 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1234 }
1235 }
1236 break;
1237
1238 default:
1239 break;
1240 }
1241
1242 //
1243 // Insert the key back to the buffer,
1244 // so the key sequence will not be destroyed.
1245 //
1246 InsertKeyCode (
1247 &(UsbKeyboardDevice->KeyboardBuffer),
1248 UsbKey.KeyCode,
1249 UsbKey.Down
1250 );
1251 Index = UsbKeyboardDevice->KeyboardBuffer.BufferHead;
1252
1253 }
1254 //
1255 // If there is new key pressed, update the RepeatKey value, and set the
1256 // timer to repeate delay timer
1257 //
1258 if (NewRepeatKey != 0) {
1259 //
1260 // Sets trigger time to "Repeat Delay Time",
1261 // to trigger the repeat timer when the key is hold long
1262 // enough time.
1263 //
1264 gBS->SetTimer (
1265 UsbKeyboardDevice->RepeatTimer,
1266 TimerRelative,
1267 USBKBD_REPEAT_DELAY
1268 );
1269 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1270 }
1271
1272 return EFI_SUCCESS;
1273 }
1274
1275
1276 /**
1277 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1278
1279 This function parses keyboard buffer. It updates state of modifier key for
1280 USB_KB_DEV instancem, and returns keycode for output.
1281
1282 @param UsbKeyboardDevice The USB_KB_DEV instance.
1283 @param KeyCode Pointer to the USB keycode for output.
1284
1285 @retval EFI_SUCCESS Keycode successfully parsed.
1286 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1287
1288 **/
1289 EFI_STATUS
1290 EFIAPI
1291 USBParseKey (
1292 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1293 OUT UINT8 *KeyCode
1294 )
1295 {
1296 USB_KEY UsbKey;
1297 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1298
1299 *KeyCode = 0;
1300
1301 while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {
1302 //
1303 // Pops one raw data off.
1304 //
1305 RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
1306
1307 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1308 ASSERT (KeyDescriptor != NULL);
1309
1310 if (!UsbKey.Down) {
1311 //
1312 // Key is released.
1313 //
1314 switch (KeyDescriptor->Modifier) {
1315
1316 //
1317 // Ctrl release
1318 //
1319 case EFI_LEFT_CONTROL_MODIFIER:
1320 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1321 UsbKeyboardDevice->CtrlOn = FALSE;
1322 break;
1323 case EFI_RIGHT_CONTROL_MODIFIER:
1324 UsbKeyboardDevice->RightCtrlOn = FALSE;
1325 UsbKeyboardDevice->CtrlOn = FALSE;
1326 break;
1327
1328 //
1329 // Shift release
1330 //
1331 case EFI_LEFT_SHIFT_MODIFIER:
1332 UsbKeyboardDevice->LeftShiftOn = FALSE;
1333 UsbKeyboardDevice->ShiftOn = FALSE;
1334 break;
1335 case EFI_RIGHT_SHIFT_MODIFIER:
1336 UsbKeyboardDevice->RightShiftOn = FALSE;
1337 UsbKeyboardDevice->ShiftOn = FALSE;
1338 break;
1339
1340 //
1341 // Alt release
1342 //
1343 case EFI_LEFT_ALT_MODIFIER:
1344 UsbKeyboardDevice->LeftAltOn = FALSE;
1345 UsbKeyboardDevice->AltOn = FALSE;
1346 break;
1347 case EFI_RIGHT_ALT_MODIFIER:
1348 UsbKeyboardDevice->RightAltOn = FALSE;
1349 UsbKeyboardDevice->AltOn = FALSE;
1350 break;
1351
1352 //
1353 // Left Logo release
1354 //
1355 case EFI_LEFT_LOGO_MODIFIER:
1356 UsbKeyboardDevice->LeftLogoOn = FALSE;
1357 break;
1358
1359 //
1360 // Right Logo release
1361 //
1362 case EFI_RIGHT_LOGO_MODIFIER:
1363 UsbKeyboardDevice->RightLogoOn = FALSE;
1364 break;
1365
1366 //
1367 // Menu key release
1368 //
1369 case EFI_MENU_MODIFIER:
1370 UsbKeyboardDevice->MenuKeyOn = FALSE;
1371 break;
1372
1373 //
1374 // SysReq release
1375 //
1376 case EFI_PRINT_MODIFIER:
1377 case EFI_SYS_REQUEST_MODIFIER:
1378 UsbKeyboardDevice->SysReqOn = FALSE;
1379 break;
1380
1381 //
1382 // AltGr release
1383 //
1384 case EFI_ALT_GR_MODIFIER:
1385 UsbKeyboardDevice->AltGrOn = FALSE;
1386 break;
1387
1388 default:
1389 break;
1390 }
1391
1392 continue;
1393 }
1394
1395 //
1396 // Analyzes key pressing situation
1397 //
1398 switch (KeyDescriptor->Modifier) {
1399
1400 //
1401 // Ctrl press
1402 //
1403 case EFI_LEFT_CONTROL_MODIFIER:
1404 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1405 UsbKeyboardDevice->CtrlOn = TRUE;
1406 continue;
1407 break;
1408 case EFI_RIGHT_CONTROL_MODIFIER:
1409 UsbKeyboardDevice->RightCtrlOn = TRUE;
1410 UsbKeyboardDevice->CtrlOn = TRUE;
1411 continue;
1412 break;
1413
1414 //
1415 // Shift press
1416 //
1417 case EFI_LEFT_SHIFT_MODIFIER:
1418 UsbKeyboardDevice->LeftShiftOn = TRUE;
1419 UsbKeyboardDevice->ShiftOn = TRUE;
1420 continue;
1421 break;
1422 case EFI_RIGHT_SHIFT_MODIFIER:
1423 UsbKeyboardDevice->RightShiftOn = TRUE;
1424 UsbKeyboardDevice->ShiftOn = TRUE;
1425 continue;
1426 break;
1427
1428 //
1429 // Alt press
1430 //
1431 case EFI_LEFT_ALT_MODIFIER:
1432 UsbKeyboardDevice->LeftAltOn = TRUE;
1433 UsbKeyboardDevice->AltOn = TRUE;
1434 continue;
1435 break;
1436 case EFI_RIGHT_ALT_MODIFIER:
1437 UsbKeyboardDevice->RightAltOn = TRUE;
1438 UsbKeyboardDevice->AltOn = TRUE;
1439 continue;
1440 break;
1441
1442 //
1443 // Left Logo press
1444 //
1445 case EFI_LEFT_LOGO_MODIFIER:
1446 UsbKeyboardDevice->LeftLogoOn = TRUE;
1447 break;
1448
1449 //
1450 // Right Logo press
1451 //
1452 case EFI_RIGHT_LOGO_MODIFIER:
1453 UsbKeyboardDevice->RightLogoOn = TRUE;
1454 break;
1455
1456 //
1457 // Menu key press
1458 //
1459 case EFI_MENU_MODIFIER:
1460 UsbKeyboardDevice->MenuKeyOn = TRUE;
1461 break;
1462
1463 //
1464 // SysReq press
1465 //
1466 case EFI_PRINT_MODIFIER:
1467 case EFI_SYS_REQUEST_MODIFIER:
1468 UsbKeyboardDevice->SysReqOn = TRUE;
1469 continue;
1470 break;
1471
1472 //
1473 // AltGr press
1474 //
1475 case EFI_ALT_GR_MODIFIER:
1476 UsbKeyboardDevice->AltGrOn = TRUE;
1477 break;
1478
1479 case EFI_NUM_LOCK_MODIFIER:
1480 //
1481 // Toggle NumLock
1482 //
1483 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1484 SetKeyLED (UsbKeyboardDevice);
1485 continue;
1486 break;
1487
1488 case EFI_CAPS_LOCK_MODIFIER:
1489 //
1490 // Toggle CapsLock
1491 //
1492 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1493 SetKeyLED (UsbKeyboardDevice);
1494 continue;
1495 break;
1496
1497 case EFI_SCROLL_LOCK_MODIFIER:
1498 //
1499 // Toggle ScrollLock
1500 //
1501 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1502 SetKeyLED (UsbKeyboardDevice);
1503 continue;
1504 break;
1505
1506 //
1507 // F11, F12, PrintScreen, Pause/Break
1508 // could not be retrieved via SimpleTextInEx protocol
1509 //
1510 case EFI_FUNCTION_KEY_ELEVEN_MODIFIER:
1511 case EFI_FUNCTION_KEY_TWELVE_MODIFIER:
1512 case EFI_PAUSE_MODIFIER:
1513 case EFI_BREAK_MODIFIER:
1514 //
1515 // Fall through
1516 //
1517 continue;
1518 break;
1519
1520 default:
1521 break;
1522 }
1523
1524 //
1525 // When encountering Ctrl + Alt + Del, then warm reset.
1526 //
1527 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1528 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1529 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1530 }
1531 }
1532
1533 *KeyCode = UsbKey.KeyCode;
1534 return EFI_SUCCESS;
1535 }
1536
1537 return EFI_NOT_READY;
1538 }
1539
1540
1541 /**
1542 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1543
1544 @param UsbKeyboardDevice The USB_KB_DEV instance.
1545 @param KeyCode Indicates the key code that will be interpreted.
1546 @param Key A pointer to a buffer that is filled in with
1547 the keystroke information for the key that
1548 was pressed.
1549
1550 @retval EFI_SUCCESS Success.
1551 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1552 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1553 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1554 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1555
1556 **/
1557 EFI_STATUS
1558 EFIAPI
1559 UsbKeyCodeToEfiInputKey (
1560 IN USB_KB_DEV *UsbKeyboardDevice,
1561 IN UINT8 KeyCode,
1562 OUT EFI_INPUT_KEY *Key
1563 )
1564 {
1565 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1566
1567 //
1568 // KeyCode must in the range of 0x4 to 0x65
1569 //
1570 if (!USBKBD_VALID_KEYCODE (KeyCode)) {
1571 return EFI_INVALID_PARAMETER;
1572 }
1573 if ((KeyCode - 4) >= NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE) {
1574 return EFI_INVALID_PARAMETER;
1575 }
1576
1577 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1578 ASSERT (KeyDescriptor != NULL);
1579
1580 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1581 //
1582 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1583 //
1584 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1585 return EFI_NOT_READY;
1586 }
1587
1588 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1589 //
1590 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1591 // physical key.
1592 //
1593 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1594 UsbKeyboardDevice->CurrentNsKey = NULL;
1595 }
1596
1597 //
1598 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1599 //
1600 if (KeyDescriptor->Modifier > EFI_FUNCTION_KEY_TWELVE_MODIFIER) {
1601 return EFI_DEVICE_ERROR;
1602 }
1603
1604 Key->ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1605 Key->UnicodeChar = KeyDescriptor->Unicode;
1606
1607 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1608 if (UsbKeyboardDevice->ShiftOn) {
1609 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1610
1611 //
1612 // Need not return associated shift state if a class of printable characters that
1613 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1614 //
1615 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1616 UsbKeyboardDevice->LeftShiftOn = FALSE;
1617 UsbKeyboardDevice->RightShiftOn = FALSE;
1618 }
1619
1620 if (UsbKeyboardDevice->AltGrOn) {
1621 Key->UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1622 }
1623 } else {
1624 //
1625 // Shift off
1626 //
1627 Key->UnicodeChar = KeyDescriptor->Unicode;
1628
1629 if (UsbKeyboardDevice->AltGrOn) {
1630 Key->UnicodeChar = KeyDescriptor->AltGrUnicode;
1631 }
1632 }
1633 }
1634
1635 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1636 if (UsbKeyboardDevice->CapsOn) {
1637 if (Key->UnicodeChar == KeyDescriptor->Unicode) {
1638 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
1639 } else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1640 Key->UnicodeChar = KeyDescriptor->Unicode;
1641 }
1642 }
1643 }
1644
1645 //
1646 // Translate the CTRL-Alpha characters to their corresponding control value
1647 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1648 //
1649 if (UsbKeyboardDevice->CtrlOn) {
1650 if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {
1651 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'a' + 1);
1652 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
1653 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'A' + 1);
1654 }
1655 }
1656
1657 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
1658 //
1659 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1660 // normal key, instead of original control key. So the ScanCode should be cleaned.
1661 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1662 //
1663 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1664 Key->ScanCode = SCAN_NULL;
1665 } else {
1666 Key->UnicodeChar = 0x00;
1667 }
1668 }
1669
1670 //
1671 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1672 //
1673 if (Key->UnicodeChar == 0x1B && Key->ScanCode == SCAN_NULL) {
1674 Key->ScanCode = SCAN_ESC;
1675 Key->UnicodeChar = 0x00;
1676 }
1677
1678 //
1679 // Not valid for key without both unicode key code and EFI Scan Code.
1680 //
1681 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
1682 return EFI_NOT_READY;
1683 }
1684
1685
1686 //
1687 // Save Shift/Toggle state
1688 //
1689 if (UsbKeyboardDevice->LeftCtrlOn) {
1690 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1691 }
1692 if (UsbKeyboardDevice->RightCtrlOn) {
1693 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1694 }
1695 if (UsbKeyboardDevice->LeftAltOn) {
1696 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1697 }
1698 if (UsbKeyboardDevice->RightAltOn) {
1699 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1700 }
1701 if (UsbKeyboardDevice->LeftShiftOn) {
1702 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1703 }
1704 if (UsbKeyboardDevice->RightShiftOn) {
1705 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1706 }
1707 if (UsbKeyboardDevice->LeftLogoOn) {
1708 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1709 }
1710 if (UsbKeyboardDevice->RightLogoOn) {
1711 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1712 }
1713 if (UsbKeyboardDevice->MenuKeyOn) {
1714 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1715 }
1716 if (UsbKeyboardDevice->SysReqOn) {
1717 UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1718 }
1719
1720 if (UsbKeyboardDevice->ScrollOn) {
1721 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1722 }
1723 if (UsbKeyboardDevice->NumLockOn) {
1724 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1725 }
1726 if (UsbKeyboardDevice->CapsOn) {
1727 UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1728 }
1729
1730 return EFI_SUCCESS;
1731
1732 }
1733
1734
1735 /**
1736 Resets USB keyboard buffer.
1737
1738 @param KeyboardBuffer Points to the USB keyboard buffer.
1739
1740 **/
1741 VOID
1742 EFIAPI
1743 InitUSBKeyBuffer (
1744 OUT USB_KB_BUFFER *KeyboardBuffer
1745 )
1746 {
1747 ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));
1748
1749 KeyboardBuffer->BufferHead = KeyboardBuffer->BufferTail;
1750 }
1751
1752
1753 /**
1754 Check whether USB keyboard buffer is empty.
1755
1756 @param KeyboardBuffer USB keyboard buffer
1757
1758 @retval TRUE Keyboard buffer is empty.
1759 @retval FALSE Keyboard buffer is not empty.
1760
1761 **/
1762 BOOLEAN
1763 EFIAPI
1764 IsUSBKeyboardBufferEmpty (
1765 IN USB_KB_BUFFER *KeyboardBuffer
1766 )
1767 {
1768 //
1769 // Meet FIFO empty condition
1770 //
1771 return (BOOLEAN) (KeyboardBuffer->BufferHead == KeyboardBuffer->BufferTail);
1772 }
1773
1774
1775 /**
1776 Check whether USB keyboard buffer is full.
1777
1778 @param KeyboardBuffer USB keyboard buffer
1779
1780 @retval TRUE Keyboard buffer is full.
1781 @retval FALSE Keyboard buffer is not full.
1782
1783 **/
1784 BOOLEAN
1785 EFIAPI
1786 IsUSBKeyboardBufferFull (
1787 IN USB_KB_BUFFER *KeyboardBuffer
1788 )
1789 {
1790 return (BOOLEAN)(((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1)) == KeyboardBuffer->BufferHead);
1791 }
1792
1793
1794 /**
1795 Inserts a keycode into keyboard buffer.
1796
1797 @param KeyboardBuffer Points to the USB keyboard buffer.
1798 @param Key Keycode to insert.
1799 @param Down TRUE means key is pressed.
1800 FALSE means key is released.
1801
1802 **/
1803 VOID
1804 EFIAPI
1805 InsertKeyCode (
1806 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1807 IN UINT8 Key,
1808 IN BOOLEAN Down
1809 )
1810 {
1811 USB_KEY UsbKey;
1812
1813 //
1814 // If keyboard buffer is full, throw the
1815 // first key out of the keyboard buffer.
1816 //
1817 if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {
1818 RemoveKeyCode (KeyboardBuffer, &UsbKey);
1819 }
1820
1821 ASSERT (KeyboardBuffer->BufferTail <= MAX_KEY_ALLOWED);
1822
1823 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].KeyCode = Key;
1824 KeyboardBuffer->Buffer[KeyboardBuffer->BufferTail].Down = Down;
1825
1826 //
1827 // Adjust the tail pointer of the FIFO keyboard buffer.
1828 //
1829 KeyboardBuffer->BufferTail = (UINT8) ((KeyboardBuffer->BufferTail + 1) % (MAX_KEY_ALLOWED + 1));
1830 }
1831
1832
1833 /**
1834 Remove a keycode from keyboard buffer and return it.
1835
1836 @param KeyboardBuffer Points to the USB keyboard buffer.
1837 @param UsbKey Points to the buffer that contains keycode for output.
1838
1839 @retval EFI_SUCCESS Keycode successfully removed from keyboard buffer.
1840 @retval EFI_DEVICE_ERROR Keyboard buffer is empty.
1841
1842 **/
1843 EFI_STATUS
1844 EFIAPI
1845 RemoveKeyCode (
1846 IN OUT USB_KB_BUFFER *KeyboardBuffer,
1847 OUT USB_KEY *UsbKey
1848 )
1849 {
1850 if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {
1851 return EFI_DEVICE_ERROR;
1852 }
1853
1854 ASSERT (KeyboardBuffer->BufferHead <= MAX_KEY_ALLOWED);
1855
1856 UsbKey->KeyCode = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].KeyCode;
1857 UsbKey->Down = KeyboardBuffer->Buffer[KeyboardBuffer->BufferHead].Down;
1858
1859 //
1860 // Adjust the head pointer of the FIFO keyboard buffer.
1861 //
1862 KeyboardBuffer->BufferHead = (UINT8) ((KeyboardBuffer->BufferHead + 1) % (MAX_KEY_ALLOWED + 1));
1863
1864 return EFI_SUCCESS;
1865 }
1866
1867
1868 /**
1869 Sets USB keyboard LED state.
1870
1871 @param UsbKeyboardDevice The USB_KB_DEV instance.
1872
1873 **/
1874 VOID
1875 EFIAPI
1876 SetKeyLED (
1877 IN USB_KB_DEV *UsbKeyboardDevice
1878 )
1879 {
1880 LED_MAP Led;
1881 UINT8 ReportId;
1882
1883 //
1884 // Set each field in Led map.
1885 //
1886 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1887 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1888 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1889 Led.Resrvd = 0;
1890
1891 ReportId = 0;
1892 //
1893 // Call Set_Report Request to lighten the LED.
1894 //
1895 UsbSetReportRequest (
1896 UsbKeyboardDevice->UsbIo,
1897 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1898 ReportId,
1899 HID_OUTPUT_REPORT,
1900 1,
1901 (UINT8 *) &Led
1902 );
1903 }
1904
1905
1906 /**
1907 Handler for Repeat Key event.
1908
1909 This function is the handler for Repeat Key event triggered
1910 by timer.
1911 After a repeatable key is pressed, the event would be triggered
1912 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1913 following trigger will come with interval of USBKBD_REPEAT_RATE.
1914
1915 @param Event The Repeat Key event.
1916 @param Context Points to the USB_KB_DEV instance.
1917
1918 **/
1919 VOID
1920 EFIAPI
1921 USBKeyboardRepeatHandler (
1922 IN EFI_EVENT Event,
1923 IN VOID *Context
1924 )
1925 {
1926 USB_KB_DEV *UsbKeyboardDevice;
1927
1928 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1929
1930 //
1931 // Do nothing when there is no repeat key.
1932 //
1933 if (UsbKeyboardDevice->RepeatKey != 0) {
1934 //
1935 // Inserts the repeat key into keyboard buffer,
1936 //
1937 InsertKeyCode (
1938 &(UsbKeyboardDevice->KeyboardBuffer),
1939 UsbKeyboardDevice->RepeatKey,
1940 TRUE
1941 );
1942
1943 //
1944 // Set repeat rate for next repeat key generation.
1945 //
1946 gBS->SetTimer (
1947 UsbKeyboardDevice->RepeatTimer,
1948 TimerRelative,
1949 USBKBD_REPEAT_RATE
1950 );
1951 }
1952 }
1953
1954
1955 /**
1956 Handler for Delayed Recovery event.
1957
1958 This function is the handler for Delayed Recovery event triggered
1959 by timer.
1960 After a device error occurs, the event would be triggered
1961 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1962 is defined in USB standard for error handling.
1963
1964 @param Event The Delayed Recovery event.
1965 @param Context Points to the USB_KB_DEV instance.
1966
1967 **/
1968 VOID
1969 EFIAPI
1970 USBKeyboardRecoveryHandler (
1971 IN EFI_EVENT Event,
1972 IN VOID *Context
1973 )
1974 {
1975
1976 USB_KB_DEV *UsbKeyboardDevice;
1977 EFI_USB_IO_PROTOCOL *UsbIo;
1978 UINT8 PacketSize;
1979
1980 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1981
1982 UsbIo = UsbKeyboardDevice->UsbIo;
1983
1984 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1985
1986 //
1987 // Re-submit Asynchronous Interrupt Transfer for recovery.
1988 //
1989 UsbIo->UsbAsyncInterruptTransfer (
1990 UsbIo,
1991 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1992 TRUE,
1993 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1994 PacketSize,
1995 KeyboardHandler,
1996 UsbKeyboardDevice
1997 );
1998 }