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