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