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