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