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