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