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