From b98c44e4120093bd9419e58a1dc68b376dfd28f9 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 17 Dec 2019 22:57:51 -0600 Subject: [PATCH] MdeModulePkg/Usb/Keyboard: add SetIdle quirk handler Some USB keyboards, like the Aspeed BMC HID keyboard, require the SetIdle command to be issued before interrupt transfers can be enabled. Add a quirk handler so any similar devices can make use of same function by the addition of the USB vendor/device IDs. Signed-off-by: Matt DeVillier --- MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c | 47 +++++++++++++++++++++++- MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.h | 14 +++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c index beee42ab19..43168dab90 100644 --- a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c +++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c @@ -793,6 +793,29 @@ InitKeyboardLayout ( } +/** + Determine if SetIdle request is needed + + @param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance. + + @retval TRUE The USB device requires SetIdle to be called. + @retval FALSE The USB device does not require SetIdle to be called. + +**/ +BOOLEAN +UsbQuirkRequireSetIdle ( + IN EFI_USB_DEVICE_DESCRIPTOR DevDesc + ) +{ + switch (DevDesc.IdVendor) { + case 0x0557: + return DevDesc.IdProduct == 0x2419; + default: + return FALSE; + } +} + + /** Initialize USB keyboard device and all private data structures. @@ -807,7 +830,8 @@ InitUSBKeyboard ( IN OUT USB_KB_DEV *UsbKeyboardDevice ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_USB_DEVICE_DESCRIPTOR DevDesc; REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, @@ -819,6 +843,17 @@ InitUSBKeyboard ( InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA)); InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA)); + // + // Get device descriptor so vendor/device IDs available + // for quirk handling + // + Status = UsbKeyboardDevice->UsbIo->UsbGetDeviceDescriptor ( + UsbKeyboardDevice->UsbIo, + &DevDesc); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // // Set boot protocol for the USB Keyboard. // This driver only supports boot protocol. @@ -865,6 +900,16 @@ InitUSBKeyboard ( UsbKeyboardDevice->CurrentNsKey = NULL; + // + // Some keyboards don't send interrupt transfers until SetIdle is called + // + if (UsbQuirkRequireSetIdle(DevDesc)) { + UsbSetIdleRequest(UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber, + 0, + 0); + } + // // Sync the initial state of lights on keyboard. // diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.h b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.h index 87f2132eac..f9eb6cb733 100644 --- a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.h +++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.h @@ -329,4 +329,18 @@ InitializeKeyState ( OUT EFI_KEY_STATE *KeyState ); +/** + Determine if SetIdle request is needed + + @param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance. + + @retval TRUE The USB device requires SetIdle to be called. + @retval FALSE The USB device does not require SetIdle to be called. + +**/ +BOOLEAN +UsbQuirkRequireSetIdle ( + IN EFI_USB_DEVICE_DESCRIPTOR DevDesc + ); + #endif