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