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