]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
Roll back r12434.
[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 SCAN_NULL, // EFI_PRINT_MODIFIER
300 SCAN_NULL, // EFI_SYS_REQUEST_MODIFIER
301 SCAN_NULL, // EFI_SCROLL_LOCK_MODIFIER
302 SCAN_PAUSE // EFI_PAUSE_MODIFIER
303 };
304
305 /**
306 Initialize Key Convention Table by using default keyboard layout.
307
308 @param UsbKeyboardDevice The USB_KB_DEV instance.
309
310 @retval EFI_SUCCESS The default keyboard layout was installed successfully
311 @retval Others Failure to install default keyboard layout.
312 **/
313 EFI_STATUS
314 InstallDefaultKeyboardLayout (
315 IN OUT USB_KB_DEV *UsbKeyboardDevice
316 )
317 {
318 EFI_STATUS Status;
319 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
320 EFI_HII_HANDLE HiiHandle;
321
322 //
323 // Locate Hii database protocol
324 //
325 Status = gBS->LocateProtocol (
326 &gEfiHiiDatabaseProtocolGuid,
327 NULL,
328 (VOID **) &HiiDatabase
329 );
330 if (EFI_ERROR (Status)) {
331 return Status;
332 }
333
334 //
335 // Install Keyboard Layout package to HII database
336 //
337 HiiHandle = HiiAddPackages (
338 &gUsbKeyboardLayoutPackageGuid,
339 UsbKeyboardDevice->ControllerHandle,
340 &mUsbKeyboardLayoutBin,
341 NULL
342 );
343 if (HiiHandle == NULL) {
344 return EFI_OUT_OF_RESOURCES;
345 }
346
347 //
348 // Set current keyboard layout
349 //
350 Status = HiiDatabase->SetKeyboardLayout (HiiDatabase, &gUsbKeyboardLayoutKeyGuid);
351
352 return Status;
353 }
354
355
356 /**
357 Uses USB I/O to check whether the device is a USB keyboard device.
358
359 @param UsbIo Pointer to a USB I/O protocol instance.
360
361 @retval TRUE Device is a USB keyboard device.
362 @retval FALSE Device is a not USB keyboard device.
363
364 **/
365 BOOLEAN
366 IsUSBKeyboard (
367 IN EFI_USB_IO_PROTOCOL *UsbIo
368 )
369 {
370 EFI_STATUS Status;
371 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
372
373 //
374 // Get the default interface descriptor
375 //
376 Status = UsbIo->UsbGetInterfaceDescriptor (
377 UsbIo,
378 &InterfaceDescriptor
379 );
380
381 if (EFI_ERROR (Status)) {
382 return FALSE;
383 }
384
385 if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
386 InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
387 InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD
388 ) {
389 return TRUE;
390 }
391
392 return FALSE;
393 }
394
395 /**
396 Get current keyboard layout from HII database.
397
398 @return Pointer to HII Keyboard Layout.
399 NULL means failure occurred while trying to get keyboard layout.
400
401 **/
402 EFI_HII_KEYBOARD_LAYOUT *
403 GetCurrentKeyboardLayout (
404 VOID
405 )
406 {
407 EFI_STATUS Status;
408 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
409 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
410 UINT16 Length;
411
412 //
413 // Locate HII Database Protocol
414 //
415 Status = gBS->LocateProtocol (
416 &gEfiHiiDatabaseProtocolGuid,
417 NULL,
418 (VOID **) &HiiDatabase
419 );
420 if (EFI_ERROR (Status)) {
421 return NULL;
422 }
423
424 //
425 // Get current keyboard layout from HII database
426 //
427 Length = 0;
428 KeyboardLayout = NULL;
429 Status = HiiDatabase->GetKeyboardLayout (
430 HiiDatabase,
431 NULL,
432 &Length,
433 KeyboardLayout
434 );
435 if (Status == EFI_BUFFER_TOO_SMALL) {
436 KeyboardLayout = AllocatePool (Length);
437 ASSERT (KeyboardLayout != NULL);
438
439 Status = HiiDatabase->GetKeyboardLayout (
440 HiiDatabase,
441 NULL,
442 &Length,
443 KeyboardLayout
444 );
445 if (EFI_ERROR (Status)) {
446 FreePool (KeyboardLayout);
447 KeyboardLayout = NULL;
448 }
449 }
450
451 return KeyboardLayout;
452 }
453
454 /**
455 Find Key Descriptor in Key Convertion Table given its USB keycode.
456
457 @param UsbKeyboardDevice The USB_KB_DEV instance.
458 @param KeyCode USB Keycode.
459
460 @return The Key Descriptor in Key Convertion Table.
461 NULL means not found.
462
463 **/
464 EFI_KEY_DESCRIPTOR *
465 GetKeyDescriptor (
466 IN USB_KB_DEV *UsbKeyboardDevice,
467 IN UINT8 KeyCode
468 )
469 {
470 UINT8 Index;
471
472 //
473 // Make sure KeyCode is in the range of [0x4, 0x65] or [0xe0, 0xe7]
474 //
475 if ((!USBKBD_VALID_KEYCODE (KeyCode)) || ((KeyCode > 0x65) && (KeyCode < 0xe0)) || (KeyCode > 0xe7)) {
476 return NULL;
477 }
478
479 //
480 // Calculate the index of Key Descriptor in Key Convertion Table
481 //
482 if (KeyCode <= 0x65) {
483 Index = (UINT8) (KeyCode - 4);
484 } else {
485 Index = (UINT8) (KeyCode - 0xe0 + NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE);
486 }
487
488 return &UsbKeyboardDevice->KeyConvertionTable[Index];
489 }
490
491 /**
492 Find Non-Spacing key for given Key descriptor.
493
494 @param UsbKeyboardDevice The USB_KB_DEV instance.
495 @param KeyDescriptor Key descriptor.
496
497 @return The Non-Spacing key corresponding to KeyDescriptor
498 NULL means not found.
499
500 **/
501 USB_NS_KEY *
502 FindUsbNsKey (
503 IN USB_KB_DEV *UsbKeyboardDevice,
504 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
505 )
506 {
507 LIST_ENTRY *Link;
508 LIST_ENTRY *NsKeyList;
509 USB_NS_KEY *UsbNsKey;
510
511 NsKeyList = &UsbKeyboardDevice->NsKeyList;
512 Link = GetFirstNode (NsKeyList);
513 while (!IsNull (NsKeyList, Link)) {
514 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
515
516 if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {
517 return UsbNsKey;
518 }
519
520 Link = GetNextNode (NsKeyList, Link);
521 }
522
523 return NULL;
524 }
525
526 /**
527 Find physical key definition for a given key descriptor.
528
529 For a specified non-spacing key, there are a list of physical
530 keys following it. This function traverses the list of
531 physical keys and tries to find the physical key matching
532 the KeyDescriptor.
533
534 @param UsbNsKey The non-spacing key information.
535 @param KeyDescriptor The key descriptor.
536
537 @return The physical key definition.
538 If no physical key is found, parameter KeyDescriptor is returned.
539
540 **/
541 EFI_KEY_DESCRIPTOR *
542 FindPhysicalKey (
543 IN USB_NS_KEY *UsbNsKey,
544 IN EFI_KEY_DESCRIPTOR *KeyDescriptor
545 )
546 {
547 UINTN Index;
548 EFI_KEY_DESCRIPTOR *PhysicalKey;
549
550 PhysicalKey = &UsbNsKey->NsKey[1];
551 for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {
552 if (KeyDescriptor->Key == PhysicalKey->Key) {
553 return PhysicalKey;
554 }
555
556 PhysicalKey++;
557 }
558
559 //
560 // No children definition matched, return original key
561 //
562 return KeyDescriptor;
563 }
564
565 /**
566 The notification function for EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID.
567
568 This function is registered to event of EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
569 group type, which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
570 It tries to get curent keyboard layout from HII database.
571
572 @param Event Event being signaled.
573 @param Context Points to USB_KB_DEV instance.
574
575 **/
576 VOID
577 EFIAPI
578 SetKeyboardLayoutEvent (
579 IN EFI_EVENT Event,
580 IN VOID *Context
581 )
582 {
583 USB_KB_DEV *UsbKeyboardDevice;
584 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
585 EFI_KEY_DESCRIPTOR TempKey;
586 EFI_KEY_DESCRIPTOR *KeyDescriptor;
587 EFI_KEY_DESCRIPTOR *TableEntry;
588 EFI_KEY_DESCRIPTOR *NsKey;
589 USB_NS_KEY *UsbNsKey;
590 UINTN Index;
591 UINTN Index2;
592 UINTN KeyCount;
593 UINT8 KeyCode;
594
595 UsbKeyboardDevice = (USB_KB_DEV *) Context;
596 if (UsbKeyboardDevice->Signature != USB_KB_DEV_SIGNATURE) {
597 return;
598 }
599
600 //
601 // Try to get current keyboard layout from HII database
602 //
603 KeyboardLayout = GetCurrentKeyboardLayout ();
604 if (KeyboardLayout == NULL) {
605 return;
606 }
607
608 //
609 // Re-allocate resource for KeyConvertionTable
610 //
611 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
612 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
613 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
614
615 //
616 // Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
617 //
618 KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));
619 for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {
620 //
621 // Copy from HII keyboard layout package binary for alignment
622 //
623 CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
624
625 //
626 // Fill the key into KeyConvertionTable, whose index is calculated from USB keycode.
627 //
628 KeyCode = EfiKeyToUsbKeyCodeConvertionTable [(UINT8) (TempKey.Key)];
629 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
630 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
631
632 //
633 // For non-spacing key, create the list with a non-spacing key followed by physical keys.
634 //
635 if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {
636 UsbNsKey = AllocatePool (sizeof (USB_NS_KEY));
637 ASSERT (UsbNsKey != NULL);
638
639 //
640 // Search for sequential children physical key definitions
641 //
642 KeyCount = 0;
643 NsKey = KeyDescriptor + 1;
644 for (Index2 = (UINT8) Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {
645 CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));
646 if (TempKey.Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER) {
647 KeyCount++;
648 } else {
649 break;
650 }
651 NsKey++;
652 }
653
654 UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;
655 UsbNsKey->KeyCount = KeyCount;
656 UsbNsKey->NsKey = AllocateCopyPool (
657 (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),
658 KeyDescriptor
659 );
660 InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);
661
662 //
663 // Skip over the child physical keys
664 //
665 Index += KeyCount;
666 KeyDescriptor += KeyCount;
667 }
668
669 KeyDescriptor++;
670 }
671
672 //
673 // There are two EfiKeyEnter, duplicate its key descriptor
674 //
675 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);
676 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);
677 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
678
679 FreePool (KeyboardLayout);
680 }
681
682 /**
683 Destroy resources for keyboard layout.
684
685 @param UsbKeyboardDevice The USB_KB_DEV instance.
686
687 **/
688 VOID
689 ReleaseKeyboardLayoutResources (
690 IN OUT USB_KB_DEV *UsbKeyboardDevice
691 )
692 {
693 USB_NS_KEY *UsbNsKey;
694 LIST_ENTRY *Link;
695
696 if (UsbKeyboardDevice->KeyConvertionTable != NULL) {
697 FreePool (UsbKeyboardDevice->KeyConvertionTable);
698 }
699 UsbKeyboardDevice->KeyConvertionTable = NULL;
700
701 while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {
702 Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);
703 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
704 RemoveEntryList (&UsbNsKey->Link);
705
706 FreePool (UsbNsKey->NsKey);
707 FreePool (UsbNsKey);
708 }
709 }
710
711 /**
712 Initialize USB keyboard layout.
713
714 This function initializes Key Convertion Table for the USB keyboard device.
715 It first tries to retrieve layout from HII database. If failed and default
716 layout is enabled, then it just uses the default layout.
717
718 @param UsbKeyboardDevice The USB_KB_DEV instance.
719
720 @retval EFI_SUCCESS Initialization succeeded.
721 @retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII
722 database, and default layout is disabled.
723 @retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.
724
725 **/
726 EFI_STATUS
727 InitKeyboardLayout (
728 OUT USB_KB_DEV *UsbKeyboardDevice
729 )
730 {
731 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
732 EFI_STATUS Status;
733
734 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR));
735 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
736
737 InitializeListHead (&UsbKeyboardDevice->NsKeyList);
738 UsbKeyboardDevice->CurrentNsKey = NULL;
739 UsbKeyboardDevice->KeyboardLayoutEvent = NULL;
740
741 //
742 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
743 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
744 //
745 Status = gBS->CreateEventEx (
746 EVT_NOTIFY_SIGNAL,
747 TPL_NOTIFY,
748 SetKeyboardLayoutEvent,
749 UsbKeyboardDevice,
750 &gEfiHiiKeyBoardLayoutGuid,
751 &UsbKeyboardDevice->KeyboardLayoutEvent
752 );
753 if (EFI_ERROR (Status)) {
754 return Status;
755 }
756
757 KeyboardLayout = GetCurrentKeyboardLayout ();
758 if (KeyboardLayout != NULL) {
759 //
760 // If current keyboard layout is successfully retrieved from HII database,
761 // force to initialize the keyboard layout.
762 //
763 gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
764 } else {
765 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {
766 //
767 // If no keyboard layout can be retrieved from HII database, and default layout
768 // is disabled, then return EFI_NOT_READY.
769 //
770 return EFI_NOT_READY;
771 }
772 //
773 // If no keyboard layout can be retrieved from HII database, and default layout
774 // is enabled, then load the default keyboard layout.
775 //
776 InstallDefaultKeyboardLayout (UsbKeyboardDevice);
777 }
778
779 return EFI_SUCCESS;
780 }
781
782
783 /**
784 Initialize USB keyboard device and all private data structures.
785
786 @param UsbKeyboardDevice The USB_KB_DEV instance.
787
788 @retval EFI_SUCCESS Initialization is successful.
789 @retval EFI_DEVICE_ERROR Keyboard initialization failed.
790
791 **/
792 EFI_STATUS
793 InitUSBKeyboard (
794 IN OUT USB_KB_DEV *UsbKeyboardDevice
795 )
796 {
797 UINT16 ConfigValue;
798 UINT8 Protocol;
799 UINT8 ReportId;
800 UINT8 Duration;
801 EFI_STATUS Status;
802 UINT32 TransferResult;
803
804 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
805 EFI_PROGRESS_CODE,
806 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST),
807 UsbKeyboardDevice->DevicePath
808 );
809
810 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));
811 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));
812
813 //
814 // Use the config out of the descriptor
815 // Assumed the first config is the correct one and this is not always the case
816 //
817 Status = UsbGetConfiguration (
818 UsbKeyboardDevice->UsbIo,
819 &ConfigValue,
820 &TransferResult
821 );
822 if (EFI_ERROR (Status)) {
823 ConfigValue = 0x01;
824 }
825
826 //
827 // Uses default configuration to configure the USB Keyboard device.
828 //
829 Status = UsbSetConfiguration (
830 UsbKeyboardDevice->UsbIo,
831 ConfigValue,
832 &TransferResult
833 );
834 if (EFI_ERROR (Status)) {
835 //
836 // If configuration could not be set here, it means
837 // the keyboard interface has some errors and could
838 // not be initialized
839 //
840 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
841 EFI_ERROR_CODE | EFI_ERROR_MINOR,
842 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
843 UsbKeyboardDevice->DevicePath
844 );
845
846 return EFI_DEVICE_ERROR;
847 }
848
849 UsbGetProtocolRequest (
850 UsbKeyboardDevice->UsbIo,
851 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
852 &Protocol
853 );
854 //
855 // Set boot protocol for the USB Keyboard.
856 // This driver only supports boot protocol.
857 //
858 if (Protocol != BOOT_PROTOCOL) {
859 UsbSetProtocolRequest (
860 UsbKeyboardDevice->UsbIo,
861 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
862 BOOT_PROTOCOL
863 );
864 }
865
866 //
867 // ReportId is zero, which means the idle rate applies to all input reports.
868 //
869 ReportId = 0;
870 //
871 // Duration is zero, which means the duration is infinite.
872 // so the endpoint will inhibit reporting forever,
873 // and only reporting when a change is detected in the report data.
874 //
875 Duration = 0;
876 UsbSetIdleRequest (
877 UsbKeyboardDevice->UsbIo,
878 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
879 ReportId,
880 Duration
881 );
882
883 UsbKeyboardDevice->CtrlOn = FALSE;
884 UsbKeyboardDevice->AltOn = FALSE;
885 UsbKeyboardDevice->ShiftOn = FALSE;
886 UsbKeyboardDevice->NumLockOn = FALSE;
887 UsbKeyboardDevice->CapsOn = FALSE;
888 UsbKeyboardDevice->ScrollOn = FALSE;
889
890 UsbKeyboardDevice->LeftCtrlOn = FALSE;
891 UsbKeyboardDevice->LeftAltOn = FALSE;
892 UsbKeyboardDevice->LeftShiftOn = FALSE;
893 UsbKeyboardDevice->LeftLogoOn = FALSE;
894 UsbKeyboardDevice->RightCtrlOn = FALSE;
895 UsbKeyboardDevice->RightAltOn = FALSE;
896 UsbKeyboardDevice->RightShiftOn = FALSE;
897 UsbKeyboardDevice->RightLogoOn = FALSE;
898 UsbKeyboardDevice->MenuKeyOn = FALSE;
899 UsbKeyboardDevice->SysReqOn = FALSE;
900
901 UsbKeyboardDevice->AltGrOn = FALSE;
902
903 UsbKeyboardDevice->CurrentNsKey = NULL;
904
905 //
906 // Sync the initial state of lights on keyboard.
907 //
908 SetKeyLED (UsbKeyboardDevice);
909
910 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
911
912 //
913 // Create event for repeat keys' generation.
914 //
915 if (UsbKeyboardDevice->RepeatTimer != NULL) {
916 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
917 UsbKeyboardDevice->RepeatTimer = NULL;
918 }
919
920 gBS->CreateEvent (
921 EVT_TIMER | EVT_NOTIFY_SIGNAL,
922 TPL_CALLBACK,
923 USBKeyboardRepeatHandler,
924 UsbKeyboardDevice,
925 &UsbKeyboardDevice->RepeatTimer
926 );
927
928 //
929 // Create event for delayed recovery, which deals with device error.
930 //
931 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
932 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
933 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
934 }
935
936 gBS->CreateEvent (
937 EVT_TIMER | EVT_NOTIFY_SIGNAL,
938 TPL_NOTIFY,
939 USBKeyboardRecoveryHandler,
940 UsbKeyboardDevice,
941 &UsbKeyboardDevice->DelayedRecoveryEvent
942 );
943
944 return EFI_SUCCESS;
945 }
946
947
948 /**
949 Handler function for USB keyboard's asynchronous interrupt transfer.
950
951 This function is the handler function for USB keyboard's asynchronous interrupt transfer
952 to manage the keyboard. It parses the USB keyboard input report, and inserts data to
953 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
954 is also set accordingly.
955
956 @param Data A pointer to a buffer that is filled with key data which is
957 retrieved via asynchronous interrupt transfer.
958 @param DataLength Indicates the size of the data buffer.
959 @param Context Pointing to USB_KB_DEV instance.
960 @param Result Indicates the result of the asynchronous interrupt transfer.
961
962 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
963 @retval EFI_DEVICE_ERROR Hardware error occurs.
964
965 **/
966 EFI_STATUS
967 EFIAPI
968 KeyboardHandler (
969 IN VOID *Data,
970 IN UINTN DataLength,
971 IN VOID *Context,
972 IN UINT32 Result
973 )
974 {
975 USB_KB_DEV *UsbKeyboardDevice;
976 EFI_USB_IO_PROTOCOL *UsbIo;
977 UINT8 *CurKeyCodeBuffer;
978 UINT8 *OldKeyCodeBuffer;
979 UINT8 CurModifierMap;
980 UINT8 OldModifierMap;
981 UINT8 Mask;
982 UINTN Index;
983 UINT8 Index2;
984 BOOLEAN KeyRelease;
985 BOOLEAN KeyPress;
986 USB_KEY UsbKey;
987 UINT8 NewRepeatKey;
988 UINT32 UsbStatus;
989 EFI_KEY_DESCRIPTOR *KeyDescriptor;
990
991 ASSERT (Context != NULL);
992
993 NewRepeatKey = 0;
994 UsbKeyboardDevice = (USB_KB_DEV *) Context;
995 UsbIo = UsbKeyboardDevice->UsbIo;
996
997 //
998 // Analyzes Result and performs corresponding action.
999 //
1000 if (Result != EFI_USB_NOERROR) {
1001 //
1002 // Some errors happen during the process
1003 //
1004 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1005 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1006 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR),
1007 UsbKeyboardDevice->DevicePath
1008 );
1009
1010 //
1011 // Stop the repeat key generation if any
1012 //
1013 UsbKeyboardDevice->RepeatKey = 0;
1014
1015 gBS->SetTimer (
1016 UsbKeyboardDevice->RepeatTimer,
1017 TimerCancel,
1018 USBKBD_REPEAT_RATE
1019 );
1020
1021 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
1022 UsbClearEndpointHalt (
1023 UsbIo,
1024 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1025 &UsbStatus
1026 );
1027 }
1028
1029 //
1030 // Delete & Submit this interrupt again
1031 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
1032 //
1033 UsbIo->UsbAsyncInterruptTransfer (
1034 UsbIo,
1035 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1036 FALSE,
1037 0,
1038 0,
1039 NULL,
1040 NULL
1041 );
1042 //
1043 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
1044 //
1045 gBS->SetTimer (
1046 UsbKeyboardDevice->DelayedRecoveryEvent,
1047 TimerRelative,
1048 EFI_USB_INTERRUPT_DELAY
1049 );
1050
1051 return EFI_DEVICE_ERROR;
1052 }
1053
1054 //
1055 // If no error and no data, just return EFI_SUCCESS.
1056 //
1057 if (DataLength == 0 || Data == NULL) {
1058 return EFI_SUCCESS;
1059 }
1060
1061 //
1062 // Following code checks current keyboard input report against old key code buffer.
1063 // According to USB HID Firmware Specification, the report consists of 8 bytes.
1064 // Byte 0 is map of Modifier keys.
1065 // Byte 1 is reserved.
1066 // Bytes 2 to 7 are keycodes.
1067 //
1068 CurKeyCodeBuffer = (UINT8 *) Data;
1069 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
1070
1071 //
1072 // Checks for new key stroke.
1073 //
1074 for (Index = 0; Index < 8; Index++) {
1075 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
1076 break;
1077 }
1078 }
1079
1080 //
1081 // If no new key, return EFI_SUCCESS immediately.
1082 //
1083 if (Index == 8) {
1084 return EFI_SUCCESS;
1085 }
1086
1087 //
1088 // Parse the modifier key, which is the first byte of keyboard input report.
1089 //
1090 CurModifierMap = CurKeyCodeBuffer[0];
1091 OldModifierMap = OldKeyCodeBuffer[0];
1092
1093 //
1094 // Handle modifier key's pressing or releasing situation.
1095 // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
1096 // Bit0: Left Control, Keycode: 0xe0
1097 // Bit1: Left Shift, Keycode: 0xe1
1098 // Bit2: Left Alt, Keycode: 0xe2
1099 // Bit3: Left GUI, Keycode: 0xe3
1100 // Bit4: Right Control, Keycode: 0xe4
1101 // Bit5: Right Shift, Keycode: 0xe5
1102 // Bit6: Right Alt, Keycode: 0xe6
1103 // Bit7: Right GUI, Keycode: 0xe7
1104 //
1105 for (Index = 0; Index < 8; Index++) {
1106 Mask = (UINT8) (1 << Index);
1107 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
1108 //
1109 // If current modifier key is up, then CurModifierMap & Mask = 0;
1110 // otherwise it is a non-zero value.
1111 // Insert the changed modifier key into key buffer.
1112 //
1113 UsbKey.KeyCode = (UINT8) (0xe0 + Index);
1114 UsbKey.Down = (BOOLEAN) ((CurModifierMap & Mask) != 0);
1115 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1116 }
1117 }
1118
1119 //
1120 // Handle normal key's releasing situation
1121 // Bytes 2 to 7 are for normal keycodes
1122 //
1123 KeyRelease = FALSE;
1124 for (Index = 2; Index < 8; Index++) {
1125
1126 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
1127 continue;
1128 }
1129 //
1130 // For any key in old keycode buffer, if it is not in current keycode buffer,
1131 // then it is released. Otherwise, it is not released.
1132 //
1133 KeyRelease = TRUE;
1134 for (Index2 = 2; Index2 < 8; Index2++) {
1135
1136 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
1137 continue;
1138 }
1139
1140 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
1141 KeyRelease = FALSE;
1142 break;
1143 }
1144 }
1145
1146 if (KeyRelease) {
1147 UsbKey.KeyCode = OldKeyCodeBuffer[Index];
1148 UsbKey.Down = FALSE;
1149 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1150 //
1151 // The original repeat key is released.
1152 //
1153 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
1154 UsbKeyboardDevice->RepeatKey = 0;
1155 }
1156 }
1157 }
1158
1159 //
1160 // If original repeat key is released, cancel the repeat timer
1161 //
1162 if (UsbKeyboardDevice->RepeatKey == 0) {
1163 gBS->SetTimer (
1164 UsbKeyboardDevice->RepeatTimer,
1165 TimerCancel,
1166 USBKBD_REPEAT_RATE
1167 );
1168 }
1169
1170 //
1171 // Handle normal key's pressing situation
1172 //
1173 KeyPress = FALSE;
1174 for (Index = 2; Index < 8; Index++) {
1175
1176 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
1177 continue;
1178 }
1179 //
1180 // For any key in current keycode buffer, if it is not in old keycode buffer,
1181 // then it is pressed. Otherwise, it is not pressed.
1182 //
1183 KeyPress = TRUE;
1184 for (Index2 = 2; Index2 < 8; Index2++) {
1185
1186 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
1187 continue;
1188 }
1189
1190 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
1191 KeyPress = FALSE;
1192 break;
1193 }
1194 }
1195
1196 if (KeyPress) {
1197 UsbKey.KeyCode = CurKeyCodeBuffer[Index];
1198 UsbKey.Down = TRUE;
1199 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1200
1201 //
1202 // Handle repeat key
1203 //
1204 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
1205 ASSERT (KeyDescriptor != NULL);
1206
1207 if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
1208 //
1209 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
1210 //
1211 UsbKeyboardDevice->RepeatKey = 0;
1212 } else {
1213 //
1214 // Prepare new repeat key, and clear the original one.
1215 //
1216 NewRepeatKey = CurKeyCodeBuffer[Index];
1217 UsbKeyboardDevice->RepeatKey = 0;
1218 }
1219 }
1220 }
1221
1222 //
1223 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
1224 //
1225 for (Index = 0; Index < 8; Index++) {
1226 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
1227 }
1228
1229 //
1230 // If there is new key pressed, update the RepeatKey value, and set the
1231 // timer to repeate delay timer
1232 //
1233 if (NewRepeatKey != 0) {
1234 //
1235 // Sets trigger time to "Repeat Delay Time",
1236 // to trigger the repeat timer when the key is hold long
1237 // enough time.
1238 //
1239 gBS->SetTimer (
1240 UsbKeyboardDevice->RepeatTimer,
1241 TimerRelative,
1242 USBKBD_REPEAT_DELAY
1243 );
1244 UsbKeyboardDevice->RepeatKey = NewRepeatKey;
1245 }
1246
1247 return EFI_SUCCESS;
1248 }
1249
1250
1251 /**
1252 Retrieves a USB keycode after parsing the raw data in keyboard buffer.
1253
1254 This function parses keyboard buffer. It updates state of modifier key for
1255 USB_KB_DEV instancem, and returns keycode for output.
1256
1257 @param UsbKeyboardDevice The USB_KB_DEV instance.
1258 @param KeyCode Pointer to the USB keycode for output.
1259
1260 @retval EFI_SUCCESS Keycode successfully parsed.
1261 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode
1262
1263 **/
1264 EFI_STATUS
1265 USBParseKey (
1266 IN OUT USB_KB_DEV *UsbKeyboardDevice,
1267 OUT UINT8 *KeyCode
1268 )
1269 {
1270 USB_KEY UsbKey;
1271 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1272
1273 *KeyCode = 0;
1274
1275 while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {
1276 //
1277 // Pops one raw data off.
1278 //
1279 Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1280
1281 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
1282 ASSERT (KeyDescriptor != NULL);
1283
1284 if (!UsbKey.Down) {
1285 //
1286 // Key is released.
1287 //
1288 switch (KeyDescriptor->Modifier) {
1289
1290 //
1291 // Ctrl release
1292 //
1293 case EFI_LEFT_CONTROL_MODIFIER:
1294 UsbKeyboardDevice->LeftCtrlOn = FALSE;
1295 UsbKeyboardDevice->CtrlOn = FALSE;
1296 break;
1297 case EFI_RIGHT_CONTROL_MODIFIER:
1298 UsbKeyboardDevice->RightCtrlOn = FALSE;
1299 UsbKeyboardDevice->CtrlOn = FALSE;
1300 break;
1301
1302 //
1303 // Shift release
1304 //
1305 case EFI_LEFT_SHIFT_MODIFIER:
1306 UsbKeyboardDevice->LeftShiftOn = FALSE;
1307 UsbKeyboardDevice->ShiftOn = FALSE;
1308 break;
1309 case EFI_RIGHT_SHIFT_MODIFIER:
1310 UsbKeyboardDevice->RightShiftOn = FALSE;
1311 UsbKeyboardDevice->ShiftOn = FALSE;
1312 break;
1313
1314 //
1315 // Alt release
1316 //
1317 case EFI_LEFT_ALT_MODIFIER:
1318 UsbKeyboardDevice->LeftAltOn = FALSE;
1319 UsbKeyboardDevice->AltOn = FALSE;
1320 break;
1321 case EFI_RIGHT_ALT_MODIFIER:
1322 UsbKeyboardDevice->RightAltOn = FALSE;
1323 UsbKeyboardDevice->AltOn = FALSE;
1324 break;
1325
1326 //
1327 // Left Logo release
1328 //
1329 case EFI_LEFT_LOGO_MODIFIER:
1330 UsbKeyboardDevice->LeftLogoOn = FALSE;
1331 break;
1332
1333 //
1334 // Right Logo release
1335 //
1336 case EFI_RIGHT_LOGO_MODIFIER:
1337 UsbKeyboardDevice->RightLogoOn = FALSE;
1338 break;
1339
1340 //
1341 // Menu key release
1342 //
1343 case EFI_MENU_MODIFIER:
1344 UsbKeyboardDevice->MenuKeyOn = FALSE;
1345 break;
1346
1347 //
1348 // SysReq release
1349 //
1350 case EFI_PRINT_MODIFIER:
1351 case EFI_SYS_REQUEST_MODIFIER:
1352 UsbKeyboardDevice->SysReqOn = FALSE;
1353 break;
1354
1355 //
1356 // AltGr release
1357 //
1358 case EFI_ALT_GR_MODIFIER:
1359 UsbKeyboardDevice->AltGrOn = FALSE;
1360 break;
1361
1362 default:
1363 break;
1364 }
1365
1366 continue;
1367 }
1368
1369 //
1370 // Analyzes key pressing situation
1371 //
1372 switch (KeyDescriptor->Modifier) {
1373
1374 //
1375 // Ctrl press
1376 //
1377 case EFI_LEFT_CONTROL_MODIFIER:
1378 UsbKeyboardDevice->LeftCtrlOn = TRUE;
1379 UsbKeyboardDevice->CtrlOn = TRUE;
1380 continue;
1381 break;
1382 case EFI_RIGHT_CONTROL_MODIFIER:
1383 UsbKeyboardDevice->RightCtrlOn = TRUE;
1384 UsbKeyboardDevice->CtrlOn = TRUE;
1385 continue;
1386 break;
1387
1388 //
1389 // Shift press
1390 //
1391 case EFI_LEFT_SHIFT_MODIFIER:
1392 UsbKeyboardDevice->LeftShiftOn = TRUE;
1393 UsbKeyboardDevice->ShiftOn = TRUE;
1394 continue;
1395 break;
1396 case EFI_RIGHT_SHIFT_MODIFIER:
1397 UsbKeyboardDevice->RightShiftOn = TRUE;
1398 UsbKeyboardDevice->ShiftOn = TRUE;
1399 continue;
1400 break;
1401
1402 //
1403 // Alt press
1404 //
1405 case EFI_LEFT_ALT_MODIFIER:
1406 UsbKeyboardDevice->LeftAltOn = TRUE;
1407 UsbKeyboardDevice->AltOn = TRUE;
1408 continue;
1409 break;
1410 case EFI_RIGHT_ALT_MODIFIER:
1411 UsbKeyboardDevice->RightAltOn = TRUE;
1412 UsbKeyboardDevice->AltOn = TRUE;
1413 continue;
1414 break;
1415
1416 //
1417 // Left Logo press
1418 //
1419 case EFI_LEFT_LOGO_MODIFIER:
1420 UsbKeyboardDevice->LeftLogoOn = TRUE;
1421 break;
1422
1423 //
1424 // Right Logo press
1425 //
1426 case EFI_RIGHT_LOGO_MODIFIER:
1427 UsbKeyboardDevice->RightLogoOn = TRUE;
1428 break;
1429
1430 //
1431 // Menu key press
1432 //
1433 case EFI_MENU_MODIFIER:
1434 UsbKeyboardDevice->MenuKeyOn = TRUE;
1435 break;
1436
1437 //
1438 // SysReq press
1439 //
1440 case EFI_PRINT_MODIFIER:
1441 case EFI_SYS_REQUEST_MODIFIER:
1442 UsbKeyboardDevice->SysReqOn = TRUE;
1443 continue;
1444 break;
1445
1446 //
1447 // AltGr press
1448 //
1449 case EFI_ALT_GR_MODIFIER:
1450 UsbKeyboardDevice->AltGrOn = TRUE;
1451 break;
1452
1453 case EFI_NUM_LOCK_MODIFIER:
1454 //
1455 // Toggle NumLock
1456 //
1457 UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
1458 SetKeyLED (UsbKeyboardDevice);
1459 continue;
1460 break;
1461
1462 case EFI_CAPS_LOCK_MODIFIER:
1463 //
1464 // Toggle CapsLock
1465 //
1466 UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
1467 SetKeyLED (UsbKeyboardDevice);
1468 continue;
1469 break;
1470
1471 case EFI_SCROLL_LOCK_MODIFIER:
1472 //
1473 // Toggle ScrollLock
1474 //
1475 UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
1476 SetKeyLED (UsbKeyboardDevice);
1477 continue;
1478 break;
1479
1480 default:
1481 break;
1482 }
1483
1484 //
1485 // When encountering Ctrl + Alt + Del, then warm reset.
1486 //
1487 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
1488 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
1489 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1490 }
1491 }
1492
1493 *KeyCode = UsbKey.KeyCode;
1494 return EFI_SUCCESS;
1495 }
1496
1497 return EFI_NOT_READY;
1498 }
1499
1500
1501 /**
1502 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
1503
1504 @param UsbKeyboardDevice The USB_KB_DEV instance.
1505 @param KeyCode Indicates the key code that will be interpreted.
1506 @param KeyData A pointer to a buffer that is filled in with
1507 the keystroke information for the key that
1508 was pressed.
1509
1510 @retval EFI_SUCCESS Success.
1511 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
1512 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
1513 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
1514 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.
1515
1516 **/
1517 EFI_STATUS
1518 UsbKeyCodeToEfiInputKey (
1519 IN USB_KB_DEV *UsbKeyboardDevice,
1520 IN UINT8 KeyCode,
1521 OUT EFI_KEY_DATA *KeyData
1522 )
1523 {
1524 EFI_KEY_DESCRIPTOR *KeyDescriptor;
1525 LIST_ENTRY *Link;
1526 LIST_ENTRY *NotifyList;
1527 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1528
1529 //
1530 // KeyCode must in the range of 0x4 to 0x65
1531 //
1532 if (!USBKBD_VALID_KEYCODE (KeyCode)) {
1533 return EFI_INVALID_PARAMETER;
1534 }
1535 if ((KeyCode - 4) >= NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE) {
1536 return EFI_INVALID_PARAMETER;
1537 }
1538
1539 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
1540 ASSERT (KeyDescriptor != NULL);
1541
1542 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
1543 //
1544 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
1545 //
1546 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
1547 return EFI_NOT_READY;
1548 }
1549
1550 if (UsbKeyboardDevice->CurrentNsKey != NULL) {
1551 //
1552 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
1553 // physical key.
1554 //
1555 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
1556 UsbKeyboardDevice->CurrentNsKey = NULL;
1557 }
1558
1559 //
1560 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
1561 //
1562 if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {
1563 return EFI_DEVICE_ERROR;
1564 }
1565
1566 KeyData->Key.ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
1567 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1568
1569 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
1570 if (UsbKeyboardDevice->ShiftOn) {
1571 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1572
1573 //
1574 // Need not return associated shift state if a class of printable characters that
1575 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1576 //
1577 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1578 UsbKeyboardDevice->LeftShiftOn = FALSE;
1579 UsbKeyboardDevice->RightShiftOn = FALSE;
1580 }
1581
1582 if (UsbKeyboardDevice->AltGrOn) {
1583 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
1584 }
1585 } else {
1586 //
1587 // Shift off
1588 //
1589 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1590
1591 if (UsbKeyboardDevice->AltGrOn) {
1592 KeyData->Key.UnicodeChar = KeyDescriptor->AltGrUnicode;
1593 }
1594 }
1595 }
1596
1597 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
1598 if (UsbKeyboardDevice->CapsOn) {
1599 if (KeyData->Key.UnicodeChar == KeyDescriptor->Unicode) {
1600 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
1601 } else if (KeyData->Key.UnicodeChar == KeyDescriptor->ShiftedUnicode) {
1602 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
1603 }
1604 }
1605 }
1606
1607 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
1608 //
1609 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
1610 // normal key, instead of original control key. So the ScanCode should be cleaned.
1611 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
1612 //
1613 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
1614 KeyData->Key.ScanCode = SCAN_NULL;
1615 } else {
1616 KeyData->Key.UnicodeChar = 0x00;
1617 }
1618 }
1619
1620 //
1621 // Translate Unicode 0x1B (ESC) to EFI Scan Code
1622 //
1623 if (KeyData->Key.UnicodeChar == 0x1B && KeyData->Key.ScanCode == SCAN_NULL) {
1624 KeyData->Key.ScanCode = SCAN_ESC;
1625 KeyData->Key.UnicodeChar = 0x00;
1626 }
1627
1628 //
1629 // Not valid for key without both unicode key code and EFI Scan Code.
1630 //
1631 if (KeyData->Key.UnicodeChar == 0 && KeyData->Key.ScanCode == SCAN_NULL) {
1632 return EFI_NOT_READY;
1633 }
1634
1635 //
1636 // Save Shift/Toggle state
1637 //
1638 KeyData->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
1639 KeyData->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
1640
1641 if (UsbKeyboardDevice->LeftCtrlOn) {
1642 KeyData->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
1643 }
1644 if (UsbKeyboardDevice->RightCtrlOn) {
1645 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
1646 }
1647 if (UsbKeyboardDevice->LeftAltOn) {
1648 KeyData->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
1649 }
1650 if (UsbKeyboardDevice->RightAltOn) {
1651 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
1652 }
1653 if (UsbKeyboardDevice->LeftShiftOn) {
1654 KeyData->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1655 }
1656 if (UsbKeyboardDevice->RightShiftOn) {
1657 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1658 }
1659 if (UsbKeyboardDevice->LeftLogoOn) {
1660 KeyData->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1661 }
1662 if (UsbKeyboardDevice->RightLogoOn) {
1663 KeyData->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1664 }
1665 if (UsbKeyboardDevice->MenuKeyOn) {
1666 KeyData->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1667 }
1668 if (UsbKeyboardDevice->SysReqOn) {
1669 KeyData->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1670 }
1671
1672 if (UsbKeyboardDevice->ScrollOn) {
1673 KeyData->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1674 }
1675 if (UsbKeyboardDevice->NumLockOn) {
1676 KeyData->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1677 }
1678 if (UsbKeyboardDevice->CapsOn) {
1679 KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1680 }
1681
1682 //
1683 // Invoke notification functions if the key is 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 CurrentNotify->KeyNotificationFn (KeyData);
1690 }
1691 }
1692
1693 //
1694 // Translate the CTRL-Alpha characters to their corresponding control value
1695 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1696 //
1697 if (UsbKeyboardDevice->CtrlOn) {
1698 if (KeyData->Key.UnicodeChar >= 'a' && KeyData->Key.UnicodeChar <= 'z') {
1699 KeyData->Key.UnicodeChar = (UINT8) (KeyData->Key.UnicodeChar - 'a' + 1);
1700 } else if (KeyData->Key.UnicodeChar >= 'A' && KeyData->Key.UnicodeChar <= 'Z') {
1701 KeyData->Key.UnicodeChar = (UINT8) (KeyData->Key.UnicodeChar - 'A' + 1);
1702 }
1703 }
1704
1705 return EFI_SUCCESS;
1706 }
1707
1708
1709 /**
1710 Create the queue.
1711
1712 @param Queue Points to the queue.
1713 @param ItemSize Size of the single item.
1714
1715 **/
1716 VOID
1717 InitQueue (
1718 IN OUT USB_SIMPLE_QUEUE *Queue,
1719 IN UINTN ItemSize
1720 )
1721 {
1722 UINTN Index;
1723
1724 Queue->ItemSize = ItemSize;
1725 Queue->Head = 0;
1726 Queue->Tail = 0;
1727
1728 if (Queue->Buffer[0] != NULL) {
1729 FreePool (Queue->Buffer[0]);
1730 }
1731
1732 Queue->Buffer[0] = AllocatePool (sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]) * ItemSize);
1733 ASSERT (Queue->Buffer[0] != NULL);
1734
1735 for (Index = 1; Index < sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]); Index++) {
1736 Queue->Buffer[Index] = ((UINT8 *) Queue->Buffer[Index - 1]) + ItemSize;
1737 }
1738 }
1739
1740 /**
1741 Destroy the queue
1742
1743 @param Queue Points to the queue.
1744 **/
1745 VOID
1746 DestroyQueue (
1747 IN OUT USB_SIMPLE_QUEUE *Queue
1748 )
1749 {
1750 FreePool (Queue->Buffer[0]);
1751 }
1752
1753
1754 /**
1755 Check whether the queue is empty.
1756
1757 @param Queue Points to the queue.
1758
1759 @retval TRUE Queue is empty.
1760 @retval FALSE Queue is not empty.
1761
1762 **/
1763 BOOLEAN
1764 IsQueueEmpty (
1765 IN USB_SIMPLE_QUEUE *Queue
1766 )
1767 {
1768 //
1769 // Meet FIFO empty condition
1770 //
1771 return (BOOLEAN) (Queue->Head == Queue->Tail);
1772 }
1773
1774
1775 /**
1776 Check whether the queue is full.
1777
1778 @param Queue Points to the queue.
1779
1780 @retval TRUE Queue is full.
1781 @retval FALSE Queue is not full.
1782
1783 **/
1784 BOOLEAN
1785 IsQueueFull (
1786 IN USB_SIMPLE_QUEUE *Queue
1787 )
1788 {
1789 return (BOOLEAN) (((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);
1790 }
1791
1792
1793 /**
1794 Enqueue the item to the queue.
1795
1796 @param Queue Points to the queue.
1797 @param Item Points to the item to be enqueued.
1798 @param ItemSize Size of the item.
1799 **/
1800 VOID
1801 Enqueue (
1802 IN OUT USB_SIMPLE_QUEUE *Queue,
1803 IN VOID *Item,
1804 IN UINTN ItemSize
1805 )
1806 {
1807 ASSERT (ItemSize == Queue->ItemSize);
1808 //
1809 // If keyboard buffer is full, throw the
1810 // first key out of the keyboard buffer.
1811 //
1812 if (IsQueueFull (Queue)) {
1813 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1814 }
1815
1816 CopyMem (Queue->Buffer[Queue->Tail], Item, ItemSize);
1817
1818 //
1819 // Adjust the tail pointer of the FIFO keyboard buffer.
1820 //
1821 Queue->Tail = (Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1);
1822 }
1823
1824
1825 /**
1826 Dequeue a item from the queue.
1827
1828 @param Queue Points to the queue.
1829 @param Item Receives the item.
1830 @param ItemSize Size of the item.
1831
1832 @retval EFI_SUCCESS Item was successfully dequeued.
1833 @retval EFI_DEVICE_ERROR The queue is empty.
1834
1835 **/
1836 EFI_STATUS
1837 Dequeue (
1838 IN OUT USB_SIMPLE_QUEUE *Queue,
1839 OUT VOID *Item,
1840 IN UINTN ItemSize
1841 )
1842 {
1843 ASSERT (Queue->ItemSize == ItemSize);
1844
1845 if (IsQueueEmpty (Queue)) {
1846 return EFI_DEVICE_ERROR;
1847 }
1848
1849 CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);
1850
1851 //
1852 // Adjust the head pointer of the FIFO keyboard buffer.
1853 //
1854 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
1855
1856 return EFI_SUCCESS;
1857 }
1858
1859
1860 /**
1861 Sets USB keyboard LED state.
1862
1863 @param UsbKeyboardDevice The USB_KB_DEV instance.
1864
1865 **/
1866 VOID
1867 SetKeyLED (
1868 IN USB_KB_DEV *UsbKeyboardDevice
1869 )
1870 {
1871 LED_MAP Led;
1872 UINT8 ReportId;
1873
1874 //
1875 // Set each field in Led map.
1876 //
1877 Led.NumLock = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
1878 Led.CapsLock = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
1879 Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
1880 Led.Resrvd = 0;
1881
1882 ReportId = 0;
1883 //
1884 // Call Set_Report Request to lighten the LED.
1885 //
1886 UsbSetReportRequest (
1887 UsbKeyboardDevice->UsbIo,
1888 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
1889 ReportId,
1890 HID_OUTPUT_REPORT,
1891 1,
1892 (UINT8 *) &Led
1893 );
1894 }
1895
1896
1897 /**
1898 Handler for Repeat Key event.
1899
1900 This function is the handler for Repeat Key event triggered
1901 by timer.
1902 After a repeatable key is pressed, the event would be triggered
1903 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
1904 following trigger will come with interval of USBKBD_REPEAT_RATE.
1905
1906 @param Event The Repeat Key event.
1907 @param Context Points to the USB_KB_DEV instance.
1908
1909 **/
1910 VOID
1911 EFIAPI
1912 USBKeyboardRepeatHandler (
1913 IN EFI_EVENT Event,
1914 IN VOID *Context
1915 )
1916 {
1917 USB_KB_DEV *UsbKeyboardDevice;
1918 USB_KEY UsbKey;
1919
1920 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1921
1922 //
1923 // Do nothing when there is no repeat key.
1924 //
1925 if (UsbKeyboardDevice->RepeatKey != 0) {
1926 //
1927 // Inserts the repeat key into keyboard buffer,
1928 //
1929 UsbKey.KeyCode = UsbKeyboardDevice->RepeatKey;
1930 UsbKey.Down = TRUE;
1931 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
1932
1933 //
1934 // Set repeat rate for next repeat key generation.
1935 //
1936 gBS->SetTimer (
1937 UsbKeyboardDevice->RepeatTimer,
1938 TimerRelative,
1939 USBKBD_REPEAT_RATE
1940 );
1941 }
1942 }
1943
1944
1945 /**
1946 Handler for Delayed Recovery event.
1947
1948 This function is the handler for Delayed Recovery event triggered
1949 by timer.
1950 After a device error occurs, the event would be triggered
1951 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
1952 is defined in USB standard for error handling.
1953
1954 @param Event The Delayed Recovery event.
1955 @param Context Points to the USB_KB_DEV instance.
1956
1957 **/
1958 VOID
1959 EFIAPI
1960 USBKeyboardRecoveryHandler (
1961 IN EFI_EVENT Event,
1962 IN VOID *Context
1963 )
1964 {
1965
1966 USB_KB_DEV *UsbKeyboardDevice;
1967 EFI_USB_IO_PROTOCOL *UsbIo;
1968 UINT8 PacketSize;
1969
1970 UsbKeyboardDevice = (USB_KB_DEV *) Context;
1971
1972 UsbIo = UsbKeyboardDevice->UsbIo;
1973
1974 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
1975
1976 //
1977 // Re-submit Asynchronous Interrupt Transfer for recovery.
1978 //
1979 UsbIo->UsbAsyncInterruptTransfer (
1980 UsbIo,
1981 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
1982 TRUE,
1983 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
1984 PacketSize,
1985 KeyboardHandler,
1986 UsbKeyboardDevice
1987 );
1988 }