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