]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
Merged in the following trackers from EDK:
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / keyboard.c
CommitLineData
ed838d0c 1/** @file\r
2\r
813acf3a 3Copyright (c) 2004 - 2008, Intel Corporation\r
ed838d0c 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
813acf3a 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
ed838d0c 293//\r
813acf3a 294// Keyboard Layout Modifier to EFI Scan Code convertion table\r
ed838d0c 295//\r
296STATIC\r
813acf3a 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
ed838d0c 332};\r
333\r
813acf3a 334EFI_GUID mKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;\r
335\r
336\r
ed838d0c 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
66aa04e4 345 { MOD_WIN_R, 0xe7 }, // 11100111 \r
ed838d0c 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
813acf3a 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
ed838d0c 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
ed838d0c 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
66aa04e4 872 \r
873 UsbKeyboardDevice->LeftCtrlOn = 0;\r
874 UsbKeyboardDevice->LeftAltOn = 0;\r
813acf3a 875 UsbKeyboardDevice->LeftShiftOn = 0;\r
876 UsbKeyboardDevice->LeftLogoOn = 0;\r
66aa04e4 877 UsbKeyboardDevice->RightCtrlOn = 0;\r
878 UsbKeyboardDevice->RightAltOn = 0;\r
813acf3a 879 UsbKeyboardDevice->RightShiftOn = 0;\r
880 UsbKeyboardDevice->RightLogoOn = 0;\r
66aa04e4 881 UsbKeyboardDevice->MenuKeyOn = 0;\r
813acf3a 882 UsbKeyboardDevice->SysReqOn = 0;\r
883\r
884 UsbKeyboardDevice->AltGrOn = 0;\r
885\r
886 UsbKeyboardDevice->CurrentNsKey = NULL;\r
ed838d0c 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
ed838d0c 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
813acf3a 965 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
ed838d0c 966\r
967 ASSERT (Context);\r
968\r
969 NewRepeatKey = 0;\r
ed838d0c 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
c52fa98c 1009 UsbIo->UsbAsyncInterruptTransfer (\r
ed838d0c 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
813acf3a 1149 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);\r
1150 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {\r
ed838d0c 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
813acf3a 1179 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
1180\r
1181 switch (KeyDescriptor->Modifier) {\r
ed838d0c 1182\r
813acf3a 1183 case EFI_LEFT_CONTROL_MODIFIER:\r
1184 case EFI_RIGHT_CONTROL_MODIFIER:\r
ed838d0c 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
813acf3a 1192 case EFI_LEFT_ALT_MODIFIER:\r
1193 case EFI_RIGHT_ALT_MODIFIER:\r
ed838d0c 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
813acf3a 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
ed838d0c 1209 //\r
1210 // Del Key Code\r
1211 //\r
813acf3a 1212 case EFI_DELETE_MODIFIER:\r
ed838d0c 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
813acf3a 1274 USB_KEY UsbKey;\r
1275 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
ed838d0c 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
813acf3a 1285 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
ed838d0c 1286 if (!UsbKey.Down) {\r
813acf3a 1287 switch (KeyDescriptor->Modifier) {\r
ed838d0c 1288\r
66aa04e4 1289 //\r
1290 // CTRL release\r
1291 //\r
813acf3a 1292 case EFI_LEFT_CONTROL_MODIFIER:\r
66aa04e4 1293 UsbKeyboardDevice->LeftCtrlOn = 0;\r
1294 UsbKeyboardDevice->CtrlOn = 0;\r
1295 break;\r
813acf3a 1296 case EFI_RIGHT_CONTROL_MODIFIER:\r
66aa04e4 1297 UsbKeyboardDevice->RightCtrlOn = 0;\r
ed838d0c 1298 UsbKeyboardDevice->CtrlOn = 0;\r
1299 break;\r
1300\r
66aa04e4 1301 //\r
1302 // Shift release\r
1303 //\r
813acf3a 1304 case EFI_LEFT_SHIFT_MODIFIER:\r
66aa04e4 1305 UsbKeyboardDevice->LeftShiftOn = 0;\r
1306 UsbKeyboardDevice->ShiftOn = 0;\r
1307 break;\r
813acf3a 1308 case EFI_RIGHT_SHIFT_MODIFIER:\r
66aa04e4 1309 UsbKeyboardDevice->RightShiftOn = 0;\r
ed838d0c 1310 UsbKeyboardDevice->ShiftOn = 0;\r
1311 break;\r
1312\r
66aa04e4 1313 //\r
1314 // Alt release\r
1315 //\r
813acf3a 1316 case EFI_LEFT_ALT_MODIFIER:\r
66aa04e4 1317 UsbKeyboardDevice->LeftAltOn = 0;\r
1318 UsbKeyboardDevice->AltOn = 0;\r
1319 break;\r
813acf3a 1320 case EFI_RIGHT_ALT_MODIFIER:\r
66aa04e4 1321 UsbKeyboardDevice->RightAltOn = 0;\r
ed838d0c 1322 UsbKeyboardDevice->AltOn = 0;\r
1323 break;\r
1324\r
66aa04e4 1325 //\r
813acf3a 1326 // Left Logo release\r
66aa04e4 1327 //\r
813acf3a 1328 case EFI_LEFT_LOGO_MODIFIER:\r
66aa04e4 1329 UsbKeyboardDevice->LeftLogoOn = 0;\r
1330 break;\r
813acf3a 1331\r
1332 //\r
1333 // Right Logo release\r
1334 //\r
1335 case EFI_RIGHT_LOGO_MODIFIER:\r
66aa04e4 1336 UsbKeyboardDevice->RightLogoOn = 0;\r
1337 break;\r
1338\r
1339 //\r
813acf3a 1340 // Menu key release\r
66aa04e4 1341 //\r
813acf3a 1342 case EFI_MENU_MODIFIER:\r
66aa04e4 1343 UsbKeyboardDevice->MenuKeyOn = 0;\r
1344 break;\r
1345\r
1346 //\r
1347 // SysReq release\r
1348 //\r
813acf3a 1349 case EFI_SYS_REQUEST_MODIFIER:\r
66aa04e4 1350 UsbKeyboardDevice->SysReqOn = 0;\r
1351 break;\r
813acf3a 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
ed838d0c 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
813acf3a 1370 switch (KeyDescriptor->Modifier) {\r
ed838d0c 1371\r
813acf3a 1372 //\r
1373 // CTRL press\r
1374 //\r
1375 case EFI_LEFT_CONTROL_MODIFIER:\r
66aa04e4 1376 UsbKeyboardDevice->LeftCtrlOn = 1;\r
1377 UsbKeyboardDevice->CtrlOn = 1;\r
813acf3a 1378 continue;\r
66aa04e4 1379 break;\r
813acf3a 1380 case EFI_RIGHT_CONTROL_MODIFIER:\r
66aa04e4 1381 UsbKeyboardDevice->RightCtrlOn = 1;\r
ed838d0c 1382 UsbKeyboardDevice->CtrlOn = 1;\r
1383 continue;\r
1384 break;\r
1385\r
66aa04e4 1386 //\r
1387 // Shift press\r
1388 //\r
813acf3a 1389 case EFI_LEFT_SHIFT_MODIFIER:\r
66aa04e4 1390 UsbKeyboardDevice->LeftShiftOn = 1;\r
1391 UsbKeyboardDevice->ShiftOn = 1;\r
1392 continue;\r
1393 break;\r
813acf3a 1394 case EFI_RIGHT_SHIFT_MODIFIER:\r
1395 UsbKeyboardDevice->RightShiftOn = 1;\r
ed838d0c 1396 UsbKeyboardDevice->ShiftOn = 1;\r
1397 continue;\r
1398 break;\r
1399\r
66aa04e4 1400 //\r
1401 // Alt press\r
1402 //\r
813acf3a 1403 case EFI_LEFT_ALT_MODIFIER:\r
66aa04e4 1404 UsbKeyboardDevice->LeftAltOn = 1;\r
1405 UsbKeyboardDevice->AltOn = 1;\r
1406 continue;\r
1407 break;\r
813acf3a 1408 case EFI_RIGHT_ALT_MODIFIER:\r
1409 UsbKeyboardDevice->RightAltOn = 1;\r
ed838d0c 1410 UsbKeyboardDevice->AltOn = 1;\r
1411 continue;\r
1412 break;\r
1413\r
66aa04e4 1414 //\r
813acf3a 1415 // Left Logo press\r
66aa04e4 1416 //\r
813acf3a 1417 case EFI_LEFT_LOGO_MODIFIER:\r
66aa04e4 1418 UsbKeyboardDevice->LeftLogoOn = 1;\r
66aa04e4 1419 break;\r
813acf3a 1420\r
1421 //\r
1422 // Right Logo press\r
1423 //\r
1424 case EFI_RIGHT_LOGO_MODIFIER:\r
66aa04e4 1425 UsbKeyboardDevice->RightLogoOn = 1;\r
ed838d0c 1426 break;\r
1427\r
ed838d0c 1428 //\r
813acf3a 1429 // Menu key press\r
66aa04e4 1430 //\r
813acf3a 1431 case EFI_MENU_MODIFIER:\r
66aa04e4 1432 UsbKeyboardDevice->MenuKeyOn = 1;\r
66aa04e4 1433 break;\r
1434\r
1435 //\r
1436 // SysReq press\r
ed838d0c 1437 //\r
813acf3a 1438 case EFI_SYS_REQUEST_MODIFIER:\r
66aa04e4 1439 UsbKeyboardDevice->SysReqOn = 1;\r
813acf3a 1440 continue;\r
66aa04e4 1441 break;\r
1442\r
813acf3a 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
66aa04e4 1451 UsbKeyboardDevice->NumLockOn ^= 1;\r
1452 //\r
1453 // Turn on the NumLock light on KB\r
1454 //\r
ed838d0c 1455 SetKeyLED (UsbKeyboardDevice);\r
1456 continue;\r
1457 break;\r
1458\r
813acf3a 1459 case EFI_CAPS_LOCK_MODIFIER:\r
ed838d0c 1460 UsbKeyboardDevice->CapsOn ^= 1;\r
66aa04e4 1461 //\r
1462 // Turn on the CapsLock light on KB\r
1463 //\r
ed838d0c 1464 SetKeyLED (UsbKeyboardDevice);\r
1465 continue;\r
1466 break;\r
1467\r
813acf3a 1468 case EFI_SCROLL_LOCK_MODIFIER:\r
ed838d0c 1469 UsbKeyboardDevice->ScrollOn ^= 1;\r
66aa04e4 1470 //\r
1471 // Turn on the ScrollLock light on KB\r
1472 //\r
ed838d0c 1473 SetKeyLED (UsbKeyboardDevice);\r
1474 continue;\r
1475 break;\r
1476\r
1477 //\r
813acf3a 1478 // F11,F12,PrintScreen,Pause/Break\r
1479 // could not be retrieved via SimpleTxtInEx protocol\r
ed838d0c 1480 //\r
813acf3a 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
ed838d0c 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
813acf3a 1499 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {\r
ed838d0c 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
ed838d0c 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
813acf3a 1534 UINT8 Index;\r
1535 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
ed838d0c 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
813acf3a 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
66aa04e4 1560 //\r
813acf3a 1561 // Check whether this keystroke follows a Non-spacing key\r
66aa04e4 1562 //\r
813acf3a 1563 if (UsbKeyboardDevice->CurrentNsKey != NULL) {\r
1564 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);\r
1565 UsbKeyboardDevice->CurrentNsKey = NULL;\r
66aa04e4 1566 }\r
1567\r
813acf3a 1568 Key->ScanCode = EfiScanCodeConvertionTable[KeyDescriptor->Modifier];\r
1569 Key->UnicodeChar = KeyDescriptor->Unicode;\r
ed838d0c 1570\r
813acf3a 1571 if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT) {\r
1572 if (UsbKeyboardDevice->ShiftOn) {\r
1573 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
ed838d0c 1574\r
813acf3a 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
ed838d0c 1583\r
813acf3a 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
ed838d0c 1592\r
813acf3a 1593 if (UsbKeyboardDevice->AltGrOn) {\r
1594 Key->UnicodeChar = KeyDescriptor->AltGrUnicode;\r
1595 }\r
1596 }\r
ed838d0c 1597 }\r
1598\r
813acf3a 1599 if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) {\r
1600 if (UsbKeyboardDevice->CapsOn) {\r
ed838d0c 1601\r
813acf3a 1602 if (Key->UnicodeChar == KeyDescriptor->Unicode) {\r
ed838d0c 1603\r
813acf3a 1604 Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
ed838d0c 1605\r
813acf3a 1606 } else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {\r
ed838d0c 1607\r
813acf3a 1608 Key->UnicodeChar = KeyDescriptor->Unicode;\r
ed838d0c 1609\r
813acf3a 1610 }\r
ed838d0c 1611 }\r
1612 }\r
813acf3a 1613\r
1f771698 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
813acf3a 1619 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'a' + 1);\r
1f771698 1620 } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
813acf3a 1621 Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'A' + 1);\r
1f771698 1622 }\r
1623 }\r
813acf3a 1624\r
1625 if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) {\r
ed838d0c 1626\r
1627 if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
1628\r
1629 Key->ScanCode = SCAN_NULL;\r
1630\r
1631 } else {\r
ed838d0c 1632 Key->UnicodeChar = 0x00;\r
1633 }\r
1634 }\r
1635\r
813acf3a 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
ed838d0c 1644 if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
1645 return EFI_NOT_READY;\r
1646 }\r
1647\r
66aa04e4 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
813acf3a 1681 }\r
66aa04e4 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
ed838d0c 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