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