3354 lines
112 KiB
C
3354 lines
112 KiB
C
/** @file
|
|
Helper functions for USB Keyboard Driver
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "Efikey.h"
|
|
#include "Keyboard.h"
|
|
|
|
USB_KEYBOARD_LAYOUT_PACK_BIN mUsbKeyboardLayoutBin = {
|
|
sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN), // Binary size
|
|
|
|
//
|
|
// EFI_HII_PACKAGE_HEADER
|
|
//
|
|
{
|
|
sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32),
|
|
EFI_HII_PACKAGE_KEYBOARD_LAYOUT
|
|
},
|
|
2, // LayoutCount
|
|
//
|
|
// US Layout
|
|
//
|
|
sizeof (USB_KEYBOARD_US_LAYOUT_PACK), // LayoutLength
|
|
H2O_USB_KEYBOARD_US_LAYOUT_KEY_GUID, // KeyGuid
|
|
sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (USB_KEYBOARD_US_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset
|
|
USB_KEYBOARD_US_KEY_COUNT, // DescriptorCount
|
|
{
|
|
//
|
|
// EFI_KEY_DESCRIPTOR (total number is USB_KEYBOARD_US_KEY_COUNT)
|
|
//
|
|
{EfiKeyC1, 'a', 'A', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB5, 'b', 'B', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB3, 'c', 'C', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC3, 'd', 'D', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD3, 'e', 'E', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC4, 'f', 'F', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC5, 'g', 'G', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC6, 'h', 'H', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD8, 'i', 'I', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC7, 'j', 'J', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC8, 'k', 'K', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC9, 'l', 'L', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB7, 'm', 'M', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB6, 'n', 'N', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD9, 'o', 'O', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD10, 'p', 'P', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD1, 'q', 'Q', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD4, 'r', 'R', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC2, 's', 'S', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD5, 't', 'T', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD7, 'u', 'U', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB4, 'v', 'V', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD2, 'w', 'W', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB2, 'x', 'X', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD6, 'y', 'Y', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB1, 'z', 'Z', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyE1, '1', '!', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE2, '2', '@', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE3, '3', '#', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE4, '4', '$', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE5, '5', '%', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE6, '6', '^', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE7, '7', '&', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE8, '8', '*', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE9, '9', '(', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE10, '0', ')', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyEsc, 0x1b, 0x1b, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyBackSpace, 0x08, 0x08, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyTab, 0x09, 0x09, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeySpaceBar, ' ', ' ', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyE11, '-', '_', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE12, '=', '+', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyD11, '[', '{', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyD12, ']', '}', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyD13, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyC12, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyC10, ';', ':', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyC11, '\'', '"', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE0, '`', '~', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB8, ',', '<', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB9, '.', '>', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB10, '/', '?', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyCapsLock, 0x00, 0x00, 0, 0, EFI_CAPS_LOCK_MODIFIER, 0},
|
|
{EfiKeyF1, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ONE_MODIFIER, 0},
|
|
{EfiKeyF2, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWO_MODIFIER, 0},
|
|
{EfiKeyF3, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_THREE_MODIFIER, 0},
|
|
{EfiKeyF4, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FOUR_MODIFIER, 0},
|
|
{EfiKeyF5, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FIVE_MODIFIER, 0},
|
|
{EfiKeyF6, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SIX_MODIFIER, 0},
|
|
{EfiKeyF7, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SEVEN_MODIFIER, 0},
|
|
{EfiKeyF8, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_EIGHT_MODIFIER, 0},
|
|
{EfiKeyF9, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_NINE_MODIFIER, 0},
|
|
{EfiKeyF10, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TEN_MODIFIER, 0},
|
|
{EfiKeyF11, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ELEVEN_MODIFIER, 0},
|
|
{EfiKeyF12, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWELVE_MODIFIER, 0},
|
|
{EfiKeyPrint, 0x00, 0x00, 0, 0, EFI_PRINT_MODIFIER, 0},
|
|
{EfiKeySLck, 0x00, 0x00, 0, 0, EFI_SCROLL_LOCK_MODIFIER, 0},
|
|
{EfiKeyPause, 0x00, 0x00, 0, 0, EFI_PAUSE_MODIFIER, 0},
|
|
{EfiKeyIns, 0x00, 0x00, 0, 0, EFI_INSERT_MODIFIER, 0},
|
|
{EfiKeyHome, 0x00, 0x00, 0, 0, EFI_HOME_MODIFIER, 0},
|
|
{EfiKeyPgUp, 0x00, 0x00, 0, 0, EFI_PAGE_UP_MODIFIER, 0},
|
|
{EfiKeyDel, 0x00, 0x00, 0, 0, EFI_DELETE_MODIFIER, 0},
|
|
{EfiKeyEnd, 0x00, 0x00, 0, 0, EFI_END_MODIFIER, 0},
|
|
{EfiKeyPgDn, 0x00, 0x00, 0, 0, EFI_PAGE_DOWN_MODIFIER, 0},
|
|
{EfiKeyRightArrow, 0x00, 0x00, 0, 0, EFI_RIGHT_ARROW_MODIFIER, 0},
|
|
{EfiKeyLeftArrow, 0x00, 0x00, 0, 0, EFI_LEFT_ARROW_MODIFIER, 0},
|
|
{EfiKeyDownArrow, 0x00, 0x00, 0, 0, EFI_DOWN_ARROW_MODIFIER, 0},
|
|
{EfiKeyUpArrow, 0x00, 0x00, 0, 0, EFI_UP_ARROW_MODIFIER, 0},
|
|
{EfiKeyNLck, 0x00, 0x00, 0, 0, EFI_NUM_LOCK_MODIFIER, 0},
|
|
{EfiKeySlash, '/', '/', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyAsterisk, '*', '*', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyMinus, '-', '-', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyPlus, '+', '+', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyOne, '1', '1', 0, 0, EFI_END_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyTwo, '2', '2', 0, 0, EFI_DOWN_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyThree, '3', '3', 0, 0, EFI_PAGE_DOWN_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyFour, '4', '4', 0, 0, EFI_LEFT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyFive, '5', '5', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeySix, '6', '6', 0, 0, EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeySeven, '7', '7', 0, 0, EFI_HOME_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyEight, '8', '8', 0, 0, EFI_UP_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyNine, '9', '9', 0, 0, EFI_PAGE_UP_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyZero, '0', '0', 0, 0, EFI_INSERT_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyPeriod, '.', '.', 0, 0, EFI_DELETE_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyA4, 0x00, 0x00, 0, 0, EFI_MENU_MODIFIER, 0},
|
|
{EfiKeyLCtrl, 0, 0, 0, 0, EFI_LEFT_CONTROL_MODIFIER, 0},
|
|
{EfiKeyLShift, 0, 0, 0, 0, EFI_LEFT_SHIFT_MODIFIER, 0},
|
|
{EfiKeyLAlt, 0, 0, 0, 0, EFI_LEFT_ALT_MODIFIER, 0},
|
|
{EfiKeyA0, 0, 0, 0, 0, EFI_LEFT_LOGO_MODIFIER, 0},
|
|
{EfiKeyRCtrl, 0, 0, 0, 0, EFI_RIGHT_CONTROL_MODIFIER, 0},
|
|
{EfiKeyRShift, 0, 0, 0, 0, EFI_RIGHT_SHIFT_MODIFIER, 0},
|
|
{EfiKeyA2, 0, 0, 0, 0, EFI_RIGHT_ALT_MODIFIER, 0},
|
|
{EfiKeyA3, 0, 0, 0, 0, EFI_RIGHT_LOGO_MODIFIER, 0},
|
|
},
|
|
1, // DescriptionCount
|
|
{'e', 'n', '-', 'U', 'S'}, // RFC4646 language code
|
|
' ', // Space
|
|
{'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '\0'}, // DescriptionString[]
|
|
//
|
|
// French Layout
|
|
//
|
|
sizeof (USB_KEYBOARD_FRENCH_LAYOUT_PACK), // LayoutLength
|
|
H2O_USB_KEYBOARD_FRENCH_LAYOUT_KEY_GUID, // KeyGuid
|
|
sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (USB_KEYBOARD_FRENCH_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset
|
|
USB_KEYBOARD_FRENCH_KEY_COUNT, // DescriptorCount
|
|
{
|
|
//
|
|
// EFI_KEY_DESCRIPTOR (total number is USB_KEYBOARD_FRENCH_KEY_COUNT)
|
|
//
|
|
{EfiKeyD1, 'a', 'A', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB5, 'b', 'B', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB3, 'c', 'C', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC3, 'd', 'D', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD3, 'e', 'E', 0x20AC, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC4, 'f', 'F', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC5, 'g', 'G', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC6, 'h', 'H', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD8, 'i', 'I', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC7, 'j', 'J', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC8, 'k', 'K', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC9, 'l', 'L', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC10, 'm', 'M', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB6, 'n', 'N', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD9, 'o', 'O', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD10, 'p', 'P', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC1, 'q', 'Q', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD4, 'r', 'R', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyC2, 's', 'S', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD5, 't', 'T', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD7, 'u', 'U', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB4, 'v', 'V', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB1, 'w', 'W', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyB2, 'x', 'X', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD6, 'y', 'Y', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyD2, 'z', 'Z', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
|
|
{EfiKeyE1, '&', '1', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE2, 0xE9, '2', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE3, '"', '3', '#', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE4, '\'', '4', '{', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE5, '(', '5', '[', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE6, '-', '6', '|', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE7, 0xE8, '7', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE8, '_', '8', '\\', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE9, 0xE7, '9', '^', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE10, 0xE0, '0', '@', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyEsc, 0x1b, 0x1b, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyBackSpace, 0x08, 0x08, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyTab, 0x09, 0x09, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeySpaceBar, ' ', ' ', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyE11, ')', 0xB0, ']', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE12, '=', '+', '}', 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyD11, 0x00, 0x00, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyD12, '$', 0xA3, 0xA4, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyC12, '*' , 0xB5, 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyC11, 0xF9, '%', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyE0, 0xB2, 0x00, 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB0, '<', '>', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB7, ',', '?', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB8, ';', '.', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB9, ':', '/', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyB10, '!', 0xA7, 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
|
|
{EfiKeyCapsLock, 0x00, 0x00, 0, 0, EFI_CAPS_LOCK_MODIFIER, 0},
|
|
{EfiKeyF1, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ONE_MODIFIER, 0},
|
|
{EfiKeyF2, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWO_MODIFIER, 0},
|
|
{EfiKeyF3, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_THREE_MODIFIER, 0},
|
|
{EfiKeyF4, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FOUR_MODIFIER, 0},
|
|
{EfiKeyF5, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FIVE_MODIFIER, 0},
|
|
{EfiKeyF6, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SIX_MODIFIER, 0},
|
|
{EfiKeyF7, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SEVEN_MODIFIER, 0},
|
|
{EfiKeyF8, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_EIGHT_MODIFIER, 0},
|
|
{EfiKeyF9, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_NINE_MODIFIER, 0},
|
|
{EfiKeyF10, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TEN_MODIFIER, 0},
|
|
{EfiKeyF11, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ELEVEN_MODIFIER, 0},
|
|
{EfiKeyF12, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWELVE_MODIFIER, 0},
|
|
{EfiKeyPrint, 0x00, 0x00, 0, 0, EFI_PRINT_MODIFIER, 0},
|
|
{EfiKeySLck, 0x00, 0x00, 0, 0, EFI_SCROLL_LOCK_MODIFIER, 0},
|
|
{EfiKeyPause, 0x00, 0x00, 0, 0, EFI_PAUSE_MODIFIER, 0},
|
|
{EfiKeyIns, 0x00, 0x00, 0, 0, EFI_INSERT_MODIFIER, 0},
|
|
{EfiKeyHome, 0x00, 0x00, 0, 0, EFI_HOME_MODIFIER, 0},
|
|
{EfiKeyPgUp, 0x00, 0x00, 0, 0, EFI_PAGE_UP_MODIFIER, 0},
|
|
{EfiKeyDel, 0x00, 0x00, 0, 0, EFI_DELETE_MODIFIER, 0},
|
|
{EfiKeyEnd, 0x00, 0x00, 0, 0, EFI_END_MODIFIER, 0},
|
|
{EfiKeyPgDn, 0x00, 0x00, 0, 0, EFI_PAGE_DOWN_MODIFIER, 0},
|
|
{EfiKeyRightArrow, 0x00, 0x00, 0, 0, EFI_RIGHT_ARROW_MODIFIER, 0},
|
|
{EfiKeyLeftArrow, 0x00, 0x00, 0, 0, EFI_LEFT_ARROW_MODIFIER, 0},
|
|
{EfiKeyDownArrow, 0x00, 0x00, 0, 0, EFI_DOWN_ARROW_MODIFIER, 0},
|
|
{EfiKeyUpArrow, 0x00, 0x00, 0, 0, EFI_UP_ARROW_MODIFIER, 0},
|
|
{EfiKeyNLck, 0x00, 0x00, 0, 0, EFI_NUM_LOCK_MODIFIER, 0},
|
|
{EfiKeySlash, '/', '/', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyAsterisk, '*', '*', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyMinus, '-', '-', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyPlus, '+', '+', 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
|
|
{EfiKeyOne, '1', '1', 0, 0, EFI_END_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyTwo, '2', '2', 0, 0, EFI_DOWN_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyThree, '3', '3', 0, 0, EFI_PAGE_DOWN_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyFour, '4', '4', 0, 0, EFI_LEFT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyFive, '5', '5', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeySix, '6', '6', 0, 0, EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeySeven, '7', '7', 0, 0, EFI_HOME_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyEight, '8', '8', 0, 0, EFI_UP_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyNine, '9', '9', 0, 0, EFI_PAGE_UP_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyZero, '0', '0', 0, 0, EFI_INSERT_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyPeriod, '.', '.', 0, 0, EFI_DELETE_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
|
|
{EfiKeyA4, 0x00, 0x00, 0, 0, EFI_MENU_MODIFIER, 0},
|
|
{EfiKeyLCtrl, 0, 0, 0, 0, EFI_LEFT_CONTROL_MODIFIER, 0},
|
|
{EfiKeyLShift, 0, 0, 0, 0, EFI_LEFT_SHIFT_MODIFIER, 0},
|
|
{EfiKeyLAlt, 0, 0, 0, 0, EFI_LEFT_ALT_MODIFIER, 0},
|
|
{EfiKeyA0, 0, 0, 0, 0, EFI_LEFT_LOGO_MODIFIER, 0},
|
|
{EfiKeyRCtrl, 0, 0, 0, 0, EFI_RIGHT_CONTROL_MODIFIER, 0},
|
|
{EfiKeyRShift, 0, 0, 0, 0, EFI_RIGHT_SHIFT_MODIFIER, 0},
|
|
{EfiKeyA2, 0, 0, 0, 0, EFI_ALT_GR_MODIFIER, 0},
|
|
{EfiKeyA3, 0, 0, 0, 0, EFI_RIGHT_LOGO_MODIFIER, 0},
|
|
},
|
|
1, // DescriptionCount
|
|
{'f', 'r', '-', 'F', 'R'}, // RFC4646 language code
|
|
' ', // Space
|
|
{'F', 'r', 'e', 'n', 'c', 'h', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '\0'}, // DescriptionString[]
|
|
};
|
|
|
|
//
|
|
// EFI_KEY to USB Keycode conversion table
|
|
// EFI_KEY is defined in UEFI spec.
|
|
// USB Keycode is defined in USB HID Firmware spec.
|
|
//
|
|
UINT8 EfiKeyToUsbKeyCodeConvertionTable[] = {
|
|
0xe0, // EfiKeyLCtrl
|
|
0xe3, // EfiKeyA0
|
|
0xe2, // EfiKeyLAlt
|
|
0x2c, // EfiKeySpaceBar
|
|
0xe6, // EfiKeyA2
|
|
0xe7, // EfiKeyA3
|
|
0x65, // EfiKeyA4
|
|
0xe4, // EfiKeyRCtrl
|
|
0x50, // EfiKeyLeftArrow
|
|
0x51, // EfiKeyDownArrow
|
|
0x4F, // EfiKeyRightArrow
|
|
0x62, // EfiKeyZero
|
|
0x63, // EfiKeyPeriod
|
|
0x28, // EfiKeyEnter
|
|
0xe1, // EfiKeyLShift
|
|
0x64, // EfiKeyB0
|
|
0x1D, // EfiKeyB1
|
|
0x1B, // EfiKeyB2
|
|
0x06, // EfiKeyB3
|
|
0x19, // EfiKeyB4
|
|
0x05, // EfiKeyB5
|
|
0x11, // EfiKeyB6
|
|
0x10, // EfiKeyB7
|
|
0x36, // EfiKeyB8
|
|
0x37, // EfiKeyB9
|
|
0x38, // EfiKeyB10
|
|
0xe5, // EfiKeyRShift
|
|
0x52, // EfiKeyUpArrow
|
|
0x59, // EfiKeyOne
|
|
0x5A, // EfiKeyTwo
|
|
0x5B, // EfiKeyThree
|
|
0x39, // EfiKeyCapsLock
|
|
0x04, // EfiKeyC1
|
|
0x16, // EfiKeyC2
|
|
0x07, // EfiKeyC3
|
|
0x09, // EfiKeyC4
|
|
0x0A, // EfiKeyC5
|
|
0x0B, // EfiKeyC6
|
|
0x0D, // EfiKeyC7
|
|
0x0E, // EfiKeyC8
|
|
0x0F, // EfiKeyC9
|
|
0x33, // EfiKeyC10
|
|
0x34, // EfiKeyC11
|
|
0x32, // EfiKeyC12
|
|
0x5C, // EfiKeyFour
|
|
0x5D, // EfiKeyFive
|
|
0x5E, // EfiKeySix
|
|
0x57, // EfiKeyPlus
|
|
0x2B, // EfiKeyTab
|
|
0x14, // EfiKeyD1
|
|
0x1A, // EfiKeyD2
|
|
0x08, // EfiKeyD3
|
|
0x15, // EfiKeyD4
|
|
0x17, // EfiKeyD5
|
|
0x1C, // EfiKeyD6
|
|
0x18, // EfiKeyD7
|
|
0x0C, // EfiKeyD8
|
|
0x12, // EfiKeyD9
|
|
0x13, // EfiKeyD10
|
|
0x2F, // EfiKeyD11
|
|
0x30, // EfiKeyD12
|
|
0x31, // EfiKeyD13
|
|
0x4C, // EfiKeyDel
|
|
0x4D, // EfiKeyEnd
|
|
0x4E, // EfiKeyPgDn
|
|
0x5F, // EfiKeySeven
|
|
0x60, // EfiKeyEight
|
|
0x61, // EfiKeyNine
|
|
0x35, // EfiKeyE0
|
|
0x1E, // EfiKeyE1
|
|
0x1F, // EfiKeyE2
|
|
0x20, // EfiKeyE3
|
|
0x21, // EfiKeyE4
|
|
0x22, // EfiKeyE5
|
|
0x23, // EfiKeyE6
|
|
0x24, // EfiKeyE7
|
|
0x25, // EfiKeyE8
|
|
0x26, // EfiKeyE9
|
|
0x27, // EfiKeyE10
|
|
0x2D, // EfiKeyE11
|
|
0x2E, // EfiKeyE12
|
|
0x2A, // EfiKeyBackSpace
|
|
0x49, // EfiKeyIns
|
|
0x4A, // EfiKeyHome
|
|
0x4B, // EfiKeyPgUp
|
|
0x53, // EfiKeyNLck
|
|
0x54, // EfiKeySlash
|
|
0x55, // EfiKeyAsterisk
|
|
0x56, // EfiKeyMinus
|
|
0x29, // EfiKeyEsc
|
|
0x3A, // EfiKeyF1
|
|
0x3B, // EfiKeyF2
|
|
0x3C, // EfiKeyF3
|
|
0x3D, // EfiKeyF4
|
|
0x3E, // EfiKeyF5
|
|
0x3F, // EfiKeyF6
|
|
0x40, // EfiKeyF7
|
|
0x41, // EfiKeyF8
|
|
0x42, // EfiKeyF9
|
|
0x43, // EfiKeyF10
|
|
0x44, // EfiKeyF11
|
|
0x45, // EfiKeyF12
|
|
0x46, // EfiKeyPrint
|
|
0x47, // EfiKeySLck
|
|
0x48 // EfiKeyPause
|
|
};
|
|
|
|
//
|
|
// Keyboard modifier value to EFI Scan Code convertion table
|
|
// EFI Scan Code and the modifier values are defined in UEFI spec.
|
|
//
|
|
UINT8 ModifierValueToEfiScanCodeConvertionTable[] = {
|
|
SCAN_NULL, // EFI_NULL_MODIFIER
|
|
SCAN_NULL, // EFI_LEFT_CONTROL_MODIFIER
|
|
SCAN_NULL, // EFI_RIGHT_CONTROL_MODIFIER
|
|
SCAN_NULL, // EFI_LEFT_ALT_MODIFIER
|
|
SCAN_NULL, // EFI_RIGHT_ALT_MODIFIER
|
|
SCAN_NULL, // EFI_ALT_GR_MODIFIER
|
|
SCAN_INSERT, // EFI_INSERT_MODIFIER
|
|
SCAN_DELETE, // EFI_DELETE_MODIFIER
|
|
SCAN_PAGE_DOWN, // EFI_PAGE_DOWN_MODIFIER
|
|
SCAN_PAGE_UP, // EFI_PAGE_UP_MODIFIER
|
|
SCAN_HOME, // EFI_HOME_MODIFIER
|
|
SCAN_END, // EFI_END_MODIFIER
|
|
SCAN_NULL, // EFI_LEFT_SHIFT_MODIFIER
|
|
SCAN_NULL, // EFI_RIGHT_SHIFT_MODIFIER
|
|
SCAN_NULL, // EFI_CAPS_LOCK_MODIFIER
|
|
SCAN_NULL, // EFI_NUM_LOCK_MODIFIER
|
|
SCAN_LEFT, // EFI_LEFT_ARROW_MODIFIER
|
|
SCAN_RIGHT, // EFI_RIGHT_ARROW_MODIFIER
|
|
SCAN_DOWN, // EFI_DOWN_ARROW_MODIFIER
|
|
SCAN_UP, // EFI_UP_ARROW_MODIFIER
|
|
SCAN_NULL, // EFI_NS_KEY_MODIFIER
|
|
SCAN_NULL, // EFI_NS_KEY_DEPENDENCY_MODIFIER
|
|
SCAN_F1, // EFI_FUNCTION_KEY_ONE_MODIFIER
|
|
SCAN_F2, // EFI_FUNCTION_KEY_TWO_MODIFIER
|
|
SCAN_F3, // EFI_FUNCTION_KEY_THREE_MODIFIER
|
|
SCAN_F4, // EFI_FUNCTION_KEY_FOUR_MODIFIER
|
|
SCAN_F5, // EFI_FUNCTION_KEY_FIVE_MODIFIER
|
|
SCAN_F6, // EFI_FUNCTION_KEY_SIX_MODIFIER
|
|
SCAN_F7, // EFI_FUNCTION_KEY_SEVEN_MODIFIER
|
|
SCAN_F8, // EFI_FUNCTION_KEY_EIGHT_MODIFIER
|
|
SCAN_F9, // EFI_FUNCTION_KEY_NINE_MODIFIER
|
|
SCAN_F10, // EFI_FUNCTION_KEY_TEN_MODIFIER
|
|
SCAN_F11, // EFI_FUNCTION_KEY_ELEVEN_MODIFIER
|
|
SCAN_F12, // EFI_FUNCTION_KEY_TWELVE_MODIFIER
|
|
//
|
|
// For Partial Keystroke support
|
|
//
|
|
SCAN_NULL, // EFI_PRINT_MODIFIER
|
|
SCAN_NULL, // EFI_SYS_REQUEST_MODIFIER
|
|
SCAN_NULL, // EFI_SCROLL_LOCK_MODIFIER
|
|
SCAN_PAUSE, // EFI_PAUSE_MODIFIER
|
|
SCAN_NULL, // EFI_BREAK_MODIFIER
|
|
SCAN_NULL, // EFI_LEFT_LOGO_MODIFIER
|
|
SCAN_NULL, // EFI_RIGHT_LOGO_MODIFER
|
|
SCAN_NULL, // EFI_MENU_MODIFER
|
|
};
|
|
|
|
STATIC KB_MODIFIER KB_Mod[8] = {
|
|
{ MOD_CONTROL_L, 0xe0 }, // 11100000
|
|
{ MOD_CONTROL_R, 0xe4 }, // 11100100
|
|
{ MOD_SHIFT_L, 0xe1 }, // 11100001
|
|
{ MOD_SHIFT_R, 0xe5 }, // 11100101
|
|
{ MOD_ALT_L, 0xe2 }, // 11100010
|
|
{ MOD_ALT_R, 0xe6 }, // 11100110
|
|
{ MOD_WIN_L, 0xe3 }, // 11100011
|
|
{ MOD_WIN_R, 0xe7 }, // 11100111
|
|
};
|
|
|
|
STATIC
|
|
UINT8 KbcCodeTable[][4] = {
|
|
// Original Shift Alt Ctrl
|
|
0x1E, 0x1E, 0x1E, 0x1E, // 0x04 'A'
|
|
0x30, 0x30, 0x30, 0x30, // 0x05 'B'
|
|
0x2E, 0x2E, 0x2E, 0x2E, // 0x06 'C'
|
|
0x20, 0x20, 0x20, 0x20, // 0x07 'D'
|
|
0x12, 0x12, 0x12, 0x12, // 0x08 'E'
|
|
0x21, 0x21, 0x21, 0x21, // 0x09 'F'
|
|
0x22, 0x22, 0x22, 0x22, // 0x0A 'G'
|
|
0x23, 0x23, 0x23, 0x23, // 0x0B 'H'
|
|
0x17, 0x17, 0x17, 0x17, // 0x0C 'I'
|
|
0x24, 0x24, 0x24, 0x24, // 0x0D 'J'
|
|
0x25, 0x25, 0x25, 0x25, // 0x0E 'K'
|
|
0x26, 0x26, 0x26, 0x26, // 0x0F 'L'
|
|
0x32, 0x32, 0x32, 0x32, // 0x10 'M'
|
|
0x31, 0x31, 0x31, 0x31, // 0x11 'N'
|
|
0x18, 0x18, 0x18, 0x18, // 0x12 'O'
|
|
0x19, 0x19, 0x19, 0x19, // 0x13 'P'
|
|
0x10, 0x10, 0x10, 0x10, // 0x14 'Q'
|
|
0x13, 0x13, 0x13, 0x13, // 0x15 'R'
|
|
0x1F, 0x1F, 0x1F, 0x1F, // 0x16 'S'
|
|
0x14, 0x14, 0x14, 0x14, // 0x17 'T'
|
|
0x16, 0x16, 0x16, 0x16, // 0x18 'U'
|
|
0x2F, 0x2F, 0x2F, 0x2F, // 0x19 'V'
|
|
0x11, 0x11, 0x11, 0x11, // 0x1A 'W'
|
|
0x2D, 0x2D, 0x2D, 0x2D, // 0x1B 'X'
|
|
0x15, 0x15, 0x15, 0x15, // 0x1C 'Y'
|
|
0x2C, 0x2C, 0x2C, 0x2C, // 0x1D 'Z'
|
|
0x02, 0x02, 0x78, 0x00, // 0x1E '1 !'
|
|
0x03, 0x03, 0x79, 0x03, // 0x1F '2 @'
|
|
0x04, 0x04, 0x7A, 0x00, // 0x20 '3 #'
|
|
0x05, 0x05, 0x7B, 0x00, // 0x21 '4 $'
|
|
0x06, 0x06, 0x7C, 0x00, // 0x22 '5 %'
|
|
0x07, 0x07, 0x7D, 0x07, // 0x23 '6 ^'
|
|
0x08, 0x08, 0x7E, 0x00, // 0x24 '7 &'
|
|
0x09, 0x09, 0x7F, 0x00, // 0x25 '8 *'
|
|
0x0A, 0x0A, 0x81, 0x00, // 0x26 '9 ('
|
|
0x0B, 0x0B, 0x82, 0x00, // 0x27 '0 )'
|
|
0x1C, 0x1C, 0x1C, 0x1C, // 0x28 'Enter'
|
|
0x01, 0x01, 0x01, 0x01, // 0x29 'Esc'
|
|
0x0E, 0x0E, 0x0E, 0x0E, // 0x2A 'Backspace'
|
|
0x0F, 0x0F, 0xA5, 0x94, // 0x2B 'Tab'
|
|
0x39, 0x39, 0x39, 0x39, // 0x2C 'Space bar'
|
|
0x0C, 0x0C, 0x82, 0x0C, // 0x2D '- _'
|
|
0x0D, 0x0D, 0x83, 0x00, // 0x2E '= +'
|
|
0x1A, 0x1A, 0x1A, 0x1A, // 0x2F '[ {'
|
|
0x1B, 0x1B, 0x1B, 0x1B, // 0x30 '] }'
|
|
0x2B, 0x2B, 0x2B, 0x2B, // 0x31 '\ |'
|
|
0x2B, 0x2B, 0x2B, 0x2B, // 0x32 Non-US '# ~' ******
|
|
0x27, 0x27, 0x27, 0x00, // 0x33 '; :'
|
|
0x28, 0x28, 0x28, 0x00, // 0x34 '' "'
|
|
0x29, 0x29, 0x29, 0x00, // 0x35 ;` ~'
|
|
0x33, 0x33, 0x33, 0x00, // 0x36 ', <'
|
|
0x34, 0x34, 0x34, 0x00, // 0x37 '. >'
|
|
0x35, 0x35, 0x35, 0x00, // 0x38 '/ ?'
|
|
0x3A, 0x3A, 0x3A, 0x3A, // 0x39 'CapsLock'
|
|
0x3B, 0x54, 0x68, 0x5E, // 0x3A 'F1'
|
|
0x3C, 0x55, 0x69, 0x5F, // 0x3B 'F2'
|
|
0x3D, 0x56, 0x6A, 0x60, // 0x3C 'F3'
|
|
0x3E, 0x57, 0x6B, 0x61, // 0x3D 'F4'
|
|
0x3F, 0x58, 0x6C, 0x62, // 0x3E 'F5'
|
|
0x40, 0x59, 0x6D, 0x63, // 0x3F 'F6'
|
|
0x41, 0x5A, 0x6E, 0x64, // 0x40 'F7'
|
|
0x42, 0x5B, 0x6F, 0x65, // 0x41 'F8'
|
|
0x43, 0x5C, 0x70, 0x66, // 0x42 'F9'
|
|
0x44, 0x5D, 0x71, 0x67, // 0x43 'F10'
|
|
0x57, 0x87, 0x8B, 0x89, // 0x44 'F11'
|
|
0x58, 0x88, 0x8C, 0x8A, // 0x45 'F12'
|
|
0x80, 0x80, 0x80, 0x72, // 0x46 'PrntScrn' E0,2A,E0,37 E0,B7,E0,AA
|
|
0x46, 0x46, 0x46, 0x46, // 0x47 'ScrollLock'
|
|
0x81, 0x81, 0x81, 0x81, // 0x48 'Pause' E1,1D,45 E1,9D,C5
|
|
0xD2, 0xD2, 0xA2, 0x92, // 0x49 'Insert' E0,52 E0,D2
|
|
0xC7, 0xC7, 0x97, 0x77, // 0x4A 'Home' E0,47 E0,C7
|
|
0xC9, 0xC9, 0x99, 0x84, // 0x4B 'PageUp' E0,49 E0,C9
|
|
0xD3, 0xD3, 0xA3, 0x93, // 0x4C 'Delete Forward' E0,53 E0,D3
|
|
0xCF, 0xCF, 0x9F, 0x75, // 0x4D 'End' E0,4F E0,CF
|
|
0xD1, 0xD1, 0xA1, 0x76, // 0x4E 'PageDown' E0,51 E0,D1
|
|
0xCD, 0xCD, 0x9D, 0x74, // 0x4F 'Right Arrow' E0,4D E0,CD
|
|
0xCB, 0xCB, 0x9B, 0x73, // 0x50 'Left Arrow' E0,4B E0,CB
|
|
0xD0, 0xD0, 0xA0, 0x91, // 0x51 'Down Arrow' E0,50 E0,D0
|
|
0xC8, 0xC8, 0x98, 0x8D, // 0x52 'Up Arrow' E0,48 E0,C8
|
|
0x45, 0x45, 0x45, 0x45, // 0x53 'NumLock'
|
|
0xB5, 0xB5, 0xA4, 0x95, // 0x54 'keypad /' E0,35 E0,B5
|
|
0x37, 0x37, 0x37, 0x96, // 0x55 'keypad *'
|
|
0x4A, 0x4A, 0x4A, 0x8E, // 0x56 'keypad -'
|
|
0x4E, 0x4E, 0x4E, 0x90, // 0x57 'keypad +'
|
|
0x9C, 0x9C, 0xA6, 0x9C, // 0x58 'keypad Enter' E0,1C E0,9C
|
|
0x4F, 0x4F, 0x9F, 0x75, // 0x59 'keypad 1 End'
|
|
0x50, 0x50, 0xA0, 0x91, // 0x5A 'keypad 2 DownArrow'
|
|
0x51, 0x51, 0xA1, 0x76, // 0x5B 'keypad 3 PageDn'
|
|
0x4B, 0x4B, 0x9B, 0x73, // 0x5C 'keypad 4 LeftArrow'
|
|
0x4C, 0x4C, 0x00, 0x8F, // 0x5D 'keypad 5'
|
|
0x4D, 0x4D, 0x9D, 0x74, // 0x5E 'keypad 6 RightArrow'
|
|
0x47, 0x47, 0x97, 0x77, // 0x5F 'keypad 7 Home'
|
|
0x48, 0x48, 0x98, 0x8D, // 0x60 'keypad 8 UpArrow'
|
|
0x49, 0x49, 0x99, 0x84, // 0x61 'keypad 9 PageUp'
|
|
0x52, 0x52, 0xA2, 0x92, // 0x62 'keypad 0 Insert'
|
|
0x53, 0x53, 0xA3, 0x93, // 0x63 'keypad . Del'
|
|
0x56, 0x56, 0x56, 0x56, // 0x64 '\ |'
|
|
0xDD, 0xDD, 0xDD, 0xDD // 0x65 'Application' E0,5D E0,DD
|
|
};
|
|
|
|
STATIC
|
|
UINT8 KbcModCodeTable[] = {
|
|
0x1D, // 0x00 'Left Ctrl'
|
|
0x2A, // 0x01 'Left Shift'
|
|
0x38, // 0x02 'Left Alt'
|
|
0xDB, // 0x03 'Left Windows' E0,5B E0,DB
|
|
0x9D, // 0x04 'Right Ctrl' E0,1D E0,9D
|
|
0x36, // 0x05 'Right Shift'
|
|
0xB8, // 0x06 'Right Alt' E0,38 E0,B8
|
|
0xDC // 0x07 'Right Windows' E0,5C E0,DC
|
|
};
|
|
|
|
STATIC
|
|
UINT8 CtrlIgnoreKey[] = {
|
|
0x1E, // '1','!'
|
|
0x20, // '3','#'
|
|
0x21, // '4','$'
|
|
0x22, // '5','%'
|
|
0x24, // '7','&'
|
|
0x25, // '8','*'
|
|
0x26, // '9','('
|
|
0x27, // '0',')'
|
|
0x2E, // '=','+'
|
|
0x33, // ';',':'
|
|
0x34, // '\'','"'
|
|
0x35, // '`','~'
|
|
0x36, // ',','<'
|
|
0x37, // '.','>'
|
|
0x38 // '/','?'
|
|
};
|
|
|
|
STATIC
|
|
UINT8 AltIgnoreKey[] = {
|
|
0x4C, // 0x4C 'Delete Forward' E0,53
|
|
0x52, // 0x52 'Up Arrow' E0,48 E0,C8
|
|
0x51, // 0x51 'Down Arrow' E0,50 E0,D0
|
|
0x50, // 0x50 'Left Arrow' E0,4B E0,CB
|
|
0x4F, // 0x4F 'Right Arrow' E0,4D E0,CD
|
|
0x62 // 0x62 'keypad 0 Insert'
|
|
};
|
|
|
|
STATIC
|
|
UINT8 KbcCodeTableJp109[] = {
|
|
0x73, // 0x87 '\ _' Key Number #56
|
|
0x70, // 0x88 'KANA/HIRA' Key Number #133
|
|
0x7D, // 0x89 '\ |' Key Number #14
|
|
0x79, // 0x8A 'HENKAN' Key Number #132
|
|
0x7B // 0x8B 'MU-HENKAN' Key Number #131
|
|
};
|
|
|
|
/**
|
|
|
|
Get Next Item
|
|
|
|
@param StartPos Start Position
|
|
@param EndPos End Position
|
|
@param HidItem HidItem to return
|
|
|
|
@retval Position
|
|
|
|
**/
|
|
STATIC
|
|
UINT8 *
|
|
GetNextItem (
|
|
IN UINT8 *StartPos,
|
|
IN UINT8 *EndPos,
|
|
OUT HID_ITEM *HidItem
|
|
)
|
|
{
|
|
UINT8 Temp;
|
|
|
|
if ((EndPos - StartPos) <= 0) {
|
|
return NULL;
|
|
}
|
|
|
|
Temp = *StartPos;
|
|
StartPos++;
|
|
//
|
|
// bit 2,3
|
|
//
|
|
HidItem->Type = (UINT8) ((Temp >> 2) & 0x03);
|
|
//
|
|
// bit 4-7
|
|
//
|
|
HidItem->Tag = (UINT8) ((Temp >> 4) & 0x0F);
|
|
|
|
if (HidItem->Tag == HID_ITEM_TAG_LONG) {
|
|
//
|
|
// Long Items are not supported by HID rev1.0,
|
|
// although we try to parse it.
|
|
//
|
|
HidItem->Format = HID_ITEM_FORMAT_LONG;
|
|
|
|
if ((EndPos - StartPos) >= 2) {
|
|
HidItem->Size = *StartPos++;
|
|
HidItem->Tag = *StartPos++;
|
|
|
|
if ((EndPos - StartPos) >= HidItem->Size) {
|
|
HidItem->Data.LongData = StartPos;
|
|
StartPos += HidItem->Size;
|
|
return StartPos;
|
|
}
|
|
}
|
|
} else {
|
|
HidItem->Format = HID_ITEM_FORMAT_SHORT;
|
|
//
|
|
// bit 0, 1
|
|
//
|
|
HidItem->Size = (UINT8) (Temp & 0x03);
|
|
switch (HidItem->Size) {
|
|
|
|
case 0:
|
|
//
|
|
// No data
|
|
//
|
|
return StartPos;
|
|
|
|
case 1:
|
|
//
|
|
// One byte data
|
|
//
|
|
if ((EndPos - StartPos) >= 1) {
|
|
HidItem->Data.U8 = *StartPos++;
|
|
return StartPos;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
//
|
|
// Two byte data
|
|
//
|
|
if ((EndPos - StartPos) >= 2) {
|
|
HidItem->Data.U16 = *(UINT16*)StartPos;
|
|
StartPos += 2;
|
|
return StartPos;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
//
|
|
// 4 byte data, adjust size
|
|
//
|
|
HidItem->Size++;
|
|
if ((EndPos - StartPos) >= 4) {
|
|
HidItem->Data.U32 = *(UINT32*)StartPos;
|
|
StartPos += 4;
|
|
return StartPos;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
|
|
Get Item Data
|
|
|
|
@param HidItem HID_ITEM
|
|
|
|
@retval HidItem Data
|
|
|
|
**/
|
|
STATIC
|
|
UINT32
|
|
GetItemData (
|
|
IN HID_ITEM *HidItem
|
|
)
|
|
{
|
|
//
|
|
// Get Data from HID_ITEM structure
|
|
//
|
|
switch (HidItem->Size) {
|
|
|
|
case 1:
|
|
return HidItem->Data.U8;
|
|
|
|
case 2:
|
|
return HidItem->Data.U16;
|
|
|
|
case 4:
|
|
return HidItem->Data.U32;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Find Key Descriptor in Key Convertion Table given its USB keycode.
|
|
|
|
@param[in] UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param[in] KeyCode USB Keycode.
|
|
|
|
@return The Key Descriptor in Key Convertion Table.
|
|
NULL means not found.
|
|
|
|
**/
|
|
EFI_KEY_DESCRIPTOR *
|
|
GetKeyDescriptor (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 KeyCode
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
|
|
//
|
|
// Make sure KeyCode is in the range of [0x4, 0x65] or [0xe0, 0xe7]
|
|
//
|
|
if ((!USBKBD_VALID_KEYCODE (KeyCode)) || ((KeyCode > 0x65) && (KeyCode < 0xe0)) || (KeyCode > 0xe7)) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Calculate the index of Key Descriptor in Key Convertion Table
|
|
//
|
|
if (KeyCode <= 0x65) {
|
|
Index = (UINT8) (KeyCode - 4);
|
|
} else {
|
|
Index = (UINT8) (KeyCode - 0xe0 + NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE);
|
|
}
|
|
|
|
return &UsbKeyboardDevice->KeyConvertionTable[Index];
|
|
}
|
|
|
|
/**
|
|
Find Non-Spacing key for given Key descriptor.
|
|
|
|
@param[in] UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param[in] KeyDescriptor Key descriptor.
|
|
|
|
@return The Non-Spacing key corresponding to KeyDescriptor
|
|
NULL means not found.
|
|
|
|
**/
|
|
USB_NS_KEY *
|
|
FindUsbNsKey (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN EFI_KEY_DESCRIPTOR *KeyDescriptor
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
LIST_ENTRY *NsKeyList;
|
|
USB_NS_KEY *UsbNsKey;
|
|
|
|
NsKeyList = &UsbKeyboardDevice->NsKeyList;
|
|
Link = GetFirstNode (NsKeyList);
|
|
while (!IsNull (NsKeyList, Link)) {
|
|
UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
|
|
|
|
if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {
|
|
return UsbNsKey;
|
|
}
|
|
|
|
Link = GetNextNode (NsKeyList, Link);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Find physical key definition for a given key descriptor.
|
|
|
|
For a specified non-spacing key, there are a list of physical
|
|
keys following it. This function traverses the list of
|
|
physical keys and tries to find the physical key matching
|
|
the KeyDescriptor.
|
|
|
|
@param[in] UsbNsKey The non-spacing key information.
|
|
@param[in] KeyDescriptor The key descriptor.
|
|
|
|
@return The physical key definition.
|
|
If no physical key is found, parameter KeyDescriptor is returned.
|
|
|
|
**/
|
|
EFI_KEY_DESCRIPTOR *
|
|
FindPhysicalKey (
|
|
IN USB_NS_KEY *UsbNsKey,
|
|
IN EFI_KEY_DESCRIPTOR *KeyDescriptor
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_KEY_DESCRIPTOR *PhysicalKey;
|
|
|
|
PhysicalKey = &UsbNsKey->NsKey[1];
|
|
for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {
|
|
if (KeyDescriptor->Key == PhysicalKey->Key) {
|
|
return PhysicalKey;
|
|
}
|
|
|
|
PhysicalKey++;
|
|
}
|
|
|
|
//
|
|
// No children definition matched, return original key
|
|
//
|
|
return KeyDescriptor;
|
|
}
|
|
|
|
/**
|
|
|
|
Parse Report Descriptor to Finding LED support
|
|
|
|
@param ReportDescriptor Report descriptor to parse
|
|
@param ReportSize Report descriptor size
|
|
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
ParseReportToFindingLed (
|
|
IN UINT8 *ReportDescriptor,
|
|
IN UINTN ReportSize
|
|
)
|
|
{
|
|
UINT8 *DescriptorEnd;
|
|
UINT8 *ptr;
|
|
HID_ITEM HidItem;
|
|
UINT8 CurrentUsagePage = 0;
|
|
UINT8 CurrentUsage = 0;
|
|
|
|
DescriptorEnd = ReportDescriptor + ReportSize;
|
|
ptr = GetNextItem (ReportDescriptor, DescriptorEnd, &HidItem);
|
|
|
|
while (ptr != NULL) {
|
|
if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {
|
|
//
|
|
// Long Format Item is not supported at current HID revision
|
|
//
|
|
return 0;
|
|
}
|
|
switch (HidItem.Type) {
|
|
|
|
case HID_ITEM_TYPE_GLOBAL:
|
|
//
|
|
// For global Item, parse global item
|
|
//
|
|
if (HidItem.Tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) {
|
|
CurrentUsagePage = (UINT8) GetItemData (&HidItem);
|
|
}
|
|
break;
|
|
|
|
case HID_ITEM_TYPE_LOCAL:
|
|
//
|
|
// For Local Item, parse local item
|
|
//
|
|
if (HidItem.Tag == HID_LOCAL_ITEM_TAG_USAGE) {
|
|
CurrentUsage = (UINT8) GetItemData (&HidItem);
|
|
}
|
|
//
|
|
// Check Touch device by Usage Page is DIGITIZERS and Usage is Touch Screen,
|
|
// or Usage Page is DIGITIZERS and Usage is PEN
|
|
//
|
|
if (CurrentUsagePage == HID_UP_LED) {
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
}
|
|
ptr = GetNextItem (ptr, DescriptorEnd, &HidItem);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
|
|
Check is it support LED in this interface
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
CheckLedExist (
|
|
IN USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
|
EFI_USB_HID_DESCRIPTOR KeyboardHidDesc;
|
|
UINT8 *ReportDesc;
|
|
BOOLEAN LedSupported = FALSE;
|
|
//
|
|
// Assuming Interface 0 is major interface and support LED
|
|
//
|
|
if (UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber == 0) return TRUE;
|
|
//
|
|
// Examining the LED page for LED support
|
|
//
|
|
UsbIo = UsbKeyboardDevice->UsbIo;
|
|
Status = mUsbCore->UsbGetHidDescriptor (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
&KeyboardHidDesc
|
|
);
|
|
if (EFI_ERROR (Status) || KeyboardHidDesc.HidClassDesc[0].DescriptorType != 0x22) {
|
|
return FALSE;
|
|
}
|
|
Status = mUsbCore->AllocateBuffer (
|
|
KeyboardHidDesc.HidClassDesc[0].DescriptorLength,
|
|
ALIGNMENT_32,
|
|
(VOID **)&ReportDesc
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return FALSE;
|
|
}
|
|
Status = mUsbCore->UsbGetReportDescriptor (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
KeyboardHidDesc.HidClassDesc[0].DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
LedSupported = ParseReportToFindingLed (
|
|
ReportDesc,
|
|
KeyboardHidDesc.HidClassDesc[0].DescriptorLength
|
|
);
|
|
}
|
|
mUsbCore->FreeBuffer (
|
|
KeyboardHidDesc.HidClassDesc[0].DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
return LedSupported;
|
|
}
|
|
|
|
/**
|
|
|
|
Uses USB I/O to check whether the device is a USB Keyboard device.
|
|
|
|
@param UsbIo Points to a USB I/O protocol instance.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsUsbKeyboard (
|
|
IN EFI_USB_IO_PROTOCOL *UsbIo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
|
EFI_USB_HID_DESCRIPTOR KeyboardHidDesc;
|
|
UINT8 *ReportDesc;
|
|
UINT16 DescriptorLength;
|
|
BOOLEAN KeyboardDeviceFound;
|
|
REPORT_FIELD_INFO ReportFieldInfo;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Get the Default interface descriptor, currently we
|
|
// assume it is interface 1
|
|
//
|
|
Status = UsbGetInterfaceDescriptor (
|
|
UsbIo,
|
|
&InterfaceDescriptor
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (InterfaceDescriptor.InterfaceClass == CLASS_HID) {
|
|
if (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
|
|
InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD) {
|
|
return TRUE;
|
|
}
|
|
if (!((InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD) ||
|
|
(InterfaceDescriptor.InterfaceProtocol == PROTOCOL_NONE && InterfaceDescriptor.InterfaceSubClass == SUBCLASS_NONE))) {
|
|
return FALSE;
|
|
}
|
|
Status = mUsbCore->UsbGetHidDescriptor (
|
|
UsbIo,
|
|
InterfaceDescriptor.InterfaceNumber,
|
|
&KeyboardHidDesc
|
|
);
|
|
if (EFI_ERROR (Status) || (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_NONE && KeyboardHidDesc.HidClassDesc[0].DescriptorType != 0x22)) {
|
|
return FALSE;
|
|
}
|
|
DescriptorLength = KeyboardHidDesc.HidClassDesc[0].DescriptorLength;
|
|
Status = mUsbCore->AllocateBuffer (
|
|
DescriptorLength,
|
|
ALIGNMENT_32,
|
|
(VOID **)&ReportDesc
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return FALSE;
|
|
}
|
|
KeyboardDeviceFound = FALSE;
|
|
for (Index = 0; Index < 3; Index ++) {
|
|
Status = mUsbCore->UsbGetReportDescriptor (
|
|
UsbIo,
|
|
InterfaceDescriptor.InterfaceNumber,
|
|
DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
break;
|
|
} else if (Status == EFI_DEVICE_ERROR) {
|
|
//
|
|
// Stall 10ms to waiting for potential signal unstable
|
|
//
|
|
mUsbCore->Stall (10 * 1000);
|
|
}
|
|
}
|
|
if (!EFI_ERROR (Status) && MatchHidDeviceType (ReportDesc, DescriptorLength, KEYBOARD_CLASS_CODE)) {
|
|
//
|
|
// Check the key value type
|
|
//
|
|
ZeroMem (&ReportFieldInfo, sizeof (REPORT_FIELD_INFO));
|
|
Status = ParseReportDescriptor (
|
|
ReportDesc,
|
|
DescriptorLength,
|
|
&ReportFieldInfo
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Searching for qualified mouse report
|
|
//
|
|
for (Index = 0; Index < ReportFieldInfo.Total; Index ++) {
|
|
if (ReportFieldInfo.ReportGroup[Index].DataValid &&
|
|
ReportFieldInfo.ReportGroup[Index].DataAttr == ATTR_KEYBOARD_INPUT &&
|
|
((ReportFieldInfo.ReportGroup[Index].DataSize == 9 && ReportFieldInfo.ReportGroup[Index].Id != 0) ||
|
|
(ReportFieldInfo.ReportGroup[Index].DataSize == 8 && ReportFieldInfo.ReportGroup[Index].Id == 0)) &&
|
|
ReportFieldInfo.ReportGroup[Index].Data.Keyboard.FieldModKeyCode.DataValid &&
|
|
ReportFieldInfo.ReportGroup[Index].Data.Keyboard.FieldKeyCode.DataValid) {
|
|
KeyboardDeviceFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
mUsbCore->FreeBuffer (
|
|
DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
if (KeyboardDeviceFound) return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Initialize Key Convention Table by using default keyboard layout.
|
|
|
|
@param[in, out] UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
@retval EFI_SUCCESS The default keyboard layout was installed successfully
|
|
@retval Others Failure to install default keyboard layout.
|
|
**/
|
|
EFI_STATUS
|
|
InstallDefaultKeyboardLayout (
|
|
IN OUT USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
|
|
EFI_HII_HANDLE HiiHandle;
|
|
EFI_GUID *DefaultKeyboardLayout;
|
|
|
|
//
|
|
// Locate Hii database protocol
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiDatabaseProtocolGuid,
|
|
NULL,
|
|
(VOID **) &HiiDatabase
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Install Keyboard Layout package to HII database
|
|
//
|
|
HiiHandle = HiiAddPackages (
|
|
&gH2OUsbKeyboardLayoutPackageGuid,
|
|
UsbKeyboardDevice->ControllerHandle,
|
|
&mUsbKeyboardLayoutBin,
|
|
NULL
|
|
);
|
|
if (HiiHandle == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DefaultKeyboardLayout = (EFI_GUID *)PcdGetPtr(PcdH2ODefautKeyboardLayout);
|
|
|
|
//
|
|
// Set current keyboard layout
|
|
//
|
|
Status = HiiDatabase->SetKeyboardLayout (HiiDatabase, DefaultKeyboardLayout);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get current keyboard layout from HII database.
|
|
|
|
@return Pointer to HII Keyboard Layout.
|
|
NULL means failure occurred while trying to get keyboard layout.
|
|
|
|
**/
|
|
EFI_HII_KEYBOARD_LAYOUT *
|
|
GetCurrentKeyboardLayout (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
|
|
EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
|
|
UINT16 Length;
|
|
|
|
//
|
|
// Locate HII Database Protocol
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiDatabaseProtocolGuid,
|
|
NULL,
|
|
(VOID **) &HiiDatabase
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Get current keyboard layout from HII database
|
|
//
|
|
Length = 0;
|
|
KeyboardLayout = NULL;
|
|
Status = HiiDatabase->GetKeyboardLayout (
|
|
HiiDatabase,
|
|
NULL,
|
|
&Length,
|
|
KeyboardLayout
|
|
);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
KeyboardLayout = AllocatePool (Length);
|
|
ASSERT (KeyboardLayout != NULL);
|
|
|
|
Status = HiiDatabase->GetKeyboardLayout (
|
|
HiiDatabase,
|
|
NULL,
|
|
&Length,
|
|
KeyboardLayout
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (KeyboardLayout);
|
|
KeyboardLayout = NULL;
|
|
}
|
|
}
|
|
|
|
return KeyboardLayout;
|
|
}
|
|
|
|
/**
|
|
The notification function for EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID.
|
|
|
|
This function is registered to event of EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
|
|
group type, which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
|
|
It tries to get current keyboard layout from HII database.
|
|
|
|
@param[in] Event Event being signaled.
|
|
@param[in] Context Points to USB_KB_DEV instance.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SetKeyboardLayoutEvent (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
|
|
EFI_KEY_DESCRIPTOR TempKey;
|
|
EFI_KEY_DESCRIPTOR *KeyDescriptor;
|
|
EFI_KEY_DESCRIPTOR *TableEntry;
|
|
EFI_KEY_DESCRIPTOR *NsKey;
|
|
USB_NS_KEY *UsbNsKey;
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
UINTN KeyCount;
|
|
UINT8 KeyCode;
|
|
|
|
UsbKeyboardDevice = (USB_KB_DEV *) Context;
|
|
if (UsbKeyboardDevice->Signature != USB_KB_DEV_SIGNATURE) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Try to get current keyboard layout from HII database
|
|
//
|
|
KeyboardLayout = GetCurrentKeyboardLayout ();
|
|
if (KeyboardLayout == NULL) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Re-allocate resource for KeyConvertionTable
|
|
//
|
|
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
|
|
Status = mUsbCore->AllocateBuffer (
|
|
(NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR),
|
|
ALIGNMENT_32,
|
|
(VOID **)&UsbKeyboardDevice->KeyConvertionTable
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
|
|
|
|
//
|
|
// Traverse the list of key descriptors following the header of EFI_HII_KEYBOARD_LAYOUT
|
|
//
|
|
KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));
|
|
for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {
|
|
//
|
|
// Copy from HII keyboard layout package binary for alignment
|
|
//
|
|
CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
|
|
|
|
//
|
|
// Fill the key into KeyConvertionTable, whose index is calculated from USB keycode.
|
|
//
|
|
KeyCode = EfiKeyToUsbKeyCodeConvertionTable [(UINT8) (TempKey.Key)];
|
|
TableEntry = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);
|
|
if (TableEntry == NULL) {
|
|
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
|
|
FreePool (KeyboardLayout);
|
|
return;
|
|
}
|
|
CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
|
|
|
|
//
|
|
// For non-spacing key, create the list with a non-spacing key followed by physical keys.
|
|
//
|
|
if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {
|
|
UsbNsKey = AllocateZeroPool (sizeof (USB_NS_KEY));
|
|
if (UsbNsKey == NULL) return;
|
|
//
|
|
// Search for sequential children physical key definitions
|
|
//
|
|
KeyCount = 0;
|
|
NsKey = KeyDescriptor + 1;
|
|
for (Index2 = (UINT8) Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {
|
|
CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));
|
|
if (TempKey.Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER) {
|
|
KeyCount++;
|
|
} else {
|
|
break;
|
|
}
|
|
NsKey++;
|
|
}
|
|
|
|
UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;
|
|
UsbNsKey->KeyCount = KeyCount;
|
|
UsbNsKey->NsKey = AllocateCopyPool (
|
|
(KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),
|
|
KeyDescriptor
|
|
);
|
|
InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);
|
|
|
|
//
|
|
// Skip over the child physical keys
|
|
//
|
|
Index += KeyCount;
|
|
KeyDescriptor += KeyCount;
|
|
}
|
|
|
|
KeyDescriptor++;
|
|
}
|
|
|
|
//
|
|
// There are two EfiKeyEnter, duplicate its key descriptor
|
|
//
|
|
TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);
|
|
KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);
|
|
CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));
|
|
CopyMem (&UsbKeyboardDevice->CurrentLayoutGuid, ((UINT8 *) KeyboardLayout) + sizeof (UINT16), sizeof (EFI_GUID));
|
|
|
|
FreePool (KeyboardLayout);
|
|
}
|
|
|
|
/**
|
|
Destroy resources for keyboard layout.
|
|
|
|
@param[in, out] UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
**/
|
|
VOID
|
|
ReleaseKeyboardLayoutResources (
|
|
IN OUT USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
USB_NS_KEY *UsbNsKey;
|
|
LIST_ENTRY *Link;
|
|
|
|
if (UsbKeyboardDevice->KeyConvertionTable != NULL) {
|
|
mUsbCore->FreeBuffer (
|
|
(NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR),
|
|
UsbKeyboardDevice->KeyConvertionTable
|
|
);
|
|
}
|
|
UsbKeyboardDevice->KeyConvertionTable = NULL;
|
|
|
|
while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {
|
|
Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);
|
|
UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);
|
|
RemoveEntryList (&UsbNsKey->Link);
|
|
|
|
FreePool (UsbNsKey->NsKey);
|
|
FreePool (UsbNsKey);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Initialize USB keyboard layout.
|
|
|
|
This function initializes Key Convertion Table for the USB keyboard device.
|
|
It first tries to retrieve layout from HII database. If failed and default
|
|
layout is enabled, then it just uses the default layout.
|
|
|
|
@param[out] UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Initialization succeeded.
|
|
@retval EFI_NOT_READY Keyboard layout cannot be retrieve from HII
|
|
database, and default layout is disabled.
|
|
@retval Other Fail to register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
InitKeyboardLayout (
|
|
OUT USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
|
|
EFI_STATUS Status;
|
|
|
|
Status = mUsbCore->AllocateBuffer (
|
|
(NUMBER_OF_VALID_USB_KEYCODE) * sizeof (EFI_KEY_DESCRIPTOR),
|
|
ALIGNMENT_32,
|
|
(VOID **)&UsbKeyboardDevice->KeyConvertionTable
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);
|
|
|
|
InitializeListHead (&UsbKeyboardDevice->NsKeyList);
|
|
UsbKeyboardDevice->CurrentNsKey = NULL;
|
|
UsbKeyboardDevice->KeyboardLayoutEvent = NULL;
|
|
|
|
//
|
|
// Register event to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
|
|
// which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
|
|
//
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
SetKeyboardLayoutEvent,
|
|
UsbKeyboardDevice,
|
|
&gEfiHiiKeyBoardLayoutGuid,
|
|
&UsbKeyboardDevice->KeyboardLayoutEvent
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
KeyboardLayout = GetCurrentKeyboardLayout ();
|
|
if (KeyboardLayout != NULL) {
|
|
//
|
|
// If current keyboard layout is successfully retrieved from HII database,
|
|
// force to initialize the keyboard layout.
|
|
//
|
|
gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
|
|
} else {
|
|
if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {
|
|
//
|
|
// If no keyboard layout can be retrieved from HII database, and default layout
|
|
// is disabled, then return EFI_NOT_READY.
|
|
//
|
|
return EFI_NOT_READY;
|
|
}
|
|
//
|
|
// If no keyboard layout can be retrieved from HII database, and default layout
|
|
// is enabled, then load the default keyboard layout.
|
|
//
|
|
InstallDefaultKeyboardLayout (UsbKeyboardDevice);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/*++
|
|
|
|
Initialize USB Keyboard device and all private data structures.
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval EFI_DEVICE_ERROR Hardware Error
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
InitUsbKeyboard (
|
|
IN USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Protocol;
|
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
|
EFI_USB_HID_DESCRIPTOR KeyboardHidDesc;
|
|
UINT8 *ReportDesc;
|
|
UINT16 DescriptorLength;
|
|
REPORT_FIELD_INFO ReportFieldInfo;
|
|
UINTN Index;
|
|
|
|
UsbIo = UsbKeyboardDevice->UsbIo;
|
|
ReportDesc = NULL;
|
|
DescriptorLength = 0;
|
|
|
|
KbdReportStatusCode (
|
|
UsbKeyboardDevice,
|
|
EFI_PROGRESS_CODE,
|
|
(EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST)
|
|
);
|
|
|
|
InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));
|
|
InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));
|
|
InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));
|
|
|
|
if (UsbKeyboardDevice->InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) {
|
|
//
|
|
// Sets boot protocol for the SUBCLASS_BOOT keyboard
|
|
//
|
|
Protocol = BOOT_PROTOCOL;
|
|
} else {
|
|
//
|
|
// Sets report protocol for the non boot protocol keyboard
|
|
//
|
|
Protocol = REPORT_PROTOCOL;
|
|
Status = mUsbCore->UsbGetHidDescriptor (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
&KeyboardHidDesc
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
DescriptorLength = KeyboardHidDesc.HidClassDesc[0].DescriptorLength;
|
|
Status = mUsbCore->AllocateBuffer (
|
|
DescriptorLength,
|
|
ALIGNMENT_32,
|
|
(VOID **)&ReportDesc
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Status = mUsbCore->UsbGetReportDescriptor (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
//
|
|
// Parse report descriptor
|
|
//
|
|
ZeroMem (&ReportFieldInfo, sizeof (REPORT_FIELD_INFO));
|
|
Status = ParseReportDescriptor (
|
|
ReportDesc,
|
|
DescriptorLength,
|
|
&ReportFieldInfo
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
//
|
|
// Searching for qualified mouse report
|
|
//
|
|
for (Index = 0; Index < ReportFieldInfo.Total; Index ++) {
|
|
if (ReportFieldInfo.ReportGroup[Index].DataValid &&
|
|
ReportFieldInfo.ReportGroup[Index].DataAttr == ATTR_KEYBOARD_INPUT &&
|
|
((ReportFieldInfo.ReportGroup[Index].DataSize == 9 && ReportFieldInfo.ReportGroup[Index].Id != 0) ||
|
|
(ReportFieldInfo.ReportGroup[Index].DataSize == 8 && ReportFieldInfo.ReportGroup[Index].Id == 0)) &&
|
|
ReportFieldInfo.ReportGroup[Index].Data.Keyboard.FieldModKeyCode.DataValid &&
|
|
ReportFieldInfo.ReportGroup[Index].Data.Keyboard.FieldKeyCode.DataValid) {
|
|
CopyMem (&UsbKeyboardDevice->ReportGroup, &ReportFieldInfo.ReportGroup[Index], sizeof (REPORT_GROUP));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Always set corresponding protocol for the USB Keyboard. Some of device must
|
|
// to do it to fix the malfunction issue after warm reset
|
|
//
|
|
mUsbCore->UsbSetProtocolRequest (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
Protocol
|
|
);
|
|
//
|
|
// Stall 2ms after SetProtocol command to workaround slow devices failed on
|
|
// accepting subsequently command issue
|
|
//
|
|
mUsbCore->Stall (2 * 1000);
|
|
//
|
|
// Idle forever until there is a key pressed and released.
|
|
//
|
|
mUsbCore->UsbSetIdleRequest (
|
|
UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
0,
|
|
0
|
|
);
|
|
|
|
UsbKeyboardDevice->CtrlOn = 0;
|
|
UsbKeyboardDevice->AltOn = 0;
|
|
UsbKeyboardDevice->ShiftOn = 0;
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
UsbKeyboardDevice->NumLockOn = 0;
|
|
UsbKeyboardDevice->CapsOn = 0;
|
|
UsbKeyboardDevice->ScrollOn = 0;
|
|
}
|
|
UsbKeyboardDevice->LeftCtrlOn = 0;
|
|
UsbKeyboardDevice->LeftAltOn = 0;
|
|
UsbKeyboardDevice->LeftShiftOn = 0;
|
|
UsbKeyboardDevice->LeftLogoOn = 0;
|
|
UsbKeyboardDevice->RightCtrlOn = 0;
|
|
UsbKeyboardDevice->RightAltOn = 0;
|
|
UsbKeyboardDevice->RightShiftOn = 0;
|
|
UsbKeyboardDevice->RightLogoOn = 0;
|
|
UsbKeyboardDevice->MenuKeyOn = 0;
|
|
UsbKeyboardDevice->SysReqOn = 0;
|
|
UsbKeyboardDevice->IsSupportPartialKey = 0;
|
|
UsbKeyboardDevice->AltGrOn = 0;
|
|
UsbKeyboardDevice->CircumflexAccentOn = 0;
|
|
UsbKeyboardDevice->CircumflexAccentShiftedOn = 0;
|
|
UsbKeyboardDevice->GraveAccentOn = 0;
|
|
UsbKeyboardDevice->TildeOn = 0;
|
|
UsbKeyboardDevice->CurrentNsKey = NULL;
|
|
if (UsbKeyboardDevice->RepeatPollingHandle) {
|
|
mUsbCore->RemovePeriodicTimer (
|
|
UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
UsbKeyboardDevice->RepeatPollingHandle = NULL;
|
|
UsbKeyboardDevice->RepeatKey = 0;
|
|
}
|
|
//
|
|
// Check is it support LED
|
|
//
|
|
UsbKeyboardDevice->LedSupported = CheckLedExist (UsbKeyboardDevice);
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
//
|
|
// Sync the initial state of LED with BDAs qualifier stat
|
|
//
|
|
UsbKeyboardCheckLEDHandler(1, UsbKeyboardDevice);
|
|
} else {
|
|
SetKeyLED(UsbKeyboardDevice);
|
|
}
|
|
ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
|
|
Status = EFI_SUCCESS;
|
|
|
|
ErrorExit:
|
|
if (EFI_ERROR (Status) && ReportDesc != NULL) {
|
|
mUsbCore->FreeBuffer (
|
|
DescriptorLength,
|
|
ReportDesc
|
|
);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
Retrieves the interface Descriptor for that controller.
|
|
|
|
@param This Indicates the calling context.
|
|
@param InterfaceDescriptor A pointer to the caller allocated USB interface
|
|
Descriptor.
|
|
|
|
@retval EFI_SUCCESS
|
|
@retval EFI_INVALID_PARAMETER
|
|
@retval EFI_NOT_FOUND
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UsbGetInterfaceDescriptor (
|
|
IN EFI_USB_IO_PROTOCOL *This,
|
|
OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor
|
|
)
|
|
{
|
|
EFI_USB_IO_GET_INTERFACE_DESCRIPTOR UsbGetInterfaceDescriptorFunc = This->UsbGetInterfaceDescriptor;
|
|
|
|
if (mInSmram) {
|
|
mUsbCore->AddressConvert (
|
|
SMM_ADDRESS,
|
|
(VOID*)(UINTN)UsbGetInterfaceDescriptorFunc,
|
|
(VOID**)&UsbGetInterfaceDescriptorFunc
|
|
);
|
|
}
|
|
return UsbGetInterfaceDescriptorFunc (
|
|
This,
|
|
InterfaceDescriptor
|
|
);
|
|
}
|
|
|
|
/**
|
|
|
|
Retrieves the endpoint Descriptor for a given endpoint.
|
|
|
|
@param This Indicates the calling context.
|
|
@param EndpointIndex Indicates which endpoint descriptor to retrieve.
|
|
The valid range is 0..15.
|
|
@param EndpointDescriptor A pointer to the caller allocated USB Endpoint
|
|
Descriptor of a USB controller.
|
|
|
|
@retval EFI_SUCCESS The endpoint descriptor was retrieved successfully.
|
|
@retval EFI_INVALID_PARAMETER EndpointIndex is not valid.
|
|
EndpointDescriptor is NULL.
|
|
@retval EFI_NOT_FOUND The endpoint descriptor cannot be found.
|
|
The device may not be correctly configured.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UsbGetEndpointDescriptor (
|
|
IN EFI_USB_IO_PROTOCOL *This,
|
|
IN UINT8 EndpointIndex,
|
|
OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor
|
|
)
|
|
{
|
|
EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptorFunc = This->UsbGetEndpointDescriptor;
|
|
|
|
if (mInSmram) {
|
|
mUsbCore->AddressConvert (
|
|
SMM_ADDRESS,
|
|
(VOID*)(UINTN)UsbGetEndpointDescriptorFunc,
|
|
(VOID**)&UsbGetEndpointDescriptorFunc
|
|
);
|
|
}
|
|
return UsbGetEndpointDescriptorFunc (
|
|
This,
|
|
EndpointIndex,
|
|
EndpointDescriptor
|
|
);
|
|
}
|
|
|
|
/*++
|
|
|
|
Usb Async Interrupt Transfer
|
|
|
|
@param This Indicates calling context.
|
|
@param DeviceEndpoint The destination USB device endpoint to which the
|
|
device request is being sent.
|
|
@param IsNewTransfer If TRUE, a new transfer will be submitted to USB
|
|
controller. If FALSE, the interrupt transfer is
|
|
deleted from the device's interrupt transfer queue.
|
|
@param PollingInterval Indicates the periodic rate, in milliseconds, that
|
|
the transfer is to be executed.
|
|
@param DataLength Specifies the length, in bytes, of the data to be
|
|
received from the USB device.
|
|
@param InterruptCallBack The Callback function. This function is called if
|
|
the asynchronous interrupt transfer is completed.
|
|
@param Context Passed to InterruptCallback
|
|
|
|
@retval EFI_SUCCESS
|
|
@retval EFI_INVALID_PARAMETER
|
|
@retval EFI_OUT_OF_RESOURCES
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UsbAsyncInterruptTransfer (
|
|
IN EFI_USB_IO_PROTOCOL *This,
|
|
IN UINT8 DeviceEndpoint,
|
|
IN BOOLEAN IsNewTransfer,
|
|
IN UINTN PollingInterval, OPTIONAL
|
|
IN UINTN DataLength, OPTIONAL
|
|
IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL
|
|
IN VOID *Context OPTIONAL
|
|
)
|
|
{
|
|
EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER UsbAsyncInterruptTransferFunc = This->UsbAsyncInterruptTransfer;
|
|
|
|
if (mInSmram) {
|
|
mUsbCore->AddressConvert (
|
|
SMM_ADDRESS,
|
|
(VOID*)(UINTN)UsbAsyncInterruptTransferFunc,
|
|
(VOID**)&UsbAsyncInterruptTransferFunc
|
|
);
|
|
}
|
|
return UsbAsyncInterruptTransferFunc (
|
|
This,
|
|
DeviceEndpoint,
|
|
IsNewTransfer,
|
|
PollingInterval,
|
|
DataLength,
|
|
InterruptCallBack,
|
|
Context
|
|
);
|
|
}
|
|
|
|
/**
|
|
|
|
Handler function for USB Keyboard's asynchronous interrupt transfer.
|
|
|
|
@param Data A pointer to a buffer that is filled with key data which is
|
|
retrieved via asynchronous interrupt transfer.
|
|
@param DataLength Indicates the size of the data buffer.
|
|
@param Context Pointing to USB_KB_DEV instance.
|
|
@param Result Indicates the result of the asynchronous interrupt transfer.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval EFI_DEVICE_ERROR Hardware Error
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
KeyboardHandler (
|
|
IN VOID *Data,
|
|
IN UINTN DataLength,
|
|
IN VOID *Context,
|
|
IN UINT32 Result
|
|
)
|
|
{
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
|
UINT8 *CurKeyCodeBuffer;
|
|
UINT8 *OldKeyCodeBuffer;
|
|
UINT8 CurModifierMap;
|
|
UINT8 OldModifierMap;
|
|
UINTN Index;
|
|
UINT8 Index2;
|
|
BOOLEAN Down;
|
|
EFI_STATUS Status;
|
|
BOOLEAN KeyRelease;
|
|
BOOLEAN KeyPress;
|
|
UINT8 NewRepeatKey;
|
|
UINT32 UsbStatus;
|
|
EFI_KEY_DESCRIPTOR *KeyDescriptor;
|
|
|
|
ASSERT (Context != NULL);
|
|
if (Context == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
NewRepeatKey = 0;
|
|
UsbKeyboardDevice = (USB_KB_DEV *) Context;
|
|
UsbIo = UsbKeyboardDevice->UsbIo;
|
|
//
|
|
// Analyzes the Result and performs corresponding action.
|
|
//
|
|
if (Result != EFI_USB_NOERROR) {
|
|
//
|
|
// Some errors happen during the process
|
|
//
|
|
KbdReportStatusCode (
|
|
UsbKeyboardDevice,
|
|
EFI_ERROR_CODE | EFI_ERROR_MINOR,
|
|
(EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR)
|
|
);
|
|
//
|
|
// stop the repeat key generation if any
|
|
//
|
|
UsbKeyboardDevice->RepeatKey = 0;
|
|
|
|
if (UsbKeyboardDevice->RepeatPollingHandle) {
|
|
mUsbCore->RemovePeriodicTimer (
|
|
UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
UsbKeyboardDevice->RepeatPollingHandle = NULL;
|
|
}
|
|
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
|
|
mUsbCore->UsbClearEndpointHalt (
|
|
UsbIo,
|
|
UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
|
|
&UsbStatus
|
|
);
|
|
}
|
|
|
|
//
|
|
// Delete & Submit this interrupt again
|
|
//
|
|
|
|
Status = UsbAsyncInterruptTransfer (
|
|
UsbIo,
|
|
UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
|
|
FALSE,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
//
|
|
// Check is the device be detached
|
|
//
|
|
if (mUsbCore->CheckDeviceDetached(UsbIo) == EFI_SUCCESS) {
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
mUsbCore->InsertPeriodicTimer(
|
|
USB_CORE_ONCE_TIMER,
|
|
UsbKeyboardRecoveryHandler,
|
|
UsbKeyboardDevice,
|
|
EFI_USB_INTERRUPT_DELAY / 10000,
|
|
&UsbKeyboardDevice->RecoveryPollingHandle
|
|
);
|
|
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
if (DataLength == 0 || Data == NULL) {
|
|
Status = EFI_SUCCESS;
|
|
goto Exit;
|
|
}
|
|
if (DataLength < 8) {
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
if (UsbKeyboardDevice->ReportGroup.Id != 0) {
|
|
if (UsbKeyboardDevice->ReportGroup.Id != *(UINT8*)Data) {
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
CurKeyCodeBuffer = (UINT8*)Data + 1;
|
|
} else {
|
|
CurKeyCodeBuffer = (UINT8*)Data;
|
|
}
|
|
OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
|
|
|
|
//
|
|
// checks for new key stroke.
|
|
// if no new key got, return immediately.
|
|
//
|
|
for (Index = 0; Index < 8; Index++) {
|
|
if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Index == 8) {
|
|
Status = EFI_SUCCESS;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Parse the modifier key
|
|
//
|
|
CurModifierMap = CurKeyCodeBuffer[0];
|
|
OldModifierMap = OldKeyCodeBuffer[0];
|
|
|
|
//
|
|
// handle modifier key's pressing or releasing situation.
|
|
//
|
|
for (Index = 0; Index < 8; Index++) {
|
|
|
|
if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) {
|
|
//
|
|
// if current modifier key is up, then
|
|
// CurModifierMap & KB_Mod[Index].Mask = 0;
|
|
// otherwise it is a non-zero value.
|
|
// Inserts the pressed modifier key into key buffer.
|
|
//
|
|
Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask);
|
|
InsertKeyCode (UsbKeyboardDevice, KB_Mod[Index].Key, Down);
|
|
}
|
|
}
|
|
|
|
//
|
|
// handle normal key's releasing situation
|
|
//
|
|
KeyRelease = FALSE;
|
|
for (Index = 2; Index < 8; Index++) {
|
|
|
|
if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
|
|
continue;
|
|
}
|
|
|
|
KeyRelease = TRUE;
|
|
for (Index2 = 2; Index2 < 8; Index2++) {
|
|
|
|
if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
|
|
continue;
|
|
}
|
|
|
|
if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
|
|
KeyRelease = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (KeyRelease) {
|
|
InsertKeyCode (
|
|
UsbKeyboardDevice,
|
|
OldKeyCodeBuffer[Index],
|
|
0
|
|
);
|
|
//
|
|
// the original repeat key is released.
|
|
//
|
|
if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
|
|
UsbKeyboardDevice->RepeatKey = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// original repeat key is released, cancel the repeat timer
|
|
//
|
|
if (UsbKeyboardDevice->RepeatKey == 0 && UsbKeyboardDevice->RepeatPollingHandle != NULL) {
|
|
mUsbCore->RemovePeriodicTimer (
|
|
UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
UsbKeyboardDevice->RepeatPollingHandle = NULL;
|
|
}
|
|
|
|
//
|
|
// handle normal key's pressing situation
|
|
//
|
|
KeyPress = FALSE;
|
|
for (Index = 2; Index < 8; Index++) {
|
|
|
|
if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
|
|
continue;
|
|
}
|
|
|
|
KeyPress = TRUE;
|
|
for (Index2 = 2; Index2 < 8; Index2++) {
|
|
|
|
if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
|
|
continue;
|
|
}
|
|
|
|
if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
|
|
KeyPress = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (KeyPress) {
|
|
InsertKeyCode (UsbKeyboardDevice, CurKeyCodeBuffer[Index], 1);
|
|
|
|
KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);
|
|
//
|
|
// NumLock/CapsLock/ScrollLock pressed
|
|
//
|
|
if (KeyDescriptor != NULL &&
|
|
(KeyDescriptor->Modifier != EFI_NUM_LOCK_MODIFIER) &&
|
|
(KeyDescriptor->Modifier != EFI_CAPS_LOCK_MODIFIER) &&
|
|
(KeyDescriptor->Modifier != EFI_SCROLL_LOCK_MODIFIER)) {
|
|
NewRepeatKey = CurKeyCodeBuffer[Index];
|
|
}
|
|
//
|
|
// do not repeat the original repeated key
|
|
//
|
|
UsbKeyboardDevice->RepeatKey = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update LastKeycodeArray[] buffer in the
|
|
// Usb Keyboard Device data structure.
|
|
//
|
|
for (Index = 0; Index < 8; Index++) {
|
|
UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
|
|
}
|
|
//
|
|
// If have new key pressed, update the RepeatKey value, and set the
|
|
// timer to repeat delay timer
|
|
//
|
|
if (NewRepeatKey != 0) {
|
|
if (UsbKeyboardDevice->RepeatPollingHandle) {
|
|
mUsbCore->RemovePeriodicTimer(
|
|
UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
UsbKeyboardDevice->RepeatPollingHandle = NULL;
|
|
}
|
|
//
|
|
// sets trigger time to "Repeat Delay Time",
|
|
// to trigger the repeat timer when the key is hold long
|
|
// enough time.
|
|
//
|
|
mUsbCore->InsertPeriodicTimer(
|
|
USB_CORE_ONCE_TIMER,
|
|
UsbKeyboardRepeatHandler,
|
|
UsbKeyboardDevice,
|
|
USBKBD_REPEAT_DELAY,
|
|
&UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
UsbKeyboardDevice->RepeatKey = NewRepeatKey;
|
|
}
|
|
Exit:
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
Convert USB key code to KBC scan code
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param Key USB key code
|
|
|
|
@retval KBC scan code
|
|
|
|
**/
|
|
STATIC
|
|
UINT16
|
|
ConvertKbcScanCode (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 Key
|
|
)
|
|
{
|
|
UINT16 KbcScanCode;
|
|
|
|
if (Key < 4 || Key >= (sizeof (KbcCodeTable) / 4) + 4) return 0;
|
|
if (UsbKeyboardDevice->AltOn) {
|
|
KbcScanCode = KbcCodeTable[Key - 4][2];
|
|
} else if (UsbKeyboardDevice->CtrlOn) {
|
|
KbcScanCode = KbcCodeTable[Key - 4][3];
|
|
} else if (UsbKeyboardDevice->ShiftOn) {
|
|
KbcScanCode = KbcCodeTable[Key - 4][1];
|
|
} else {
|
|
KbcScanCode = KbcCodeTable[Key - 4][0];
|
|
if (KbcScanCode == 0x57 || KbcScanCode == 0x58) {
|
|
//
|
|
// Convert F11/F12 to KBC converted code
|
|
//
|
|
KbcScanCode = 0x85 + (KbcScanCode - 0x57);
|
|
} else if (KbcScanCode >= 0x82) {
|
|
//
|
|
// Double code key
|
|
//
|
|
KbcScanCode &= ~0x80;
|
|
KbcScanCode <<= 8;
|
|
KbcScanCode |= 0xE0;
|
|
}
|
|
}
|
|
return KbcScanCode;
|
|
}
|
|
|
|
/**
|
|
|
|
Retrieves a key character after parsing the raw data in keyboard buffer.
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param KeyChar Points to the Key character after key parsing.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval EFI_NOT_READY Device is not ready
|
|
|
|
**/
|
|
EFI_STATUS
|
|
UsbParseKey (
|
|
IN OUT USB_KB_DEV *UsbKeyboardDevice,
|
|
OUT UINT8 *KeyChar
|
|
)
|
|
{
|
|
USB_KEY UsbKey;
|
|
EFI_KEY_DESCRIPTOR *KeyDescriptor = NULL;
|
|
|
|
*KeyChar = 0;
|
|
|
|
while (!IsQueueEmpty (&UsbKeyboardDevice->UsbKeyQueue)) {
|
|
//
|
|
// pops one raw data off.
|
|
//
|
|
Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
|
|
|
|
KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);
|
|
if (KeyDescriptor == NULL) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
if (!UsbKey.Down) {
|
|
|
|
switch (KeyDescriptor->Modifier) {
|
|
|
|
//
|
|
// Ctrl release
|
|
//
|
|
case EFI_LEFT_CONTROL_MODIFIER:
|
|
UsbKeyboardDevice->LeftCtrlOn = 0;
|
|
UsbKeyboardDevice->CtrlOn = 0;
|
|
break;
|
|
case EFI_RIGHT_CONTROL_MODIFIER:
|
|
UsbKeyboardDevice->RightCtrlOn = 0;
|
|
UsbKeyboardDevice->CtrlOn = 0;
|
|
break;
|
|
|
|
//
|
|
// Shift release
|
|
//
|
|
case EFI_LEFT_SHIFT_MODIFIER:
|
|
UsbKeyboardDevice->LeftShiftOn = 0;
|
|
UsbKeyboardDevice->ShiftOn = 0;
|
|
break;
|
|
case EFI_RIGHT_SHIFT_MODIFIER:
|
|
UsbKeyboardDevice->RightShiftOn = 0;
|
|
UsbKeyboardDevice->ShiftOn = 0;
|
|
break;
|
|
|
|
//
|
|
// Alt release
|
|
//
|
|
case EFI_LEFT_ALT_MODIFIER:
|
|
UsbKeyboardDevice->LeftAltOn = 0;
|
|
UsbKeyboardDevice->AltOn = 0;
|
|
break;
|
|
case EFI_RIGHT_ALT_MODIFIER:
|
|
UsbKeyboardDevice->RightAltOn = 0;
|
|
UsbKeyboardDevice->AltOn = 0;
|
|
break;
|
|
|
|
//
|
|
// Left Logo release
|
|
//
|
|
case EFI_LEFT_LOGO_MODIFIER:
|
|
UsbKeyboardDevice->LeftLogoOn = 0;
|
|
break;
|
|
|
|
//
|
|
// Right Logo release
|
|
//
|
|
case EFI_RIGHT_LOGO_MODIFIER:
|
|
UsbKeyboardDevice->RightLogoOn = 0;
|
|
break;
|
|
|
|
//
|
|
// Menu key release
|
|
//
|
|
case EFI_MENU_MODIFIER:
|
|
UsbKeyboardDevice->MenuKeyOn = 0;
|
|
break;
|
|
|
|
//
|
|
// SysReq release
|
|
//
|
|
case EFI_PRINT_MODIFIER:
|
|
case EFI_SYS_REQUEST_MODIFIER:
|
|
UsbKeyboardDevice->SysReqOn = 0;
|
|
break;
|
|
|
|
//
|
|
// AltGr release
|
|
//
|
|
case EFI_ALT_GR_MODIFIER:
|
|
UsbKeyboardDevice->AltGrOn = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Analyzes key pressing situation
|
|
//
|
|
switch (KeyDescriptor->Modifier) {
|
|
|
|
//
|
|
// Ctrl press
|
|
//
|
|
case EFI_LEFT_CONTROL_MODIFIER:
|
|
UsbKeyboardDevice->LeftCtrlOn = 1;
|
|
UsbKeyboardDevice->CtrlOn = 1;
|
|
break;
|
|
case EFI_RIGHT_CONTROL_MODIFIER:
|
|
UsbKeyboardDevice->RightCtrlOn = 1;
|
|
UsbKeyboardDevice->CtrlOn = 1;
|
|
break;
|
|
|
|
//
|
|
// Shift press
|
|
//
|
|
case EFI_LEFT_SHIFT_MODIFIER:
|
|
UsbKeyboardDevice->LeftShiftOn = 1;
|
|
UsbKeyboardDevice->ShiftOn = 1;
|
|
break;
|
|
case EFI_RIGHT_SHIFT_MODIFIER:
|
|
UsbKeyboardDevice->RightShiftOn = 1;
|
|
UsbKeyboardDevice->ShiftOn = 1;
|
|
break;
|
|
|
|
//
|
|
// Alt press
|
|
//
|
|
case EFI_LEFT_ALT_MODIFIER:
|
|
UsbKeyboardDevice->LeftAltOn = 1;
|
|
UsbKeyboardDevice->AltOn = 1;
|
|
break;
|
|
case EFI_RIGHT_ALT_MODIFIER:
|
|
UsbKeyboardDevice->RightAltOn = 1;
|
|
UsbKeyboardDevice->AltOn = 1;
|
|
break;
|
|
|
|
//
|
|
// Left Logo press
|
|
//
|
|
case EFI_LEFT_LOGO_MODIFIER:
|
|
UsbKeyboardDevice->LeftLogoOn = 1;
|
|
break;
|
|
|
|
//
|
|
// Right Logo press
|
|
//
|
|
case EFI_RIGHT_LOGO_MODIFIER:
|
|
UsbKeyboardDevice->RightLogoOn = 1;
|
|
break;
|
|
|
|
//
|
|
// Menu key press
|
|
//
|
|
case EFI_MENU_MODIFIER:
|
|
UsbKeyboardDevice->MenuKeyOn = 1;
|
|
break;
|
|
|
|
//
|
|
// SysReq press
|
|
//
|
|
case EFI_PRINT_MODIFIER:
|
|
case EFI_SYS_REQUEST_MODIFIER:
|
|
UsbKeyboardDevice->SysReqOn = 1;
|
|
break;
|
|
|
|
//
|
|
// AltGr press
|
|
//
|
|
case EFI_ALT_GR_MODIFIER:
|
|
UsbKeyboardDevice->AltGrOn = 1;
|
|
break;
|
|
|
|
case EFI_NUM_LOCK_MODIFIER:
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
if (!PS2_LED_UPDATING) {
|
|
USB_LED_UPDATE;
|
|
UsbKeyboardDevice->NumLockOn ^= 1;
|
|
SetKeyLED (UsbKeyboardDevice);
|
|
if (mUsbCore->IsKbcExist() == EFI_NOT_FOUND) {
|
|
mUsbCore->SyncKbdLed();
|
|
}
|
|
USB_LED_UPDATED;
|
|
}
|
|
} else {
|
|
UsbKeyboardDevice->NumLockOn ^= 1;
|
|
UsbKeyboardCheckLEDHandler(0, UsbKeyboardDevice);
|
|
}
|
|
break;
|
|
|
|
case EFI_CAPS_LOCK_MODIFIER:
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
if (!PS2_LED_UPDATING) {
|
|
USB_LED_UPDATE;
|
|
UsbKeyboardDevice->CapsOn ^= 1;
|
|
SetKeyLED (UsbKeyboardDevice);
|
|
if (mUsbCore->IsKbcExist() == EFI_NOT_FOUND) {
|
|
mUsbCore->SyncKbdLed();
|
|
}
|
|
USB_LED_UPDATED;
|
|
}
|
|
} else {
|
|
UsbKeyboardDevice->CapsOn ^= 1;
|
|
UsbKeyboardCheckLEDHandler(0, UsbKeyboardDevice);
|
|
}
|
|
break;
|
|
|
|
case EFI_SCROLL_LOCK_MODIFIER:
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
if (!PS2_LED_UPDATING) {
|
|
USB_LED_UPDATE;
|
|
UsbKeyboardDevice->ScrollOn ^= 1;
|
|
SetKeyLED (UsbKeyboardDevice);
|
|
if (mUsbCore->IsKbcExist() == EFI_NOT_FOUND) {
|
|
mUsbCore->SyncKbdLed();
|
|
}
|
|
USB_LED_UPDATED;
|
|
}
|
|
} else {
|
|
UsbKeyboardDevice->ScrollOn ^= 1;
|
|
UsbKeyboardCheckLEDHandler(0, UsbKeyboardDevice);
|
|
}
|
|
break;
|
|
|
|
case EFI_NULL_MODIFIER:
|
|
//
|
|
// Special IME for French Layout keyboard
|
|
//
|
|
if (CompareGuid (&UsbKeyboardDevice->CurrentLayoutGuid, &gH2OUsbKeyboardFrenchLayoutKeyGuid)) {
|
|
if (KeyDescriptor->Key == EfiKeyD11) {
|
|
if (UsbKeyboardDevice->ShiftOn) {
|
|
if (UsbKeyboardDevice->CircumflexAccentShiftedOn == 0) {
|
|
UsbKeyboardDevice->CircumflexAccentShiftedOn = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
if (UsbKeyboardDevice->CircumflexAccentOn == 0) {
|
|
UsbKeyboardDevice->CircumflexAccentOn = 1;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
if ((KeyDescriptor->Key == EfiKeyE2) &&
|
|
(UsbKeyboardDevice->AltGrOn)) {
|
|
if (UsbKeyboardDevice->TildeOn == 0) {
|
|
UsbKeyboardDevice->TildeOn = 1;
|
|
continue;
|
|
}
|
|
}
|
|
if ((KeyDescriptor->Key == EfiKeyE7) &&
|
|
(UsbKeyboardDevice->AltGrOn)) {
|
|
if (UsbKeyboardDevice->GraveAccentOn == 0) {
|
|
UsbKeyboardDevice->GraveAccentOn = 1;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// When encountered Del Key...
|
|
//
|
|
if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {
|
|
if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {
|
|
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, KEYBOARD_RESET_SIGNATURE);
|
|
//
|
|
// Return EFI_NOT_READY in case some OEM feature ignore the reset in purposely through hook the ResetSystem function
|
|
//
|
|
return EFI_NOT_READY;
|
|
}
|
|
}
|
|
|
|
*KeyChar = UsbKey.KeyCode;
|
|
if ((mUsbCore->IsCsmEnabled() == EFI_SUCCESS) && (UsbKey.Down) && (UsbKey.KeyCode < 0xe0) && (UsbKey.KeyCode != 0x46) && (UsbKey.KeyCode != 0x48)) {
|
|
//
|
|
// Put the KBC scan code into EBDA+0x164. The PrntScrn and Pause will be filter out to sync with PS2 path
|
|
//
|
|
*(UINT16*)&(EBDA(EBDA_KEYBORD_SCAN_CODE)) = ConvertKbcScanCode (UsbKeyboardDevice, UsbKey.KeyCode);
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_NOT_READY;
|
|
|
|
}
|
|
|
|
/**
|
|
Initialize the key state.
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param KeyState A pointer to receive the key state information.
|
|
**/
|
|
VOID
|
|
InitializeKeyState (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
OUT EFI_KEY_STATE *KeyState
|
|
)
|
|
{
|
|
KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;
|
|
KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;
|
|
|
|
if (UsbKeyboardDevice->LeftCtrlOn) {
|
|
KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->RightCtrlOn) {
|
|
KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->LeftAltOn) {
|
|
KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->RightAltOn) {
|
|
KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->LeftShiftOn) {
|
|
KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->RightShiftOn) {
|
|
KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->LeftLogoOn) {
|
|
KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->RightLogoOn) {
|
|
KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->MenuKeyOn) {
|
|
KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;
|
|
}
|
|
if (UsbKeyboardDevice->SysReqOn) {
|
|
KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->ScrollOn) {
|
|
KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
|
|
}
|
|
if (UsbKeyboardDevice->NumLockOn) {
|
|
KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
|
|
}
|
|
if (UsbKeyboardDevice->CapsOn) {
|
|
KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
|
|
}
|
|
if (UsbKeyboardDevice->IsSupportPartialKey) {
|
|
KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;
|
|
}
|
|
}
|
|
|
|
/**
|
|
|
|
Converts USB Keyboard code to EFI Scan Code.
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
@param KeyChar Indicates the key code that will be interpreted.
|
|
@param Key A pointer to a buffer that is filled in with
|
|
the keystroke information for the key that
|
|
was pressed.
|
|
|
|
@retval EFI_NOT_READY Device is not ready
|
|
@retval EFI_SUCCESS Success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
UsbKeyCodeToEFIScanCode (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 KeyChar,
|
|
OUT EFI_INPUT_KEY *Key
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
EFI_KEY_DESCRIPTOR *KeyDescriptor = NULL;
|
|
|
|
if (!USBKBD_VALID_KEYCODE (KeyChar)) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyChar);
|
|
if (KeyDescriptor == NULL) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {
|
|
//
|
|
// If this is a dead key with EFI_NS_KEY_MODIFIER, then record it and return.
|
|
//
|
|
UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->CurrentNsKey != NULL) {
|
|
//
|
|
// If this keystroke follows a non-spacing key, then find the descriptor for corresponding
|
|
// physical key.
|
|
//
|
|
KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);
|
|
UsbKeyboardDevice->CurrentNsKey = NULL;
|
|
}
|
|
|
|
//
|
|
// Make sure modifier of Key Descriptor is in the valid range according to UEFI spec.
|
|
//
|
|
if (KeyDescriptor->Modifier >= (sizeof (ModifierValueToEfiScanCodeConvertionTable) / sizeof (UINT8))) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
if ((KeyChar >= 0xe0) && (KeyChar <= 0xe7)) {
|
|
//
|
|
// For Partial Keystroke support
|
|
//
|
|
Key->ScanCode = SCAN_NULL;
|
|
Key->UnicodeChar = CHAR_NULL;
|
|
} else {
|
|
|
|
Key->ScanCode = ModifierValueToEfiScanCodeConvertionTable[KeyDescriptor->Modifier];
|
|
Key->UnicodeChar = KeyDescriptor->Unicode;
|
|
|
|
if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT)!= 0) {
|
|
if (UsbKeyboardDevice->ShiftOn) {
|
|
Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
|
|
|
|
//
|
|
// Need not return associated shift state if a class of printable characters that
|
|
// are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
|
|
//
|
|
if ((KeyDescriptor->Unicode != CHAR_NULL) && (KeyDescriptor->ShiftedUnicode != CHAR_NULL) &&
|
|
(KeyDescriptor->Unicode != KeyDescriptor->ShiftedUnicode)) {
|
|
UsbKeyboardDevice->LeftShiftOn = FALSE;
|
|
UsbKeyboardDevice->RightShiftOn = FALSE;
|
|
}
|
|
if (UsbKeyboardDevice->AltGrOn) {
|
|
Key->UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;
|
|
}
|
|
} else {
|
|
//
|
|
// Shift off
|
|
//
|
|
Key->UnicodeChar = KeyDescriptor->Unicode;
|
|
|
|
if (UsbKeyboardDevice->AltGrOn) {
|
|
Key->UnicodeChar = KeyDescriptor->AltGrUnicode;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {
|
|
if (UsbKeyboardDevice->CapsOn) {
|
|
if (Key->UnicodeChar == KeyDescriptor->Unicode) {
|
|
Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;
|
|
} else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {
|
|
Key->UnicodeChar = KeyDescriptor->Unicode;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (UsbKeyboardDevice->CtrlOn) {
|
|
for (Index = 0; Index < sizeof (CtrlIgnoreKey); Index++) {
|
|
if (KeyChar == CtrlIgnoreKey[Index]) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (UsbKeyboardDevice->CircumflexAccentShiftedOn) {
|
|
UsbKeyboardDevice->CircumflexAccentShiftedOn += 1;
|
|
if (Key->UnicodeChar == 'a') {
|
|
Key->UnicodeChar = 0xE4;
|
|
} else if (Key->UnicodeChar == 'e') {
|
|
Key->UnicodeChar = 0xEB;
|
|
} else if (Key->UnicodeChar == 'i') {
|
|
Key->UnicodeChar = 0xEF;
|
|
} else if (Key->UnicodeChar == 'o') {
|
|
Key->UnicodeChar = 0xF6;
|
|
} else if (Key->UnicodeChar == 'u') {
|
|
Key->UnicodeChar = 0xFC;
|
|
} else if (Key->UnicodeChar == 'y') {
|
|
Key->UnicodeChar = 0xFF;
|
|
} else if (Key->UnicodeChar == 'A') {
|
|
Key->UnicodeChar = 0xC4;
|
|
} else if (Key->UnicodeChar == 'E') {
|
|
Key->UnicodeChar = 0xCB;
|
|
} else if (Key->UnicodeChar == 'I') {
|
|
Key->UnicodeChar = 0xCF;
|
|
} else if (Key->UnicodeChar == 'O') {
|
|
Key->UnicodeChar = 0xD6;
|
|
} else if (Key->UnicodeChar == 'U') {
|
|
Key->UnicodeChar = 0xDC;
|
|
} else {
|
|
Key->UnicodeChar = 0xA8;
|
|
}
|
|
if (UsbKeyboardDevice->CircumflexAccentShiftedOn > 3)
|
|
UsbKeyboardDevice->CircumflexAccentShiftedOn = 0;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->CircumflexAccentOn) {
|
|
UsbKeyboardDevice->CircumflexAccentOn += 1;
|
|
if (Key->UnicodeChar == 'a') {
|
|
Key->UnicodeChar = 0xE2;
|
|
} else if (Key->UnicodeChar == 'e') {
|
|
Key->UnicodeChar = 0xEA;
|
|
} else if (Key->UnicodeChar == 'i') {
|
|
Key->UnicodeChar = 0xEE;
|
|
} else if (Key->UnicodeChar == 'o') {
|
|
Key->UnicodeChar = 0xF4;
|
|
} else if (Key->UnicodeChar == 'u') {
|
|
Key->UnicodeChar = 0xFB;
|
|
} else if (Key->UnicodeChar == 'A') {
|
|
Key->UnicodeChar = 0xC2;
|
|
} else if (Key->UnicodeChar == 'E') {
|
|
Key->UnicodeChar = 0xCA;
|
|
} else if (Key->UnicodeChar == 'I') {
|
|
Key->UnicodeChar = 0xCE;
|
|
} else if (Key->UnicodeChar == 'O') {
|
|
Key->UnicodeChar = 0xD4;
|
|
} else if (Key->UnicodeChar == 'U') {
|
|
Key->UnicodeChar = 0xDB;
|
|
} else {
|
|
Key->UnicodeChar = '^';
|
|
}
|
|
if (UsbKeyboardDevice->CircumflexAccentOn > 3)
|
|
UsbKeyboardDevice->CircumflexAccentOn = 0;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->TildeOn) {
|
|
UsbKeyboardDevice->TildeOn += 1;
|
|
if (Key->UnicodeChar == 'a') {
|
|
Key->UnicodeChar = 0xE3;
|
|
} else if (Key->UnicodeChar == 'A') {
|
|
Key->UnicodeChar = 0xC3;
|
|
} else if (Key->UnicodeChar == 'n') {
|
|
Key->UnicodeChar = 0xF1;
|
|
} else if (Key->UnicodeChar == 'N') {
|
|
Key->UnicodeChar = 0xD1;
|
|
} else if (Key->UnicodeChar == 'o') {
|
|
Key->UnicodeChar = 0xF5;
|
|
} else if (Key->UnicodeChar == 'O') {
|
|
Key->UnicodeChar = 0xD5;
|
|
} else {
|
|
Key->UnicodeChar = '~';
|
|
}
|
|
if (UsbKeyboardDevice->TildeOn > 3)
|
|
UsbKeyboardDevice->TildeOn = 0;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->GraveAccentOn) {
|
|
UsbKeyboardDevice->GraveAccentOn += 1;
|
|
if (Key->UnicodeChar == 'a') {
|
|
Key->UnicodeChar = 0xE0;
|
|
} else if (Key->UnicodeChar == 'e') {
|
|
Key->UnicodeChar = 0xE8;
|
|
} else if (Key->UnicodeChar == 'i') {
|
|
Key->UnicodeChar = 0xEC;
|
|
} else if (Key->UnicodeChar == 'o') {
|
|
Key->UnicodeChar = 0xF2;
|
|
} else if (Key->UnicodeChar == 'u') {
|
|
Key->UnicodeChar = 0xF9;
|
|
} else if (Key->UnicodeChar == 'A') {
|
|
Key->UnicodeChar = 0xC0;
|
|
} else if (Key->UnicodeChar == 'E') {
|
|
Key->UnicodeChar = 0xC8;
|
|
} else if (Key->UnicodeChar == 'I') {
|
|
Key->UnicodeChar = 0xCC;
|
|
} else if (Key->UnicodeChar == 'O') {
|
|
Key->UnicodeChar = 0xD2;
|
|
} else if (Key->UnicodeChar == 'U') {
|
|
Key->UnicodeChar = 0xD9;
|
|
} else {
|
|
Key->UnicodeChar = 0x60;
|
|
}
|
|
if (UsbKeyboardDevice->GraveAccentOn> 3)
|
|
UsbKeyboardDevice->GraveAccentOn = 0;
|
|
}
|
|
|
|
if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) != 0) {
|
|
//
|
|
// For key affected by NumLock, if NumLock is on and Shift is not pressed, then it means
|
|
// normal key, instead of original control key. So the ScanCode should be cleaned.
|
|
// Otherwise, it means control key, so preserve the EFI Scan Code and clear the unicode keycode.
|
|
//
|
|
if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {
|
|
Key->ScanCode = SCAN_NULL;
|
|
} else {
|
|
Key->UnicodeChar = CHAR_NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Translate Unicode 0x1B (ESC) to EFI Scan Code
|
|
//
|
|
if (Key->UnicodeChar == 0x1B && Key->ScanCode == SCAN_NULL) {
|
|
Key->ScanCode = SCAN_ESC;
|
|
Key->UnicodeChar = CHAR_NULL;
|
|
}
|
|
|
|
if (UsbKeyboardDevice->AltOn) {
|
|
for (Index = 0; Index < sizeof (AltIgnoreKey); Index++) {
|
|
if (KeyChar == AltIgnoreKey[Index]) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Alt + numpad 1~9
|
|
//
|
|
if (KeyChar >= 0x59 && KeyChar <= 0x61) {
|
|
Key->UnicodeChar = KeyDescriptor->Unicode;
|
|
|
|
if (Key->UnicodeChar >= '1' && Key->UnicodeChar <= '9') {
|
|
Key->UnicodeChar = Key->UnicodeChar - '1' + 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Alt + (Up, Down, Left, Right)
|
|
//
|
|
if (Key->ScanCode >= SCAN_UP && Key->ScanCode <= SCAN_PAGE_DOWN) {
|
|
Key->ScanCode = SCAN_NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
|
|
if (!UsbKeyboardDevice->IsSupportPartialKey) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
}
|
|
//
|
|
// Save Shift/Toggle state
|
|
//
|
|
InitializeKeyState (UsbKeyboardDevice, &UsbKeyboardDevice->KeyState);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Create USB keyboard device buffer.
|
|
|
|
@return The USB keyboard device buffer pointer or NULL if allocate buffer failed.
|
|
**/
|
|
USB_KB_DEV *
|
|
CreateUsbKeyboardDeviceBuffer (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Allocate enough buffer to store USB_KB_DEV and key queues (UsbKey, EfiKey, and EfiKeyForNotify).
|
|
//
|
|
Status = mUsbCore->AllocateBuffer (
|
|
USB_KB_DEV_BUFFER_SIZE,
|
|
ALIGNMENT_32,
|
|
(VOID **)&UsbKeyboardDevice
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
UsbKeyboardDevice->UsbKeyQueue.Buffer[0] = ((UINT8 *) UsbKeyboardDevice) + sizeof(USB_KB_DEV);
|
|
UsbKeyboardDevice->EfiKeyQueue.Buffer[0] = ((UINT8 *) UsbKeyboardDevice->UsbKeyQueue.Buffer[0]) + (MAX_KEY_ALLOWED + 1) * sizeof(USB_KEY);
|
|
UsbKeyboardDevice->EfiKeyQueueForNotify.Buffer[0] = ((UINT8 *) UsbKeyboardDevice->EfiKeyQueue.Buffer[0]) + (MAX_KEY_ALLOWED + 1) * sizeof(EFI_KEY_DATA);
|
|
|
|
for (Index = 1; Index < (MAX_KEY_ALLOWED + 1); Index++) {
|
|
UsbKeyboardDevice->UsbKeyQueue.Buffer[Index] = ((UINT8 *) UsbKeyboardDevice->UsbKeyQueue.Buffer[Index - 1] ) + sizeof(USB_KEY);
|
|
UsbKeyboardDevice->EfiKeyQueue.Buffer[Index] = ((UINT8 *) UsbKeyboardDevice->EfiKeyQueue.Buffer[Index - 1] ) + sizeof(EFI_KEY_DATA);
|
|
UsbKeyboardDevice->EfiKeyQueueForNotify.Buffer[Index] = ((UINT8 *) UsbKeyboardDevice->EfiKeyQueueForNotify.Buffer[Index - 1]) + sizeof(EFI_KEY_DATA);
|
|
}
|
|
|
|
return UsbKeyboardDevice;
|
|
}
|
|
|
|
/**
|
|
Create the queue.
|
|
|
|
@param Queue Points to the queue.
|
|
@param ItemSize Size of the single item.
|
|
|
|
**/
|
|
VOID
|
|
InitQueue (
|
|
IN OUT USB_SIMPLE_QUEUE *Queue,
|
|
IN UINTN ItemSize
|
|
)
|
|
{
|
|
Queue->ItemSize = ItemSize;
|
|
Queue->Head = 0;
|
|
Queue->Tail = 0;
|
|
|
|
ZeroMem (Queue->Buffer[0], (MAX_KEY_ALLOWED + 1) * ItemSize);
|
|
}
|
|
|
|
/**
|
|
Check whether the queue is empty.
|
|
|
|
@param Queue Points to the queue.
|
|
|
|
@retval TRUE Queue is empty.
|
|
@retval FALSE Queue is not empty.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsQueueEmpty (
|
|
IN USB_SIMPLE_QUEUE *Queue
|
|
)
|
|
{
|
|
//
|
|
// Meet FIFO empty condition
|
|
//
|
|
return (BOOLEAN) (Queue->Head == Queue->Tail);
|
|
}
|
|
|
|
/**
|
|
Check whether the queue is full.
|
|
|
|
@param Queue Points to the queue.
|
|
|
|
@retval TRUE Queue is full.
|
|
@retval FALSE Queue is not full.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsQueueFull (
|
|
IN USB_SIMPLE_QUEUE *Queue
|
|
)
|
|
{
|
|
return (BOOLEAN) (((Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1)) == Queue->Head);
|
|
}
|
|
|
|
/**
|
|
Enqueue the item to the queue.
|
|
|
|
@param Queue Points to the queue.
|
|
@param Item Points to the item to be enqueued.
|
|
@param ItemSize Size of the item.
|
|
**/
|
|
VOID
|
|
Enqueue (
|
|
IN OUT USB_SIMPLE_QUEUE *Queue,
|
|
IN VOID *Item,
|
|
IN UINTN ItemSize
|
|
)
|
|
{
|
|
ASSERT (ItemSize == Queue->ItemSize);
|
|
//
|
|
// If keyboard buffer is full, throw the
|
|
// first key out of the keyboard buffer.
|
|
//
|
|
if (IsQueueFull (Queue)) {
|
|
Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
|
|
}
|
|
|
|
CopyMem (Queue->Buffer[Queue->Tail], Item, ItemSize);
|
|
|
|
//
|
|
// Adjust the tail pointer of the FIFO keyboard buffer.
|
|
//
|
|
Queue->Tail = (Queue->Tail + 1) % (MAX_KEY_ALLOWED + 1);
|
|
}
|
|
|
|
/**
|
|
Dequeue a item from the queue.
|
|
|
|
@param Queue Points to the queue.
|
|
@param Item Receives the item.
|
|
@param ItemSize Size of the item.
|
|
|
|
@retval EFI_SUCCESS Item was successfully dequeued.
|
|
@retval EFI_DEVICE_ERROR The queue is empty.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
Dequeue (
|
|
IN OUT USB_SIMPLE_QUEUE *Queue,
|
|
OUT VOID *Item,
|
|
IN UINTN ItemSize
|
|
)
|
|
{
|
|
ASSERT (Queue->ItemSize == ItemSize);
|
|
|
|
if (IsQueueEmpty (Queue)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
CopyMem (Item, Queue->Buffer[Queue->Head], ItemSize);
|
|
|
|
//
|
|
// Adjust the head pointer of the FIFO keyboard buffer.
|
|
//
|
|
Queue->Head = (Queue->Head + 1) % (MAX_KEY_ALLOWED + 1);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Sets monitor keys for SCU (SETUP_HOT_KEY / BOOT_MANAGER_HOT_KEY...)
|
|
|
|
@param KeyboardBuffer Points to the USB Keyboard Buffer.
|
|
@param Key Key code
|
|
|
|
**/
|
|
VOID
|
|
SetMonitorKey (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 Key
|
|
)
|
|
{
|
|
UINT8 *FilterKeyList;
|
|
UINT8 ModKey;
|
|
UINTN Index;
|
|
UINTN BitIndex;
|
|
UINT16 KbcScanCode;
|
|
//
|
|
// Skip if no MonitorKey installed
|
|
//
|
|
if (EBDA(EBDA_MONITOR_KEY_TABLE) != 0x55 || Key >= 0xe0) return;
|
|
//
|
|
// Convert USB key code to KBC key code
|
|
//
|
|
KbcScanCode = ConvertKbcScanCode (UsbKeyboardDevice, Key);
|
|
if ((KbcScanCode & 0xff) == 0xe0) {
|
|
//
|
|
// To synchronize with CSM16, covert the scan code of "Enter KP" (0xe0, 0x1c) or "/ KP" (0xe0, 0x35)
|
|
// to invalid code (0xe0) and needn't covert other double code to single code.
|
|
//
|
|
KbcScanCode >>= 8;
|
|
if ((UINT8) KbcScanCode == 0x1c || (UINT8) KbcScanCode == 0x35) {
|
|
KbcScanCode = 0xe0;
|
|
}
|
|
}
|
|
//
|
|
// Get FilterKeyList pointer
|
|
//
|
|
FilterKeyList = (UINT8*)(UINTN)((*(UINT16*)&(EBDA(EBDA_MONITOR_KEY_TABLE + 3)) << 4) + *(UINT16*)&(EBDA(EBDA_MONITOR_KEY_TABLE + 1)));
|
|
for (Index = 0, BitIndex = 0; FilterKeyList[Index] != 0; Index += 3, BitIndex ++) {
|
|
if (FilterKeyList[Index] == (UINT8)KbcScanCode) {
|
|
//
|
|
// Also checks Shift/Alt/Ctrl keys
|
|
//
|
|
if ((ModKey = FilterKeyList[Index + 1]) != 0) {
|
|
if (((ModKey & 0x01) && !UsbKeyboardDevice->ShiftOn) ||
|
|
((ModKey & 0x02) && !UsbKeyboardDevice->AltOn) ||
|
|
((ModKey & 0x04) && !UsbKeyboardDevice->CtrlOn)) {
|
|
continue;
|
|
}
|
|
}
|
|
*(UINT32*)&(EBDA(EBDA_MONITOR_KEY_TABLE + 5)) |= (1 << BitIndex);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
|
|
Sync the control key status to CSM environment
|
|
|
|
@param KeyboardBuffer Points to the USB Keyboard Buffer.
|
|
@param Key Key code
|
|
@param Down Special key
|
|
|
|
@retval EFI_SUCCESS Success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SyncEfiKeyToCsmkey (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 KeyCode,
|
|
IN UINT8 Down
|
|
)
|
|
{
|
|
QUALIFIER_STAT *QualifierStat;
|
|
|
|
QualifierStat = (QUALIFIER_STAT*)(UINTN)(BDA_QUALIFIER_STAT);
|
|
|
|
switch (KeyCode) {
|
|
case 0xe1:
|
|
if (Down) {
|
|
QualifierStat->LeftShift = 1;
|
|
} else {
|
|
QualifierStat->LeftShift = 0;
|
|
}
|
|
break;
|
|
case 0xe5:
|
|
if (Down) {
|
|
QualifierStat->RightShift = 1;
|
|
} else {
|
|
QualifierStat->RightShift = 0;
|
|
}
|
|
break;
|
|
|
|
case 0xe0:
|
|
case 0xe4:
|
|
if (Down) {
|
|
QualifierStat->Ctrl = 1;
|
|
} else {
|
|
QualifierStat->Ctrl = 0;
|
|
}
|
|
break;
|
|
|
|
case 0xe2:
|
|
case 0xe6:
|
|
if (Down) {
|
|
QualifierStat->Alt = 1;
|
|
} else {
|
|
QualifierStat->Alt = 0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Sync the control key status to EFI environment
|
|
|
|
@param KeyboardBuffer Points to the USB Keyboard Buffer.
|
|
@param Key Key code
|
|
@param Down Special key
|
|
|
|
@retval EFI_SUCCESS Success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SyncCsmKeyToEfikey (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 KeyCode,
|
|
IN UINT8 Down
|
|
)
|
|
{
|
|
USB_KEY UsbKey;
|
|
|
|
UsbKey.KeyCode = KeyCode;
|
|
UsbKey.Down = Down;
|
|
Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Inserts a key code into keyboard buffer.
|
|
|
|
@param KeyboardBuffer Points to the USB Keyboard Buffer.
|
|
@param Key Key code
|
|
@param Down Special key
|
|
|
|
@retval EFI_SUCCESS Success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
InsertKeyCode (
|
|
IN USB_KB_DEV *UsbKeyboardDevice,
|
|
IN UINT8 Key,
|
|
IN UINT8 Down
|
|
)
|
|
{
|
|
USB_KEY UsbKey;
|
|
UINT8 KbcKeyCode[4];
|
|
UINTN Mode;
|
|
EFI_STATUS IsCsmEnabled;
|
|
|
|
if (!USBKBD_VALID_KEYCODE (Key)) return EFI_NOT_FOUND;
|
|
mUsbCore->GetMode(&Mode);
|
|
IsCsmEnabled = mUsbCore->IsCsmEnabled();
|
|
//
|
|
// Ignore LED update if it is updating by Int9
|
|
//
|
|
if (IsCsmEnabled == EFI_SUCCESS && PS2_LED_UPDATING && (Key == 0x53 || Key == 0x39 || Key == 0x47)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
if ((IsCsmEnabled != EFI_SUCCESS) || (Mode != USB_CORE_RUNTIME_MODE && EBDA(EBDA_OPROM_PROCESSING_FLAG) == 0 && !PAUSE_IN_PROGRESS && (mUsbCore->IsKbcExist() == EFI_NOT_FOUND || Key != 0x48))) {
|
|
UsbKey.KeyCode = Key;
|
|
UsbKey.Down = Down;
|
|
Enqueue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));
|
|
|
|
//
|
|
// Sets monitor keys for SCU (SETUP_HOT_KEY / BOOT_MANAGER_HOT_KEY...)
|
|
//
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
SetMonitorKey(UsbKeyboardDevice, Key);
|
|
if (Key >= 0xe0) {
|
|
SyncEfiKeyToCsmkey (UsbKeyboardDevice, Key, Down);
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// Insert KBC code for legacy mode
|
|
//
|
|
if (Key >= 0xe0) {
|
|
if (Mode != USB_CORE_RUNTIME_MODE) {
|
|
SyncCsmKeyToEfikey (UsbKeyboardDevice, Key, Down);
|
|
}
|
|
KbcKeyCode[0] = KbcModCodeTable[Key - 0xe0];
|
|
} else if (Key >= 4 && Key < (sizeof (KbcCodeTable) / 4) + 4) {
|
|
KbcKeyCode[0] = KbcCodeTable[Key - 4][0];
|
|
} else if (Key >= 0x87 && Key < 0x8C) {
|
|
KbcKeyCode[0] = KbcCodeTableJp109[Key - 0x87];
|
|
} else {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
if (!(KbcKeyCode[0] & 0x80)) {
|
|
//
|
|
// Single code key
|
|
//
|
|
if (!Down) KbcKeyCode[0] |= 0x80;
|
|
mUsbCore->InsertKbcKeyCode(USB_CORE_KEYBOARD_CODE, KbcKeyCode, 1);
|
|
} else if (KbcKeyCode[0] == 0x80) {
|
|
//
|
|
// PrntScrn
|
|
//
|
|
*(UINT32*)KbcKeyCode = (Down) ? 0x37E02AE0 : 0xAAE0B7E0;
|
|
mUsbCore->InsertKbcKeyCode(USB_CORE_KEYBOARD_CODE, KbcKeyCode, 4);
|
|
} else if (KbcKeyCode[0] == 0x81) {
|
|
//
|
|
// Pause
|
|
//
|
|
*(UINT32*)KbcKeyCode = (Down) ? 0x00451DE1 : 0x00C59DE1;
|
|
mUsbCore->InsertKbcKeyCode(USB_CORE_KEYBOARD_CODE, KbcKeyCode, 3);
|
|
} else {
|
|
//
|
|
// Double code key
|
|
//
|
|
if (Down) KbcKeyCode[0] &= ~0x80;
|
|
KbcKeyCode[1] = KbcKeyCode[0];
|
|
KbcKeyCode[0] = 0xE0;
|
|
mUsbCore->InsertKbcKeyCode(USB_CORE_KEYBOARD_CODE, KbcKeyCode, 2);
|
|
}
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Sets USB Keyboard LED state.
|
|
|
|
@param UsbKeyboardDevice The USB_KB_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetKeyLED (
|
|
IN USB_KB_DEV *UsbKeyboardDevice
|
|
)
|
|
{
|
|
LED_MAP Led;
|
|
QUALIFIER_STAT *QualifierStat;
|
|
|
|
//
|
|
// Set each field in Led map.
|
|
//
|
|
Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;
|
|
Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;
|
|
Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn;
|
|
Led.Resrvd = 0;
|
|
//
|
|
// Make synchronize with BDA qualifier stat
|
|
//
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
QualifierStat = (QUALIFIER_STAT*)(UINTN)(BDA_QUALIFIER_STAT);
|
|
QualifierStat->ScrollLock = Led.ScrollLock;
|
|
QualifierStat->NumLock = Led.NumLock;
|
|
QualifierStat->CapsLock = Led.CapsLock;
|
|
}
|
|
//
|
|
// Only lighten LED if supported
|
|
//
|
|
if (UsbKeyboardDevice->LedSupported) {
|
|
//
|
|
// call Set Report Request to lighten the LED.
|
|
//
|
|
mUsbCore->UsbSetReportRequest (
|
|
UsbKeyboardDevice->UsbIo,
|
|
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
|
|
0,
|
|
HID_OUTPUT_REPORT,
|
|
1,
|
|
(UINT8 *) &Led
|
|
);
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Timer handler for Repeat Key timer.
|
|
|
|
@param Context Points to the USB_KB_DEV instance.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
UsbKeyboardRepeatHandler (
|
|
IN UINTN Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
|
|
UsbKeyboardDevice = (USB_KB_DEV *) Context;
|
|
//
|
|
// Do nothing when there is no repeat key.
|
|
//
|
|
if (UsbKeyboardDevice->RepeatKey != 0) {
|
|
//
|
|
// Inserts one Repeat key into keyboard buffer,
|
|
//
|
|
InsertKeyCode (
|
|
UsbKeyboardDevice,
|
|
UsbKeyboardDevice->RepeatKey,
|
|
1
|
|
);
|
|
//
|
|
// set repeat rate for repeat key generation.
|
|
//
|
|
mUsbCore->InsertPeriodicTimer(
|
|
USB_CORE_ONCE_TIMER,
|
|
UsbKeyboardRepeatHandler,
|
|
UsbKeyboardDevice,
|
|
USBKBD_REPEAT_RATE,
|
|
&UsbKeyboardDevice->RepeatPollingHandle
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
|
|
Timer handler for Delayed Recovery timer.
|
|
|
|
@param Context Points to the USB_KB_DEV instance.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
UsbKeyboardRecoveryHandler (
|
|
IN UINTN Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
|
UINT8 PacketSize;
|
|
|
|
UsbKeyboardDevice = (USB_KB_DEV *) Context;
|
|
|
|
UsbIo = UsbKeyboardDevice->UsbIo;
|
|
|
|
PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
|
|
|
|
UsbAsyncInterruptTransfer (
|
|
UsbIo,
|
|
UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
|
|
TRUE,
|
|
UsbKeyboardDevice->IntEndpointDescriptor.Interval,
|
|
PacketSize,
|
|
KeyboardHandler,
|
|
UsbKeyboardDevice
|
|
);
|
|
}
|
|
|
|
/**
|
|
|
|
Timer handler for Repeat Key timer.
|
|
|
|
@param Context Points to the USB_KB_DEV instance.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
UsbKeyboardCheckLEDHandler (
|
|
IN UINTN ForceSet,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
USB_KB_DEV *UsbKeyboardDevice;
|
|
QUALIFIER_STAT QualifierStat;
|
|
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConSplitterEx;
|
|
EFI_KEY_TOGGLE_STATE KeyToggleState;
|
|
EFI_STATUS Status;
|
|
|
|
UsbKeyboardDevice = (USB_KB_DEV *) Context;
|
|
KeyToggleState = UsbKeyboardDevice->IsSupportPartialKey ? EFI_TOGGLE_STATE_VALID | EFI_KEY_STATE_EXPOSED : EFI_TOGGLE_STATE_VALID;
|
|
if (mUsbCore->IsCsmEnabled() == EFI_SUCCESS) {
|
|
//
|
|
// Get Qualifier Stat in BDA
|
|
//
|
|
QualifierStat = *(QUALIFIER_STAT*)(UINTN)(BDA_QUALIFIER_STAT);
|
|
//
|
|
// Make it synchronization
|
|
//
|
|
if (ForceSet ||
|
|
QualifierStat.ScrollLock != UsbKeyboardDevice->ScrollOn ||
|
|
QualifierStat.NumLock != UsbKeyboardDevice->NumLockOn ||
|
|
QualifierStat.CapsLock != UsbKeyboardDevice->CapsOn) {
|
|
UsbKeyboardDevice->ScrollOn = QualifierStat.ScrollLock;
|
|
UsbKeyboardDevice->NumLockOn = QualifierStat.NumLock;
|
|
UsbKeyboardDevice->CapsOn = QualifierStat.CapsLock;
|
|
SetKeyLED(UsbKeyboardDevice);
|
|
}
|
|
} else {
|
|
if (UsbKeyboardDevice->ScrollOn == 1) {
|
|
KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
|
|
}
|
|
if (UsbKeyboardDevice->NumLockOn == 1) {
|
|
KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
|
|
}
|
|
if (UsbKeyboardDevice->CapsOn == 1) {
|
|
KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
|
|
}
|
|
|
|
if (gST->ConsoleInHandle != NULL) {
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleInHandle,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
(VOID **)&ConSplitterEx
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Update all of ConInEx device State.
|
|
//
|
|
Status = ConSplitterEx->SetState (ConSplitterEx, &KeyToggleState);
|
|
if (Status == EFI_SUCCESS) return;
|
|
}
|
|
}
|
|
//
|
|
// Update USB Keyboard State
|
|
//
|
|
UsbKeyboardDevice->SimpleInputEx.SetState (&UsbKeyboardDevice->SimpleInputEx, &KeyToggleState);
|
|
}
|
|
}
|