Home | History | Annotate | Download | only in UsbKbDxe
      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
    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
    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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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