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