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