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