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