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