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