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