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