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