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