]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
MdeModulePkg: add support for ORICO PEUS3-2P card
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / KeyBoard.c
1 /** @file
2 Helper functions for USB Keyboard Driver.
3
4 Copyright (c) 2004 - 2012, 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 //
300 // For Partial Keystroke support
301 //
302 SCAN_NULL, // EFI_PRINT_MODIFIER
303 SCAN_NULL, // EFI_SYS_REQUEST_MODIFIER
304 SCAN_NULL, // EFI_SCROLL_LOCK_MODIFIER
305 SCAN_PAUSE, // EFI_PAUSE_MODIFIER
306 SCAN_NULL, // EFI_BREAK_MODIFIER
307 SCAN_NULL, // EFI_LEFT_LOGO_MODIFIER
308 SCAN_NULL, // EFI_RIGHT_LOGO_MODIFER
309 SCAN_NULL, // EFI_MENU_MODIFER
310 };
311
312 /**
313 Initialize Key Convention Table by using default keyboard layout.
314
315 @param UsbKeyboardDevice The USB_KB_DEV instance.
316
317 @retval EFI_SUCCESS The default keyboard layout was installed successfully
318 @retval Others Failure to install default keyboard layout.
319 **/
320 EFI_STATUS
321 InstallDefaultKeyboardLayout (
322 IN OUT USB_KB_DEV *UsbKeyboardDevice
323 )
324 {
325 EFI_STATUS Status;
326 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
327 EFI_HII_HANDLE HiiHandle;
328
329 //
330 // Locate Hii database protocol
331 //
332 Status = gBS->LocateProtocol (
333 &gEfiHiiDatabaseProtocolGuid,
334 NULL,
335 (VOID **) &HiiDatabase
336 );
337 if (EFI_ERROR (Status)) {
338 return Status;
339 }
340
341 //
342 // Install Keyboard Layout package to HII database
343 //
344 HiiHandle = HiiAddPackages (
345 &gUsbKeyboardLayoutPackageGuid,
346 UsbKeyboardDevice->ControllerHandle,
347 &mUsbKeyboardLayoutBin,
348 NULL
349 );
350 if (HiiHandle == NULL) {
351 return EFI_OUT_OF_RESOURCES;
352 }
353
354 //
355 // Set current keyboard layout
356 //
357 Status = HiiDatabase->SetKeyboardLayout (HiiDatabase, &gUsbKeyboardLayoutKeyGuid);
358
359 return Status;
360 }
361
362
363 /**
364 Uses USB I/O to check whether the device is a USB keyboard device.
365
366 @param UsbIo Pointer to a USB I/O protocol instance.
367
368 @retval TRUE Device is a USB keyboard device.
369 @retval FALSE Device is a not USB keyboard device.
370
371 **/
372 BOOLEAN
373 IsUSBKeyboard (
374 IN EFI_USB_IO_PROTOCOL *UsbIo
375 )
376 {
377 EFI_STATUS Status;
378 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
379
380 //
381 // Get the default interface descriptor
382 //
383 Status = UsbIo->UsbGetInterfaceDescriptor (
384 UsbIo,
385 &InterfaceDescriptor
386 );
387
388 if (EFI_ERROR (Status)) {
389 return FALSE;
390 }
391
392 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
393 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
394 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD
395 ) {
396 return TRUE;
397 }
398
399 return FALSE;
400 }
401
402 /**
403 Get current keyboard layout from HII database.
404
405 @return Pointer to HII Keyboard Layout.
406 NULL means failure occurred while trying to get keyboard layout.
407
408 **/
409 EFI_HII_KEYBOARD_LAYOUT *
410 GetCurrentKeyboardLayout (
411 VOID
412 )
413 {
414 EFI_STATUS Status;
415 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
416 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
417 UINT16 Length;
418
419 //
420 // Locate HII Database Protocol
421 //
422 Status = gBS->LocateProtocol (
423 &gEfiHiiDatabaseProtocolGuid,
424 NULL,
425 (VOID **) &HiiDatabase
426 );
427 if (EFI_ERROR (Status)) {
428 return NULL;
429 }
430
431 //
432 // Get current keyboard layout from HII database
433 //
434 Length = 0;
435 KeyboardLayout = NULL;
436 Status = HiiDatabase->GetKeyboardLayout (
437 HiiDatabase,
438 NULL,
439 &Length,
440 KeyboardLayout
441 );
442 if (Status == EFI_BUFFER_TOO_SMALL) {
443 KeyboardLayout = AllocatePool (Length);
444 ASSERT (KeyboardLayout != NULL);
445
446 Status = HiiDatabase->GetKeyboardLayout (
447 HiiDatabase,
448 NULL,
449 &Length,
450 KeyboardLayout
451 );
452 if (EFI_ERROR (Status)) {
453 FreePool (KeyboardLayout);
454 KeyboardLayout = NULL;
455 }
456 }
457
458 return KeyboardLayout;
459 }
460
461 /**
462 Find Key Descriptor in Key Convertion Table given its USB keycode.
463
464 @param UsbKeyboardDevice The USB_KB_DEV instance.
465 @param KeyCode USB Keycode.
466
467 @return The Key Descriptor in Key Convertion Table.
468 NULL means not found.
469
470 **/
471 EFI_KEY_DESCRIPTOR *
472 GetKeyDescriptor (
473 IN USB_KB_DEV *UsbKeyboardDevice,
474 IN UINT8 KeyCode
475 )
476 {
477 UINT8 Index;
478
479 //
480 // Make sure KeyCode is in the range of [0x4, 0x65] or [0xe0, 0xe7]
481 //
482 if ((!USBKBD_VALID_KEYCODE (KeyCode)) || ((KeyCode > 0x65) && (KeyCode < 0xe0)) || (KeyCode > 0xe7)) {
483 return NULL;
484 }
485
486 //
487 // Calculate the index of Key Descriptor in Key Convertion Table
488 //
489 if (KeyCode <= 0x65) {
490 Index = (UINT8) (KeyCode - 4);
491 } else {
492 Index = (UINT8) (KeyCode - 0xe0 + NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE);
493 }
494
495 return &UsbKeyboardDevice->KeyConvertionTable[Index];
496 }
497
498 /**
499 Find Non-Spacing key for given Key descriptor.
500
501 @param UsbKeyboardDevice The USB_KB_DEV instance.
502 @param KeyDescriptor Key descriptor.
503
504 @return The Non-Spacing key corresponding to KeyDescriptor
505 NULL means not found.
506
507 **/
508 USB_NS_KEY *
509 FindUsbNsKey (
510 IN USB_KB_DEV *UsbKeyboardDevice,
511 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
512 )
513 {
514 LIST_ENTRY *Link;
515 LIST_ENTRY *NsKeyList;
516 USB_NS_KEY *UsbNsKey;
517
518 NsKeyList = &UsbKeyboardDevice->NsKeyList;
519 Link = GetFirstNode (NsKeyList);
520 while (!IsNull (NsKeyList, Link)) {
521 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
522
523 if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {
524 return UsbNsKey;
525 }
526
527 Link = GetNextNode (NsKeyList, Link);
528 }
529
530 return NULL;
531 }
532
533 /**
534 Find physical key definition for a given key descriptor.
535
536 For a specified non-spacing key, there are a list of physical
537 keys following it. This function traverses the list of
538 physical keys and tries to find the physical key matching
539 the KeyDescriptor.
540
541 @param UsbNsKey The non-spacing key information.
542 @param KeyDescriptor The key descriptor.
543
544 @return The physical key definition.
545 If no physical key is found, parameter KeyDescriptor is returned.
546
547 **/
548 EFI_KEY_DESCRIPTOR *
549 FindPhysicalKey (
550 IN USB_NS_KEY *UsbNsKey,
551 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
552 )
553 {
554 UINTN Index;
555 EFI_KEY_DESCRIPTOR *PhysicalKey;
556
557 PhysicalKey = &UsbNsKey->NsKey[1];
558 for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {
559 if (KeyDescriptor->Key == PhysicalKey->Key) {
560 return PhysicalKey;
561 }
562
563 PhysicalKey++;
564 }
565
566 //
567 // No children definition matched, return original key
568 //
569 return KeyDescriptor;
570 }
571
572 /**
573 The notification function for EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID.
574
575 This function is registered to event of EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
576 group type, which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
577 It tries to get curent keyboard layout from HII database.
578
579 @param Event Event being signaled.
580 @param Context Points to USB_KB_DEV instance.
581
582 **/
583 VOID
584 EFIAPI
585 SetKeyboardLayoutEvent (
586 IN EFI_EVENT Event,
587 IN VOID *Context
588 )
589 {
590 USB_KB_DEV *UsbKeyboardDevice;
591 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
592 EFI_KEY_DESCRIPTOR TempKey;
593 EFI_KEY_DESCRIPTOR *KeyDescriptor;
594 EFI_KEY_DESCRIPTOR *TableEntry;
595 EFI_KEY_DESCRIPTOR *NsKey;
596 USB_NS_KEY *UsbNsKey;
597 UINTN Index;
598 UINTN Index2;
599 UINTN KeyCount;
600 UINT8 KeyCode;
601
602 UsbKeyboardDevice = (USB_KB_DEV *) Context;
603 if (UsbKeyboardDevice->Signature != USB_KB_DEV_SIGNATURE) {
604 return;
605 }
606
607 //
608 // Try to get current keyboard layout from HII database
609 //
610 KeyboardLayout = GetCurrentKeyboardLayout ();
611 if (KeyboardLayout == NULL) {
612 return;
613 }
614
615 //
616 // Re-allocate resource for KeyConvertionTable
617 //
618 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
619 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
620 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
621
622 //
623 // Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
624 //
625 KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));
626 for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {
627 //
628 // Copy from HII keyboard layout package binary for alignment
629 //
630 CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
631
632 //
633 // Fill the key into KeyConvertionTable, whose index is calculated from USB keycode.
634 //
635 KeyCode = EfiKeyToUsbKeyCodeConvertionTable [(UINT8) (TempKey.Key)];
636 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
637 if (TableEntry == NULL) {
638 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
639 FreePool (KeyboardLayout);
640 return;
641 }
642 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
643
644 //
645 // For non-spacing key, create the list with a non-spacing key followed by physical keys.
646 //
647 if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {
648 UsbNsKey = AllocateZeroPool (sizeof (USB_NS_KEY));
649 ASSERT (UsbNsKey != NULL);
650
651 //
652 // Search for sequential children physical key definitions
653 //
654 KeyCount = 0;
655 NsKey = KeyDescriptor + 1;
656 for (Index2 = (UINT8) Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {
657 CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));
658 if (TempKey.Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER) {
659 KeyCount++;
660 } else {
661 break;
662 }
663 NsKey++;
664 }
665
666 UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;
667 UsbNsKey->KeyCount = KeyCount;
668 UsbNsKey->NsKey = AllocateCopyPool (
669 (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),
670 KeyDescriptor
671 );
672 InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);
673
674 //
675 // Skip over the child physical keys
676 //
677 Index += KeyCount;
678 KeyDescriptor += KeyCount;
679 }
680
681 KeyDescriptor++;
682 }
683
684 //
685 // There are two EfiKeyEnter, duplicate its key descriptor
686 //
687 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);
688 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);
689 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
690
691 FreePool (KeyboardLayout);
692 }
693
694 /**
695 Destroy resources for keyboard layout.
696
697 @param UsbKeyboardDevice The USB_KB_DEV instance.
698
699 **/
700 VOID
701 ReleaseKeyboardLayoutResources (
702 IN OUT USB_KB_DEV *UsbKeyboardDevice
703 )
704 {
705 USB_NS_KEY *UsbNsKey;
706 LIST_ENTRY *Link;
707
708 if (UsbKeyboardDevice->KeyConvertionTable != NULL) {
709 FreePool (UsbKeyboardDevice->KeyConvertionTable);
710 }
711 UsbKeyboardDevice->KeyConvertionTable = NULL;
712
713 while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {
714 Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);
715 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
716 RemoveEntryList (&UsbNsKey->Link);
717
718 FreePool (UsbNsKey->NsKey);
719 FreePool (UsbNsKey);
720 }
721 }
722
723 /**
724 Initialize USB keyboard layout.
725
726 This function initializes Key Convertion Table for the USB keyboard device.
727 It first tries to retrieve layout from HII database. If failed and default
728 layout is enabled, then it just uses the default layout.
729
730 @param UsbKeyboardDevice The USB_KB_DEV instance.
731
732 @retval EFI_SUCCESS Initialization succeeded.
733 @retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII
734 database, and default layout is disabled.
735 @retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.
736
737 **/
738 EFI_STATUS
739 InitKeyboardLayout (
740 OUT USB_KB_DEV *UsbKeyboardDevice
741 )
742 {
743 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
744 EFI_STATUS Status;
745
746 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
747 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
748
749 InitializeListHead (&UsbKeyboardDevice->NsKeyList);
750 UsbKeyboardDevice->CurrentNsKey = NULL;
751 UsbKeyboardDevice->KeyboardLayoutEvent = NULL;
752
753 //
754 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
755 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
756 //
757 Status = gBS->CreateEventEx (
758 EVT_NOTIFY_SIGNAL,
759 TPL_NOTIFY,
760 SetKeyboardLayoutEvent,
761 UsbKeyboardDevice,
762 &gEfiHiiKeyBoardLayoutGuid,
763 &UsbKeyboardDevice->KeyboardLayoutEvent
764 );
765 if (EFI_ERROR (Status)) {
766 return Status;
767 }
768
769 KeyboardLayout = GetCurrentKeyboardLayout ();
770 if (KeyboardLayout != NULL) {
771 //
772 // If current keyboard layout is successfully retrieved from HII database,
773 // force to initialize the keyboard layout.
774 //
775 gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
776 } else {
777 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {
778 //
779 // If no keyboard layout can be retrieved from HII database, and default layout
780 // is disabled, then return EFI_NOT_READY.
781 //
782 return EFI_NOT_READY;
783 }
784 //
785 // If no keyboard layout can be retrieved from HII database, and default layout
786 // is enabled, then load the default keyboard layout.
787 //
788 InstallDefaultKeyboardLayout (UsbKeyboardDevice);
789 }
790
791 return EFI_SUCCESS;
792 }
793
794
795 /**
796 Initialize USB keyboard device and all private data structures.
797
798 @param UsbKeyboardDevice The USB_KB_DEV instance.
799
800 @retval EFI_SUCCESS Initialization is successful.
801 @retval EFI_DEVICE_ERROR Keyboard initialization failed.
802
803 **/
804 EFI_STATUS
805 InitUSBKeyboard (
806 IN OUT USB_KB_DEV *UsbKeyboardDevice
807 )
808 {
809 UINT16 ConfigValue;
810 UINT8 Protocol;
811 UINT8 ReportId;
812 UINT8 Duration;
813 EFI_STATUS Status;
814 UINT32 TransferResult;
815
816 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
817 EFI_PROGRESS_CODE,
818 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST),
819 UsbKeyboardDevice->DevicePath
820 );
821
822 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));
823 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));
824
825 //
826 // Use the config out of the descriptor
827 // Assumed the first config is the correct one and this is not always the case
828 //
829 Status = UsbGetConfiguration (
830 UsbKeyboardDevice->UsbIo,
831 &ConfigValue,
832 &TransferResult
833 );
834 if (EFI_ERROR (Status)) {
835 ConfigValue = 0x01;
836 //
837 // Uses default configuration to configure the USB Keyboard device.
838 //
839 Status = UsbSetConfiguration (
840 UsbKeyboardDevice->UsbIo,
841 ConfigValue,
842 &TransferResult
843 );
844 if (EFI_ERROR (Status)) {
845 //
846 // If configuration could not be set here, it means
847 // the keyboard interface has some errors and could
848 // not be initialized
849 //
850 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
851 EFI_ERROR_CODE | EFI_ERROR_MINOR,
852 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
853 UsbKeyboardDevice->DevicePath
854 );
855
856 return EFI_DEVICE_ERROR;
857 }
858 }
859
860 UsbGetProtocolRequest (
861 UsbKeyboardDevice->UsbIo,
862 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
863 &Protocol
864 );
865 //
866 // Set boot protocol for the USB Keyboard.
867 // This driver only supports boot protocol.
868 //
869 if (Protocol != BOOT_PROTOCOL) {
870 UsbSetProtocolRequest (
871 UsbKeyboardDevice->UsbIo,
872 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
873 BOOT_PROTOCOL
874 );
875 }
876
877 //
878 // ReportId is zero, which means the idle rate applies to all input reports.
879 //
880 ReportId = 0;
881 //
882 // Duration is zero, which means the duration is infinite.
883 // so the endpoint will inhibit reporting forever,
884 // and only reporting when a change is detected in the report data.
885 //
886 Duration = 0;
887 UsbSetIdleRequest (
888 UsbKeyboardDevice->UsbIo,
889 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
890 ReportId,
891 Duration
892 );
893
894 UsbKeyboardDevice->CtrlOn = FALSE;
895 UsbKeyboardDevice->AltOn = FALSE;
896 UsbKeyboardDevice->ShiftOn = FALSE;
897 UsbKeyboardDevice->NumLockOn = FALSE;
898 UsbKeyboardDevice->CapsOn = FALSE;
899 UsbKeyboardDevice->ScrollOn = FALSE;
900
901 UsbKeyboardDevice->LeftCtrlOn = FALSE;
902 UsbKeyboardDevice->LeftAltOn = FALSE;
903 UsbKeyboardDevice->LeftShiftOn = FALSE;
904 UsbKeyboardDevice->LeftLogoOn = FALSE;
905 UsbKeyboardDevice->RightCtrlOn = FALSE;
906 UsbKeyboardDevice->RightAltOn = FALSE;
907 UsbKeyboardDevice->RightShiftOn = FALSE;
908 UsbKeyboardDevice->RightLogoOn = FALSE;
909 UsbKeyboardDevice->MenuKeyOn = FALSE;
910 UsbKeyboardDevice->SysReqOn = FALSE;
911
912 UsbKeyboardDevice->AltGrOn = FALSE;
913
914 UsbKeyboardDevice->CurrentNsKey = NULL;
915
916 //
917 // Sync the initial state of lights on keyboard.
918 //
919 SetKeyLED (UsbKeyboardDevice);
920
921 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
922
923 //
924 // Create event for repeat keys' generation.
925 //
926 if (UsbKeyboardDevice->RepeatTimer != NULL) {
927 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
928 UsbKeyboardDevice->RepeatTimer = NULL;
929 }
930
931 gBS->CreateEvent (
932 EVT_TIMER | EVT_NOTIFY_SIGNAL,
933 TPL_CALLBACK,
934 USBKeyboardRepeatHandler,
935 UsbKeyboardDevice,
936 &UsbKeyboardDevice->RepeatTimer
937 );
938
939 //
940 // Create event for delayed recovery, which deals with device error.
941 //
942 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
943 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
944 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
945 }
946
947 gBS->CreateEvent (
948 EVT_TIMER | EVT_NOTIFY_SIGNAL,
949 TPL_NOTIFY,
950 USBKeyboardRecoveryHandler,
951 UsbKeyboardDevice,
952 &UsbKeyboardDevice->DelayedRecoveryEvent
953 );
954
955 return EFI_SUCCESS;
956 }
957
958
959 /**
960 Handler function for USB keyboard's asynchronous interrupt transfer.
961
962 This function is the handler function for USB keyboard's asynchronous interrupt transfer
963 to manage the keyboard. It parses the USB keyboard input report, and inserts data to
964 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
965 is also set accordingly.
966
967 @param Data A pointer to a buffer that is filled with key data which is
968 retrieved via asynchronous interrupt transfer.
969 @param DataLength Indicates the size of the data buffer.
970 @param Context Pointing to USB_KB_DEV instance.
971 @param Result Indicates the result of the asynchronous interrupt transfer.
972
973 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
974 @retval EFI_DEVICE_ERROR Hardware error occurs.
975
976 **/
977 EFI_STATUS
978 EFIAPI
979 KeyboardHandler (
980 IN VOID *Data,
981 IN UINTN DataLength,
982 IN VOID *Context,
983 IN UINT32 Result
984 )
985 {
986 USB_KB_DEV *UsbKeyboardDevice;
987 EFI_USB_IO_PROTOCOL *UsbIo;
988 UINT8 *CurKeyCodeBuffer;
989 UINT8 *OldKeyCodeBuffer;
990 UINT8 CurModifierMap;
991 UINT8 OldModifierMap;
992 UINT8 Mask;
993 UINTN Index;
994 UINT8 Index2;
995 BOOLEAN KeyRelease;
996 BOOLEAN KeyPress;
997 USB_KEY UsbKey;
998 UINT8 NewRepeatKey;
999 UINT32 UsbStatus;
1000 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1001
1002 ASSERT (Context != NULL);
1003
1004 NewRepeatKey = 0;
1005 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1006 UsbIo = UsbKeyboardDevice->UsbIo;
1007
1008 //
1009 // Analyzes Result and performs corresponding action.
1010 //
1011 if (Result != EFI_USB_NOERROR) {
1012 //
1013 // Some errors happen during the process
1014 //
1015 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1016 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1017 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR),
1018 UsbKeyboardDevice->DevicePath
1019 );
1020
1021 //
1022 // Stop the repeat key generation if any
1023 //
1024 UsbKeyboardDevice->RepeatKey = 0;
1025
1026 gBS->SetTimer (
1027 UsbKeyboardDevice->RepeatTimer,
1028 TimerCancel,
1029 USBKBD_REPEAT_RATE
1030 );
1031
1032 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
1033 UsbClearEndpointHalt (
1034 UsbIo,
1035 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1036 &UsbStatus
1037 );
1038 }
1039
1040 //
1041 // Delete & Submit this interrupt again
1042 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
1043 //
1044 UsbIo->UsbAsyncInterruptTransfer (
1045 UsbIo,
1046 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1047 FALSE,
1048 0,
1049 0,
1050 NULL,
1051 NULL
1052 );
1053 //
1054 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
1055 //
1056 gBS->SetTimer (
1057 UsbKeyboardDevice->DelayedRecoveryEvent,
1058 TimerRelative,
1059 EFI_USB_INTERRUPT_DELAY
1060 );
1061
1062 return EFI_DEVICE_ERROR;
1063 }
1064
1065 //
1066 // If no error and no data, just return EFI_SUCCESS.
1067 //
1068 if (DataLength == 0 || Data == NULL) {
1069 return EFI_SUCCESS;
1070 }
1071
1072 //
1073 // Following code checks current keyboard input report against old key code buffer.
1074 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1075 // Byte 0 is map of Modifier keys.
1076 // Byte 1 is reserved.
1077 // Bytes 2 to 7 are keycodes.
1078 //
1079 CurKeyCodeBuffer = (UINT8 *) Data;
1080 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
1081
1082 //
1083 // Checks for new key stroke.
1084 //
1085 for (Index = 0; Index < 8; Index++) {
1086 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
1087 break;
1088 }
1089 }
1090
1091 //
1092 // If no new key, return EFI_SUCCESS immediately.
1093 //
1094 if (Index == 8) {
1095 return EFI_SUCCESS;
1096 }
1097
1098 //
1099 // Parse the modifier key, which is the first byte of keyboard input report.
1100 //
1101 CurModifierMap = CurKeyCodeBuffer[0];
1102 OldModifierMap = OldKeyCodeBuffer[0];
1103
1104 //
1105 // Handle modifier key's pressing or releasing situation.
1106 // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
1107 // Bit0: Left Control, Keycode: 0xe0
1108 // Bit1: Left Shift, Keycode: 0xe1
1109 // Bit2: Left Alt, Keycode: 0xe2
1110 // Bit3: Left GUI, Keycode: 0xe3
1111 // Bit4: Right Control, Keycode: 0xe4
1112 // Bit5: Right Shift, Keycode: 0xe5
1113 // Bit6: Right Alt, Keycode: 0xe6
1114 // Bit7: Right GUI, Keycode: 0xe7
1115 //
1116 for (Index = 0; Index < 8; Index++) {
1117 Mask = (UINT8) (1 << Index);
1118 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
1119 //
1120 // If current modifier key is up, then CurModifierMap & Mask = 0;
1121 // otherwise it is a non-zero value.
1122 // Insert the changed modifier key into key buffer.
1123 //
1124 UsbKey.KeyCode = (UINT8) (0xe0 + Index);
1125 UsbKey.Down = (BOOLEAN) ((CurModifierMap & Mask) != 0);
1126 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1127 }
1128 }
1129
1130 //
1131 // Handle normal key's releasing situation
1132 // Bytes 2 to 7 are for normal keycodes
1133 //
1134 KeyRelease = FALSE;
1135 for (Index = 2; Index < 8; Index++) {
1136
1137 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
1138 continue;
1139 }
1140 //
1141 // For any key in old keycode buffer, if it is not in current keycode buffer,
1142 // then it is released. Otherwise, it is not released.
1143 //
1144 KeyRelease = TRUE;
1145 for (Index2 = 2; Index2 < 8; Index2++) {
1146
1147 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
1148 continue;
1149 }
1150
1151 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
1152 KeyRelease = FALSE;
1153 break;
1154 }
1155 }
1156
1157 if (KeyRelease) {
1158 UsbKey.KeyCode = OldKeyCodeBuffer[Index];
1159 UsbKey.Down = FALSE;
1160 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1161 //
1162 // The original repeat key is released.
1163 //
1164 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
1165 UsbKeyboardDevice->RepeatKey = 0;
1166 }
1167 }
1168 }
1169
1170 //
1171 // If original repeat key is released, cancel the repeat timer
1172 //
1173 if (UsbKeyboardDevice->RepeatKey == 0) {
1174 gBS->SetTimer (
1175 UsbKeyboardDevice->RepeatTimer,
1176 TimerCancel,
1177 USBKBD_REPEAT_RATE
1178 );
1179 }
1180
1181 //
1182 // Handle normal key's pressing situation
1183 //
1184 KeyPress = FALSE;
1185 for (Index = 2; Index < 8; Index++) {
1186
1187 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
1188 continue;
1189 }
1190 //
1191 // For any key in current keycode buffer, if it is not in old keycode buffer,
1192 // then it is pressed. Otherwise, it is not pressed.
1193 //
1194 KeyPress = TRUE;
1195 for (Index2 = 2; Index2 < 8; Index2++) {
1196
1197 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
1198 continue;
1199 }
1200
1201 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
1202 KeyPress = FALSE;
1203 break;
1204 }
1205 }
1206
1207 if (KeyPress) {
1208 UsbKey.KeyCode = CurKeyCodeBuffer[Index];
1209 UsbKey.Down = TRUE;
1210 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1211
1212 //
1213 // Handle repeat key
1214 //
1215 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
1216 ASSERT (KeyDescriptor != NULL);
1217
1218 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
1219 //
1220 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1221 //
1222 UsbKeyboardDevice->RepeatKey = 0;
1223 } else {
1224 //
1225 // Prepare new repeat key, and clear the original one.
1226 //
1227 NewRepeatKey = CurKeyCodeBuffer[Index];
1228 UsbKeyboardDevice->RepeatKey = 0;
1229 }
1230 }
1231 }
1232
1233 //
1234 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
1235 //
1236 for (Index = 0; Index < 8; Index++) {
1237 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
1238 }
1239
1240 //
1241 // If there is new key pressed, update the RepeatKey value, and set the
1242 // timer to repeate delay timer
1243 //
1244 if (NewRepeatKey != 0) {
1245 //
1246 // Sets trigger time to "Repeat Delay Time",
1247 // to trigger the repeat timer when the key is hold long
1248 // enough time.
1249 //
1250 gBS->SetTimer (
1251 UsbKeyboardDevice->RepeatTimer,
1252 TimerRelative,
1253 USBKBD_REPEAT_DELAY
1254 );
1255 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1256 }
1257
1258 return EFI_SUCCESS;
1259 }
1260
1261
1262 /**
1263 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1264
1265 This function parses keyboard buffer. It updates state of modifier key for
1266 USB_KB_DEV instancem, and returns keycode for output.
1267
1268 @param UsbKeyboardDevice The USB_KB_DEV instance.
1269 @param KeyCode Pointer to the USB keycode for output.
1270
1271 @retval EFI_SUCCESS Keycode successfully parsed.
1272 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1273
1274 **/
1275 EFI_STATUS
1276 USBParseKey (
1277 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1278 OUT UINT8 *KeyCode
1279 )
1280 {
1281 USB_KEY UsbKey;
1282 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1283
1284 *KeyCode = 0;
1285
1286 while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {
1287 //
1288 // Pops one raw data off.
1289 //
1290 Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1291
1292 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1293 ASSERT (KeyDescriptor != NULL);
1294
1295 if (!UsbKey.Down) {
1296 //
1297 // Key is released.
1298 //
1299 switch (KeyDescriptor->Modifier) {
1300
1301 //
1302 // Ctrl release
1303 //
1304 case EFI_LEFT_CONTROL_MODIFIER:
1305 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1306 UsbKeyboardDevice->CtrlOn = FALSE;
1307 break;
1308 case EFI_RIGHT_CONTROL_MODIFIER:
1309 UsbKeyboardDevice->RightCtrlOn = FALSE;
1310 UsbKeyboardDevice->CtrlOn = FALSE;
1311 break;
1312
1313 //
1314 // Shift release
1315 //
1316 case EFI_LEFT_SHIFT_MODIFIER:
1317 UsbKeyboardDevice->LeftShiftOn = FALSE;
1318 UsbKeyboardDevice->ShiftOn = FALSE;
1319 break;
1320 case EFI_RIGHT_SHIFT_MODIFIER:
1321 UsbKeyboardDevice->RightShiftOn = FALSE;
1322 UsbKeyboardDevice->ShiftOn = FALSE;
1323 break;
1324
1325 //
1326 // Alt release
1327 //
1328 case EFI_LEFT_ALT_MODIFIER:
1329 UsbKeyboardDevice->LeftAltOn = FALSE;
1330 UsbKeyboardDevice->AltOn = FALSE;
1331 break;
1332 case EFI_RIGHT_ALT_MODIFIER:
1333 UsbKeyboardDevice->RightAltOn = FALSE;
1334 UsbKeyboardDevice->AltOn = FALSE;
1335 break;
1336
1337 //
1338 // Left Logo release
1339 //
1340 case EFI_LEFT_LOGO_MODIFIER:
1341 UsbKeyboardDevice->LeftLogoOn = FALSE;
1342 break;
1343
1344 //
1345 // Right Logo release
1346 //
1347 case EFI_RIGHT_LOGO_MODIFIER:
1348 UsbKeyboardDevice->RightLogoOn = FALSE;
1349 break;
1350
1351 //
1352 // Menu key release
1353 //
1354 case EFI_MENU_MODIFIER:
1355 UsbKeyboardDevice->MenuKeyOn = FALSE;
1356 break;
1357
1358 //
1359 // SysReq release
1360 //
1361 case EFI_PRINT_MODIFIER:
1362 case EFI_SYS_REQUEST_MODIFIER:
1363 UsbKeyboardDevice->SysReqOn = FALSE;
1364 break;
1365
1366 //
1367 // AltGr release
1368 //
1369 case EFI_ALT_GR_MODIFIER:
1370 UsbKeyboardDevice->AltGrOn = FALSE;
1371 break;
1372
1373 default:
1374 break;
1375 }
1376
1377 continue;
1378 }
1379
1380 //
1381 // Analyzes key pressing situation
1382 //
1383 switch (KeyDescriptor->Modifier) {
1384
1385 //
1386 // Ctrl press
1387 //
1388 case EFI_LEFT_CONTROL_MODIFIER:
1389 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1390 UsbKeyboardDevice->CtrlOn = TRUE;
1391 break;
1392 case EFI_RIGHT_CONTROL_MODIFIER:
1393 UsbKeyboardDevice->RightCtrlOn = TRUE;
1394 UsbKeyboardDevice->CtrlOn = TRUE;
1395 break;
1396
1397 //
1398 // Shift press
1399 //
1400 case EFI_LEFT_SHIFT_MODIFIER:
1401 UsbKeyboardDevice->LeftShiftOn = TRUE;
1402 UsbKeyboardDevice->ShiftOn = TRUE;
1403 break;
1404 case EFI_RIGHT_SHIFT_MODIFIER:
1405 UsbKeyboardDevice->RightShiftOn = TRUE;
1406 UsbKeyboardDevice->ShiftOn = TRUE;
1407 break;
1408
1409 //
1410 // Alt press
1411 //
1412 case EFI_LEFT_ALT_MODIFIER:
1413 UsbKeyboardDevice->LeftAltOn = TRUE;
1414 UsbKeyboardDevice->AltOn = TRUE;
1415 break;
1416 case EFI_RIGHT_ALT_MODIFIER:
1417 UsbKeyboardDevice->RightAltOn = TRUE;
1418 UsbKeyboardDevice->AltOn = TRUE;
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 break;
1449
1450 //
1451 // AltGr press
1452 //
1453 case EFI_ALT_GR_MODIFIER:
1454 UsbKeyboardDevice->AltGrOn = TRUE;
1455 break;
1456
1457 case EFI_NUM_LOCK_MODIFIER:
1458 //
1459 // Toggle NumLock
1460 //
1461 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1462 SetKeyLED (UsbKeyboardDevice);
1463 break;
1464
1465 case EFI_CAPS_LOCK_MODIFIER:
1466 //
1467 // Toggle CapsLock
1468 //
1469 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1470 SetKeyLED (UsbKeyboardDevice);
1471 break;
1472
1473 case EFI_SCROLL_LOCK_MODIFIER:
1474 //
1475 // Toggle ScrollLock
1476 //
1477 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1478 SetKeyLED (UsbKeyboardDevice);
1479 break;
1480
1481 default:
1482 break;
1483 }
1484
1485 //
1486 // When encountering Ctrl + Alt + Del, then warm reset.
1487 //
1488 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1489 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1490 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1491 }
1492 }
1493
1494 *KeyCode = UsbKey.KeyCode;
1495 return EFI_SUCCESS;
1496 }
1497
1498 return EFI_NOT_READY;
1499 }
1500
1501
1502 /**
1503 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1504
1505 @param UsbKeyboardDevice The USB_KB_DEV instance.
1506 @param KeyCode Indicates the key code that will be interpreted.
1507 @param KeyData A pointer to a buffer that is filled in with
1508 the keystroke information for the key that
1509 was pressed.
1510
1511 @retval EFI_SUCCESS Success.
1512 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1513 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1514 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1515 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1516
1517 **/
1518 EFI_STATUS
1519 UsbKeyCodeToEfiInputKey (
1520 IN USB_KB_DEV *UsbKeyboardDevice,
1521 IN UINT8 KeyCode,
1522 OUT EFI_KEY_DATA *KeyData
1523 )
1524 {
1525 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1526 LIST_ENTRY *Link;
1527 LIST_ENTRY *NotifyList;
1528 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1529
1530 //
1531 // KeyCode must in the range of [0x4, 0x65] or [0xe0, 0xe7].
1532 //
1533 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1534 ASSERT (KeyDescriptor != NULL);
1535
1536 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1537 //
1538 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1539 //
1540 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1541 return EFI_NOT_READY;
1542 }
1543
1544 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1545 //
1546 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1547 // physical key.
1548 //
1549 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1550 UsbKeyboardDevice->CurrentNsKey = NULL;
1551 }
1552
1553 //
1554 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1555 //
1556 if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {
1557 return EFI_DEVICE_ERROR;
1558 }
1559
1560 KeyData->Key.ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1561 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1562
1563 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1564 if (UsbKeyboardDevice->ShiftOn) {
1565 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1566
1567 //
1568 // Need not return associated shift state if a class of printable characters that
1569 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1570 //
1571 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1572 UsbKeyboardDevice->LeftShiftOn = FALSE;
1573 UsbKeyboardDevice->RightShiftOn = FALSE;
1574 }
1575
1576 if (UsbKeyboardDevice->AltGrOn) {
1577 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1578 }
1579 } else {
1580 //
1581 // Shift off
1582 //
1583 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1584
1585 if (UsbKeyboardDevice->AltGrOn) {
1586 KeyData->Key.UnicodeChar = KeyDescriptor->AltGrUnicode;
1587 }
1588 }
1589 }
1590
1591 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1592 if (UsbKeyboardDevice->CapsOn) {
1593 if (KeyData->Key.UnicodeChar == KeyDescriptor->Unicode) {
1594 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1595 } else if (KeyData->Key.UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1596 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1597 }
1598 }
1599 }
1600
1601 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
1602 //
1603 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1604 // normal key, instead of original control key. So the ScanCode should be cleaned.
1605 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1606 //
1607 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1608 KeyData->Key.ScanCode = SCAN_NULL;
1609 } else {
1610 KeyData->Key.UnicodeChar = CHAR_NULL;
1611 }
1612 }
1613
1614 //
1615 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1616 //
1617 if (KeyData->Key.UnicodeChar == 0x1B && KeyData->Key.ScanCode == SCAN_NULL) {
1618 KeyData->Key.ScanCode = SCAN_ESC;
1619 KeyData->Key.UnicodeChar = CHAR_NULL;
1620 }
1621
1622 //
1623 // Not valid for key without both unicode key code and EFI Scan Code.
1624 //
1625 if (KeyData->Key.UnicodeChar == 0 && KeyData->Key.ScanCode == SCAN_NULL) {
1626 if (!UsbKeyboardDevice->IsSupportPartialKey) {
1627 return EFI_NOT_READY;
1628 }
1629 }
1630
1631 //
1632 // Save Shift/Toggle state
1633 //
1634 KeyData->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
1635 KeyData->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
1636
1637 if (UsbKeyboardDevice->LeftCtrlOn) {
1638 KeyData->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1639 }
1640 if (UsbKeyboardDevice->RightCtrlOn) {
1641 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1642 }
1643 if (UsbKeyboardDevice->LeftAltOn) {
1644 KeyData->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1645 }
1646 if (UsbKeyboardDevice->RightAltOn) {
1647 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1648 }
1649 if (UsbKeyboardDevice->LeftShiftOn) {
1650 KeyData->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1651 }
1652 if (UsbKeyboardDevice->RightShiftOn) {
1653 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1654 }
1655 if (UsbKeyboardDevice->LeftLogoOn) {
1656 KeyData->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1657 }
1658 if (UsbKeyboardDevice->RightLogoOn) {
1659 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1660 }
1661 if (UsbKeyboardDevice->MenuKeyOn) {
1662 KeyData->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1663 }
1664 if (UsbKeyboardDevice->SysReqOn) {
1665 KeyData->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1666 }
1667
1668 if (UsbKeyboardDevice->ScrollOn) {
1669 KeyData->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1670 }
1671 if (UsbKeyboardDevice->NumLockOn) {
1672 KeyData->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1673 }
1674 if (UsbKeyboardDevice->CapsOn) {
1675 KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1676 }
1677 if (UsbKeyboardDevice->IsSupportPartialKey) {
1678 KeyData->KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED;
1679 }
1680 //
1681 // Invoke notification functions if the key is registered.
1682 //
1683 NotifyList = &UsbKeyboardDevice->NotifyList;
1684 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
1685 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
1686 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
1687 CurrentNotify->KeyNotificationFn (KeyData);
1688 }
1689 }
1690
1691 return EFI_SUCCESS;
1692 }
1693
1694
1695 /**
1696 Create the queue.
1697
1698 @param Queue Points to the queue.
1699 @param ItemSize Size of the single item.
1700
1701 **/
1702 VOID
1703 InitQueue (
1704 IN OUT USB_SIMPLE_QUEUE *Queue,
1705 IN UINTN ItemSize
1706 )
1707 {
1708 UINTN Index;
1709
1710 Queue->ItemSize = ItemSize;
1711 Queue->Head = 0;
1712 Queue->Tail = 0;
1713
1714 if (Queue->Buffer[0] != NULL) {
1715 FreePool (Queue->Buffer[0]);
1716 }
1717
1718 Queue->Buffer[0] = AllocatePool (sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]) * ItemSize);
1719 ASSERT (Queue->Buffer[0] != NULL);
1720
1721 for (Index = 1; Index < sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]); Index++) {
1722 Queue->Buffer[Index] = ((UINT8 *) Queue->Buffer[Index - 1]) + ItemSize;
1723 }
1724 }
1725
1726 /**
1727 Destroy the queue
1728
1729 @param Queue Points to the queue.
1730 **/
1731 VOID
1732 DestroyQueue (
1733 IN OUT USB_SIMPLE_QUEUE *Queue
1734 )
1735 {
1736 FreePool (Queue->Buffer[0]);
1737 }
1738
1739
1740 /**
1741 Check whether the queue is empty.
1742
1743 @param Queue Points to the queue.
1744
1745 @retval TRUE Queue is empty.
1746 @retval FALSE Queue is not empty.
1747
1748 **/
1749 BOOLEAN
1750 IsQueueEmpty (
1751 IN USB_SIMPLE_QUEUE *Queue
1752 )
1753 {
1754 //
1755 // Meet FIFO empty condition
1756 //
1757 return (BOOLEAN) (Queue->Head == Queue->Tail);
1758 }
1759
1760
1761 /**
1762 Check whether the queue is full.
1763
1764 @param Queue Points to the queue.
1765
1766 @retval TRUE Queue is full.
1767 @retval FALSE Queue is not full.
1768
1769 **/
1770 BOOLEAN
1771 IsQueueFull (
1772 IN USB_SIMPLE_QUEUE *Queue
1773 )
1774 {
1775 return (BOOLEAN) (((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);
1776 }
1777
1778
1779 /**
1780 Enqueue the item to the queue.
1781
1782 @param Queue Points to the queue.
1783 @param Item Points to the item to be enqueued.
1784 @param ItemSize Size of the item.
1785 **/
1786 VOID
1787 Enqueue (
1788 IN OUT USB_SIMPLE_QUEUE *Queue,
1789 IN VOID *Item,
1790 IN UINTN ItemSize
1791 )
1792 {
1793 ASSERT (ItemSize == Queue->ItemSize);
1794 //
1795 // If keyboard buffer is full, throw the
1796 // first key out of the keyboard buffer.
1797 //
1798 if (IsQueueFull (Queue)) {
1799 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1800 }
1801
1802 CopyMem (Queue->Buffer[Queue->Tail], Item, ItemSize);
1803
1804 //
1805 // Adjust the tail pointer of the FIFO keyboard buffer.
1806 //
1807 Queue->Tail = (Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1);
1808 }
1809
1810
1811 /**
1812 Dequeue a item from the queue.
1813
1814 @param Queue Points to the queue.
1815 @param Item Receives the item.
1816 @param ItemSize Size of the item.
1817
1818 @retval EFI_SUCCESS Item was successfully dequeued.
1819 @retval EFI_DEVICE_ERROR The queue is empty.
1820
1821 **/
1822 EFI_STATUS
1823 Dequeue (
1824 IN OUT USB_SIMPLE_QUEUE *Queue,
1825 OUT VOID *Item,
1826 IN UINTN ItemSize
1827 )
1828 {
1829 ASSERT (Queue->ItemSize == ItemSize);
1830
1831 if (IsQueueEmpty (Queue)) {
1832 return EFI_DEVICE_ERROR;
1833 }
1834
1835 CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);
1836
1837 //
1838 // Adjust the head pointer of the FIFO keyboard buffer.
1839 //
1840 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1841
1842 return EFI_SUCCESS;
1843 }
1844
1845
1846 /**
1847 Sets USB keyboard LED state.
1848
1849 @param UsbKeyboardDevice The USB_KB_DEV instance.
1850
1851 **/
1852 VOID
1853 SetKeyLED (
1854 IN USB_KB_DEV *UsbKeyboardDevice
1855 )
1856 {
1857 LED_MAP Led;
1858 UINT8 ReportId;
1859
1860 //
1861 // Set each field in Led map.
1862 //
1863 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1864 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1865 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1866 Led.Resrvd = 0;
1867
1868 ReportId = 0;
1869 //
1870 // Call Set_Report Request to lighten the LED.
1871 //
1872 UsbSetReportRequest (
1873 UsbKeyboardDevice->UsbIo,
1874 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1875 ReportId,
1876 HID_OUTPUT_REPORT,
1877 1,
1878 (UINT8 *) &Led
1879 );
1880 }
1881
1882
1883 /**
1884 Handler for Repeat Key event.
1885
1886 This function is the handler for Repeat Key event triggered
1887 by timer.
1888 After a repeatable key is pressed, the event would be triggered
1889 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1890 following trigger will come with interval of USBKBD_REPEAT_RATE.
1891
1892 @param Event The Repeat Key event.
1893 @param Context Points to the USB_KB_DEV instance.
1894
1895 **/
1896 VOID
1897 EFIAPI
1898 USBKeyboardRepeatHandler (
1899 IN EFI_EVENT Event,
1900 IN VOID *Context
1901 )
1902 {
1903 USB_KB_DEV *UsbKeyboardDevice;
1904 USB_KEY UsbKey;
1905
1906 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1907
1908 //
1909 // Do nothing when there is no repeat key.
1910 //
1911 if (UsbKeyboardDevice->RepeatKey != 0) {
1912 //
1913 // Inserts the repeat key into keyboard buffer,
1914 //
1915 UsbKey.KeyCode = UsbKeyboardDevice->RepeatKey;
1916 UsbKey.Down = TRUE;
1917 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1918
1919 //
1920 // Set repeat rate for next repeat key generation.
1921 //
1922 gBS->SetTimer (
1923 UsbKeyboardDevice->RepeatTimer,
1924 TimerRelative,
1925 USBKBD_REPEAT_RATE
1926 );
1927 }
1928 }
1929
1930
1931 /**
1932 Handler for Delayed Recovery event.
1933
1934 This function is the handler for Delayed Recovery event triggered
1935 by timer.
1936 After a device error occurs, the event would be triggered
1937 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1938 is defined in USB standard for error handling.
1939
1940 @param Event The Delayed Recovery event.
1941 @param Context Points to the USB_KB_DEV instance.
1942
1943 **/
1944 VOID
1945 EFIAPI
1946 USBKeyboardRecoveryHandler (
1947 IN EFI_EVENT Event,
1948 IN VOID *Context
1949 )
1950 {
1951
1952 USB_KB_DEV *UsbKeyboardDevice;
1953 EFI_USB_IO_PROTOCOL *UsbIo;
1954 UINT8 PacketSize;
1955
1956 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1957
1958 UsbIo = UsbKeyboardDevice->UsbIo;
1959
1960 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1961
1962 //
1963 // Re-submit Asynchronous Interrupt Transfer for recovery.
1964 //
1965 UsbIo->UsbAsyncInterruptTransfer (
1966 UsbIo,
1967 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1968 TRUE,
1969 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1970 PacketSize,
1971 KeyboardHandler,
1972 UsbKeyboardDevice
1973 );
1974 }