Home | History | Annotate | Download | only in UsbKbDxe
      1 /** @file
      2   Helper functions for USB Keyboard Driver.
      3 
      4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "KeyBoard.h"
     16 
     17 USB_KEYBOARD_LAYOUT_PACK_BIN  mUsbKeyboardLayoutBin = {
     18   sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN),   // Binary size
     19 
     20   //
     21   // EFI_HII_PACKAGE_HEADER
     22   //
     23   {
     24     sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32),
     25     EFI_HII_PACKAGE_KEYBOARD_LAYOUT
     26   },
     27   1,  // LayoutCount
     28   sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32) - sizeof (EFI_HII_PACKAGE_HEADER) - sizeof (UINT16), // LayoutLength
     29   USB_KEYBOARD_LAYOUT_KEY_GUID,  // KeyGuid
     30   sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (USB_KEYBOARD_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset
     31   USB_KEYBOARD_KEY_COUNT, // DescriptorCount
     32   {
     33     //
     34     // EFI_KEY_DESCRIPTOR (total number is USB_KEYBOARD_KEY_COUNT)
     35     //
     36     {EfiKeyC1,         'a',      'A',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     37     {EfiKeyB5,         'b',      'B',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     38     {EfiKeyB3,         'c',      'C',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     39     {EfiKeyC3,         'd',      'D',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     40     {EfiKeyD3,         'e',      'E',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     41     {EfiKeyC4,         'f',      'F',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     42     {EfiKeyC5,         'g',      'G',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     43     {EfiKeyC6,         'h',      'H',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     44     {EfiKeyD8,         'i',      'I',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     45     {EfiKeyC7,         'j',      'J',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     46     {EfiKeyC8,         'k',      'K',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     47     {EfiKeyC9,         'l',      'L',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     48     {EfiKeyB7,         'm',      'M',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     49     {EfiKeyB6,         'n',      'N',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     50     {EfiKeyD9,         'o',      'O',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     51     {EfiKeyD10,        'p',      'P',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     52     {EfiKeyD1,         'q',      'Q',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     53     {EfiKeyD4,         'r',      'R',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     54     {EfiKeyC2,         's',      'S',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     55     {EfiKeyD5,         't',      'T',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     56     {EfiKeyD7,         'u',      'U',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     57     {EfiKeyB4,         'v',      'V',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     58     {EfiKeyD2,         'w',      'W',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     59     {EfiKeyB2,         'x',      'X',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     60     {EfiKeyD6,         'y',      'Y',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     61     {EfiKeyB1,         'z',      'Z',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
     62     {EfiKeyE1,         '1',      '!',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     63     {EfiKeyE2,         '2',      '@',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     64     {EfiKeyE3,         '3',      '#',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     65     {EfiKeyE4,         '4',      '$',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     66     {EfiKeyE5,         '5',      '%',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     67     {EfiKeyE6,         '6',      '^',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     68     {EfiKeyE7,         '7',      '&',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     69     {EfiKeyE8,         '8',      '*',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     70     {EfiKeyE9,         '9',      '(',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     71     {EfiKeyE10,        '0',      ')',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     72     {EfiKeyEnter,      0x0d,     0x0d, 0, 0,  EFI_NULL_MODIFIER,   0},
     73     {EfiKeyEsc,        0x1b,     0x1b, 0, 0,  EFI_NULL_MODIFIER,   0},
     74     {EfiKeyBackSpace,  0x08,     0x08, 0, 0,  EFI_NULL_MODIFIER,   0},
     75     {EfiKeyTab,        0x09,     0x09, 0, 0,  EFI_NULL_MODIFIER,   0},
     76     {EfiKeySpaceBar,   ' ',      ' ',  0, 0,  EFI_NULL_MODIFIER,   0},
     77     {EfiKeyE11,        '-',      '_',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     78     {EfiKeyE12,        '=',      '+',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     79     {EfiKeyD11,        '[',      '{',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     80     {EfiKeyD12,        ']',      '}',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     81     {EfiKeyD13,        '\\',     '|',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     82     {EfiKeyC12,        '\\',     '|',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     83     {EfiKeyC10,        ';',      ':',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     84     {EfiKeyC11,        '\'',     '"',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     85     {EfiKeyE0,         '`',      '~',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     86     {EfiKeyB8,         ',',      '<',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     87     {EfiKeyB9,         '.',      '>',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     88     {EfiKeyB10,        '/',      '?',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},
     89     {EfiKeyCapsLock,   0x00,     0x00, 0, 0,  EFI_CAPS_LOCK_MODIFIER,            0},
     90     {EfiKeyF1,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_ONE_MODIFIER,     0},
     91     {EfiKeyF2,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_TWO_MODIFIER,     0},
     92     {EfiKeyF3,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_THREE_MODIFIER,   0},
     93     {EfiKeyF4,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_FOUR_MODIFIER,    0},
     94     {EfiKeyF5,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_FIVE_MODIFIER,    0},
     95     {EfiKeyF6,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_SIX_MODIFIER,     0},
     96     {EfiKeyF7,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_SEVEN_MODIFIER,   0},
     97     {EfiKeyF8,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_EIGHT_MODIFIER,   0},
     98     {EfiKeyF9,         0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_NINE_MODIFIER,    0},
     99     {EfiKeyF10,        0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_TEN_MODIFIER,     0},
    100     {EfiKeyF11,        0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_ELEVEN_MODIFIER,  0},
    101     {EfiKeyF12,        0x00,     0x00, 0, 0,  EFI_FUNCTION_KEY_TWELVE_MODIFIER,  0},
    102     {EfiKeyPrint,      0x00,     0x00, 0, 0,  EFI_PRINT_MODIFIER,                0},
    103     {EfiKeySLck,       0x00,     0x00, 0, 0,  EFI_SCROLL_LOCK_MODIFIER,          0},
    104     {EfiKeyPause,      0x00,     0x00, 0, 0,  EFI_PAUSE_MODIFIER,                0},
    105     {EfiKeyIns,        0x00,     0x00, 0, 0,  EFI_INSERT_MODIFIER,               0},
    106     {EfiKeyHome,       0x00,     0x00, 0, 0,  EFI_HOME_MODIFIER,                 0},
    107     {EfiKeyPgUp,       0x00,     0x00, 0, 0,  EFI_PAGE_UP_MODIFIER,              0},
    108     {EfiKeyDel,        0x00,     0x00, 0, 0,  EFI_DELETE_MODIFIER,               0},
    109     {EfiKeyEnd,        0x00,     0x00, 0, 0,  EFI_END_MODIFIER,                  0},
    110     {EfiKeyPgDn,       0x00,     0x00, 0, 0,  EFI_PAGE_DOWN_MODIFIER,            0},
    111     {EfiKeyRightArrow, 0x00,     0x00, 0, 0,  EFI_RIGHT_ARROW_MODIFIER,          0},
    112     {EfiKeyLeftArrow,  0x00,     0x00, 0, 0,  EFI_LEFT_ARROW_MODIFIER,           0},
    113     {EfiKeyDownArrow,  0x00,     0x00, 0, 0,  EFI_DOWN_ARROW_MODIFIER,           0},
    114     {EfiKeyUpArrow,    0x00,     0x00, 0, 0,  EFI_UP_ARROW_MODIFIER,             0},
    115     {EfiKeyNLck,       0x00,     0x00, 0, 0,  EFI_NUM_LOCK_MODIFIER,             0},
    116     {EfiKeySlash,      '/',      '/',  0, 0,  EFI_NULL_MODIFIER,                 0},
    117     {EfiKeyAsterisk,   '*',      '*',  0, 0,  EFI_NULL_MODIFIER,                 0},
    118     {EfiKeyMinus,      '-',      '-',  0, 0,  EFI_NULL_MODIFIER,                 0},
    119     {EfiKeyPlus,       '+',      '+',  0, 0,  EFI_NULL_MODIFIER,                 0},
    120     {EfiKeyEnter,      0x0d,     0x0d, 0, 0,  EFI_NULL_MODIFIER,                 0},
    121     {EfiKeyOne,        '1',      '1',  0, 0,  EFI_END_MODIFIER,         EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    122     {EfiKeyTwo,        '2',      '2',  0, 0,  EFI_DOWN_ARROW_MODIFIER,  EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    123     {EfiKeyThree,      '3',      '3',  0, 0,  EFI_PAGE_DOWN_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    124     {EfiKeyFour,       '4',      '4',  0, 0,  EFI_LEFT_ARROW_MODIFIER,  EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    125     {EfiKeyFive,       '5',      '5',  0, 0,  EFI_NULL_MODIFIER,        EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    126     {EfiKeySix,        '6',      '6',  0, 0,  EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    127     {EfiKeySeven,      '7',      '7',  0, 0,  EFI_HOME_MODIFIER,        EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    128     {EfiKeyEight,      '8',      '8',  0, 0,  EFI_UP_ARROW_MODIFIER,    EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    129     {EfiKeyNine,       '9',      '9',  0, 0,  EFI_PAGE_UP_MODIFIER,     EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    130     {EfiKeyZero,       '0',      '0',  0, 0,  EFI_INSERT_MODIFIER,      EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    131     {EfiKeyPeriod,     '.',      '.',  0, 0,  EFI_DELETE_MODIFIER,      EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
    132     {EfiKeyA4,         0x00,     0x00, 0, 0,  EFI_MENU_MODIFIER,            0},
    133     {EfiKeyLCtrl,      0,        0,    0, 0,  EFI_LEFT_CONTROL_MODIFIER,    0},
    134     {EfiKeyLShift,     0,        0,    0, 0,  EFI_LEFT_SHIFT_MODIFIER,      0},
    135     {EfiKeyLAlt,       0,        0,    0, 0,  EFI_LEFT_ALT_MODIFIER,        0},
    136     {EfiKeyA0,         0,        0,    0, 0,  EFI_LEFT_LOGO_MODIFIER,       0},
    137     {EfiKeyRCtrl,      0,        0,    0, 0,  EFI_RIGHT_CONTROL_MODIFIER,   0},
    138     {EfiKeyRShift,     0,        0,    0, 0,  EFI_RIGHT_SHIFT_MODIFIER,     0},
    139     {EfiKeyA2,         0,        0,    0, 0,  EFI_RIGHT_ALT_MODIFIER,       0},
    140     {EfiKeyA3,         0,        0,    0, 0,  EFI_RIGHT_LOGO_MODIFIER,      0},
    141   },
    142   1,                          // DescriptionCount
    143   {'e', 'n', '-', 'U', 'S'},  // RFC4646 language code
    144   ' ',                        // Space
    145   {'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '\0'}, // DescriptionString[]
    146 };
    147 
    148 //
    149 // EFI_KEY to USB Keycode conversion table
    150 // EFI_KEY is defined in UEFI spec.
    151 // USB Keycode is defined in USB HID Firmware spec.
    152 //
    153 UINT8 EfiKeyToUsbKeyCodeConvertionTable[] = {
    154   0xe0,  //  EfiKeyLCtrl
    155   0xe3,  //  EfiKeyA0
    156   0xe2,  //  EfiKeyLAlt
    157   0x2c,  //  EfiKeySpaceBar
    158   0xe6,  //  EfiKeyA2
    159   0xe7,  //  EfiKeyA3
    160   0x65,  //  EfiKeyA4
    161   0xe4,  //  EfiKeyRCtrl
    162   0x50,  //  EfiKeyLeftArrow
    163   0x51,  //  EfiKeyDownArrow
    164   0x4F,  //  EfiKeyRightArrow
    165   0x62,  //  EfiKeyZero
    166   0x63,  //  EfiKeyPeriod
    167   0x28,  //  EfiKeyEnter
    168   0xe1,  //  EfiKeyLShift
    169   0x64,  //  EfiKeyB0
    170   0x1D,  //  EfiKeyB1
    171   0x1B,  //  EfiKeyB2
    172   0x06,  //  EfiKeyB3
    173   0x19,  //  EfiKeyB4
    174   0x05,  //  EfiKeyB5
    175   0x11,  //  EfiKeyB6
    176   0x10,  //  EfiKeyB7
    177   0x36,  //  EfiKeyB8
    178   0x37,  //  EfiKeyB9
    179   0x38,  //  EfiKeyB10
    180   0xe5,  //  EfiKeyRShift
    181   0x52,  //  EfiKeyUpArrow
    182   0x59,  //  EfiKeyOne
    183   0x5A,  //  EfiKeyTwo
    184   0x5B,  //  EfiKeyThree
    185   0x39,  //  EfiKeyCapsLock
    186   0x04,  //  EfiKeyC1
    187   0x16,  //  EfiKeyC2
    188   0x07,  //  EfiKeyC3
    189   0x09,  //  EfiKeyC4
    190   0x0A,  //  EfiKeyC5
    191   0x0B,  //  EfiKeyC6
    192   0x0D,  //  EfiKeyC7
    193   0x0E,  //  EfiKeyC8
    194   0x0F,  //  EfiKeyC9
    195   0x33,  //  EfiKeyC10
    196   0x34,  //  EfiKeyC11
    197   0x32,  //  EfiKeyC12
    198   0x5C,  //  EfiKeyFour
    199   0x5D,  //  EfiKeyFive
    200   0x5E,  //  EfiKeySix
    201   0x57,  //  EfiKeyPlus
    202   0x2B,  //  EfiKeyTab
    203   0x14,  //  EfiKeyD1
    204   0x1A,  //  EfiKeyD2
    205   0x08,  //  EfiKeyD3
    206   0x15,  //  EfiKeyD4
    207   0x17,  //  EfiKeyD5
    208   0x1C,  //  EfiKeyD6
    209   0x18,  //  EfiKeyD7
    210   0x0C,  //  EfiKeyD8
    211   0x12,  //  EfiKeyD9
    212   0x13,  //  EfiKeyD10
    213   0x2F,  //  EfiKeyD11
    214   0x30,  //  EfiKeyD12
    215   0x31,  //  EfiKeyD13
    216   0x4C,  //  EfiKeyDel
    217   0x4D,  //  EfiKeyEnd
    218   0x4E,  //  EfiKeyPgDn
    219   0x5F,  //  EfiKeySeven
    220   0x60,  //  EfiKeyEight
    221   0x61,  //  EfiKeyNine
    222   0x35,  //  EfiKeyE0
    223   0x1E,  //  EfiKeyE1
    224   0x1F,  //  EfiKeyE2
    225   0x20,  //  EfiKeyE3
    226   0x21,  //  EfiKeyE4
    227   0x22,  //  EfiKeyE5
    228   0x23,  //  EfiKeyE6
    229   0x24,  //  EfiKeyE7
    230   0x25,  //  EfiKeyE8
    231   0x26,  //  EfiKeyE9
    232   0x27,  //  EfiKeyE10
    233   0x2D,  //  EfiKeyE11
    234   0x2E,  //  EfiKeyE12
    235   0x2A,  //  EfiKeyBackSpace
    236   0x49,  //  EfiKeyIns
    237   0x4A,  //  EfiKeyHome
    238   0x4B,  //  EfiKeyPgUp
    239   0x53,  //  EfiKeyNLck
    240   0x54,  //  EfiKeySlash
    241   0x55,  //  EfiKeyAsterisk
    242   0x56,  //  EfiKeyMinus
    243   0x29,  //  EfiKeyEsc
    244   0x3A,  //  EfiKeyF1
    245   0x3B,  //  EfiKeyF2
    246   0x3C,  //  EfiKeyF3
    247   0x3D,  //  EfiKeyF4
    248   0x3E,  //  EfiKeyF5
    249   0x3F,  //  EfiKeyF6
    250   0x40,  //  EfiKeyF7
    251   0x41,  //  EfiKeyF8
    252   0x42,  //  EfiKeyF9
    253   0x43,  //  EfiKeyF10
    254   0x44,  //  EfiKeyF11
    255   0x45,  //  EfiKeyF12
    256   0x46,  //  EfiKeyPrint
    257   0x47,  //  EfiKeySLck
    258   0x48   //  EfiKeyPause
    259 };
    260 
    261 //
    262 // Keyboard modifier value to EFI Scan Code convertion table
    263 // EFI Scan Code and the modifier values are defined in UEFI spec.
    264 //
    265 UINT8 ModifierValueToEfiScanCodeConvertionTable[] = {
    266   SCAN_NULL,       // EFI_NULL_MODIFIER
    267   SCAN_NULL,       // EFI_LEFT_CONTROL_MODIFIER
    268   SCAN_NULL,       // EFI_RIGHT_CONTROL_MODIFIER
    269   SCAN_NULL,       // EFI_LEFT_ALT_MODIFIER
    270   SCAN_NULL,       // EFI_RIGHT_ALT_MODIFIER
    271   SCAN_NULL,       // EFI_ALT_GR_MODIFIER
    272   SCAN_INSERT,     // EFI_INSERT_MODIFIER
    273   SCAN_DELETE,     // EFI_DELETE_MODIFIER
    274   SCAN_PAGE_DOWN,  // EFI_PAGE_DOWN_MODIFIER
    275   SCAN_PAGE_UP,    // EFI_PAGE_UP_MODIFIER
    276   SCAN_HOME,       // EFI_HOME_MODIFIER
    277   SCAN_END,        // EFI_END_MODIFIER
    278   SCAN_NULL,       // EFI_LEFT_SHIFT_MODIFIER
    279   SCAN_NULL,       // EFI_RIGHT_SHIFT_MODIFIER
    280   SCAN_NULL,       // EFI_CAPS_LOCK_MODIFIER
    281   SCAN_NULL,       // EFI_NUM_LOCK_MODIFIER
    282   SCAN_LEFT,       // EFI_LEFT_ARROW_MODIFIER
    283   SCAN_RIGHT,      // EFI_RIGHT_ARROW_MODIFIER
    284   SCAN_DOWN,       // EFI_DOWN_ARROW_MODIFIER
    285   SCAN_UP,         // EFI_UP_ARROW_MODIFIER
    286   SCAN_NULL,       // EFI_NS_KEY_MODIFIER
    287   SCAN_NULL,       // EFI_NS_KEY_DEPENDENCY_MODIFIER
    288   SCAN_F1,         // EFI_FUNCTION_KEY_ONE_MODIFIER
    289   SCAN_F2,         // EFI_FUNCTION_KEY_TWO_MODIFIER
    290   SCAN_F3,         // EFI_FUNCTION_KEY_THREE_MODIFIER
    291   SCAN_F4,         // EFI_FUNCTION_KEY_FOUR_MODIFIER
    292   SCAN_F5,         // EFI_FUNCTION_KEY_FIVE_MODIFIER
    293   SCAN_F6,         // EFI_FUNCTION_KEY_SIX_MODIFIER
    294   SCAN_F7,         // EFI_FUNCTION_KEY_SEVEN_MODIFIER
    295   SCAN_F8,         // EFI_FUNCTION_KEY_EIGHT_MODIFIER
    296   SCAN_F9,         // EFI_FUNCTION_KEY_NINE_MODIFIER
    297   SCAN_F10,        // EFI_FUNCTION_KEY_TEN_MODIFIER
    298   SCAN_F11,        // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
    299   SCAN_F12,        // EFI_FUNCTION_KEY_TWELVE_MODIFIER
    300   //
    301   // For Partial Keystroke support
    302   //
    303   SCAN_NULL,       // EFI_PRINT_MODIFIER
    304   SCAN_NULL,       // EFI_SYS_REQUEST_MODIFIER
    305   SCAN_NULL,       // EFI_SCROLL_LOCK_MODIFIER
    306   SCAN_PAUSE,      // EFI_PAUSE_MODIFIER
    307   SCAN_NULL,       // EFI_BREAK_MODIFIER
    308   SCAN_NULL,       // EFI_LEFT_LOGO_MODIFIER
    309   SCAN_NULL,       // EFI_RIGHT_LOGO_MODIFER
    310   SCAN_NULL,       // EFI_MENU_MODIFER
    311 };
    312 
    313 /**
    314   Initialize Key Convention Table by using default keyboard layout.
    315 
    316   @param  UsbKeyboardDevice    The USB_KB_DEV instance.
    317 
    318   @retval EFI_SUCCESS          The default keyboard layout was installed successfully
    319   @retval Others               Failure to install default keyboard layout.
    320 **/
    321 EFI_STATUS
    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 
    824   //
    825   // Use the config out of the descriptor
    826   // Assumed the first config is the correct one and this is not always the case
    827   //
    828   Status = UsbGetConfiguration (
    829              UsbKeyboardDevice->UsbIo,
    830              &ConfigValue,
    831              &TransferResult
    832              );
    833   if (EFI_ERROR (Status)) {
    834     ConfigValue = 0x01;
    835     //
    836     // Uses default configuration to configure the USB Keyboard device.
    837     //
    838     Status = UsbSetConfiguration (
    839                UsbKeyboardDevice->UsbIo,
    840                ConfigValue,
    841                &TransferResult
    842                );
    843     if (EFI_ERROR (Status)) {
    844       //
    845       // If configuration could not be set here, it means
    846       // the keyboard interface has some errors and could
    847       // not be initialized
    848       //
    849       REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    850         EFI_ERROR_CODE | EFI_ERROR_MINOR,
    851         (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
    852         UsbKeyboardDevice->DevicePath
    853         );
    854 
    855       return EFI_DEVICE_ERROR;
    856     }
    857   }
    858 
    859   UsbGetProtocolRequest (
    860     UsbKeyboardDevice->UsbIo,
    861     UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
    862     &Protocol
    863     );
    864   //
    865   // Set boot protocol for the USB Keyboard.
    866   // This driver only supports boot protocol.
    867   //
    868   if (Protocol != BOOT_PROTOCOL) {
    869     UsbSetProtocolRequest (
    870       UsbKeyboardDevice->UsbIo,
    871       UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
    872       BOOT_PROTOCOL
    873       );
    874   }
    875 
    876   UsbKeyboardDevice->CtrlOn     = FALSE;
    877   UsbKeyboardDevice->AltOn      = FALSE;
    878   UsbKeyboardDevice->ShiftOn    = FALSE;
    879   UsbKeyboardDevice->NumLockOn  = FALSE;
    880   UsbKeyboardDevice->CapsOn     = FALSE;
    881   UsbKeyboardDevice->ScrollOn   = FALSE;
    882 
    883   UsbKeyboardDevice->LeftCtrlOn   = FALSE;
    884   UsbKeyboardDevice->LeftAltOn    = FALSE;
    885   UsbKeyboardDevice->LeftShiftOn  = FALSE;
    886   UsbKeyboardDevice->LeftLogoOn   = FALSE;
    887   UsbKeyboardDevice->RightCtrlOn  = FALSE;
    888   UsbKeyboardDevice->RightAltOn   = FALSE;
    889   UsbKeyboardDevice->RightShiftOn = FALSE;
    890   UsbKeyboardDevice->RightLogoOn  = FALSE;
    891   UsbKeyboardDevice->MenuKeyOn    = FALSE;
    892   UsbKeyboardDevice->SysReqOn     = FALSE;
    893 
    894   UsbKeyboardDevice->AltGrOn      = FALSE;
    895 
    896   UsbKeyboardDevice->CurrentNsKey = NULL;
    897 
    898   //
    899   // Sync the initial state of lights on keyboard.
    900   //
    901   SetKeyLED (UsbKeyboardDevice);
    902 
    903   ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
    904 
    905   //
    906   // Create event for repeat keys' generation.
    907   //
    908   if (UsbKeyboardDevice->RepeatTimer != NULL) {
    909     gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
    910     UsbKeyboardDevice->RepeatTimer = NULL;
    911   }
    912 
    913   gBS->CreateEvent (
    914          EVT_TIMER | EVT_NOTIFY_SIGNAL,
    915          TPL_CALLBACK,
    916          USBKeyboardRepeatHandler,
    917          UsbKeyboardDevice,
    918          &UsbKeyboardDevice->RepeatTimer
    919          );
    920 
    921   //
    922   // Create event for delayed recovery, which deals with device error.
    923   //
    924   if (UsbKeyboardDevice->DelayedRecoveryEvent != NULL) {
    925     gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
    926     UsbKeyboardDevice->DelayedRecoveryEvent = NULL;
    927   }
    928 
    929   gBS->CreateEvent (
    930          EVT_TIMER | EVT_NOTIFY_SIGNAL,
    931          TPL_NOTIFY,
    932          USBKeyboardRecoveryHandler,
    933          UsbKeyboardDevice,
    934          &UsbKeyboardDevice->DelayedRecoveryEvent
    935          );
    936 
    937   return EFI_SUCCESS;
    938 }
    939 
    940 
    941 /**
    942   Handler function for USB keyboard's asynchronous interrupt transfer.
    943 
    944   This function is the handler function for USB keyboard's asynchronous interrupt transfer
    945   to manage the keyboard. It parses the USB keyboard input report, and inserts data to
    946   keyboard buffer according to state of modifer keys and normal keys. Timer for repeat key
    947   is also set accordingly.
    948 
    949   @param  Data             A pointer to a buffer that is filled with key data which is
    950                            retrieved via asynchronous interrupt transfer.
    951   @param  DataLength       Indicates the size of the data buffer.
    952   @param  Context          Pointing to USB_KB_DEV instance.
    953   @param  Result           Indicates the result of the asynchronous interrupt transfer.
    954 
    955   @retval EFI_SUCCESS      Asynchronous interrupt transfer is handled successfully.
    956   @retval EFI_DEVICE_ERROR Hardware error occurs.
    957 
    958 **/
    959 EFI_STATUS
    960 EFIAPI
    961 KeyboardHandler (
    962   IN  VOID          *Data,
    963   IN  UINTN         DataLength,
    964   IN  VOID          *Context,
    965   IN  UINT32        Result
    966   )
    967 {
    968   USB_KB_DEV          *UsbKeyboardDevice;
    969   EFI_USB_IO_PROTOCOL *UsbIo;
    970   UINT8               *CurKeyCodeBuffer;
    971   UINT8               *OldKeyCodeBuffer;
    972   UINT8               CurModifierMap;
    973   UINT8               OldModifierMap;
    974   UINT8               Mask;
    975   UINTN               Index;
    976   UINT8               Index2;
    977   BOOLEAN             KeyRelease;
    978   BOOLEAN             KeyPress;
    979   USB_KEY             UsbKey;
    980   UINT8               NewRepeatKey;
    981   UINT32              UsbStatus;
    982   EFI_KEY_DESCRIPTOR  *KeyDescriptor;
    983 
    984   ASSERT (Context != NULL);
    985 
    986   NewRepeatKey      = 0;
    987   UsbKeyboardDevice = (USB_KB_DEV *) Context;
    988   UsbIo             = UsbKeyboardDevice->UsbIo;
    989 
    990   //
    991   // Analyzes Result and performs corresponding action.
    992   //
    993   if (Result != EFI_USB_NOERROR) {
    994     //
    995     // Some errors happen during the process
    996     //
    997     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    998       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    999       (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR),
   1000       UsbKeyboardDevice->DevicePath
   1001       );
   1002 
   1003     //
   1004     // Stop the repeat key generation if any
   1005     //
   1006     UsbKeyboardDevice->RepeatKey = 0;
   1007 
   1008     gBS->SetTimer (
   1009           UsbKeyboardDevice->RepeatTimer,
   1010           TimerCancel,
   1011           USBKBD_REPEAT_RATE
   1012           );
   1013 
   1014     if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
   1015       UsbClearEndpointHalt (
   1016         UsbIo,
   1017         UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
   1018         &UsbStatus
   1019         );
   1020     }
   1021 
   1022     //
   1023     // Delete & Submit this interrupt again
   1024     // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
   1025     //
   1026     UsbIo->UsbAsyncInterruptTransfer (
   1027              UsbIo,
   1028              UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
   1029              FALSE,
   1030              0,
   1031              0,
   1032              NULL,
   1033              NULL
   1034              );
   1035     //
   1036     // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
   1037     //
   1038     gBS->SetTimer (
   1039            UsbKeyboardDevice->DelayedRecoveryEvent,
   1040            TimerRelative,
   1041            EFI_USB_INTERRUPT_DELAY
   1042            );
   1043 
   1044     return EFI_DEVICE_ERROR;
   1045   }
   1046 
   1047   //
   1048   // If no error and no data, just return EFI_SUCCESS.
   1049   //
   1050   if (DataLength == 0 || Data == NULL) {
   1051     return EFI_SUCCESS;
   1052   }
   1053 
   1054   //
   1055   // Following code checks current keyboard input report against old key code buffer.
   1056   // According to USB HID Firmware Specification, the report consists of 8 bytes.
   1057   // Byte 0 is map of Modifier keys.
   1058   // Byte 1 is reserved.
   1059   // Bytes 2 to 7 are keycodes.
   1060   //
   1061   CurKeyCodeBuffer  = (UINT8 *) Data;
   1062   OldKeyCodeBuffer  = UsbKeyboardDevice->LastKeyCodeArray;
   1063 
   1064   //
   1065   // Checks for new key stroke.
   1066   //
   1067   for (Index = 0; Index < 8; Index++) {
   1068     if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
   1069       break;
   1070     }
   1071   }
   1072 
   1073   //
   1074   // If no new key, return EFI_SUCCESS immediately.
   1075   //
   1076   if (Index == 8) {
   1077     return EFI_SUCCESS;
   1078   }
   1079 
   1080   //
   1081   // Parse the modifier key, which is the first byte of keyboard input report.
   1082   //
   1083   CurModifierMap  = CurKeyCodeBuffer[0];
   1084   OldModifierMap  = OldKeyCodeBuffer[0];
   1085 
   1086   //
   1087   // Handle modifier key's pressing or releasing situation.
   1088   // According to USB HID Firmware spec, Byte 0 uses folloing map of Modifier keys:
   1089   // Bit0: Left Control,  Keycode: 0xe0
   1090   // Bit1: Left Shift,    Keycode: 0xe1
   1091   // Bit2: Left Alt,      Keycode: 0xe2
   1092   // Bit3: Left GUI,      Keycode: 0xe3
   1093   // Bit4: Right Control, Keycode: 0xe4
   1094   // Bit5: Right Shift,   Keycode: 0xe5
   1095   // Bit6: Right Alt,     Keycode: 0xe6
   1096   // Bit7: Right GUI,     Keycode: 0xe7
   1097   //
   1098   for (Index = 0; Index < 8; Index++) {
   1099     Mask = (UINT8) (1 << Index);
   1100     if ((CurModifierMap & Mask) != (OldModifierMap & Mask)) {
   1101       //
   1102       // If current modifier key is up, then CurModifierMap & Mask = 0;
   1103       // otherwise it is a non-zero value.
   1104       // Insert the changed modifier key into key buffer.
   1105       //
   1106       UsbKey.KeyCode = (UINT8) (0xe0 + Index);
   1107       UsbKey.Down    = (BOOLEAN) ((CurModifierMap & Mask) != 0);
   1108       Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
   1109     }
   1110   }
   1111 
   1112   //
   1113   // Handle normal key's releasing situation
   1114   // Bytes 2 to 7 are for normal keycodes
   1115   //
   1116   KeyRelease = FALSE;
   1117   for (Index = 2; Index < 8; Index++) {
   1118 
   1119     if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
   1120       continue;
   1121     }
   1122     //
   1123     // For any key in old keycode buffer, if it is not in current keycode buffer,
   1124     // then it is released. Otherwise, it is not released.
   1125     //
   1126     KeyRelease = TRUE;
   1127     for (Index2 = 2; Index2 < 8; Index2++) {
   1128 
   1129       if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
   1130         continue;
   1131       }
   1132 
   1133       if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
   1134         KeyRelease = FALSE;
   1135         break;
   1136       }
   1137     }
   1138 
   1139     if (KeyRelease) {
   1140       UsbKey.KeyCode = OldKeyCodeBuffer[Index];
   1141       UsbKey.Down    = FALSE;
   1142       Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
   1143       //
   1144       // The original repeat key is released.
   1145       //
   1146       if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
   1147         UsbKeyboardDevice->RepeatKey = 0;
   1148       }
   1149     }
   1150   }
   1151 
   1152   //
   1153   // If original repeat key is released, cancel the repeat timer
   1154   //
   1155   if (UsbKeyboardDevice->RepeatKey == 0) {
   1156     gBS->SetTimer (
   1157            UsbKeyboardDevice->RepeatTimer,
   1158            TimerCancel,
   1159            USBKBD_REPEAT_RATE
   1160            );
   1161   }
   1162 
   1163   //
   1164   // Handle normal key's pressing situation
   1165   //
   1166   KeyPress = FALSE;
   1167   for (Index = 2; Index < 8; Index++) {
   1168 
   1169     if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
   1170       continue;
   1171     }
   1172     //
   1173     // For any key in current keycode buffer, if it is not in old keycode buffer,
   1174     // then it is pressed. Otherwise, it is not pressed.
   1175     //
   1176     KeyPress = TRUE;
   1177     for (Index2 = 2; Index2 < 8; Index2++) {
   1178 
   1179       if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
   1180         continue;
   1181       }
   1182 
   1183       if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
   1184         KeyPress = FALSE;
   1185         break;
   1186       }
   1187     }
   1188 
   1189     if (KeyPress) {
   1190       UsbKey.KeyCode = CurKeyCodeBuffer[Index];
   1191       UsbKey.Down    = TRUE;
   1192       Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
   1193 
   1194       //
   1195       // Handle repeat key
   1196       //
   1197       KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
   1198       ASSERT (KeyDescriptor != NULL);
   1199 
   1200       if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
   1201         //
   1202         // For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
   1203         //
   1204         UsbKeyboardDevice->RepeatKey = 0;
   1205       } else {
   1206         //
   1207         // Prepare new repeat key, and clear the original one.
   1208         //
   1209         NewRepeatKey = CurKeyCodeBuffer[Index];
   1210         UsbKeyboardDevice->RepeatKey = 0;
   1211       }
   1212     }
   1213   }
   1214 
   1215   //
   1216   // Update LastKeycodeArray buffer in the UsbKeyboardDevice data structure.
   1217   //
   1218   for (Index = 0; Index < 8; Index++) {
   1219     UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
   1220   }
   1221 
   1222   //
   1223   // If there is new key pressed, update the RepeatKey value, and set the
   1224   // timer to repeate delay timer
   1225   //
   1226   if (NewRepeatKey != 0) {
   1227     //
   1228     // Sets trigger time to "Repeat Delay Time",
   1229     // to trigger the repeat timer when the key is hold long
   1230     // enough time.
   1231     //
   1232     gBS->SetTimer (
   1233            UsbKeyboardDevice->RepeatTimer,
   1234            TimerRelative,
   1235            USBKBD_REPEAT_DELAY
   1236            );
   1237     UsbKeyboardDevice->RepeatKey = NewRepeatKey;
   1238   }
   1239 
   1240   return EFI_SUCCESS;
   1241 }
   1242 
   1243 
   1244 /**
   1245   Retrieves a USB keycode after parsing the raw data in keyboard buffer.
   1246 
   1247   This function parses keyboard buffer. It updates state of modifier key for
   1248   USB_KB_DEV instancem, and returns keycode for output.
   1249 
   1250   @param  UsbKeyboardDevice    The USB_KB_DEV instance.
   1251   @param  KeyCode              Pointer to the USB keycode for output.
   1252 
   1253   @retval EFI_SUCCESS          Keycode successfully parsed.
   1254   @retval EFI_NOT_READY        Keyboard buffer is not ready for a valid keycode
   1255 
   1256 **/
   1257 EFI_STATUS
   1258 USBParseKey (
   1259   IN OUT  USB_KB_DEV  *UsbKeyboardDevice,
   1260      OUT  UINT8       *KeyCode
   1261   )
   1262 {
   1263   USB_KEY             UsbKey;
   1264   EFI_KEY_DESCRIPTOR  *KeyDescriptor;
   1265 
   1266   *KeyCode = 0;
   1267 
   1268   while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {
   1269     //
   1270     // Pops one raw data off.
   1271     //
   1272     Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
   1273 
   1274     KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
   1275     ASSERT (KeyDescriptor != NULL);
   1276 
   1277     if (!UsbKey.Down) {
   1278       //
   1279       // Key is released.
   1280       //
   1281       switch (KeyDescriptor->Modifier) {
   1282 
   1283       //
   1284       // Ctrl release
   1285       //
   1286       case EFI_LEFT_CONTROL_MODIFIER:
   1287         UsbKeyboardDevice->LeftCtrlOn = FALSE;
   1288         UsbKeyboardDevice->CtrlOn = FALSE;
   1289         break;
   1290       case EFI_RIGHT_CONTROL_MODIFIER:
   1291         UsbKeyboardDevice->RightCtrlOn = FALSE;
   1292         UsbKeyboardDevice->CtrlOn = FALSE;
   1293         break;
   1294 
   1295       //
   1296       // Shift release
   1297       //
   1298       case EFI_LEFT_SHIFT_MODIFIER:
   1299         UsbKeyboardDevice->LeftShiftOn = FALSE;
   1300         UsbKeyboardDevice->ShiftOn = FALSE;
   1301         break;
   1302       case EFI_RIGHT_SHIFT_MODIFIER:
   1303         UsbKeyboardDevice->RightShiftOn = FALSE;
   1304         UsbKeyboardDevice->ShiftOn = FALSE;
   1305         break;
   1306 
   1307       //
   1308       // Alt release
   1309       //
   1310       case EFI_LEFT_ALT_MODIFIER:
   1311         UsbKeyboardDevice->LeftAltOn = FALSE;
   1312         UsbKeyboardDevice->AltOn = FALSE;
   1313         break;
   1314       case EFI_RIGHT_ALT_MODIFIER:
   1315         UsbKeyboardDevice->RightAltOn = FALSE;
   1316         UsbKeyboardDevice->AltOn = FALSE;
   1317         break;
   1318 
   1319       //
   1320       // Left Logo release
   1321       //
   1322       case EFI_LEFT_LOGO_MODIFIER:
   1323         UsbKeyboardDevice->LeftLogoOn = FALSE;
   1324         break;
   1325 
   1326       //
   1327       // Right Logo release
   1328       //
   1329       case EFI_RIGHT_LOGO_MODIFIER:
   1330         UsbKeyboardDevice->RightLogoOn = FALSE;
   1331         break;
   1332 
   1333       //
   1334       // Menu key release
   1335       //
   1336       case EFI_MENU_MODIFIER:
   1337         UsbKeyboardDevice->MenuKeyOn = FALSE;
   1338         break;
   1339 
   1340       //
   1341       // SysReq release
   1342       //
   1343       case EFI_PRINT_MODIFIER:
   1344       case EFI_SYS_REQUEST_MODIFIER:
   1345         UsbKeyboardDevice->SysReqOn = FALSE;
   1346         break;
   1347 
   1348       //
   1349       // AltGr release
   1350       //
   1351       case EFI_ALT_GR_MODIFIER:
   1352         UsbKeyboardDevice->AltGrOn = FALSE;
   1353         break;
   1354 
   1355       default:
   1356         break;
   1357       }
   1358 
   1359       continue;
   1360     }
   1361 
   1362     //
   1363     // Analyzes key pressing situation
   1364     //
   1365     switch (KeyDescriptor->Modifier) {
   1366 
   1367     //
   1368     // Ctrl press
   1369     //
   1370     case EFI_LEFT_CONTROL_MODIFIER:
   1371       UsbKeyboardDevice->LeftCtrlOn = TRUE;
   1372       UsbKeyboardDevice->CtrlOn = TRUE;
   1373       break;
   1374     case EFI_RIGHT_CONTROL_MODIFIER:
   1375       UsbKeyboardDevice->RightCtrlOn = TRUE;
   1376       UsbKeyboardDevice->CtrlOn = TRUE;
   1377       break;
   1378 
   1379     //
   1380     // Shift press
   1381     //
   1382     case EFI_LEFT_SHIFT_MODIFIER:
   1383       UsbKeyboardDevice->LeftShiftOn = TRUE;
   1384       UsbKeyboardDevice->ShiftOn = TRUE;
   1385       break;
   1386     case EFI_RIGHT_SHIFT_MODIFIER:
   1387       UsbKeyboardDevice->RightShiftOn = TRUE;
   1388       UsbKeyboardDevice->ShiftOn = TRUE;
   1389       break;
   1390 
   1391     //
   1392     // Alt press
   1393     //
   1394     case EFI_LEFT_ALT_MODIFIER:
   1395       UsbKeyboardDevice->LeftAltOn = TRUE;
   1396       UsbKeyboardDevice->AltOn = TRUE;
   1397       break;
   1398     case EFI_RIGHT_ALT_MODIFIER:
   1399       UsbKeyboardDevice->RightAltOn = TRUE;
   1400       UsbKeyboardDevice->AltOn = TRUE;
   1401       break;
   1402 
   1403     //
   1404     // Left Logo press
   1405     //
   1406     case EFI_LEFT_LOGO_MODIFIER:
   1407       UsbKeyboardDevice->LeftLogoOn = TRUE;
   1408       break;
   1409 
   1410     //
   1411     // Right Logo press
   1412     //
   1413     case EFI_RIGHT_LOGO_MODIFIER:
   1414       UsbKeyboardDevice->RightLogoOn = TRUE;
   1415       break;
   1416 
   1417     //
   1418     // Menu key press
   1419     //
   1420     case EFI_MENU_MODIFIER:
   1421       UsbKeyboardDevice->MenuKeyOn = TRUE;
   1422       break;
   1423 
   1424     //
   1425     // SysReq press
   1426     //
   1427     case EFI_PRINT_MODIFIER:
   1428     case EFI_SYS_REQUEST_MODIFIER:
   1429       UsbKeyboardDevice->SysReqOn = TRUE;
   1430       break;
   1431 
   1432     //
   1433     // AltGr press
   1434     //
   1435     case EFI_ALT_GR_MODIFIER:
   1436       UsbKeyboardDevice->AltGrOn = TRUE;
   1437       break;
   1438 
   1439     case EFI_NUM_LOCK_MODIFIER:
   1440       //
   1441       // Toggle NumLock
   1442       //
   1443       UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));
   1444       SetKeyLED (UsbKeyboardDevice);
   1445       break;
   1446 
   1447     case EFI_CAPS_LOCK_MODIFIER:
   1448       //
   1449       // Toggle CapsLock
   1450       //
   1451       UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));
   1452       SetKeyLED (UsbKeyboardDevice);
   1453       break;
   1454 
   1455     case EFI_SCROLL_LOCK_MODIFIER:
   1456       //
   1457       // Toggle ScrollLock
   1458       //
   1459       UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));
   1460       SetKeyLED (UsbKeyboardDevice);
   1461       break;
   1462 
   1463     default:
   1464       break;
   1465     }
   1466 
   1467     //
   1468     // When encountering Ctrl + Alt + Del, then warm reset.
   1469     //
   1470     if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
   1471       if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
   1472         gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
   1473       }
   1474     }
   1475 
   1476     *KeyCode = UsbKey.KeyCode;
   1477     return EFI_SUCCESS;
   1478   }
   1479 
   1480   return EFI_NOT_READY;
   1481 }
   1482 
   1483 
   1484 /**
   1485   Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.
   1486 
   1487   @param  UsbKeyboardDevice     The USB_KB_DEV instance.
   1488   @param  KeyCode               Indicates the key code that will be interpreted.
   1489   @param  KeyData               A pointer to a buffer that is filled in with
   1490                                 the keystroke information for the key that
   1491                                 was pressed.
   1492 
   1493   @retval EFI_SUCCESS           Success.
   1494   @retval EFI_INVALID_PARAMETER KeyCode is not in the range of 0x4 to 0x65.
   1495   @retval EFI_INVALID_PARAMETER Translated EFI_INPUT_KEY has zero for both ScanCode and UnicodeChar.
   1496   @retval EFI_NOT_READY         KeyCode represents a dead key with EFI_NS_KEY_MODIFIER
   1497   @retval EFI_DEVICE_ERROR      Keyboard layout is invalid.
   1498 
   1499 **/
   1500 EFI_STATUS
   1501 UsbKeyCodeToEfiInputKey (
   1502   IN  USB_KB_DEV                *UsbKeyboardDevice,
   1503   IN  UINT8                     KeyCode,
   1504   OUT EFI_KEY_DATA              *KeyData
   1505   )
   1506 {
   1507   EFI_KEY_DESCRIPTOR            *KeyDescriptor;
   1508   LIST_ENTRY                    *Link;
   1509   LIST_ENTRY                    *NotifyList;
   1510   KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
   1511 
   1512   //
   1513   // KeyCode must in the range of  [0x4, 0x65] or [0xe0, 0xe7].
   1514   //
   1515   KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
   1516   ASSERT (KeyDescriptor != NULL);
   1517 
   1518   if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
   1519     //
   1520     // If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
   1521     //
   1522     UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
   1523     return EFI_NOT_READY;
   1524   }
   1525 
   1526   if (UsbKeyboardDevice->CurrentNsKey != NULL) {
   1527     //
   1528     // If this keystroke follows a non-spacing key, then find the descriptor for corresponding
   1529     // physical key.
   1530     //
   1531     KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
   1532     UsbKeyboardDevice->CurrentNsKey = NULL;
   1533   }
   1534 
   1535   //
   1536   // Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
   1537   //
   1538   if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {
   1539     return EFI_DEVICE_ERROR;
   1540   }
   1541 
   1542   KeyData->Key.ScanCode    = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
   1543   KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
   1544 
   1545   if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
   1546     if (UsbKeyboardDevice->ShiftOn) {
   1547       KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
   1548 
   1549       //
   1550       // Need not return associated shift state if a class of printable characters that
   1551       // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
   1552       //
   1553       if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
   1554         UsbKeyboardDevice->LeftShiftOn = FALSE;
   1555         UsbKeyboardDevice->RightShiftOn = FALSE;
   1556       }
   1557 
   1558       if (UsbKeyboardDevice->AltGrOn) {
   1559         KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
   1560       }
   1561     } else {
   1562       //
   1563       // Shift off
   1564       //
   1565       KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
   1566 
   1567       if (UsbKeyboardDevice->AltGrOn) {
   1568         KeyData->Key.UnicodeChar = KeyDescriptor->AltGrUnicode;
   1569       }
   1570     }
   1571   }
   1572 
   1573   if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
   1574     if (UsbKeyboardDevice->CapsOn) {
   1575       if (KeyData->Key.UnicodeChar == KeyDescriptor->Unicode) {
   1576         KeyData->Key.UnicodeChar = KeyDescriptor->ShiftedUnicode;
   1577       } else if (KeyData->Key.UnicodeChar == KeyDescriptor->ShiftedUnicode) {
   1578         KeyData->Key.UnicodeChar = KeyDescriptor->Unicode;
   1579       }
   1580     }
   1581   }
   1582 
   1583   if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
   1584     //
   1585     // For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
   1586     // normal key, instead of original control key. So the ScanCode should be cleaned.
   1587     // Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
   1588     //
   1589     if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
   1590       KeyData->Key.ScanCode = SCAN_NULL;
   1591     } else {
   1592       KeyData->Key.UnicodeChar = CHAR_NULL;
   1593     }
   1594   }
   1595 
   1596   //
   1597   // Translate Unicode 0x1B (ESC) to EFI Scan Code
   1598   //
   1599   if (KeyData->Key.UnicodeChar == 0x1B && KeyData->Key.ScanCode == SCAN_NULL) {
   1600     KeyData->Key.ScanCode = SCAN_ESC;
   1601     KeyData->Key.UnicodeChar = CHAR_NULL;
   1602   }
   1603 
   1604   //
   1605   // Not valid for key without both unicode key code and EFI Scan Code.
   1606   //
   1607   if (KeyData->Key.UnicodeChar == 0 && KeyData->Key.ScanCode == SCAN_NULL) {
   1608     if (!UsbKeyboardDevice->IsSupportPartialKey) {
   1609     return EFI_NOT_READY;
   1610     }
   1611   }
   1612 
   1613   //
   1614   // Save Shift/Toggle state
   1615   //
   1616   KeyData->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;
   1617   KeyData->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
   1618 
   1619   if (UsbKeyboardDevice->LeftCtrlOn) {
   1620     KeyData->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
   1621   }
   1622   if (UsbKeyboardDevice->RightCtrlOn) {
   1623     KeyData->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
   1624   }
   1625   if (UsbKeyboardDevice->LeftAltOn) {
   1626     KeyData->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
   1627   }
   1628   if (UsbKeyboardDevice->RightAltOn) {
   1629     KeyData->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
   1630   }
   1631   if (UsbKeyboardDevice->LeftShiftOn) {
   1632     KeyData->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
   1633   }
   1634   if (UsbKeyboardDevice->RightShiftOn) {
   1635     KeyData->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
   1636   }
   1637   if (UsbKeyboardDevice->LeftLogoOn) {
   1638     KeyData->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
   1639   }
   1640   if (UsbKeyboardDevice->RightLogoOn) {
   1641     KeyData->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
   1642   }
   1643   if (UsbKeyboardDevice->MenuKeyOn) {
   1644     KeyData->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
   1645   }
   1646   if (UsbKeyboardDevice->SysReqOn) {
   1647     KeyData->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
   1648   }
   1649 
   1650   if (UsbKeyboardDevice->ScrollOn) {
   1651     KeyData->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
   1652   }
   1653   if (UsbKeyboardDevice->NumLockOn) {
   1654     KeyData->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
   1655   }
   1656   if (UsbKeyboardDevice->CapsOn) {
   1657     KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
   1658   }
   1659   if (UsbKeyboardDevice->IsSupportPartialKey) {
   1660     KeyData->KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED;
   1661   }
   1662   //
   1663   // Invoke notification functions if the key is registered.
   1664   //
   1665   NotifyList = &UsbKeyboardDevice->NotifyList;
   1666   for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
   1667     CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
   1668     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
   1669       CurrentNotify->KeyNotificationFn (KeyData);
   1670     }
   1671   }
   1672 
   1673   return EFI_SUCCESS;
   1674 }
   1675 
   1676 
   1677 /**
   1678   Create the queue.
   1679 
   1680   @param  Queue     Points to the queue.
   1681   @param  ItemSize  Size of the single item.
   1682 
   1683 **/
   1684 VOID
   1685 InitQueue (
   1686   IN OUT  USB_SIMPLE_QUEUE   *Queue,
   1687   IN      UINTN              ItemSize
   1688   )
   1689 {
   1690   UINTN                      Index;
   1691 
   1692   Queue->ItemSize  = ItemSize;
   1693   Queue->Head      = 0;
   1694   Queue->Tail      = 0;
   1695 
   1696   if (Queue->Buffer[0] != NULL) {
   1697     FreePool (Queue->Buffer[0]);
   1698   }
   1699 
   1700   Queue->Buffer[0] = AllocatePool (sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]) * ItemSize);
   1701   ASSERT (Queue->Buffer[0] != NULL);
   1702 
   1703   for (Index = 1; Index < sizeof (Queue->Buffer) / sizeof (Queue->Buffer[0]); Index++) {
   1704     Queue->Buffer[Index] = ((UINT8 *) Queue->Buffer[Index - 1]) + ItemSize;
   1705   }
   1706 }
   1707 
   1708 /**
   1709   Destroy the queue
   1710 
   1711   @param Queue    Points to the queue.
   1712 **/
   1713 VOID
   1714 DestroyQueue (
   1715   IN OUT USB_SIMPLE_QUEUE   *Queue
   1716   )
   1717 {
   1718   FreePool (Queue->Buffer[0]);
   1719 }
   1720 
   1721 
   1722 /**
   1723   Check whether the queue is empty.
   1724 
   1725   @param  Queue     Points to the queue.
   1726 
   1727   @retval TRUE      Queue is empty.
   1728   @retval FALSE     Queue is not empty.
   1729 
   1730 **/
   1731 BOOLEAN
   1732 IsQueueEmpty (
   1733   IN  USB_SIMPLE_QUEUE   *Queue
   1734   )
   1735 {
   1736   //
   1737   // Meet FIFO empty condition
   1738   //
   1739   return (BOOLEAN) (Queue->Head == Queue->Tail);
   1740 }
   1741 
   1742 
   1743 /**
   1744   Check whether the queue is full.
   1745 
   1746   @param  Queue     Points to the queue.
   1747 
   1748   @retval TRUE      Queue is full.
   1749   @retval FALSE     Queue is not full.
   1750 
   1751 **/
   1752 BOOLEAN
   1753 IsQueueFull (
   1754   IN  USB_SIMPLE_QUEUE   *Queue
   1755   )
   1756 {
   1757   return (BOOLEAN) (((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);
   1758 }
   1759 
   1760 
   1761 /**
   1762   Enqueue the item to the queue.
   1763 
   1764   @param  Queue     Points to the queue.
   1765   @param  Item      Points to the item to be enqueued.
   1766   @param  ItemSize  Size of the item.
   1767 **/
   1768 VOID
   1769 Enqueue (
   1770   IN OUT  USB_SIMPLE_QUEUE *Queue,
   1771   IN      VOID             *Item,
   1772   IN      UINTN            ItemSize
   1773   )
   1774 {
   1775   ASSERT (ItemSize == Queue->ItemSize);
   1776   //
   1777   // If keyboard buffer is full, throw the
   1778   // first key out of the keyboard buffer.
   1779   //
   1780   if (IsQueueFull (Queue)) {
   1781     Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
   1782   }
   1783 
   1784   CopyMem (Queue->Buffer[Queue->Tail], Item, ItemSize);
   1785 
   1786   //
   1787   // Adjust the tail pointer of the FIFO keyboard buffer.
   1788   //
   1789   Queue->Tail = (Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1);
   1790 }
   1791 
   1792 
   1793 /**
   1794   Dequeue a item from the queue.
   1795 
   1796   @param  Queue     Points to the queue.
   1797   @param  Item      Receives the item.
   1798   @param  ItemSize  Size of the item.
   1799 
   1800   @retval EFI_SUCCESS        Item was successfully dequeued.
   1801   @retval EFI_DEVICE_ERROR   The queue is empty.
   1802 
   1803 **/
   1804 EFI_STATUS
   1805 Dequeue (
   1806   IN OUT  USB_SIMPLE_QUEUE *Queue,
   1807      OUT  VOID             *Item,
   1808   IN      UINTN            ItemSize
   1809   )
   1810 {
   1811   ASSERT (Queue->ItemSize == ItemSize);
   1812 
   1813   if (IsQueueEmpty (Queue)) {
   1814     return EFI_DEVICE_ERROR;
   1815   }
   1816 
   1817   CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);
   1818 
   1819   //
   1820   // Adjust the head pointer of the FIFO keyboard buffer.
   1821   //
   1822   Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
   1823 
   1824   return EFI_SUCCESS;
   1825 }
   1826 
   1827 
   1828 /**
   1829   Sets USB keyboard LED state.
   1830 
   1831   @param  UsbKeyboardDevice  The USB_KB_DEV instance.
   1832 
   1833 **/
   1834 VOID
   1835 SetKeyLED (
   1836   IN  USB_KB_DEV    *UsbKeyboardDevice
   1837   )
   1838 {
   1839   LED_MAP Led;
   1840   UINT8   ReportId;
   1841 
   1842   //
   1843   // Set each field in Led map.
   1844   //
   1845   Led.NumLock    = (UINT8) ((UsbKeyboardDevice->NumLockOn) ? 1 : 0);
   1846   Led.CapsLock   = (UINT8) ((UsbKeyboardDevice->CapsOn) ? 1 : 0);
   1847   Led.ScrollLock = (UINT8) ((UsbKeyboardDevice->ScrollOn) ? 1 : 0);
   1848   Led.Resrvd     = 0;
   1849 
   1850   ReportId       = 0;
   1851   //
   1852   // Call Set_Report Request to lighten the LED.
   1853   //
   1854   UsbSetReportRequest (
   1855     UsbKeyboardDevice->UsbIo,
   1856     UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
   1857     ReportId,
   1858     HID_OUTPUT_REPORT,
   1859     1,
   1860     (UINT8 *) &Led
   1861     );
   1862 }
   1863 
   1864 
   1865 /**
   1866   Handler for Repeat Key event.
   1867 
   1868   This function is the handler for Repeat Key event triggered
   1869   by timer.
   1870   After a repeatable key is pressed, the event would be triggered
   1871   with interval of USBKBD_REPEAT_DELAY. Once the event is triggered,
   1872   following trigger will come with interval of USBKBD_REPEAT_RATE.
   1873 
   1874   @param  Event              The Repeat Key event.
   1875   @param  Context            Points to the USB_KB_DEV instance.
   1876 
   1877 **/
   1878 VOID
   1879 EFIAPI
   1880 USBKeyboardRepeatHandler (
   1881   IN    EFI_EVENT    Event,
   1882   IN    VOID         *Context
   1883   )
   1884 {
   1885   USB_KB_DEV  *UsbKeyboardDevice;
   1886   USB_KEY     UsbKey;
   1887 
   1888   UsbKeyboardDevice = (USB_KB_DEV *) Context;
   1889 
   1890   //
   1891   // Do nothing when there is no repeat key.
   1892   //
   1893   if (UsbKeyboardDevice->RepeatKey != 0) {
   1894     //
   1895     // Inserts the repeat key into keyboard buffer,
   1896     //
   1897     UsbKey.KeyCode = UsbKeyboardDevice->RepeatKey;
   1898     UsbKey.Down    = TRUE;
   1899     Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
   1900 
   1901     //
   1902     // Set repeat rate for next repeat key generation.
   1903     //
   1904     gBS->SetTimer (
   1905            UsbKeyboardDevice->RepeatTimer,
   1906            TimerRelative,
   1907            USBKBD_REPEAT_RATE
   1908            );
   1909   }
   1910 }
   1911 
   1912 
   1913 /**
   1914   Handler for Delayed Recovery event.
   1915 
   1916   This function is the handler for Delayed Recovery event triggered
   1917   by timer.
   1918   After a device error occurs, the event would be triggered
   1919   with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
   1920   is defined in USB standard for error handling.
   1921 
   1922   @param  Event              The Delayed Recovery event.
   1923   @param  Context            Points to the USB_KB_DEV instance.
   1924 
   1925 **/
   1926 VOID
   1927 EFIAPI
   1928 USBKeyboardRecoveryHandler (
   1929   IN    EFI_EVENT    Event,
   1930   IN    VOID         *Context
   1931   )
   1932 {
   1933 
   1934   USB_KB_DEV          *UsbKeyboardDevice;
   1935   EFI_USB_IO_PROTOCOL *UsbIo;
   1936   UINT8               PacketSize;
   1937 
   1938   UsbKeyboardDevice = (USB_KB_DEV *) Context;
   1939 
   1940   UsbIo             = UsbKeyboardDevice->UsbIo;
   1941 
   1942   PacketSize        = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
   1943 
   1944   //
   1945   // Re-submit Asynchronous Interrupt Transfer for recovery.
   1946   //
   1947   UsbIo->UsbAsyncInterruptTransfer (
   1948            UsbIo,
   1949            UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
   1950            TRUE,
   1951            UsbKeyboardDevice->IntEndpointDescriptor.Interval,
   1952            PacketSize,
   1953            KeyboardHandler,
   1954            UsbKeyboardDevice
   1955            );
   1956 }
   1957