From 61204778d87c3b7d6db29fdbeb959929184c07a5 Mon Sep 17 00:00:00 2001 From: Marlboro_Chuang Date: Sun, 27 Jul 2025 18:39:54 +0800 Subject: [PATCH] MdeModulePkg/UsbBusDxe: Handle a quirk in Interface descriptor Some specific device requires a quirk in the Interface descriptor for InterfaceNumber to work properly [Suggested Solution] Implement the mechanism to ensure the first InterfaceNumber not equal to zero. Signed-off-by: Marlboro_Chuang --- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c | 18 ++++++++++++++++-- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c | 13 +++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c index 106757ecb8..19d0ca130a 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c @@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "UsbBus.h" +#define INTERFACE_NOT_SET 0xFF + /** Free the interface setting descriptor. @@ -394,6 +396,7 @@ UsbParseConfigDesc ( UINTN Index; UINTN NumIf; UINTN Consumed; + UINT8 FirstIntfNum; ASSERT (DescBuf != NULL); @@ -441,6 +444,8 @@ UsbParseConfigDesc ( DescBuf += Consumed; Len -= Consumed; + FirstIntfNum = INTERFACE_NOT_SET; + // // Make allowances for devices that return extra data at the // end of their config descriptors @@ -448,10 +453,19 @@ UsbParseConfigDesc ( while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) { Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed); + // Usb standard spec expects the interface number to start from 0. + // Some devices might have the first interface number not equal to zero. + // This is a work around for these devices. For example, Dell WWAN DW2811e + if (Setting != NULL) { + if (FirstIntfNum == INTERFACE_NOT_SET) { + FirstIntfNum = Setting->Desc.InterfaceNumber; + } + } + if (Setting == NULL) { DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n")); break; - } else if (Setting->Desc.InterfaceNumber >= NumIf) { + } else if (Setting->Desc.InterfaceNumber >= (NumIf + FirstIntfNum)) { DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: malformatted interface descriptor\n")); UsbFreeInterfaceDesc (Setting); @@ -461,7 +475,7 @@ UsbParseConfigDesc ( // // Insert the descriptor to the corresponding set. // - Interface = Config->Interfaces[Setting->Desc.InterfaceNumber]; + Interface = Config->Interfaces[(Setting->Desc.InterfaceNumber - FirstIntfNum)]; if (Interface->NumOfSetting >= USB_MAX_INTERFACE_SETTING) { goto ON_ERROR; diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index 64da8d7bfc..afc364ced8 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -417,6 +417,19 @@ UsbSelectConfig ( // the endpoint toggles to zero for its endpoints. // IfDesc = ConfigDesc->Interfaces[Index]; + + // + // Protect against hang. This is added to work around faulty device like Digidesign Mbox3 mini + // + if ((IfDesc == NULL) || (IfDesc->Settings[0] == NULL)) { + // + // If UsbCreateDesc() bailed on an interface or endpoint desc, don't try to + // configure that interface here. + // + DEBUG ((DEBUG_INFO, "UsbSelectConfig: Skipping uninitialized interface %d.\n", Index)); + continue; + } + UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting); //