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