[LIBUSB][USBCCGP]
[reactos.git] / reactos / lib / drivers / libusb / usb_device.cpp
index 072ab68..2050dd0 100644 (file)
@@ -65,6 +65,8 @@ public:
     virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
     virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
     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
     CUSBDevice(IUnknown *OuterUnknown){}
@@ -74,7 +76,7 @@ protected:
     LONG m_Ref;
     PHUBCONTROLLER m_HubController;
     PUSBHARDWAREDEVICE m_Device;
-    PVOID m_Parent; 
+    PVOID m_Parent;
     ULONG m_Port;
     UCHAR m_DeviceAddress;
     PVOID m_Data;
@@ -101,9 +103,9 @@ CUSBDevice::QueryInterface(
 //----------------------------------------------------------------------------------------
 NTSTATUS
 CUSBDevice::Initialize(
-    IN PHUBCONTROLLER HubController, 
-    IN PUSBHARDWAREDEVICE Device, 
-    IN PVOID Parent, 
+    IN PHUBCONTROLLER HubController,
+    IN PUSBHARDWAREDEVICE Device,
+    IN PVOID Parent,
     IN ULONG Port,
     IN ULONG PortStatus)
 {
@@ -307,7 +309,7 @@ CUSBDevice::SetDeviceAddress(
     UCHAR OldAddress;
     UCHAR Index;
 
-    DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress);
+    DPRINT1("CUSBDevice::SetDeviceAddress> Address %x\n", DeviceAddress);
 
     CtrlSetup = (PUSB_DEFAULT_PIPE_SETUP_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), TAG_USBLIB);
     if (!CtrlSetup)
@@ -321,7 +323,7 @@ CUSBDevice::SetDeviceAddress(
     CtrlSetup->wValue.W = DeviceAddress;
 
     // set device address
-    Status = CommitSetupPacket(CtrlSetup, 0, 0, 0);
+    Status = CommitSetupPacket(CtrlSetup, NULL, 0, NULL);
 
     // free setup packet
     ExFreePoolWithTag(CtrlSetup, TAG_USBLIB);
@@ -330,7 +332,7 @@ CUSBDevice::SetDeviceAddress(
     if (!NT_SUCCESS(Status))
     {
         // failed to set device address
-        DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status, DeviceAddress);
+        DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %lx Address %x\n", Status, DeviceAddress);
         return Status;
     }
 
@@ -347,7 +349,7 @@ CUSBDevice::SetDeviceAddress(
     Status = CreateDeviceDescriptor();
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status);
+        DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %lx\n", Status);
         // return error status
         return Status;
     }
@@ -358,7 +360,7 @@ CUSBDevice::SetDeviceAddress(
         m_DeviceDescriptor.bNumConfigurations == 0)
     {
         // failed to retrieve device descriptor
-        DPRINT1("CUSBbDevice::SetDeviceAddress> device returned bogus device descriptor\n");
+        DPRINT1("CUSBDevice::SetDeviceAddress> device returned bogus device descriptor\n");
         DumpDeviceDescriptor(&m_DeviceDescriptor);
 
         // return error status
@@ -378,7 +380,7 @@ CUSBDevice::SetDeviceAddress(
     RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations);
 
     // retrieve the configuration descriptors
-    for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
+    for (Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
     {
         // retrieve configuration descriptors from device
         Status = CreateConfigurationDescriptor(Index);
@@ -428,7 +430,7 @@ CUSBDevice::CommitIrp(
         //
         // no queue, wtf?
         //
-        DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
+        DPRINT1("CUSBDevice::CommitIrp> no queue / dma !!!\n");
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -441,7 +443,7 @@ CUSBDevice::CommitIrp(
         //
         // failed to build request
         //
-        DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status);
+        DPRINT1("CUSBDevice::CommitIrp> CreateUSBRequest failed with %lx\n", Status);
         return Status;
     }
 
@@ -464,7 +466,7 @@ CUSBDevice::CommitIrp(
         //
         // failed to add request
         //
-        DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status);
+        DPRINT1("CUSBDevice::CommitIrp> failed add request to queue with %lx\n", Status);
         Request->Release();
         return Status;
     }
@@ -500,12 +502,13 @@ CUSBDevice::SubmitIrp(
 
     return Status;
 }
+
 //----------------------------------------------------------------------------------------
 NTSTATUS
 CUSBDevice::CommitSetupPacket(
     IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
     IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
-    IN ULONG BufferLength, 
+    IN ULONG BufferLength,
     IN OUT PMDL Mdl)
 {
     NTSTATUS Status;
@@ -637,7 +640,7 @@ CUSBDevice::CreateDeviceDescriptor()
     //
     // commit setup packet
     //
-    Status = CommitSetupPacket(&CtrlSetup, 0, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
+    Status = CommitSetupPacket(&CtrlSetup, NULL, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
 
     //
     // now free the mdl
@@ -667,7 +670,7 @@ CUSBDevice::CreateDeviceDescriptor()
 //----------------------------------------------------------------------------------------
 NTSTATUS
 CUSBDevice::GetConfigurationDescriptor(
-    IN UCHAR ConfigurationIndex, 
+    IN UCHAR ConfigurationIndex,
     IN USHORT BufferSize,
     IN PVOID Buffer)
 {
@@ -710,7 +713,7 @@ CUSBDevice::GetConfigurationDescriptor(
     //
     // commit packet
     //
-    Status = CommitSetupPacket(&CtrlSetup, 0, BufferSize, Mdl);
+    Status = CommitSetupPacket(&CtrlSetup, NULL, BufferSize, Mdl);
 
     //
     // free mdl
@@ -806,6 +809,8 @@ CUSBDevice::GetConfigurationDescriptors(
     IN ULONG BufferLength,
     OUT PULONG OutBufferLength)
 {
+    ULONG Length;
+
     // sanity check
     ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
     ASSERT(ConfigDescriptorBuffer);
@@ -818,8 +823,9 @@ CUSBDevice::GetConfigurationDescriptors(
     PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
 
     // copy configuration descriptor
-    RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength));
-    *OutBufferLength = m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
+    Length = min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength);
+    RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, Length);
+    *OutBufferLength = Length;
 }
 
 //----------------------------------------------------------------------------------------
@@ -871,8 +877,8 @@ CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR Configurat
 //----------------------------------------------------------------------------------------
 NTSTATUS
 CUSBDevice::SubmitSetupPacket(
-    IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, 
-    IN OUT ULONG BufferLength, 
+    IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+    IN OUT ULONG BufferLength,
     OUT PVOID Buffer)
 {
     NTSTATUS Status;
@@ -901,7 +907,7 @@ CUSBDevice::SubmitSetupPacket(
     //
     // commit setup packet
     //
-    Status = CommitSetupPacket(SetupPacket, 0, BufferLength, Mdl);
+    Status = CommitSetupPacket(SetupPacket, NULL, BufferLength, Mdl);
 
     if (Mdl != NULL)
     {
@@ -916,6 +922,92 @@ CUSBDevice::SubmitSetupPacket(
     //
     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("[USBLIB] 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
@@ -924,7 +1016,7 @@ CUSBDevice::SelectConfiguration(
     IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
     OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
 {
-    ULONG InterfaceIndex, PipeIndex;
+    ULONG InterfaceIndex;
     USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
     NTSTATUS Status;
     UCHAR bConfigurationValue = 0;
@@ -932,13 +1024,12 @@ CUSBDevice::SelectConfiguration(
     UCHAR Found = FALSE;
     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
     PUSB_INTERFACE UsbInterface;
-    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
     PLIST_ENTRY Entry;
 
     if (ConfigurationDescriptor)
     {
         // find configuration index
-        for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
+        for (Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
         {
             if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bConfigurationValue  == ConfigurationDescriptor->bConfigurationValue)
             {
@@ -950,7 +1041,7 @@ CUSBDevice::SelectConfiguration(
 
         if (!Found)
         {
-            DPRINT1("[USBUHCI] invalid configuration value %lu\n", ConfigurationDescriptor->bConfigurationValue);
+            DPRINT1("[USBLIB] invalid configuration value %u\n", ConfigurationDescriptor->bConfigurationValue);
             return STATUS_INVALID_PARAMETER;
         }
 
@@ -967,18 +1058,18 @@ CUSBDevice::SelectConfiguration(
     CtrlSetup.wValue.W = bConfigurationValue;
 
     // select configuration
-    Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
+    Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL);
 
     if (!ConfigurationDescriptor)
     {
         // unconfigure request
-        DPRINT1("CUsbDevice::SelectConfiguration Unconfigure Request Status %x\n", Status);
+        DPRINT1("CUSBDevice::SelectConfiguration Unconfigure Request Status %lx\n", Status);
         m_ConfigurationIndex = 0;
         return Status;
     }
 
     // informal debug print
-    DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationIndex, m_ConfigurationIndex, Status);
+    DPRINT1("CUSBDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", ConfigurationIndex, m_ConfigurationIndex, Status);
     if (!NT_SUCCESS(Status))
     {
         //
@@ -988,7 +1079,7 @@ CUSBDevice::SelectConfiguration(
     }
 
     // destroy old interface info
-    while(!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList))
+    while (!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList))
     {
         // remove entry
         Entry = RemoveHeadList(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList);
@@ -1029,65 +1120,15 @@ CUSBDevice::SelectConfiguration(
         ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
 
         // copy interface info
-        InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
-        InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
-        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++)
+        Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL);
+        if (!NT_SUCCESS(Status))
         {
-            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
-                    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));
-
-            // 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);
+            // failed
+            break;
         }
 
         // move offset
-        InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)PtrToUlong(InterfaceInfo) + InterfaceInfo->Length);
+        InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
     }
 
     //
@@ -1108,6 +1149,7 @@ CUSBDevice::SelectInterface(
     ULONG Index, ConfigurationIndex = 0, Found = FALSE;
     PUSB_INTERFACE UsbInterface;
     PLIST_ENTRY Entry;
+    PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
 
     // check if handle is valid
     for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
@@ -1123,7 +1165,7 @@ CUSBDevice::SelectInterface(
     if (!Found)
     {
         // invalid handle passed
-        DPRINT1("[USBEHCI] Invalid configuration handle passed %p\n", ConfigurationHandle);
+        DPRINT1("[USBLIB] Invalid configuration handle passed %p\n", ConfigurationHandle);
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -1135,12 +1177,12 @@ CUSBDevice::SelectInterface(
     CtrlSetup.bmRequestType.B = 0x01;
 
     // issue request
-    Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
+    Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL);
 
     // informal debug print
-    DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
+    DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %lx\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
 #if 0
-       if (!NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
         // failed to select interface
         return Status;
@@ -1149,11 +1191,10 @@ CUSBDevice::SelectInterface(
 
     Status = STATUS_SUCCESS;
 
-
     // find interface
     Found = FALSE;
     Entry = m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList.Flink;
-    while(Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)
+    while (Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)
     {
         // grab interface descriptor
         UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
@@ -1171,17 +1212,35 @@ CUSBDevice::SelectInterface(
 
     if (!Found)
     {
-        // selected interface but interface not found
-        // something is really wrong
-        DPRINT1("[USBEHCI] Error: interface not found!!!\n");
-        return STATUS_UNSUCCESSFUL;
+        // find interface descriptor
+        InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
+        if (!InterfaceDescriptor)
+        {
+            DPRINT1("[LIBUSB] No such interface Alternate %x InterfaceNumber %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber);
+            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(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
-    for(PipeIndex = 0; PipeIndex < min(InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints); PipeIndex++)
+    for (PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++)
     {
         // copy pipe handle
         DPRINT1("PipeIndex %lu\n", PipeIndex);
@@ -1190,7 +1249,7 @@ CUSBDevice::SelectInterface(
         DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
         DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
         DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
-        DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
+        DPRINT1("PipeType %d\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
         DPRINT1("UsbEndPoint %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
 
         // sanity checks
@@ -1204,7 +1263,6 @@ CUSBDevice::SelectInterface(
         UsbInterface->EndPoints[PipeIndex].DataToggle = FALSE;
     }
 
-
     //
     // done
     //