mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 15:03:00 +00:00
[LIBUSB]
- Fix bug while scanning endpoint descriptors - Do not assume interface info has the correct number of pipes set - Fix alternate interface handling - Tested in VBox + USB Audio Device svn path=/trunk/; revision=55992
This commit is contained in:
parent
9bb1ba5ee4
commit
a5bdcfa727
3 changed files with 119 additions and 63 deletions
|
@ -798,6 +798,7 @@ CHubController::HandleIsochronousTransfer(
|
||||||
// sanity checks
|
// sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(EndPointDesc);
|
ASSERT(EndPointDesc);
|
||||||
|
DPRINT("HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", EndPointDesc, EndPointDesc->bEndpointAddress, EndPointDesc->bmAttributes);
|
||||||
ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS);
|
ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -13,7 +13,6 @@ extern "C"
|
||||||
#include <usbdlib.h>
|
#include <usbdlib.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME:
|
// FIXME:
|
||||||
// #include <usbprotocoldefs.h>
|
// #include <usbprotocoldefs.h>
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
|
virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
|
||||||
virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
||||||
virtual NTSTATUS GetConfigurationDescriptor(UCHAR ConfigurationIndex, USHORT BufferSize, PVOID Buffer);
|
virtual NTSTATUS GetConfigurationDescriptor(UCHAR ConfigurationIndex, USHORT BufferSize, PVOID Buffer);
|
||||||
|
virtual NTSTATUS BuildInterfaceDescriptor(IN ULONG ConfigurationIndex, IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo, OUT PUSB_INTERFACE *OutUsbInterface);
|
||||||
|
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBDevice(IUnknown *OuterUnknown){}
|
CUSBDevice(IUnknown *OuterUnknown){}
|
||||||
|
@ -916,6 +918,92 @@ CUSBDevice::SubmitSetupPacket(
|
||||||
//
|
//
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBDevice::BuildInterfaceDescriptor(
|
||||||
|
IN ULONG ConfigurationIndex,
|
||||||
|
IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
|
||||||
|
OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo,
|
||||||
|
OUT PUSB_INTERFACE *OutUsbInterface)
|
||||||
|
{
|
||||||
|
PUSB_INTERFACE UsbInterface;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
ULONG PipeIndex;
|
||||||
|
|
||||||
|
// allocate interface handle
|
||||||
|
UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
|
||||||
|
if (!UsbInterface)
|
||||||
|
{
|
||||||
|
// failed to allocate memory
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero descriptor
|
||||||
|
RtlZeroMemory(UsbInterface, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
|
||||||
|
|
||||||
|
// store handle
|
||||||
|
InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface;
|
||||||
|
InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
|
||||||
|
InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
|
||||||
|
InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
|
||||||
|
InterfaceInfo->Reserved = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// init interface handle
|
||||||
|
UsbInterface->InterfaceDescriptor = InterfaceDescriptor;
|
||||||
|
InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry);
|
||||||
|
|
||||||
|
// grab first endpoint descriptor
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1);
|
||||||
|
|
||||||
|
// now copy all endpoint information
|
||||||
|
for(PipeIndex = 0; PipeIndex < InterfaceDescriptor->bNumEndpoints; PipeIndex++)
|
||||||
|
{
|
||||||
|
while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
// skip intermediate descriptors
|
||||||
|
if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
// bogus configuration descriptor
|
||||||
|
DPRINT1("[USBEHCI] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex,
|
||||||
|
EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType);
|
||||||
|
|
||||||
|
// failed
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move to next descriptor
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store in interface info
|
||||||
|
RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
|
||||||
|
|
||||||
|
DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->wTotalLength);
|
||||||
|
DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor, EndpointDescriptor->bDescriptorType, EndpointDescriptor->bLength);
|
||||||
|
DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface->EndPoints[PipeIndex], UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress,
|
||||||
|
UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes);
|
||||||
|
|
||||||
|
// copy pipe info
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex];
|
||||||
|
|
||||||
|
// move to next descriptor
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OutUsbInterface)
|
||||||
|
{
|
||||||
|
// output result
|
||||||
|
*OutUsbInterface = UsbInterface;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -924,7 +1012,7 @@ CUSBDevice::SelectConfiguration(
|
||||||
IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
|
IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
|
||||||
OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
|
OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
|
||||||
{
|
{
|
||||||
ULONG InterfaceIndex, PipeIndex;
|
ULONG InterfaceIndex;
|
||||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UCHAR bConfigurationValue = 0;
|
UCHAR bConfigurationValue = 0;
|
||||||
|
@ -932,7 +1020,6 @@ CUSBDevice::SelectConfiguration(
|
||||||
UCHAR Found = FALSE;
|
UCHAR Found = FALSE;
|
||||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
PUSB_INTERFACE UsbInterface;
|
PUSB_INTERFACE UsbInterface;
|
||||||
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
|
|
||||||
if (ConfigurationDescriptor)
|
if (ConfigurationDescriptor)
|
||||||
|
@ -1029,61 +1116,11 @@ CUSBDevice::SelectConfiguration(
|
||||||
ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
|
ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
|
||||||
|
|
||||||
// copy interface info
|
// copy interface info
|
||||||
InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
|
Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL);
|
||||||
InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
|
if (!NT_SUCCESS(Status))
|
||||||
InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
|
|
||||||
InterfaceInfo->Reserved = 0;
|
|
||||||
|
|
||||||
// allocate interface handle
|
|
||||||
UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceInfo->NumberOfPipes - 1) * sizeof(USB_ENDPOINT));
|
|
||||||
if (!UsbInterface)
|
|
||||||
{
|
{
|
||||||
// failed to allocate memory
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store handle
|
|
||||||
InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface;
|
|
||||||
|
|
||||||
// init interface handle
|
|
||||||
UsbInterface->InterfaceDescriptor = InterfaceDescriptor;
|
|
||||||
InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry);
|
|
||||||
|
|
||||||
// grab first endpoint descriptor
|
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1);
|
|
||||||
|
|
||||||
// now copy all endpoint information
|
|
||||||
for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
|
|
||||||
{
|
|
||||||
while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE && EndpointDescriptor->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR))
|
|
||||||
{
|
|
||||||
// skip intermediate descriptors
|
|
||||||
if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
|
||||||
{
|
|
||||||
// bogus configuration descriptor
|
|
||||||
DPRINT1("[USBEHCI] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex,
|
|
||||||
EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType);
|
|
||||||
|
|
||||||
// failed
|
// failed
|
||||||
return STATUS_UNSUCCESSFUL;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// move to next descriptor
|
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
// store in interface info
|
|
||||||
RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
|
|
||||||
|
|
||||||
// copy pipe info
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex];
|
|
||||||
|
|
||||||
// move to next descriptor
|
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// move offset
|
// move offset
|
||||||
|
@ -1108,6 +1145,7 @@ CUSBDevice::SelectInterface(
|
||||||
ULONG Index, ConfigurationIndex = 0, Found = FALSE;
|
ULONG Index, ConfigurationIndex = 0, Found = FALSE;
|
||||||
PUSB_INTERFACE UsbInterface;
|
PUSB_INTERFACE UsbInterface;
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
|
||||||
// check if handle is valid
|
// check if handle is valid
|
||||||
for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
|
for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
|
||||||
|
@ -1171,17 +1209,35 @@ CUSBDevice::SelectInterface(
|
||||||
|
|
||||||
if (!Found)
|
if (!Found)
|
||||||
{
|
{
|
||||||
// selected interface but interface not found
|
// find interface descriptor
|
||||||
// something is really wrong
|
InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
|
||||||
DPRINT1("[USBEHCI] Error: interface not found!!!\n");
|
if (!InterfaceDescriptor)
|
||||||
|
{
|
||||||
|
DPRINT1("[LIBUSB] No such interface Alternate %x InterfaceNumber %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build interface descriptor
|
||||||
|
Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, &UsbInterface);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
// failed
|
||||||
|
DPRINT1("[LIBUSB] Failed to build interface descriptor Status %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// assert on pipe length mismatch
|
// assert on pipe length mismatch
|
||||||
ASSERT(InterfaceInfo->NumberOfPipes == UsbInterface->InterfaceDescriptor->bNumEndpoints);
|
DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints, InterfaceInfo->Length);
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface->InterfaceDescriptor->bNumEndpoints) == InterfaceInfo->Length);
|
||||||
|
|
||||||
|
// store number of pipes
|
||||||
|
InterfaceInfo->NumberOfPipes = UsbInterface->InterfaceDescriptor->bNumEndpoints;
|
||||||
|
|
||||||
// copy pipe handles
|
// copy pipe handles
|
||||||
for(PipeIndex = 0; PipeIndex < min(InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints); PipeIndex++)
|
for(PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++)
|
||||||
{
|
{
|
||||||
// copy pipe handle
|
// copy pipe handle
|
||||||
DPRINT1("PipeIndex %lu\n", PipeIndex);
|
DPRINT1("PipeIndex %lu\n", PipeIndex);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue