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