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