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