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