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