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