]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
MdeModulePkg/Usb/Keyboard.c: Don't request protocol before setting
[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
1436aea4
MK
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
c41c3e55 24 sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (USB_KEYBOARD_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset\r
1436aea4 25 USB_KEYBOARD_KEY_COUNT, // DescriptorCount\r
c41c3e55 26 {\r
27 //\r
28 // EFI_KEY_DESCRIPTOR (total number is USB_KEYBOARD_KEY_COUNT)\r
29 //\r
1436aea4
MK
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
76 { EfiKeyC12, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },\r
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
c41c3e55 135 },\r
1436aea4
MK
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
1436aea4 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
1436aea4 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
1436aea4 317 IN OUT USB_KB_DEV *UsbKeyboardDevice\r
aa79b0b3 318 )\r
319{\r
1436aea4
MK
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
1436aea4 330 (VOID **)&HiiDatabase\r
c41c3e55 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
ed838d0c 357/**\r
b4e73a63 358 Uses USB I/O to check whether the device is a USB keyboard device.\r
359\r
360 @param UsbIo Pointer to a USB I/O protocol instance.\r
ed838d0c 361\r
b4e73a63 362 @retval TRUE Device is a USB keyboard device.\r
363 @retval FALSE Device is a not USB keyboard device.\r
ed838d0c 364\r
365**/\r
366BOOLEAN\r
367IsUSBKeyboard (\r
1436aea4 368 IN EFI_USB_IO_PROTOCOL *UsbIo\r
ed838d0c 369 )\r
370{\r
371 EFI_STATUS Status;\r
372 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
373\r
374 //\r
b4e73a63 375 // Get the default interface descriptor\r
ed838d0c 376 //\r
377 Status = UsbIo->UsbGetInterfaceDescriptor (\r
378 UsbIo,\r
379 &InterfaceDescriptor\r
380 );\r
381\r
382 if (EFI_ERROR (Status)) {\r
383 return FALSE;\r
384 }\r
385\r
1436aea4
MK
386 if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&\r
387 (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&\r
388 (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD)\r
389 )\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
1436aea4
MK
409 EFI_STATUS Status;\r
410 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
411 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;\r
412 UINT16 Length;\r
813acf3a 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
1436aea4 420 (VOID **)&HiiDatabase\r
813acf3a 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
1436aea4 429 Length = 0;\r
813acf3a 430 KeyboardLayout = NULL;\r
1436aea4
MK
431 Status = HiiDatabase->GetKeyboardLayout (\r
432 HiiDatabase,\r
433 NULL,\r
434 &Length,\r
435 KeyboardLayout\r
436 );\r
813acf3a 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
1436aea4
MK
468 IN USB_KB_DEV *UsbKeyboardDevice,\r
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
1436aea4 485 Index = (UINT8)(KeyCode - 4);\r
813acf3a 486 } else {\r
1436aea4 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
1436aea4
MK
509 LIST_ENTRY *Link;\r
510 LIST_ENTRY *NsKeyList;\r
511 USB_NS_KEY *UsbNsKey;\r
3765794c 512\r
e15c65a3 513 NsKeyList = &UsbKeyboardDevice->NsKeyList;\r
1436aea4 514 Link = GetFirstNode (NsKeyList);\r
e15c65a3 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
1436aea4
MK
581 IN EFI_EVENT Event,\r
582 IN VOID *Context\r
813acf3a 583 )\r
813acf3a 584{\r
1436aea4
MK
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
595 UINT8 KeyCode;\r
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
1436aea4 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
1436aea4 620 KeyDescriptor = (EFI_KEY_DESCRIPTOR *)(((UINT8 *)KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));\r
813acf3a 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
1436aea4 630 KeyCode = EfiKeyToUsbKeyCodeConvertionTable[(UINT8)(TempKey.Key)];\r
b4e73a63 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
1436aea4 637\r
813acf3a 638 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));\r
639\r
b4e73a63 640 //\r
641 // For non-spacing key, create the list with a non-spacing key followed by physical keys.\r
642 //\r
813acf3a 643 if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {\r
d12c6a78 644 UsbNsKey = AllocateZeroPool (sizeof (USB_NS_KEY));\r
813acf3a 645 ASSERT (UsbNsKey != NULL);\r
646\r
647 //\r
648 // Search for sequential children physical key definitions\r
649 //\r
650 KeyCount = 0;\r
1436aea4
MK
651 NsKey = KeyDescriptor + 1;\r
652 for (Index2 = (UINT8)Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {\r
813acf3a 653 CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));\r
ed3a31b5 654 if (TempKey.Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER) {\r
813acf3a 655 KeyCount++;\r
656 } else {\r
657 break;\r
658 }\r
1436aea4 659\r
813acf3a 660 NsKey++;\r
661 }\r
662\r
663 UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;\r
1436aea4
MK
664 UsbNsKey->KeyCount = KeyCount;\r
665 UsbNsKey->NsKey = AllocateCopyPool (\r
666 (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),\r
667 KeyDescriptor\r
668 );\r
813acf3a 669 InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);\r
670\r
671 //\r
672 // Skip over the child physical keys\r
673 //\r
1436aea4 674 Index += KeyCount;\r
813acf3a 675 KeyDescriptor += KeyCount;\r
676 }\r
677\r
678 KeyDescriptor++;\r
679 }\r
680\r
681 //\r
b4e73a63 682 // There are two EfiKeyEnter, duplicate its key descriptor\r
813acf3a 683 //\r
1436aea4 684 TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);\r
813acf3a 685 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);\r
686 CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));\r
687\r
e15c65a3 688 FreePool (KeyboardLayout);\r
813acf3a 689}\r
690\r
a7022cec 691/**\r
b4e73a63 692 Destroy resources for keyboard layout.\r
a7022cec 693\r
694 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
695\r
696**/\r
813acf3a 697VOID\r
698ReleaseKeyboardLayoutResources (\r
1436aea4 699 IN OUT USB_KB_DEV *UsbKeyboardDevice\r
813acf3a 700 )\r
813acf3a 701{\r
1436aea4
MK
702 USB_NS_KEY *UsbNsKey;\r
703 LIST_ENTRY *Link;\r
813acf3a 704\r
676df92c 705 if (UsbKeyboardDevice->KeyConvertionTable != NULL) {\r
706 FreePool (UsbKeyboardDevice->KeyConvertionTable);\r
707 }\r
1436aea4 708\r
813acf3a 709 UsbKeyboardDevice->KeyConvertionTable = NULL;\r
710\r
711 while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {\r
1436aea4 712 Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);\r
813acf3a 713 UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);\r
714 RemoveEntryList (&UsbNsKey->Link);\r
715\r
676df92c 716 FreePool (UsbNsKey->NsKey);\r
717 FreePool (UsbNsKey);\r
813acf3a 718 }\r
719}\r
720\r
a7022cec 721/**\r
b4e73a63 722 Initialize USB keyboard layout.\r
723\r
724 This function initializes Key Convertion Table for the USB keyboard device.\r
725 It first tries to retrieve layout from HII database. If failed and default\r
726 layout is enabled, then it just uses the default layout.\r
a7022cec 727\r
728 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
729\r
b4e73a63 730 @retval EFI_SUCCESS Initialization succeeded.\r
731 @retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII\r
732 database, and default layout is disabled.\r
733 @retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.\r
a7022cec 734\r
735**/\r
813acf3a 736EFI_STATUS\r
737InitKeyboardLayout (\r
1436aea4 738 OUT USB_KB_DEV *UsbKeyboardDevice\r
813acf3a 739 )\r
813acf3a 740{\r
1436aea4
MK
741 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;\r
742 EFI_STATUS Status;\r
813acf3a 743\r
1436aea4 744 UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((NUMBER_OF_VALID_USB_KEYCODE)*sizeof (EFI_KEY_DESCRIPTOR));\r
813acf3a 745 ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);\r
746\r
747 InitializeListHead (&UsbKeyboardDevice->NsKeyList);\r
1436aea4 748 UsbKeyboardDevice->CurrentNsKey = NULL;\r
813acf3a 749 UsbKeyboardDevice->KeyboardLayoutEvent = NULL;\r
750\r
751 //\r
5899f27e 752 // Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,\r
b4e73a63 753 // which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().\r
813acf3a 754 //\r
755 Status = gBS->CreateEventEx (\r
e53a6ea9 756 EVT_NOTIFY_SIGNAL,\r
813acf3a 757 TPL_NOTIFY,\r
758 SetKeyboardLayoutEvent,\r
759 UsbKeyboardDevice,\r
7772b176 760 &gEfiHiiKeyBoardLayoutGuid,\r
813acf3a 761 &UsbKeyboardDevice->KeyboardLayoutEvent\r
762 );\r
763 if (EFI_ERROR (Status)) {\r
764 return Status;\r
765 }\r
766\r
813acf3a 767 KeyboardLayout = GetCurrentKeyboardLayout ();\r
768 if (KeyboardLayout != NULL) {\r
769 //\r
5899f27e 770 // If current keyboard layout is successfully retrieved from HII database,\r
771 // force to initialize the keyboard layout.\r
813acf3a 772 //\r
773 gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
774 } else {\r
775 if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {\r
813acf3a 776 //\r
5899f27e 777 // If no keyboard layout can be retrieved from HII database, and default layout\r
778 // is disabled, then return EFI_NOT_READY.\r
813acf3a 779 //\r
5899f27e 780 return EFI_NOT_READY;\r
813acf3a 781 }\r
1436aea4 782\r
5899f27e 783 //\r
784 // If no keyboard layout can be retrieved from HII database, and default layout\r
785 // is enabled, then load the default keyboard layout.\r
786 //\r
c41c3e55 787 InstallDefaultKeyboardLayout (UsbKeyboardDevice);\r
813acf3a 788 }\r
3765794c 789\r
813acf3a 790 return EFI_SUCCESS;\r
791}\r
792\r
ed838d0c 793/**\r
b4e73a63 794 Initialize USB keyboard device and all private data structures.\r
ed838d0c 795\r
a7022cec 796 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
ed838d0c 797\r
a7022cec 798 @retval EFI_SUCCESS Initialization is successful.\r
b4e73a63 799 @retval EFI_DEVICE_ERROR Keyboard initialization failed.\r
ed838d0c 800\r
801**/\r
802EFI_STATUS\r
803InitUSBKeyboard (\r
1436aea4 804 IN OUT USB_KB_DEV *UsbKeyboardDevice\r
ed838d0c 805 )\r
806{\r
1436aea4 807 UINT16 ConfigValue;\r
1436aea4
MK
808 EFI_STATUS Status;\r
809 UINT32 TransferResult;\r
ed838d0c 810\r
5899f27e 811 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 812 EFI_PROGRESS_CODE,\r
f9876ecf 813 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST),\r
5899f27e 814 UsbKeyboardDevice->DevicePath\r
ed838d0c 815 );\r
816\r
c1fd2767
RN
817 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
818 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
4ae46dba 819 InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));\r
ed838d0c 820\r
821 //\r
efe9186f 822 // Use the config out of the descriptor\r
823 // Assumed the first config is the correct one and this is not always the case\r
824 //\r
825 Status = UsbGetConfiguration (\r
3765794c 826 UsbKeyboardDevice->UsbIo,\r
827 &ConfigValue,\r
efe9186f 828 &TransferResult\r
829 );\r
830 if (EFI_ERROR (Status)) {\r
831 ConfigValue = 0x01;\r
ed838d0c 832 //\r
16d718a5 833 // Uses default configuration to configure the USB Keyboard device.\r
ed838d0c 834 //\r
16d718a5 835 Status = UsbSetConfiguration (\r
836 UsbKeyboardDevice->UsbIo,\r
837 ConfigValue,\r
838 &TransferResult\r
839 );\r
840 if (EFI_ERROR (Status)) {\r
841 //\r
842 // If configuration could not be set here, it means\r
843 // the keyboard interface has some errors and could\r
844 // not be initialized\r
845 //\r
846 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
847 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
848 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),\r
849 UsbKeyboardDevice->DevicePath\r
850 );\r
ed838d0c 851\r
16d718a5 852 return EFI_DEVICE_ERROR;\r
853 }\r
ed838d0c 854 }\r
855\r
ed838d0c 856 //\r
5899f27e 857 // Set boot protocol for the USB Keyboard.\r
ed838d0c 858 // This driver only supports boot protocol.\r
ed838d0c 859 //\r
589d51df
SR
860 UsbSetProtocolRequest (\r
861 UsbKeyboardDevice->UsbIo,\r
862 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
863 BOOT_PROTOCOL\r
864 );\r
ed838d0c 865\r
1436aea4
MK
866 UsbKeyboardDevice->CtrlOn = FALSE;\r
867 UsbKeyboardDevice->AltOn = FALSE;\r
868 UsbKeyboardDevice->ShiftOn = FALSE;\r
869 UsbKeyboardDevice->NumLockOn = FALSE;\r
870 UsbKeyboardDevice->CapsOn = FALSE;\r
871 UsbKeyboardDevice->ScrollOn = FALSE;\r
3765794c 872\r
b4e73a63 873 UsbKeyboardDevice->LeftCtrlOn = FALSE;\r
874 UsbKeyboardDevice->LeftAltOn = FALSE;\r
875 UsbKeyboardDevice->LeftShiftOn = FALSE;\r
876 UsbKeyboardDevice->LeftLogoOn = FALSE;\r
877 UsbKeyboardDevice->RightCtrlOn = FALSE;\r
878 UsbKeyboardDevice->RightAltOn = FALSE;\r
879 UsbKeyboardDevice->RightShiftOn = FALSE;\r
880 UsbKeyboardDevice->RightLogoOn = FALSE;\r
881 UsbKeyboardDevice->MenuKeyOn = FALSE;\r
882 UsbKeyboardDevice->SysReqOn = FALSE;\r
883\r
1436aea4 884 UsbKeyboardDevice->AltGrOn = FALSE;\r
813acf3a 885\r
886 UsbKeyboardDevice->CurrentNsKey = NULL;\r
ed838d0c 887\r
888 //\r
b4e73a63 889 // Sync the initial state of lights on keyboard.\r
ed838d0c 890 //\r
891 SetKeyLED (UsbKeyboardDevice);\r
892\r
893 ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);\r
894\r
895 //\r
c92e277d 896 // Create event for repeat keys' generation.\r
ed838d0c 897 //\r
a7022cec 898 if (UsbKeyboardDevice->RepeatTimer != NULL) {\r
ed838d0c 899 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
5899f27e 900 UsbKeyboardDevice->RepeatTimer = NULL;\r
ed838d0c 901 }\r
902\r
c92e277d 903 gBS->CreateEvent (\r
904 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
4607d9e5 905 TPL_CALLBACK,\r
c92e277d 906 USBKeyboardRepeatHandler,\r
907 UsbKeyboardDevice,\r
908 &UsbKeyboardDevice->RepeatTimer\r
909 );\r
ed838d0c 910\r
c92e277d 911 //\r
912 // Create event for delayed recovery, which deals with device error.\r
913 //\r
a7022cec 914 if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {\r
ed838d0c 915 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
5899f27e 916 UsbKeyboardDevice->DelayedRecoveryEvent = NULL;\r
ed838d0c 917 }\r
918\r
c92e277d 919 gBS->CreateEvent (\r
920 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
921 TPL_NOTIFY,\r
922 USBKeyboardRecoveryHandler,\r
923 UsbKeyboardDevice,\r
924 &UsbKeyboardDevice->DelayedRecoveryEvent\r
925 );\r
ed838d0c 926\r
927 return EFI_SUCCESS;\r
928}\r
929\r
ed838d0c 930/**\r
b4e73a63 931 Handler function for USB keyboard's asynchronous interrupt transfer.\r
932\r
933 This function is the handler function for USB keyboard's asynchronous interrupt transfer\r
934 to manage the keyboard. It parses the USB keyboard input report, and inserts data to\r
935 keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key\r
936 is also set accordingly.\r
ed838d0c 937\r
a7022cec 938 @param Data A pointer to a buffer that is filled with key data which is\r
939 retrieved via asynchronous interrupt transfer.\r
940 @param DataLength Indicates the size of the data buffer.\r
941 @param Context Pointing to USB_KB_DEV instance.\r
942 @param Result Indicates the result of the asynchronous interrupt transfer.\r
ed838d0c 943\r
b4e73a63 944 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.\r
945 @retval EFI_DEVICE_ERROR Hardware error occurs.\r
ed838d0c 946\r
947**/\r
948EFI_STATUS\r
949EFIAPI\r
950KeyboardHandler (\r
1436aea4
MK
951 IN VOID *Data,\r
952 IN UINTN DataLength,\r
953 IN VOID *Context,\r
954 IN UINT32 Result\r
ed838d0c 955 )\r
956{\r
1436aea4
MK
957 USB_KB_DEV *UsbKeyboardDevice;\r
958 EFI_USB_IO_PROTOCOL *UsbIo;\r
959 UINT8 *CurKeyCodeBuffer;\r
960 UINT8 *OldKeyCodeBuffer;\r
961 UINT8 CurModifierMap;\r
962 UINT8 OldModifierMap;\r
963 UINT8 Mask;\r
964 UINTN Index;\r
965 UINT8 Index2;\r
966 BOOLEAN KeyRelease;\r
967 BOOLEAN KeyPress;\r
968 USB_KEY UsbKey;\r
969 UINT8 NewRepeatKey;\r
970 UINT32 UsbStatus;\r
971 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
ed838d0c 972\r
5899f27e 973 ASSERT (Context != NULL);\r
ed838d0c 974\r
975 NewRepeatKey = 0;\r
1436aea4 976 UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
ed838d0c 977 UsbIo = UsbKeyboardDevice->UsbIo;\r
978\r
979 //\r
b4e73a63 980 // Analyzes Result and performs corresponding action.\r
ed838d0c 981 //\r
982 if (Result != EFI_USB_NOERROR) {\r
983 //\r
984 // Some errors happen during the process\r
985 //\r
5899f27e 986 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 987 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 988 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR),\r
5899f27e 989 UsbKeyboardDevice->DevicePath\r
ed838d0c 990 );\r
991\r
992 //\r
b4e73a63 993 // Stop the repeat key generation if any\r
ed838d0c 994 //\r
995 UsbKeyboardDevice->RepeatKey = 0;\r
996\r
997 gBS->SetTimer (\r
1436aea4
MK
998 UsbKeyboardDevice->RepeatTimer,\r
999 TimerCancel,\r
1000 USBKBD_REPEAT_RATE\r
1001 );\r
ed838d0c 1002\r
1003 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
1004 UsbClearEndpointHalt (\r
1005 UsbIo,\r
1006 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1007 &UsbStatus\r
1008 );\r
1009 }\r
1010\r
1011 //\r
1012 // Delete & Submit this interrupt again\r
3765794c 1013 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.\r
ed838d0c 1014 //\r
c52fa98c 1015 UsbIo->UsbAsyncInterruptTransfer (\r
5899f27e 1016 UsbIo,\r
1017 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1018 FALSE,\r
1019 0,\r
1020 0,\r
1021 NULL,\r
1022 NULL\r
1023 );\r
1024 //\r
b4e73a63 1025 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.\r
5899f27e 1026 //\r
ed838d0c 1027 gBS->SetTimer (\r
5899f27e 1028 UsbKeyboardDevice->DelayedRecoveryEvent,\r
1029 TimerRelative,\r
1030 EFI_USB_INTERRUPT_DELAY\r
1031 );\r
ed838d0c 1032\r
1033 return EFI_DEVICE_ERROR;\r
1034 }\r
1035\r
5899f27e 1036 //\r
1037 // If no error and no data, just return EFI_SUCCESS.\r
1038 //\r
1436aea4 1039 if ((DataLength == 0) || (Data == NULL)) {\r
ed838d0c 1040 return EFI_SUCCESS;\r
1041 }\r
1042\r
5899f27e 1043 //\r
1044 // Following code checks current keyboard input report against old key code buffer.\r
1045 // According to USB HID Firmware Specification, the report consists of 8 bytes.\r
1046 // Byte 0 is map of Modifier keys.\r
1047 // Byte 1 is reserved.\r
1048 // Bytes 2 to 7 are keycodes.\r
1049 //\r
8bcbe587
RN
1050 if (DataLength < 8) {\r
1051 return EFI_DEVICE_ERROR;\r
1052 }\r
1053\r
1436aea4
MK
1054 CurKeyCodeBuffer = (UINT8 *)Data;\r
1055 OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;\r
ed838d0c 1056\r
1057 //\r
5899f27e 1058 // Checks for new key stroke.\r
ed838d0c 1059 //\r
1060 for (Index = 0; Index < 8; Index++) {\r
1061 if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {\r
1062 break;\r
1063 }\r
1064 }\r
1065\r
5899f27e 1066 //\r
1067 // If no new key, return EFI_SUCCESS immediately.\r
1068 //\r
ed838d0c 1069 if (Index == 8) {\r
1070 return EFI_SUCCESS;\r
1071 }\r
1072\r
1073 //\r
5899f27e 1074 // Parse the modifier key, which is the first byte of keyboard input report.\r
ed838d0c 1075 //\r
1436aea4
MK
1076 CurModifierMap = CurKeyCodeBuffer[0];\r
1077 OldModifierMap = OldKeyCodeBuffer[0];\r
ed838d0c 1078\r
1079 //\r
5899f27e 1080 // Handle modifier key's pressing or releasing situation.\r
0dbaba42 1081 // According to USB HID Firmware spec, Byte 0 uses following map of Modifier keys:\r
b4e73a63 1082 // Bit0: Left Control, Keycode: 0xe0\r
1083 // Bit1: Left Shift, Keycode: 0xe1\r
1084 // Bit2: Left Alt, Keycode: 0xe2\r
1085 // Bit3: Left GUI, Keycode: 0xe3\r
1086 // Bit4: Right Control, Keycode: 0xe4\r
1087 // Bit5: Right Shift, Keycode: 0xe5\r
1088 // Bit6: Right Alt, Keycode: 0xe6\r
1089 // Bit7: Right GUI, Keycode: 0xe7\r
ed838d0c 1090 //\r
1091 for (Index = 0; Index < 8; Index++) {\r
1436aea4 1092 Mask = (UINT8)(1 << Index);\r
b4e73a63 1093 if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {\r
ed838d0c 1094 //\r
b4e73a63 1095 // If current modifier key is up, then CurModifierMap & Mask = 0;\r
5899f27e 1096 // otherwise it is a non-zero value.\r
b4e73a63 1097 // Insert the changed modifier key into key buffer.\r
ed838d0c 1098 //\r
1436aea4
MK
1099 UsbKey.KeyCode = (UINT8)(0xe0 + Index);\r
1100 UsbKey.Down = (BOOLEAN)((CurModifierMap & Mask) != 0);\r
c1fd2767 1101 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
ed838d0c 1102 }\r
1103 }\r
1104\r
1105 //\r
5899f27e 1106 // Handle normal key's releasing situation\r
b4e73a63 1107 // Bytes 2 to 7 are for normal keycodes\r
ed838d0c 1108 //\r
1109 KeyRelease = FALSE;\r
1110 for (Index = 2; Index < 8; Index++) {\r
ed838d0c 1111 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {\r
1112 continue;\r
1113 }\r
1436aea4 1114\r
5899f27e 1115 //\r
1116 // For any key in old keycode buffer, if it is not in current keycode buffer,\r
1117 // then it is released. Otherwise, it is not released.\r
1118 //\r
ed838d0c 1119 KeyRelease = TRUE;\r
1120 for (Index2 = 2; Index2 < 8; Index2++) {\r
ed838d0c 1121 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {\r
1122 continue;\r
1123 }\r
1124\r
1125 if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {\r
1126 KeyRelease = FALSE;\r
1127 break;\r
1128 }\r
1129 }\r
1130\r
1131 if (KeyRelease) {\r
c1fd2767
RN
1132 UsbKey.KeyCode = OldKeyCodeBuffer[Index];\r
1133 UsbKey.Down = FALSE;\r
1134 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
ed838d0c 1135 //\r
5899f27e 1136 // The original repeat key is released.\r
ed838d0c 1137 //\r
1138 if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {\r
1139 UsbKeyboardDevice->RepeatKey = 0;\r
1140 }\r
1141 }\r
1142 }\r
1143\r
1144 //\r
5899f27e 1145 // If original repeat key is released, cancel the repeat timer\r
ed838d0c 1146 //\r
1147 if (UsbKeyboardDevice->RepeatKey == 0) {\r
1148 gBS->SetTimer (\r
5899f27e 1149 UsbKeyboardDevice->RepeatTimer,\r
1150 TimerCancel,\r
1151 USBKBD_REPEAT_RATE\r
1152 );\r
ed838d0c 1153 }\r
1154\r
1155 //\r
5899f27e 1156 // Handle normal key's pressing situation\r
ed838d0c 1157 //\r
1158 KeyPress = FALSE;\r
1159 for (Index = 2; Index < 8; Index++) {\r
ed838d0c 1160 if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {\r
1161 continue;\r
1162 }\r
1436aea4 1163\r
5899f27e 1164 //\r
1165 // For any key in current keycode buffer, if it is not in old keycode buffer,\r
1166 // then it is pressed. Otherwise, it is not pressed.\r
1167 //\r
ed838d0c 1168 KeyPress = TRUE;\r
1169 for (Index2 = 2; Index2 < 8; Index2++) {\r
ed838d0c 1170 if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {\r
1171 continue;\r
1172 }\r
1173\r
1174 if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {\r
1175 KeyPress = FALSE;\r
1176 break;\r
1177 }\r
1178 }\r
1179\r
1180 if (KeyPress) {\r
c1fd2767
RN
1181 UsbKey.KeyCode = CurKeyCodeBuffer[Index];\r
1182 UsbKey.Down = TRUE;\r
1183 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
5899f27e 1184\r
ed838d0c 1185 //\r
5899f27e 1186 // Handle repeat key\r
ed838d0c 1187 //\r
813acf3a 1188 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);\r
18b50d66
FT
1189 if (KeyDescriptor == NULL) {\r
1190 continue;\r
1191 }\r
81464cf1 1192\r
1436aea4 1193 if ((KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER) || (KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER)) {\r
5899f27e 1194 //\r
1195 // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.\r
1196 //\r
ed838d0c 1197 UsbKeyboardDevice->RepeatKey = 0;\r
1198 } else {\r
ed838d0c 1199 //\r
5899f27e 1200 // Prepare new repeat key, and clear the original one.\r
ed838d0c 1201 //\r
1436aea4 1202 NewRepeatKey = CurKeyCodeBuffer[Index];\r
ed838d0c 1203 UsbKeyboardDevice->RepeatKey = 0;\r
1204 }\r
1205 }\r
1206 }\r
1207\r
1208 //\r
b4e73a63 1209 // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.\r
ed838d0c 1210 //\r
1211 for (Index = 0; Index < 8; Index++) {\r
1212 UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];\r
1213 }\r
1214\r
ed838d0c 1215 //\r
b4e73a63 1216 // If there is new key pressed, update the RepeatKey value, and set the\r
ed838d0c 1217 // timer to repeate delay timer\r
1218 //\r
1219 if (NewRepeatKey != 0) {\r
1220 //\r
5899f27e 1221 // Sets trigger time to "Repeat Delay Time",\r
ed838d0c 1222 // to trigger the repeat timer when the key is hold long\r
1223 // enough time.\r
1224 //\r
1225 gBS->SetTimer (\r
b4e73a63 1226 UsbKeyboardDevice->RepeatTimer,\r
1227 TimerRelative,\r
1228 USBKBD_REPEAT_DELAY\r
1229 );\r
ed838d0c 1230 UsbKeyboardDevice->RepeatKey = NewRepeatKey;\r
1231 }\r
1232\r
1233 return EFI_SUCCESS;\r
1234}\r
1235\r
ed838d0c 1236/**\r
b4e73a63 1237 Retrieves a USB keycode after parsing the raw data in keyboard buffer.\r
1238\r
1239 This function parses keyboard buffer. It updates state of modifier key for\r
1240 USB_KB_DEV instancem, and returns keycode for output.\r
ed838d0c 1241\r
a7022cec 1242 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
b4e73a63 1243 @param KeyCode Pointer to the USB keycode for output.\r
ed838d0c 1244\r
b4e73a63 1245 @retval EFI_SUCCESS Keycode successfully parsed.\r
1246 @retval EFI_NOT_READY Keyboard buffer is not ready for a valid keycode\r
ed838d0c 1247\r
1248**/\r
1249EFI_STATUS\r
1250USBParseKey (\r
1251 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
1436aea4 1252 OUT UINT8 *KeyCode\r
ed838d0c 1253 )\r
1254{\r
813acf3a 1255 USB_KEY UsbKey;\r
1256 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
ed838d0c 1257\r
b4e73a63 1258 *KeyCode = 0;\r
ed838d0c 1259\r
c1fd2767 1260 while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {\r
ed838d0c 1261 //\r
5899f27e 1262 // Pops one raw data off.\r
ed838d0c 1263 //\r
c1fd2767 1264 Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
ed838d0c 1265\r
813acf3a 1266 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
18b50d66
FT
1267 if (KeyDescriptor == NULL) {\r
1268 continue;\r
1269 }\r
1436aea4 1270\r
b4e73a63 1271 if (!UsbKey.Down) {\r
5899f27e 1272 //\r
1273 // Key is released.\r
1274 //\r
813acf3a 1275 switch (KeyDescriptor->Modifier) {\r
1436aea4
MK
1276 //\r
1277 // Ctrl release\r
1278 //\r
1279 case EFI_LEFT_CONTROL_MODIFIER:\r
1280 UsbKeyboardDevice->LeftCtrlOn = FALSE;\r
1281 UsbKeyboardDevice->CtrlOn = FALSE;\r
1282 break;\r
1283 case EFI_RIGHT_CONTROL_MODIFIER:\r
1284 UsbKeyboardDevice->RightCtrlOn = FALSE;\r
1285 UsbKeyboardDevice->CtrlOn = FALSE;\r
1286 break;\r
1287\r
1288 //\r
1289 // Shift release\r
1290 //\r
1291 case EFI_LEFT_SHIFT_MODIFIER:\r
1292 UsbKeyboardDevice->LeftShiftOn = FALSE;\r
1293 UsbKeyboardDevice->ShiftOn = FALSE;\r
1294 break;\r
1295 case EFI_RIGHT_SHIFT_MODIFIER:\r
1296 UsbKeyboardDevice->RightShiftOn = FALSE;\r
1297 UsbKeyboardDevice->ShiftOn = FALSE;\r
1298 break;\r
1299\r
1300 //\r
1301 // Alt release\r
1302 //\r
1303 case EFI_LEFT_ALT_MODIFIER:\r
1304 UsbKeyboardDevice->LeftAltOn = FALSE;\r
1305 UsbKeyboardDevice->AltOn = FALSE;\r
1306 break;\r
1307 case EFI_RIGHT_ALT_MODIFIER:\r
1308 UsbKeyboardDevice->RightAltOn = FALSE;\r
1309 UsbKeyboardDevice->AltOn = FALSE;\r
1310 break;\r
ed838d0c 1311\r
1436aea4
MK
1312 //\r
1313 // Left Logo release\r
1314 //\r
1315 case EFI_LEFT_LOGO_MODIFIER:\r
1316 UsbKeyboardDevice->LeftLogoOn = FALSE;\r
1317 break;\r
1318\r
1319 //\r
1320 // Right Logo release\r
1321 //\r
1322 case EFI_RIGHT_LOGO_MODIFIER:\r
1323 UsbKeyboardDevice->RightLogoOn = FALSE;\r
1324 break;\r
1325\r
1326 //\r
1327 // Menu key release\r
1328 //\r
1329 case EFI_MENU_MODIFIER:\r
1330 UsbKeyboardDevice->MenuKeyOn = FALSE;\r
1331 break;\r
1332\r
1333 //\r
1334 // SysReq release\r
1335 //\r
1336 case EFI_PRINT_MODIFIER:\r
1337 case EFI_SYS_REQUEST_MODIFIER:\r
1338 UsbKeyboardDevice->SysReqOn = FALSE;\r
1339 break;\r
1340\r
1341 //\r
1342 // AltGr release\r
1343 //\r
1344 case EFI_ALT_GR_MODIFIER:\r
1345 UsbKeyboardDevice->AltGrOn = FALSE;\r
1346 break;\r
1347\r
1348 default:\r
1349 break;\r
1350 }\r
1351\r
1352 continue;\r
1353 }\r
1354\r
1355 //\r
1356 // Analyzes key pressing situation\r
1357 //\r
1358 switch (KeyDescriptor->Modifier) {\r
66aa04e4 1359 //\r
1436aea4 1360 // Ctrl press\r
66aa04e4 1361 //\r
813acf3a 1362 case EFI_LEFT_CONTROL_MODIFIER:\r
1436aea4
MK
1363 UsbKeyboardDevice->LeftCtrlOn = TRUE;\r
1364 UsbKeyboardDevice->CtrlOn = TRUE;\r
66aa04e4 1365 break;\r
813acf3a 1366 case EFI_RIGHT_CONTROL_MODIFIER:\r
1436aea4
MK
1367 UsbKeyboardDevice->RightCtrlOn = TRUE;\r
1368 UsbKeyboardDevice->CtrlOn = TRUE;\r
ed838d0c 1369 break;\r
1370\r
66aa04e4 1371 //\r
1436aea4 1372 // Shift press\r
66aa04e4 1373 //\r
813acf3a 1374 case EFI_LEFT_SHIFT_MODIFIER:\r
1436aea4
MK
1375 UsbKeyboardDevice->LeftShiftOn = TRUE;\r
1376 UsbKeyboardDevice->ShiftOn = TRUE;\r
66aa04e4 1377 break;\r
813acf3a 1378 case EFI_RIGHT_SHIFT_MODIFIER:\r
1436aea4
MK
1379 UsbKeyboardDevice->RightShiftOn = TRUE;\r
1380 UsbKeyboardDevice->ShiftOn = TRUE;\r
ed838d0c 1381 break;\r
1382\r
66aa04e4 1383 //\r
1436aea4 1384 // Alt press\r
66aa04e4 1385 //\r
813acf3a 1386 case EFI_LEFT_ALT_MODIFIER:\r
1436aea4
MK
1387 UsbKeyboardDevice->LeftAltOn = TRUE;\r
1388 UsbKeyboardDevice->AltOn = TRUE;\r
66aa04e4 1389 break;\r
813acf3a 1390 case EFI_RIGHT_ALT_MODIFIER:\r
1436aea4
MK
1391 UsbKeyboardDevice->RightAltOn = TRUE;\r
1392 UsbKeyboardDevice->AltOn = TRUE;\r
ed838d0c 1393 break;\r
1394\r
66aa04e4 1395 //\r
1436aea4 1396 // Left Logo press\r
66aa04e4 1397 //\r
813acf3a 1398 case EFI_LEFT_LOGO_MODIFIER:\r
1436aea4 1399 UsbKeyboardDevice->LeftLogoOn = TRUE;\r
66aa04e4 1400 break;\r
813acf3a 1401\r
1402 //\r
1436aea4 1403 // Right Logo press\r
813acf3a 1404 //\r
1405 case EFI_RIGHT_LOGO_MODIFIER:\r
1436aea4 1406 UsbKeyboardDevice->RightLogoOn = TRUE;\r
66aa04e4 1407 break;\r
1408\r
1409 //\r
1436aea4 1410 // Menu key press\r
66aa04e4 1411 //\r
813acf3a 1412 case EFI_MENU_MODIFIER:\r
1436aea4 1413 UsbKeyboardDevice->MenuKeyOn = TRUE;\r
66aa04e4 1414 break;\r
1415\r
1416 //\r
1436aea4 1417 // SysReq press\r
66aa04e4 1418 //\r
a77267d2 1419 case EFI_PRINT_MODIFIER:\r
813acf3a 1420 case EFI_SYS_REQUEST_MODIFIER:\r
1436aea4 1421 UsbKeyboardDevice->SysReqOn = TRUE;\r
66aa04e4 1422 break;\r
813acf3a 1423\r
1424 //\r
1436aea4 1425 // AltGr press\r
813acf3a 1426 //\r
1427 case EFI_ALT_GR_MODIFIER:\r
1436aea4 1428 UsbKeyboardDevice->AltGrOn = TRUE;\r
813acf3a 1429 break;\r
1430\r
1436aea4
MK
1431 case EFI_NUM_LOCK_MODIFIER:\r
1432 //\r
1433 // Toggle NumLock\r
1434 //\r
1435 UsbKeyboardDevice->NumLockOn = (BOOLEAN)(!(UsbKeyboardDevice->NumLockOn));\r
1436 SetKeyLED (UsbKeyboardDevice);\r
ed838d0c 1437 break;\r
813acf3a 1438\r
1436aea4
MK
1439 case EFI_CAPS_LOCK_MODIFIER:\r
1440 //\r
1441 // Toggle CapsLock\r
1442 //\r
1443 UsbKeyboardDevice->CapsOn = (BOOLEAN)(!(UsbKeyboardDevice->CapsOn));\r
1444 SetKeyLED (UsbKeyboardDevice);\r
1445 break;\r
ed838d0c 1446\r
1436aea4
MK
1447 case EFI_SCROLL_LOCK_MODIFIER:\r
1448 //\r
1449 // Toggle ScrollLock\r
1450 //\r
1451 UsbKeyboardDevice->ScrollOn = (BOOLEAN)(!(UsbKeyboardDevice->ScrollOn));\r
1452 SetKeyLED (UsbKeyboardDevice);\r
1453 break;\r
ed838d0c 1454\r
1436aea4
MK
1455 default:\r
1456 break;\r
ed838d0c 1457 }\r
1458\r
1459 //\r
5899f27e 1460 // When encountering Ctrl + Alt + Del, then warm reset.\r
ed838d0c 1461 //\r
813acf3a 1462 if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {\r
b4e73a63 1463 if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {\r
ed838d0c 1464 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1465 }\r
1466 }\r
1467\r
b4e73a63 1468 *KeyCode = UsbKey.KeyCode;\r
ed838d0c 1469 return EFI_SUCCESS;\r
1470 }\r
1471\r
1472 return EFI_NOT_READY;\r
ed838d0c 1473}\r
1474\r
c095341c
RN
1475/**\r
1476 Initialize the key state.\r
1477\r
1478 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
1479 @param KeyState A pointer to receive the key state information.\r
1480**/\r
1481VOID\r
1482InitializeKeyState (\r
1436aea4
MK
1483 IN USB_KB_DEV *UsbKeyboardDevice,\r
1484 OUT EFI_KEY_STATE *KeyState\r
c095341c
RN
1485 )\r
1486{\r
1487 KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;\r
1488 KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
1489\r
1490 if (UsbKeyboardDevice->LeftCtrlOn) {\r
1491 KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
1492 }\r
1436aea4 1493\r
c095341c
RN
1494 if (UsbKeyboardDevice->RightCtrlOn) {\r
1495 KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
1496 }\r
1436aea4 1497\r
c095341c
RN
1498 if (UsbKeyboardDevice->LeftAltOn) {\r
1499 KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
1500 }\r
1436aea4 1501\r
c095341c
RN
1502 if (UsbKeyboardDevice->RightAltOn) {\r
1503 KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
1504 }\r
1436aea4 1505\r
c095341c
RN
1506 if (UsbKeyboardDevice->LeftShiftOn) {\r
1507 KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
1508 }\r
1436aea4 1509\r
c095341c
RN
1510 if (UsbKeyboardDevice->RightShiftOn) {\r
1511 KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
1512 }\r
1436aea4 1513\r
c095341c
RN
1514 if (UsbKeyboardDevice->LeftLogoOn) {\r
1515 KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
1516 }\r
1436aea4 1517\r
c095341c
RN
1518 if (UsbKeyboardDevice->RightLogoOn) {\r
1519 KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
1520 }\r
1436aea4 1521\r
c095341c
RN
1522 if (UsbKeyboardDevice->MenuKeyOn) {\r
1523 KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
1524 }\r
1436aea4 1525\r
c095341c
RN
1526 if (UsbKeyboardDevice->SysReqOn) {\r
1527 KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
1528 }\r
1529\r
1530 if (UsbKeyboardDevice->ScrollOn) {\r
1531 KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
1532 }\r
1436aea4 1533\r
c095341c
RN
1534 if (UsbKeyboardDevice->NumLockOn) {\r
1535 KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
1536 }\r
1436aea4 1537\r
c095341c
RN
1538 if (UsbKeyboardDevice->CapsOn) {\r
1539 KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
1540 }\r
1436aea4 1541\r
c095341c
RN
1542 if (UsbKeyboardDevice->IsSupportPartialKey) {\r
1543 KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;\r
1544 }\r
1545}\r
ed838d0c 1546\r
ed838d0c 1547/**\r
b4e73a63 1548 Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.\r
ed838d0c 1549\r
b4e73a63 1550 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
1551 @param KeyCode Indicates the key code that will be interpreted.\r
c1fd2767 1552 @param KeyData A pointer to a buffer that is filled in with\r
b4e73a63 1553 the keystroke information for the key that\r
1554 was pressed.\r
ed838d0c 1555\r
b4e73a63 1556 @retval EFI_SUCCESS Success.\r
1557 @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.\r
1558 @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.\r
1559 @retval EFI_NOT_READY KeyCode represents a dead key with EFI_NS_KEY_MODIFIER\r
81464cf1 1560 @retval EFI_DEVICE_ERROR Keyboard layout is invalid.\r
ed838d0c 1561\r
1562**/\r
1563EFI_STATUS\r
5899f27e 1564UsbKeyCodeToEfiInputKey (\r
1436aea4
MK
1565 IN USB_KB_DEV *UsbKeyboardDevice,\r
1566 IN UINT8 KeyCode,\r
1567 OUT EFI_KEY_DATA *KeyData\r
ed838d0c 1568 )\r
1569{\r
1436aea4
MK
1570 EFI_KEY_DESCRIPTOR *KeyDescriptor;\r
1571 LIST_ENTRY *Link;\r
1572 LIST_ENTRY *NotifyList;\r
1573 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
ed838d0c 1574\r
ed838d0c 1575 //\r
3765794c 1576 // KeyCode must in the range of [0x4, 0x65] or [0xe0, 0xe7].\r
ed838d0c 1577 //\r
b4e73a63 1578 KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);\r
18b50d66
FT
1579 if (KeyDescriptor == NULL) {\r
1580 return EFI_DEVICE_ERROR;\r
1581 }\r
813acf3a 1582\r
813acf3a 1583 if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {\r
5899f27e 1584 //\r
1585 // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.\r
1586 //\r
813acf3a 1587 UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);\r
1588 return EFI_NOT_READY;\r
1589 }\r
1590\r
813acf3a 1591 if (UsbKeyboardDevice->CurrentNsKey != NULL) {\r
5899f27e 1592 //\r
1593 // If this keystroke follows a non-spacing key, then find the descriptor for corresponding\r
1594 // physical key.\r
1595 //\r
1436aea4 1596 KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);\r
813acf3a 1597 UsbKeyboardDevice->CurrentNsKey = NULL;\r
66aa04e4 1598 }\r
1599\r
81464cf1 1600 //\r
1601 // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.\r
1602 //\r
26fab514 1603 if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {\r
81464cf1 1604 return EFI_DEVICE_ERROR;\r
1605 }\r
1606\r
c1fd2767
RN
1607 KeyData->Key.ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];\r
1608 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;\r
ed838d0c 1609\r
1436aea4 1610 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT) != 0) {\r
b4e73a63 1611 if (UsbKeyboardDevice->ShiftOn) {\r
c1fd2767 1612 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
ed838d0c 1613\r
813acf3a 1614 //\r
1615 // Need not return associated shift state if a class of printable characters that\r
1616 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
1617 //\r
dd190645 1618 if ((KeyDescriptor->Unicode != CHAR_NULL) && (KeyDescriptor->ShiftedUnicode != CHAR_NULL) &&\r
1436aea4
MK
1619 (KeyDescriptor->Unicode != KeyDescriptor->ShiftedUnicode))\r
1620 {\r
1621 UsbKeyboardDevice->LeftShiftOn = FALSE;\r
b4e73a63 1622 UsbKeyboardDevice->RightShiftOn = FALSE;\r
813acf3a 1623 }\r
ed838d0c 1624\r
b4e73a63 1625 if (UsbKeyboardDevice->AltGrOn) {\r
c1fd2767 1626 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;\r
813acf3a 1627 }\r
1628 } else {\r
1629 //\r
1630 // Shift off\r
1631 //\r
c1fd2767 1632 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;\r
ed838d0c 1633\r
b4e73a63 1634 if (UsbKeyboardDevice->AltGrOn) {\r
c1fd2767 1635 KeyData->Key.UnicodeChar = KeyDescriptor->AltGrUnicode;\r
813acf3a 1636 }\r
1637 }\r
ed838d0c 1638 }\r
1639\r
5899f27e 1640 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {\r
b4e73a63 1641 if (UsbKeyboardDevice->CapsOn) {\r
c1fd2767
RN
1642 if (KeyData->Key.UnicodeChar == KeyDescriptor->Unicode) {\r
1643 KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
1644 } else if (KeyData->Key.UnicodeChar == KeyDescriptor->ShiftedUnicode) {\r
1645 KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;\r
813acf3a 1646 }\r
ed838d0c 1647 }\r
1648 }\r
813acf3a 1649\r
ed3a31b5 1650 if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {\r
5899f27e 1651 //\r
1652 // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means\r
1653 // normal key, instead of original control key. So the ScanCode should be cleaned.\r
1654 // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.\r
1655 //\r
b4e73a63 1656 if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {\r
c1fd2767 1657 KeyData->Key.ScanCode = SCAN_NULL;\r
ed838d0c 1658 } else {\r
3765794c 1659 KeyData->Key.UnicodeChar = CHAR_NULL;\r
ed838d0c 1660 }\r
1661 }\r
1662\r
813acf3a 1663 //\r
1664 // Translate Unicode 0x1B (ESC) to EFI Scan Code\r
1665 //\r
1436aea4
MK
1666 if ((KeyData->Key.UnicodeChar == 0x1B) && (KeyData->Key.ScanCode == SCAN_NULL)) {\r
1667 KeyData->Key.ScanCode = SCAN_ESC;\r
3765794c 1668 KeyData->Key.UnicodeChar = CHAR_NULL;\r
813acf3a 1669 }\r
1670\r
5899f27e 1671 //\r
1672 // Not valid for key without both unicode key code and EFI Scan Code.\r
1673 //\r
1436aea4 1674 if ((KeyData->Key.UnicodeChar == 0) && (KeyData->Key.ScanCode == SCAN_NULL)) {\r
3765794c 1675 if (!UsbKeyboardDevice->IsSupportPartialKey) {\r
1436aea4 1676 return EFI_NOT_READY;\r
3765794c 1677 }\r
ed838d0c 1678 }\r
1679\r
66aa04e4 1680 //\r
1681 // Save Shift/Toggle state\r
1682 //\r
c095341c 1683 InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
c1fd2767 1684\r
c1fd2767 1685 //\r
4ae46dba 1686 // Signal KeyNotify process event if this key pressed matches any key registered.\r
c1fd2767
RN
1687 //\r
1688 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1689 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
1690 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
3765794c 1691 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
4ae46dba
SZ
1692 //\r
1693 // The key notification function needs to run at TPL_CALLBACK\r
1694 // while current TPL is TPL_NOTIFY. It will be invoked in\r
1695 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
1696 //\r
1697 Enqueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, KeyData, sizeof (*KeyData));\r
1698 gBS->SignalEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
f316a260 1699 break;\r
c1fd2767
RN
1700 }\r
1701 }\r
1702\r
c1fd2767 1703 return EFI_SUCCESS;\r
ed838d0c 1704}\r
1705\r
ed838d0c 1706/**\r
c1fd2767 1707 Create the queue.\r
ed838d0c 1708\r
c1fd2767
RN
1709 @param Queue Points to the queue.\r
1710 @param ItemSize Size of the single item.\r
ed838d0c 1711\r
ed838d0c 1712**/\r
5899f27e 1713VOID\r
c1fd2767 1714InitQueue (\r
1436aea4
MK
1715 IN OUT USB_SIMPLE_QUEUE *Queue,\r
1716 IN UINTN ItemSize\r
ed838d0c 1717 )\r
1718{\r
1436aea4 1719 UINTN Index;\r
ed838d0c 1720\r
1436aea4
MK
1721 Queue->ItemSize = ItemSize;\r
1722 Queue->Head = 0;\r
1723 Queue->Tail = 0;\r
c1fd2767
RN
1724\r
1725 if (Queue->Buffer[0] != NULL) {\r
1726 FreePool (Queue->Buffer[0]);\r
1727 }\r
1728\r
1729 Queue->Buffer[0] = AllocatePool (sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]) * ItemSize);\r
1730 ASSERT (Queue->Buffer[0] != NULL);\r
1731\r
1732 for (Index = 1; Index < sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]); Index++) {\r
1436aea4 1733 Queue->Buffer[Index] = ((UINT8 *)Queue->Buffer[Index - 1]) + ItemSize;\r
c1fd2767
RN
1734 }\r
1735}\r
1736\r
1737/**\r
1738 Destroy the queue\r
1739\r
1740 @param Queue Points to the queue.\r
1741**/\r
1742VOID\r
1743DestroyQueue (\r
1436aea4 1744 IN OUT USB_SIMPLE_QUEUE *Queue\r
c1fd2767
RN
1745 )\r
1746{\r
1747 FreePool (Queue->Buffer[0]);\r
ed838d0c 1748}\r
1749\r
ed838d0c 1750/**\r
c1fd2767 1751 Check whether the queue is empty.\r
ed838d0c 1752\r
c1fd2767 1753 @param Queue Points to the queue.\r
ed838d0c 1754\r
c1fd2767
RN
1755 @retval TRUE Queue is empty.\r
1756 @retval FALSE Queue is not empty.\r
ed838d0c 1757\r
1758**/\r
1759BOOLEAN\r
c1fd2767 1760IsQueueEmpty (\r
1436aea4 1761 IN USB_SIMPLE_QUEUE *Queue\r
ed838d0c 1762 )\r
1763{\r
1764 //\r
b4e73a63 1765 // Meet FIFO empty condition\r
ed838d0c 1766 //\r
1436aea4 1767 return (BOOLEAN)(Queue->Head == Queue->Tail);\r
ed838d0c 1768}\r
1769\r
ed838d0c 1770/**\r
c1fd2767 1771 Check whether the queue is full.\r
ed838d0c 1772\r
c1fd2767 1773 @param Queue Points to the queue.\r
ed838d0c 1774\r
c1fd2767
RN
1775 @retval TRUE Queue is full.\r
1776 @retval FALSE Queue is not full.\r
ed838d0c 1777\r
1778**/\r
1779BOOLEAN\r
c1fd2767 1780IsQueueFull (\r
1436aea4 1781 IN USB_SIMPLE_QUEUE *Queue\r
ed838d0c 1782 )\r
1783{\r
1436aea4 1784 return (BOOLEAN)(((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);\r
ed838d0c 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 1795Enqueue (\r
1436aea4
MK
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
ed838d0c 1818/**\r
c1fd2767 1819 Dequeue a item from the queue.\r
ed838d0c 1820\r
c1fd2767
RN
1821 @param Queue Points to the queue.\r
1822 @param Item Receives the item.\r
1823 @param ItemSize Size of the item.\r
ed838d0c 1824\r
c1fd2767
RN
1825 @retval EFI_SUCCESS Item was successfully dequeued.\r
1826 @retval EFI_DEVICE_ERROR The queue is empty.\r
ed838d0c 1827\r
1828**/\r
1829EFI_STATUS\r
c1fd2767 1830Dequeue (\r
1436aea4
MK
1831 IN OUT USB_SIMPLE_QUEUE *Queue,\r
1832 OUT VOID *Item,\r
1833 IN UINTN ItemSize\r
ed838d0c 1834 )\r
1835{\r
c1fd2767
RN
1836 ASSERT (Queue->ItemSize == ItemSize);\r
1837\r
1838 if (IsQueueEmpty (Queue)) {\r
ed838d0c 1839 return EFI_DEVICE_ERROR;\r
1840 }\r
1841\r
c1fd2767 1842 CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);\r
ed838d0c 1843\r
1844 //\r
5899f27e 1845 // Adjust the head pointer of the FIFO keyboard buffer.\r
ed838d0c 1846 //\r
c1fd2767 1847 Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);\r
ed838d0c 1848\r
1849 return EFI_SUCCESS;\r
1850}\r
1851\r
ed838d0c 1852/**\r
b4e73a63 1853 Sets USB keyboard LED state.\r
ed838d0c 1854\r
1855 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
1856\r
ed838d0c 1857**/\r
5899f27e 1858VOID\r
ed838d0c 1859SetKeyLED (\r
1436aea4 1860 IN USB_KB_DEV *UsbKeyboardDevice\r
ed838d0c 1861 )\r
1862{\r
1436aea4
MK
1863 LED_MAP Led;\r
1864 UINT8 ReportId;\r
ed838d0c 1865\r
1866 //\r
1867 // Set each field in Led map.\r
1868 //\r
1436aea4
MK
1869 Led.NumLock = (UINT8)((UsbKeyboardDevice->NumLockOn) ? 1 : 0);\r
1870 Led.CapsLock = (UINT8)((UsbKeyboardDevice->CapsOn) ? 1 : 0);\r
1871 Led.ScrollLock = (UINT8)((UsbKeyboardDevice->ScrollOn) ? 1 : 0);\r
ed838d0c 1872 Led.Resrvd = 0;\r
1873\r
1436aea4 1874 ReportId = 0;\r
ed838d0c 1875 //\r
5899f27e 1876 // Call Set_Report Request to lighten the LED.\r
ed838d0c 1877 //\r
1878 UsbSetReportRequest (\r
1879 UsbKeyboardDevice->UsbIo,\r
1880 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
1881 ReportId,\r
1882 HID_OUTPUT_REPORT,\r
1883 1,\r
1436aea4 1884 (UINT8 *)&Led\r
ed838d0c 1885 );\r
ed838d0c 1886}\r
1887\r
ed838d0c 1888/**\r
b4e73a63 1889 Handler for Repeat Key event.\r
1890\r
1891 This function is the handler for Repeat Key event triggered\r
1892 by timer.\r
1893 After a repeatable key is pressed, the event would be triggered\r
1894 with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,\r
1895 following trigger will come with interval of USBKBD_REPEAT_RATE.\r
ed838d0c 1896\r
1897 @param Event The Repeat Key event.\r
1898 @param Context Points to the USB_KB_DEV instance.\r
1899\r
ed838d0c 1900**/\r
1901VOID\r
1902EFIAPI\r
1903USBKeyboardRepeatHandler (\r
1436aea4
MK
1904 IN EFI_EVENT Event,\r
1905 IN VOID *Context\r
ed838d0c 1906 )\r
1907{\r
1908 USB_KB_DEV *UsbKeyboardDevice;\r
c1fd2767 1909 USB_KEY UsbKey;\r
ed838d0c 1910\r
1436aea4 1911 UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
ed838d0c 1912\r
1913 //\r
1914 // Do nothing when there is no repeat key.\r
1915 //\r
1916 if (UsbKeyboardDevice->RepeatKey != 0) {\r
1917 //\r
b4e73a63 1918 // Inserts the repeat key into keyboard buffer,\r
ed838d0c 1919 //\r
c1fd2767
RN
1920 UsbKey.KeyCode = UsbKeyboardDevice->RepeatKey;\r
1921 UsbKey.Down = TRUE;\r
1922 Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
ed838d0c 1923\r
1924 //\r
e15c65a3 1925 // Set repeat rate for next repeat key generation.\r
ed838d0c 1926 //\r
1927 gBS->SetTimer (\r
5899f27e 1928 UsbKeyboardDevice->RepeatTimer,\r
1929 TimerRelative,\r
1930 USBKBD_REPEAT_RATE\r
1931 );\r
ed838d0c 1932 }\r
1933}\r
1934\r
ed838d0c 1935/**\r
b4e73a63 1936 Handler for Delayed Recovery event.\r
1937\r
1938 This function is the handler for Delayed Recovery event triggered\r
1939 by timer.\r
1940 After a device error occurs, the event would be triggered\r
1941 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY\r
1942 is defined in USB standard for error handling.\r
ed838d0c 1943\r
1944 @param Event The Delayed Recovery event.\r
1945 @param Context Points to the USB_KB_DEV instance.\r
1946\r
ed838d0c 1947**/\r
1948VOID\r
1949EFIAPI\r
1950USBKeyboardRecoveryHandler (\r
1436aea4
MK
1951 IN EFI_EVENT Event,\r
1952 IN VOID *Context\r
ed838d0c 1953 )\r
1954{\r
1436aea4
MK
1955 USB_KB_DEV *UsbKeyboardDevice;\r
1956 EFI_USB_IO_PROTOCOL *UsbIo;\r
1957 UINT8 PacketSize;\r
ed838d0c 1958\r
1436aea4 1959 UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
ed838d0c 1960\r
1436aea4 1961 UsbIo = UsbKeyboardDevice->UsbIo;\r
ed838d0c 1962\r
1436aea4 1963 PacketSize = (UINT8)(UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
ed838d0c 1964\r
5899f27e 1965 //\r
1966 // Re-submit Asynchronous Interrupt Transfer for recovery.\r
1967 //\r
ed838d0c 1968 UsbIo->UsbAsyncInterruptTransfer (\r
5899f27e 1969 UsbIo,\r
1970 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
1971 TRUE,\r
1972 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
1973 PacketSize,\r
1974 KeyboardHandler,\r
1975 UsbKeyboardDevice\r
1976 );\r
ed838d0c 1977}\r