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