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