[USBCCGP] [USBPORT] USB Stack improvements (#7740)

[USBCCGP]

Ignore invalid devices
Group audio function interfaces together
[USBPORT]

Prevent infinite loop in USBPORT_OpenPipe when endpoint is not becoming ready
This commit is contained in:
Johannes Anderwald 2025-03-19 09:35:36 +01:00 committed by GitHub
parent 4bc97ad145
commit dba4efbcae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 82 additions and 29 deletions

View file

@ -189,8 +189,15 @@ FDO_CreateChildPdo(
} }
/* Create pdo for each function */ /* Create pdo for each function */
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++) for (Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
{ {
if (FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces == 0)
{
// Ignore invalid devices
DPRINT1("[USBCCGP] Found descriptor with 0 interfaces\n");
continue;
}
/* Create the PDO */ /* Create the PDO */
Status = IoCreateDevice(FDODeviceExtension->DriverObject, Status = IoCreateDevice(FDODeviceExtension->DriverObject,
sizeof(PDO_DEVICE_EXTENSION), sizeof(PDO_DEVICE_EXTENSION),

View file

@ -607,10 +607,10 @@ NTSTATUS
USBCCGP_LegacyEnum( USBCCGP_LegacyEnum(
IN PDEVICE_OBJECT DeviceObject) IN PDEVICE_OBJECT DeviceObject)
{ {
ULONG Index; ULONG Index, SubIndex;
PFDO_DEVICE_EXTENSION FDODeviceExtension; PFDO_DEVICE_EXTENSION FDODeviceExtension;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, NextInterfaceDescriptor;
// //
// get device extension // get device extension
@ -639,7 +639,7 @@ USBCCGP_LegacyEnum(
// //
// init function descriptors // init function descriptors
// //
FDODeviceExtension->FunctionDescriptorCount = 0; FDODeviceExtension->FunctionDescriptorCount = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces;
for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++) for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
{ {
// get interface descriptor // get interface descriptor
@ -654,12 +654,53 @@ USBCCGP_LegacyEnum(
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
SubIndex = 0;
if (InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_AUDIO)
{
// AUDIO CLASS lets group all audio interfaces together
// //
// init function descriptor // init function descriptor
// //
FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index; FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1; FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1); FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
{
//
// no memory
//
FreeItem(FDODeviceExtension->FunctionDescriptor);
FDODeviceExtension->FunctionDescriptor = NULL;
FDODeviceExtension->FunctionDescriptorCount = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// store interface descriptor
//
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex] = InterfaceDescriptor;
while (TRUE)
{
NextInterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index + SubIndex + 1, 0, -1, -1, -1);
if (!NextInterfaceDescriptor || NextInterfaceDescriptor->bInterfaceClass != USB_DEVICE_CLASS_AUDIO)
{
// end of collection
break;
}
SubIndex++;
ASSERT(SubIndex < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces++;
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex] = NextInterfaceDescriptor;
}
}
else
{
//
// init function descriptor
//
FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR));
if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList) if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
{ {
// //
@ -672,6 +713,7 @@ USBCCGP_LegacyEnum(
// store interface descriptor // store interface descriptor
// //
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor; FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor;
}
// //
// now init the device ids // now init the device ids
@ -685,11 +727,10 @@ USBCCGP_LegacyEnum(
DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status); DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
return Status; return Status;
} }
// //
// store function count // increment interface count
// //
FDODeviceExtension->FunctionDescriptorCount++; Index += SubIndex;
} }
// //
@ -734,7 +775,7 @@ USBCCGP_EnumWithAudioLegacy(
DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor); DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor);
ASSERT(InterfaceDescriptor); ASSERT(InterfaceDescriptor);
if (InterfaceDescriptor->bInterfaceClass != 0x1) if (InterfaceDescriptor->bInterfaceClass != USB_DEVICE_CLASS_AUDIO)
{ {
// //
// collection contains non audio class // collection contains non audio class

View file

@ -769,7 +769,8 @@ USBCCGP_PDOSelectConfiguration(
Entry = NULL; Entry = NULL;
do do
{ {
DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x Length %lu InterfaceInformation->Length %lu\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, Length, InterfaceInformation->Length); DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x Length %lu InterfaceInformation->Length %lu\n",
PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, Length, InterfaceInformation->Length);
ASSERT(InterfaceInformation->Length); ASSERT(InterfaceInformation->Length);
// //
// search for the interface in the local interface list // search for the interface in the local interface list

View file

@ -4,6 +4,7 @@
#include <wdm.h> #include <wdm.h>
#include <hubbusif.h> #include <hubbusif.h>
#include <usbbusif.h> #include <usbbusif.h>
#include <usb100.h>
#include <usbdlib.h> #include <usbdlib.h>
#include <stdio.h> #include <stdio.h>

View file

@ -778,12 +778,13 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0}; USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0};
PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer; PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
MPSTATUS MpStatus; MPSTATUS MpStatus;
USBD_STATUS USBDStatus; USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
NTSTATUS Status; NTSTATUS Status;
KIRQL OldIrql; KIRQL OldIrql;
USHORT MaxPacketSize; USHORT MaxPacketSize;
USHORT AdditionalTransaction; USHORT AdditionalTransaction;
BOOLEAN IsAllocatedBandwidth; BOOLEAN IsAllocatedBandwidth;
ULONG RetryCount;
DPRINT1("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n", DPRINT1("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n",
DeviceHandle, DeviceHandle,
@ -1074,7 +1075,8 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
KeReleaseSpinLock(&Endpoint->EndpointSpinLock, KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
Endpoint->EndpointOldIrql); Endpoint->EndpointOldIrql);
while (TRUE) /* Wait maximum 1 second for the endpoint to be active */
for (RetryCount = 0; RetryCount < 1000; RetryCount++)
{ {
KeAcquireSpinLock(&Endpoint->EndpointSpinLock, KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
&Endpoint->EndpointOldIrql); &Endpoint->EndpointOldIrql);
@ -1091,6 +1093,11 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
USBPORT_Wait(FdoDevice, 1); // 1 msec. USBPORT_Wait(FdoDevice, 1); // 1 msec.
} }
if (State != USBPORT_ENDPOINT_ACTIVE)
{
DPRINT1("Timeout State %x\n", State);
USBDStatus = USBD_STATUS_TIMEOUT;
}
} }
} }
else else
@ -1103,10 +1110,6 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
{ {
USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES; USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
} }
else
{
USBDStatus = USBD_STATUS_SUCCESS;
}
} }
if (UsbdStatus) if (UsbdStatus)