]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
Change the SimpleTextInEx implementation to return CTRL+C when CTRL and C are both...
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / KeyBoard.c
1 /** @file
2 Helper functions for USB Keyboard Driver.
3
4 Copyright (c) 2004 - 2011, 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 UINT8 ReportId;
812 UINT8 Duration;
813 EFI_STATUS Status;
814 UINT32 TransferResult;
815
816 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
817 EFI_PROGRESS_CODE,
818 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST),
819 UsbKeyboardDevice->DevicePath
820 );
821
822 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));
823 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));
824
825 //
826 // Use the config out of the descriptor
827 // Assumed the first config is the correct one and this is not always the case
828 //
829 Status = UsbGetConfiguration (
830 UsbKeyboardDevice->UsbIo,
831 &ConfigValue,
832 &TransferResult
833 );
834 if (EFI_ERROR (Status)) {
835 ConfigValue = 0x01;
836 }
837
838 //
839 // Uses default configuration to configure the USB Keyboard device.
840 //
841 Status = UsbSetConfiguration (
842 UsbKeyboardDevice->UsbIo,
843 ConfigValue,
844 &TransferResult
845 );
846 if (EFI_ERROR (Status)) {
847 //
848 // If configuration could not be set here, it means
849 // the keyboard interface has some errors and could
850 // not be initialized
851 //
852 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
853 EFI_ERROR_CODE | EFI_ERROR_MINOR,
854 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
855 UsbKeyboardDevice->DevicePath
856 );
857
858 return EFI_DEVICE_ERROR;
859 }
860
861 UsbGetProtocolRequest (
862 UsbKeyboardDevice->UsbIo,
863 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
864 &Protocol
865 );
866 //
867 // Set boot protocol for the USB Keyboard.
868 // This driver only supports boot protocol.
869 //
870 if (Protocol != BOOT_PROTOCOL) {
871 UsbSetProtocolRequest (
872 UsbKeyboardDevice->UsbIo,
873 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
874 BOOT_PROTOCOL
875 );
876 }
877
878 //
879 // ReportId is zero, which means the idle rate applies to all input reports.
880 //
881 ReportId = 0;
882 //
883 // Duration is zero, which means the duration is infinite.
884 // so the endpoint will inhibit reporting forever,
885 // and only reporting when a change is detected in the report data.
886 //
887 Duration = 0;
888 UsbSetIdleRequest (
889 UsbKeyboardDevice->UsbIo,
890 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
891 ReportId,
892 Duration
893 );
894
895 UsbKeyboardDevice->CtrlOn = FALSE;
896 UsbKeyboardDevice->AltOn = FALSE;
897 UsbKeyboardDevice->ShiftOn = FALSE;
898 UsbKeyboardDevice->NumLockOn = FALSE;
899 UsbKeyboardDevice->CapsOn = FALSE;
900 UsbKeyboardDevice->ScrollOn = FALSE;
901
902 UsbKeyboardDevice->LeftCtrlOn = FALSE;
903 UsbKeyboardDevice->LeftAltOn = FALSE;
904 UsbKeyboardDevice->LeftShiftOn = FALSE;
905 UsbKeyboardDevice->LeftLogoOn = FALSE;
906 UsbKeyboardDevice->RightCtrlOn = FALSE;
907 UsbKeyboardDevice->RightAltOn = FALSE;
908 UsbKeyboardDevice->RightShiftOn = FALSE;
909 UsbKeyboardDevice->RightLogoOn = FALSE;
910 UsbKeyboardDevice->MenuKeyOn = FALSE;
911 UsbKeyboardDevice->SysReqOn = FALSE;
912
913 UsbKeyboardDevice->AltGrOn = FALSE;
914
915 UsbKeyboardDevice->CurrentNsKey = NULL;
916
917 //
918 // Sync the initial state of lights on keyboard.
919 //
920 SetKeyLED (UsbKeyboardDevice);
921
922 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
923
924 //
925 // Create event for repeat keys' generation.
926 //
927 if (UsbKeyboardDevice->RepeatTimer != NULL) {
928 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
929 UsbKeyboardDevice->RepeatTimer = NULL;
930 }
931
932 gBS->CreateEvent (
933 EVT_TIMER | EVT_NOTIFY_SIGNAL,
934 TPL_CALLBACK,
935 USBKeyboardRepeatHandler,
936 UsbKeyboardDevice,
937 &UsbKeyboardDevice->RepeatTimer
938 );
939
940 //
941 // Create event for delayed recovery, which deals with device error.
942 //
943 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
944 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
945 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
946 }
947
948 gBS->CreateEvent (
949 EVT_TIMER | EVT_NOTIFY_SIGNAL,
950 TPL_NOTIFY,
951 USBKeyboardRecoveryHandler,
952 UsbKeyboardDevice,
953 &UsbKeyboardDevice->DelayedRecoveryEvent
954 );
955
956 return EFI_SUCCESS;
957 }
958
959
960 /**
961 Handler function for USB keyboard's asynchronous interrupt transfer.
962
963 This function is the handler function for USB keyboard's asynchronous interrupt transfer
964 to manage the keyboard. It parses the USB keyboard input report, and inserts data to
965 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
966 is also set accordingly.
967
968 @param Data A pointer to a buffer that is filled with key data which is
969 retrieved via asynchronous interrupt transfer.
970 @param DataLength Indicates the size of the data buffer.
971 @param Context Pointing to USB_KB_DEV instance.
972 @param Result Indicates the result of the asynchronous interrupt transfer.
973
974 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
975 @retval EFI_DEVICE_ERROR Hardware error occurs.
976
977 **/
978 EFI_STATUS
979 EFIAPI
980 KeyboardHandler (
981 IN VOID *Data,
982 IN UINTN DataLength,
983 IN VOID *Context,
984 IN UINT32 Result
985 )
986 {
987 USB_KB_DEV *UsbKeyboardDevice;
988 EFI_USB_IO_PROTOCOL *UsbIo;
989 UINT8 *CurKeyCodeBuffer;
990 UINT8 *OldKeyCodeBuffer;
991 UINT8 CurModifierMap;
992 UINT8 OldModifierMap;
993 UINT8 Mask;
994 UINTN Index;
995 UINT8 Index2;
996 BOOLEAN KeyRelease;
997 BOOLEAN KeyPress;
998 USB_KEY UsbKey;
999 UINT8 NewRepeatKey;
1000 UINT32 UsbStatus;
1001 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1002
1003 ASSERT (Context != NULL);
1004
1005 NewRepeatKey = 0;
1006 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1007 UsbIo = UsbKeyboardDevice->UsbIo;
1008
1009 //
1010 // Analyzes Result and performs corresponding action.
1011 //
1012 if (Result != EFI_USB_NOERROR) {
1013 //
1014 // Some errors happen during the process
1015 //
1016 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1017 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1018 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR),
1019 UsbKeyboardDevice->DevicePath
1020 );
1021
1022 //
1023 // Stop the repeat key generation if any
1024 //
1025 UsbKeyboardDevice->RepeatKey = 0;
1026
1027 gBS->SetTimer (
1028 UsbKeyboardDevice->RepeatTimer,
1029 TimerCancel,
1030 USBKBD_REPEAT_RATE
1031 );
1032
1033 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
1034 UsbClearEndpointHalt (
1035 UsbIo,
1036 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1037 &UsbStatus
1038 );
1039 }
1040
1041 //
1042 // Delete & Submit this interrupt again
1043 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
1044 //
1045 UsbIo->UsbAsyncInterruptTransfer (
1046 UsbIo,
1047 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1048 FALSE,
1049 0,
1050 0,
1051 NULL,
1052 NULL
1053 );
1054 //
1055 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
1056 //
1057 gBS->SetTimer (
1058 UsbKeyboardDevice->DelayedRecoveryEvent,
1059 TimerRelative,
1060 EFI_USB_INTERRUPT_DELAY
1061 );
1062
1063 return EFI_DEVICE_ERROR;
1064 }
1065
1066 //
1067 // If no error and no data, just return EFI_SUCCESS.
1068 //
1069 if (DataLength == 0 || Data == NULL) {
1070 return EFI_SUCCESS;
1071 }
1072
1073 //
1074 // Following code checks current keyboard input report against old key code buffer.
1075 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1076 // Byte 0 is map of Modifier keys.
1077 // Byte 1 is reserved.
1078 // Bytes 2 to 7 are keycodes.
1079 //
1080 CurKeyCodeBuffer = (UINT8 *) Data;
1081 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
1082
1083 //
1084 // Checks for new key stroke.
1085 //
1086 for (Index = 0; Index < 8; Index++) {
1087 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
1088 break;
1089 }
1090 }
1091
1092 //
1093 // If no new key, return EFI_SUCCESS immediately.
1094 //
1095 if (Index == 8) {
1096 return EFI_SUCCESS;
1097 }
1098
1099 //
1100 // Parse the modifier key, which is the first byte of keyboard input report.
1101 //
1102 CurModifierMap = CurKeyCodeBuffer[0];
1103 OldModifierMap = OldKeyCodeBuffer[0];
1104
1105 //
1106 // Handle modifier key's pressing or releasing situation.
1107 // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
1108 // Bit0: Left Control, Keycode: 0xe0
1109 // Bit1: Left Shift, Keycode: 0xe1
1110 // Bit2: Left Alt, Keycode: 0xe2
1111 // Bit3: Left GUI, Keycode: 0xe3
1112 // Bit4: Right Control, Keycode: 0xe4
1113 // Bit5: Right Shift, Keycode: 0xe5
1114 // Bit6: Right Alt, Keycode: 0xe6
1115 // Bit7: Right GUI, Keycode: 0xe7
1116 //
1117 for (Index = 0; Index < 8; Index++) {
1118 Mask = (UINT8) (1 << Index);
1119 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
1120 //
1121 // If current modifier key is up, then CurModifierMap & Mask = 0;
1122 // otherwise it is a non-zero value.
1123 // Insert the changed modifier key into key buffer.
1124 //
1125 UsbKey.KeyCode = (UINT8) (0xe0 + Index);
1126 UsbKey.Down = (BOOLEAN) ((CurModifierMap & Mask) != 0);
1127 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1128 }
1129 }
1130
1131 //
1132 // Handle normal key's releasing situation
1133 // Bytes 2 to 7 are for normal keycodes
1134 //
1135 KeyRelease = FALSE;
1136 for (Index = 2; Index < 8; Index++) {
1137
1138 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
1139 continue;
1140 }
1141 //
1142 // For any key in old keycode buffer, if it is not in current keycode buffer,
1143 // then it is released. Otherwise, it is not released.
1144 //
1145 KeyRelease = TRUE;
1146 for (Index2 = 2; Index2 < 8; Index2++) {
1147
1148 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
1149 continue;
1150 }
1151
1152 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
1153 KeyRelease = FALSE;
1154 break;
1155 }
1156 }
1157
1158 if (KeyRelease) {
1159 UsbKey.KeyCode = OldKeyCodeBuffer[Index];
1160 UsbKey.Down = FALSE;
1161 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1162 //
1163 // The original repeat key is released.
1164 //
1165 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
1166 UsbKeyboardDevice->RepeatKey = 0;
1167 }
1168 }
1169 }
1170
1171 //
1172 // If original repeat key is released, cancel the repeat timer
1173 //
1174 if (UsbKeyboardDevice->RepeatKey == 0) {
1175 gBS->SetTimer (
1176 UsbKeyboardDevice->RepeatTimer,
1177 TimerCancel,
1178 USBKBD_REPEAT_RATE
1179 );
1180 }
1181
1182 //
1183 // Handle normal key's pressing situation
1184 //
1185 KeyPress = FALSE;
1186 for (Index = 2; Index < 8; Index++) {
1187
1188 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
1189 continue;
1190 }
1191 //
1192 // For any key in current keycode buffer, if it is not in old keycode buffer,
1193 // then it is pressed. Otherwise, it is not pressed.
1194 //
1195 KeyPress = TRUE;
1196 for (Index2 = 2; Index2 < 8; Index2++) {
1197
1198 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
1199 continue;
1200 }
1201
1202 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
1203 KeyPress = FALSE;
1204 break;
1205 }
1206 }
1207
1208 if (KeyPress) {
1209 UsbKey.KeyCode = CurKeyCodeBuffer[Index];
1210 UsbKey.Down = TRUE;
1211 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1212
1213 //
1214 // Handle repeat key
1215 //
1216 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
1217 ASSERT (KeyDescriptor != NULL);
1218
1219 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
1220 //
1221 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1222 //
1223 UsbKeyboardDevice->RepeatKey = 0;
1224 } else {
1225 //
1226 // Prepare new repeat key, and clear the original one.
1227 //
1228 NewRepeatKey = CurKeyCodeBuffer[Index];
1229 UsbKeyboardDevice->RepeatKey = 0;
1230 }
1231 }
1232 }
1233
1234 //
1235 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
1236 //
1237 for (Index = 0; Index < 8; Index++) {
1238 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
1239 }
1240
1241 //
1242 // If there is new key pressed, update the RepeatKey value, and set the
1243 // timer to repeate delay timer
1244 //
1245 if (NewRepeatKey != 0) {
1246 //
1247 // Sets trigger time to "Repeat Delay Time",
1248 // to trigger the repeat timer when the key is hold long
1249 // enough time.
1250 //
1251 gBS->SetTimer (
1252 UsbKeyboardDevice->RepeatTimer,
1253 TimerRelative,
1254 USBKBD_REPEAT_DELAY
1255 );
1256 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1257 }
1258
1259 return EFI_SUCCESS;
1260 }
1261
1262
1263 /**
1264 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1265
1266 This function parses keyboard buffer. It updates state of modifier key for
1267 USB_KB_DEV instancem, and returns keycode for output.
1268
1269 @param UsbKeyboardDevice The USB_KB_DEV instance.
1270 @param KeyCode Pointer to the USB keycode for output.
1271
1272 @retval EFI_SUCCESS Keycode successfully parsed.
1273 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1274
1275 **/
1276 EFI_STATUS
1277 USBParseKey (
1278 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1279 OUT UINT8 *KeyCode
1280 )
1281 {
1282 USB_KEY UsbKey;
1283 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1284
1285 *KeyCode = 0;
1286
1287 while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {
1288 //
1289 // Pops one raw data off.
1290 //
1291 Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1292
1293 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1294 ASSERT (KeyDescriptor != NULL);
1295
1296 if (!UsbKey.Down) {
1297 //
1298 // Key is released.
1299 //
1300 switch (KeyDescriptor->Modifier) {
1301
1302 //
1303 // Ctrl release
1304 //
1305 case EFI_LEFT_CONTROL_MODIFIER:
1306 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1307 UsbKeyboardDevice->CtrlOn = FALSE;
1308 break;
1309 case EFI_RIGHT_CONTROL_MODIFIER:
1310 UsbKeyboardDevice->RightCtrlOn = FALSE;
1311 UsbKeyboardDevice->CtrlOn = FALSE;
1312 break;
1313
1314 //
1315 // Shift release
1316 //
1317 case EFI_LEFT_SHIFT_MODIFIER:
1318 UsbKeyboardDevice->LeftShiftOn = FALSE;
1319 UsbKeyboardDevice->ShiftOn = FALSE;
1320 break;
1321 case EFI_RIGHT_SHIFT_MODIFIER:
1322 UsbKeyboardDevice->RightShiftOn = FALSE;
1323 UsbKeyboardDevice->ShiftOn = FALSE;
1324 break;
1325
1326 //
1327 // Alt release
1328 //
1329 case EFI_LEFT_ALT_MODIFIER:
1330 UsbKeyboardDevice->LeftAltOn = FALSE;
1331 UsbKeyboardDevice->AltOn = FALSE;
1332 break;
1333 case EFI_RIGHT_ALT_MODIFIER:
1334 UsbKeyboardDevice->RightAltOn = FALSE;
1335 UsbKeyboardDevice->AltOn = FALSE;
1336 break;
1337
1338 //
1339 // Left Logo release
1340 //
1341 case EFI_LEFT_LOGO_MODIFIER:
1342 UsbKeyboardDevice->LeftLogoOn = FALSE;
1343 break;
1344
1345 //
1346 // Right Logo release
1347 //
1348 case EFI_RIGHT_LOGO_MODIFIER:
1349 UsbKeyboardDevice->RightLogoOn = FALSE;
1350 break;
1351
1352 //
1353 // Menu key release
1354 //
1355 case EFI_MENU_MODIFIER:
1356 UsbKeyboardDevice->MenuKeyOn = FALSE;
1357 break;
1358
1359 //
1360 // SysReq release
1361 //
1362 case EFI_PRINT_MODIFIER:
1363 case EFI_SYS_REQUEST_MODIFIER:
1364 UsbKeyboardDevice->SysReqOn = FALSE;
1365 break;
1366
1367 //
1368 // AltGr release
1369 //
1370 case EFI_ALT_GR_MODIFIER:
1371 UsbKeyboardDevice->AltGrOn = FALSE;
1372 break;
1373
1374 default:
1375 break;
1376 }
1377
1378 continue;
1379 }
1380
1381 //
1382 // Analyzes key pressing situation
1383 //
1384 switch (KeyDescriptor->Modifier) {
1385
1386 //
1387 // Ctrl press
1388 //
1389 case EFI_LEFT_CONTROL_MODIFIER:
1390 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1391 UsbKeyboardDevice->CtrlOn = TRUE;
1392 break;
1393 case EFI_RIGHT_CONTROL_MODIFIER:
1394 UsbKeyboardDevice->RightCtrlOn = TRUE;
1395 UsbKeyboardDevice->CtrlOn = TRUE;
1396 break;
1397
1398 //
1399 // Shift press
1400 //
1401 case EFI_LEFT_SHIFT_MODIFIER:
1402 UsbKeyboardDevice->LeftShiftOn = TRUE;
1403 UsbKeyboardDevice->ShiftOn = TRUE;
1404 break;
1405 case EFI_RIGHT_SHIFT_MODIFIER:
1406 UsbKeyboardDevice->RightShiftOn = TRUE;
1407 UsbKeyboardDevice->ShiftOn = TRUE;
1408 break;
1409
1410 //
1411 // Alt press
1412 //
1413 case EFI_LEFT_ALT_MODIFIER:
1414 UsbKeyboardDevice->LeftAltOn = TRUE;
1415 UsbKeyboardDevice->AltOn = TRUE;
1416 break;
1417 case EFI_RIGHT_ALT_MODIFIER:
1418 UsbKeyboardDevice->RightAltOn = TRUE;
1419 UsbKeyboardDevice->AltOn = TRUE;
1420 break;
1421
1422 //
1423 // Left Logo press
1424 //
1425 case EFI_LEFT_LOGO_MODIFIER:
1426 UsbKeyboardDevice->LeftLogoOn = TRUE;
1427 break;
1428
1429 //
1430 // Right Logo press
1431 //
1432 case EFI_RIGHT_LOGO_MODIFIER:
1433 UsbKeyboardDevice->RightLogoOn = TRUE;
1434 break;
1435
1436 //
1437 // Menu key press
1438 //
1439 case EFI_MENU_MODIFIER:
1440 UsbKeyboardDevice->MenuKeyOn = TRUE;
1441 break;
1442
1443 //
1444 // SysReq press
1445 //
1446 case EFI_PRINT_MODIFIER:
1447 case EFI_SYS_REQUEST_MODIFIER:
1448 UsbKeyboardDevice->SysReqOn = TRUE;
1449 break;
1450
1451 //
1452 // AltGr press
1453 //
1454 case EFI_ALT_GR_MODIFIER:
1455 UsbKeyboardDevice->AltGrOn = TRUE;
1456 break;
1457
1458 case EFI_NUM_LOCK_MODIFIER:
1459 //
1460 // Toggle NumLock
1461 //
1462 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1463 SetKeyLED (UsbKeyboardDevice);
1464 break;
1465
1466 case EFI_CAPS_LOCK_MODIFIER:
1467 //
1468 // Toggle CapsLock
1469 //
1470 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1471 SetKeyLED (UsbKeyboardDevice);
1472 break;
1473
1474 case EFI_SCROLL_LOCK_MODIFIER:
1475 //
1476 // Toggle ScrollLock
1477 //
1478 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1479 SetKeyLED (UsbKeyboardDevice);
1480 break;
1481
1482 default:
1483 break;
1484 }
1485
1486 //
1487 // When encountering Ctrl + Alt + Del, then warm reset.
1488 //
1489 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1490 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1491 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1492 }
1493 }
1494
1495 *KeyCode = UsbKey.KeyCode;
1496 return EFI_SUCCESS;
1497 }
1498
1499 return EFI_NOT_READY;
1500 }
1501
1502
1503 /**
1504 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1505
1506 @param UsbKeyboardDevice The USB_KB_DEV instance.
1507 @param KeyCode Indicates the key code that will be interpreted.
1508 @param KeyData A pointer to a buffer that is filled in with
1509 the keystroke information for the key that
1510 was pressed.
1511
1512 @retval EFI_SUCCESS Success.
1513 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1514 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1515 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1516 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1517
1518 **/
1519 EFI_STATUS
1520 UsbKeyCodeToEfiInputKey (
1521 IN USB_KB_DEV *UsbKeyboardDevice,
1522 IN UINT8 KeyCode,
1523 OUT EFI_KEY_DATA *KeyData
1524 )
1525 {
1526 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1527 LIST_ENTRY *Link;
1528 LIST_ENTRY *NotifyList;
1529 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1530
1531 //
1532 // KeyCode must in the range of [0x4, 0x65] or [0xe0, 0xe7].
1533 //
1534 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1535 ASSERT (KeyDescriptor != NULL);
1536
1537 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1538 //
1539 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1540 //
1541 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1542 return EFI_NOT_READY;
1543 }
1544
1545 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1546 //
1547 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1548 // physical key.
1549 //
1550 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1551 UsbKeyboardDevice->CurrentNsKey = NULL;
1552 }
1553
1554 //
1555 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1556 //
1557 if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {
1558 return EFI_DEVICE_ERROR;
1559 }
1560
1561 KeyData->Key.ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1562 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1563
1564 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1565 if (UsbKeyboardDevice->ShiftOn) {
1566 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1567
1568 //
1569 // Need not return associated shift state if a class of printable characters that
1570 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1571 //
1572 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1573 UsbKeyboardDevice->LeftShiftOn = FALSE;
1574 UsbKeyboardDevice->RightShiftOn = FALSE;
1575 }
1576
1577 if (UsbKeyboardDevice->AltGrOn) {
1578 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1579 }
1580 } else {
1581 //
1582 // Shift off
1583 //
1584 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1585
1586 if (UsbKeyboardDevice->AltGrOn) {
1587 KeyData->Key.UnicodeChar = KeyDescriptor->AltGrUnicode;
1588 }
1589 }
1590 }
1591
1592 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1593 if (UsbKeyboardDevice->CapsOn) {
1594 if (KeyData->Key.UnicodeChar == KeyDescriptor->Unicode) {
1595 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1596 } else if (KeyData->Key.UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1597 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1598 }
1599 }
1600 }
1601
1602 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
1603 //
1604 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1605 // normal key, instead of original control key. So the ScanCode should be cleaned.
1606 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1607 //
1608 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1609 KeyData->Key.ScanCode = SCAN_NULL;
1610 } else {
1611 KeyData->Key.UnicodeChar = CHAR_NULL;
1612 }
1613 }
1614
1615 //
1616 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1617 //
1618 if (KeyData->Key.UnicodeChar == 0x1B && KeyData->Key.ScanCode == SCAN_NULL) {
1619 KeyData->Key.ScanCode = SCAN_ESC;
1620 KeyData->Key.UnicodeChar = CHAR_NULL;
1621 }
1622
1623 //
1624 // Not valid for key without both unicode key code and EFI Scan Code.
1625 //
1626 if (KeyData->Key.UnicodeChar == 0 && KeyData->Key.ScanCode == SCAN_NULL) {
1627 if (!UsbKeyboardDevice->IsSupportPartialKey) {
1628 return EFI_NOT_READY;
1629 }
1630 }
1631
1632 //
1633 // Save Shift/Toggle state
1634 //
1635 KeyData->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
1636 KeyData->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
1637
1638 if (UsbKeyboardDevice->LeftCtrlOn) {
1639 KeyData->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1640 }
1641 if (UsbKeyboardDevice->RightCtrlOn) {
1642 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1643 }
1644 if (UsbKeyboardDevice->LeftAltOn) {
1645 KeyData->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1646 }
1647 if (UsbKeyboardDevice->RightAltOn) {
1648 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1649 }
1650 if (UsbKeyboardDevice->LeftShiftOn) {
1651 KeyData->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1652 }
1653 if (UsbKeyboardDevice->RightShiftOn) {
1654 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1655 }
1656 if (UsbKeyboardDevice->LeftLogoOn) {
1657 KeyData->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1658 }
1659 if (UsbKeyboardDevice->RightLogoOn) {
1660 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1661 }
1662 if (UsbKeyboardDevice->MenuKeyOn) {
1663 KeyData->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1664 }
1665 if (UsbKeyboardDevice->SysReqOn) {
1666 KeyData->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1667 }
1668
1669 if (UsbKeyboardDevice->ScrollOn) {
1670 KeyData->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1671 }
1672 if (UsbKeyboardDevice->NumLockOn) {
1673 KeyData->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1674 }
1675 if (UsbKeyboardDevice->CapsOn) {
1676 KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1677 }
1678 if (UsbKeyboardDevice->IsSupportPartialKey) {
1679 KeyData->KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED;
1680 }
1681 //
1682 // Invoke notification functions if the key is registered.
1683 //
1684 NotifyList = &UsbKeyboardDevice->NotifyList;
1685 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
1686 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
1687 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
1688 CurrentNotify->KeyNotificationFn (KeyData);
1689 }
1690 }
1691
1692 return EFI_SUCCESS;
1693 }
1694
1695
1696 /**
1697 Create the queue.
1698
1699 @param Queue Points to the queue.
1700 @param ItemSize Size of the single item.
1701
1702 **/
1703 VOID
1704 InitQueue (
1705 IN OUT USB_SIMPLE_QUEUE *Queue,
1706 IN UINTN ItemSize
1707 )
1708 {
1709 UINTN Index;
1710
1711 Queue->ItemSize = ItemSize;
1712 Queue->Head = 0;
1713 Queue->Tail = 0;
1714
1715 if (Queue->Buffer[0] != NULL) {
1716 FreePool (Queue->Buffer[0]);
1717 }
1718
1719 Queue->Buffer[0] = AllocatePool (sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]) * ItemSize);
1720 ASSERT (Queue->Buffer[0] != NULL);
1721
1722 for (Index = 1; Index < sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]); Index++) {
1723 Queue->Buffer[Index] = ((UINT8 *) Queue->Buffer[Index - 1]) + ItemSize;
1724 }
1725 }
1726
1727 /**
1728 Destroy the queue
1729
1730 @param Queue Points to the queue.
1731 **/
1732 VOID
1733 DestroyQueue (
1734 IN OUT USB_SIMPLE_QUEUE *Queue
1735 )
1736 {
1737 FreePool (Queue->Buffer[0]);
1738 }
1739
1740
1741 /**
1742 Check whether the queue is empty.
1743
1744 @param Queue Points to the queue.
1745
1746 @retval TRUE Queue is empty.
1747 @retval FALSE Queue is not empty.
1748
1749 **/
1750 BOOLEAN
1751 IsQueueEmpty (
1752 IN USB_SIMPLE_QUEUE *Queue
1753 )
1754 {
1755 //
1756 // Meet FIFO empty condition
1757 //
1758 return (BOOLEAN) (Queue->Head == Queue->Tail);
1759 }
1760
1761
1762 /**
1763 Check whether the queue is full.
1764
1765 @param Queue Points to the queue.
1766
1767 @retval TRUE Queue is full.
1768 @retval FALSE Queue is not full.
1769
1770 **/
1771 BOOLEAN
1772 IsQueueFull (
1773 IN USB_SIMPLE_QUEUE *Queue
1774 )
1775 {
1776 return (BOOLEAN) (((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);
1777 }
1778
1779
1780 /**
1781 Enqueue the item to the queue.
1782
1783 @param Queue Points to the queue.
1784 @param Item Points to the item to be enqueued.
1785 @param ItemSize Size of the item.
1786 **/
1787 VOID
1788 Enqueue (
1789 IN OUT USB_SIMPLE_QUEUE *Queue,
1790 IN VOID *Item,
1791 IN UINTN ItemSize
1792 )
1793 {
1794 ASSERT (ItemSize == Queue->ItemSize);
1795 //
1796 // If keyboard buffer is full, throw the
1797 // first key out of the keyboard buffer.
1798 //
1799 if (IsQueueFull (Queue)) {
1800 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1801 }
1802
1803 CopyMem (Queue->Buffer[Queue->Tail], Item, ItemSize);
1804
1805 //
1806 // Adjust the tail pointer of the FIFO keyboard buffer.
1807 //
1808 Queue->Tail = (Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1);
1809 }
1810
1811
1812 /**
1813 Dequeue a item from the queue.
1814
1815 @param Queue Points to the queue.
1816 @param Item Receives the item.
1817 @param ItemSize Size of the item.
1818
1819 @retval EFI_SUCCESS Item was successfully dequeued.
1820 @retval EFI_DEVICE_ERROR The queue is empty.
1821
1822 **/
1823 EFI_STATUS
1824 Dequeue (
1825 IN OUT USB_SIMPLE_QUEUE *Queue,
1826 OUT VOID *Item,
1827 IN UINTN ItemSize
1828 )
1829 {
1830 ASSERT (Queue->ItemSize == ItemSize);
1831
1832 if (IsQueueEmpty (Queue)) {
1833 return EFI_DEVICE_ERROR;
1834 }
1835
1836 CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);
1837
1838 //
1839 // Adjust the head pointer of the FIFO keyboard buffer.
1840 //
1841 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1842
1843 return EFI_SUCCESS;
1844 }
1845
1846
1847 /**
1848 Sets USB keyboard LED state.
1849
1850 @param UsbKeyboardDevice The USB_KB_DEV instance.
1851
1852 **/
1853 VOID
1854 SetKeyLED (
1855 IN USB_KB_DEV *UsbKeyboardDevice
1856 )
1857 {
1858 LED_MAP Led;
1859 UINT8 ReportId;
1860
1861 //
1862 // Set each field in Led map.
1863 //
1864 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1865 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1866 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1867 Led.Resrvd = 0;
1868
1869 ReportId = 0;
1870 //
1871 // Call Set_Report Request to lighten the LED.
1872 //
1873 UsbSetReportRequest (
1874 UsbKeyboardDevice->UsbIo,
1875 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1876 ReportId,
1877 HID_OUTPUT_REPORT,
1878 1,
1879 (UINT8 *) &Led
1880 );
1881 }
1882
1883
1884 /**
1885 Handler for Repeat Key event.
1886
1887 This function is the handler for Repeat Key event triggered
1888 by timer.
1889 After a repeatable key is pressed, the event would be triggered
1890 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1891 following trigger will come with interval of USBKBD_REPEAT_RATE.
1892
1893 @param Event The Repeat Key event.
1894 @param Context Points to the USB_KB_DEV instance.
1895
1896 **/
1897 VOID
1898 EFIAPI
1899 USBKeyboardRepeatHandler (
1900 IN EFI_EVENT Event,
1901 IN VOID *Context
1902 )
1903 {
1904 USB_KB_DEV *UsbKeyboardDevice;
1905 USB_KEY UsbKey;
1906
1907 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1908
1909 //
1910 // Do nothing when there is no repeat key.
1911 //
1912 if (UsbKeyboardDevice->RepeatKey != 0) {
1913 //
1914 // Inserts the repeat key into keyboard buffer,
1915 //
1916 UsbKey.KeyCode = UsbKeyboardDevice->RepeatKey;
1917 UsbKey.Down = TRUE;
1918 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1919
1920 //
1921 // Set repeat rate for next repeat key generation.
1922 //
1923 gBS->SetTimer (
1924 UsbKeyboardDevice->RepeatTimer,
1925 TimerRelative,
1926 USBKBD_REPEAT_RATE
1927 );
1928 }
1929 }
1930
1931
1932 /**
1933 Handler for Delayed Recovery event.
1934
1935 This function is the handler for Delayed Recovery event triggered
1936 by timer.
1937 After a device error occurs, the event would be triggered
1938 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1939 is defined in USB standard for error handling.
1940
1941 @param Event The Delayed Recovery event.
1942 @param Context Points to the USB_KB_DEV instance.
1943
1944 **/
1945 VOID
1946 EFIAPI
1947 USBKeyboardRecoveryHandler (
1948 IN EFI_EVENT Event,
1949 IN VOID *Context
1950 )
1951 {
1952
1953 USB_KB_DEV *UsbKeyboardDevice;
1954 EFI_USB_IO_PROTOCOL *UsbIo;
1955 UINT8 PacketSize;
1956
1957 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1958
1959 UsbIo = UsbKeyboardDevice->UsbIo;
1960
1961 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1962
1963 //
1964 // Re-submit Asynchronous Interrupt Transfer for recovery.
1965 //
1966 UsbIo->UsbAsyncInterruptTransfer (
1967 UsbIo,
1968 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1969 TRUE,
1970 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1971 PacketSize,
1972 KeyboardHandler,
1973 UsbKeyboardDevice
1974 );
1975 }