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