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