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