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