diff --git a/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLib.c b/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLib.c index 6bce4c65..d2b01e3a 100644 --- a/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLib.c +++ b/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLib.c @@ -9,10 +9,13 @@ #include #include +#define ARROW_KEY_MODIFIER 0x1000 + CONST CHAR8 *mKeyboardKeyMap[] = { "abcdefghijklmnopqrstuvwxyz1234567890\r\x1b\b\t -=[]\\ ;'`,./", "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()\r\x1b\b\t _+{}| :\"~<>?", - "/*-+\r1234567890." + "/*-+\r1234567890.", + "CDBA" }; USB_KB_DEV mUsbKbDevice; @@ -489,6 +492,44 @@ CheckQueue ( return EFI_SUCCESS; } +/** + Enqueue the key. + + @param Queue The queue to be enqueued. + @param Char The key data to be enqueued. + + @retval EFI_NOT_READY The queue is full. + @retval EFI_UNSUPPORTED The char is invalid. + @retval EFI_SUCCESS Successfully enqueued the key data. + +**/ +EFI_STATUS +EnqueueChar ( + IN SIMPLE_QUEUE *Queue, + IN CHAR16 Char + ) +{ + CHAR16 Modifier; + CHAR8 AnsiChar; + EFI_STATUS Status; + + Status = EFI_UNSUPPORTED; + Modifier = Char & 0xFF00; + AnsiChar = (CHAR8)Char; + if (Modifier == 0) { + if (AnsiChar > 0) { + Status = Enqueue (Queue, AnsiChar); + } + } else if (Modifier == ARROW_KEY_MODIFIER) { + // Convert arrow key to ANSI escape sequence + Enqueue (Queue, '\x1b'); + Enqueue (Queue, '['); + Status = Enqueue (Queue, AnsiChar); + } + return Status; +} + + /** Return queue length. @@ -522,7 +563,7 @@ GetQueueLength ( @retval The ascii for the key code. **/ -CHAR8 +CHAR16 ConvertKeyToAscii ( IN UINT8 Modifier, IN UINT8 Key @@ -547,6 +588,11 @@ ConvertKeyToAscii ( } } + if (Key >= 0x4F && Key <= 0x52) { + // Arrow key + return ARROW_KEY_MODIFIER | mKeyboardKeyMap[3][Key - 0x4F]; + } + if (Key == 0x53) { // Num Lock mUsbKbDevice.NumLockOn = mUsbKbDevice.NumLockOn ? FALSE : TRUE; @@ -580,7 +626,7 @@ KeyboardPoll ( EFI_STATUS Status; USB_KB_DEV *UsbKbDevice; UINT8 KeyBuf[8]; - CHAR8 Char; + CHAR16 Char; UINTN DataSize; UINTN Index; UINTN Index2; @@ -682,7 +728,7 @@ KeyboardPoll ( if (KeyPress) { Char = ConvertKeyToAscii (CurKeyCodeBuffer[0], CurKeyCodeBuffer[Index]); if (Char > 0) { - Enqueue (&UsbKbDevice->Queue, Char); + EnqueueChar (&UsbKbDevice->Queue, Char); // Prepare new repeat key, and clear the original one. UsbKbDevice->RepeatCounter = 0; UsbKbDevice->RepeatChar = Char; @@ -710,7 +756,7 @@ KeyboardPoll ( if (UsbKbDevice->RepeatCounter < KEY_REPEAT_DELAY) { UsbKbDevice->RepeatCounter++; } else { - Enqueue (&UsbKbDevice->Queue, UsbKbDevice->RepeatChar); + EnqueueChar (&UsbKbDevice->Queue, UsbKbDevice->RepeatChar); } } } diff --git a/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLibInternal.h b/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLibInternal.h index cd34bb82..c953e5e7 100644 --- a/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLibInternal.h +++ b/BootloaderCommonPkg/Library/UsbKbLib/UsbKbLibInternal.h @@ -23,7 +23,7 @@ #define USB_KB_DEVICE_SIG SIGNATURE_32 ('U', 'S', 'K', 'B') -#define QUEUE_MAX_COUNT 32 +#define QUEUE_MAX_COUNT 64 #define KEY_REPEAT_DELAY 10 #define USBKBD_VALID_KEYCODE(Key) ((UINT8) (Key) > 3) @@ -51,8 +51,8 @@ typedef struct { BOOLEAN ScrollOn; SIMPLE_QUEUE Queue; UINT32 RepeatCounter; + CHAR16 RepeatChar; UINT8 RepeatKey; - CHAR8 RepeatChar; UINT8 LastKeyCodeArray[8]; UINT32 TimeStampFreqKhz; UINT64 LastTransferTimeStamp;