[ros-diffs] [janderwald] 55530: [USBEHCI] - Partly revert 55516, as the memory bug got fixed

janderwald at svn.reactos.org janderwald at svn.reactos.org
Fri Feb 10 20:15:39 UTC 2012


Author: janderwald
Date: Fri Feb 10 20:15:39 2012
New Revision: 55530

URL: http://svn.reactos.org/svn/reactos?rev=55530&view=rev
Log:
[USBEHCI]
- Partly revert 55516, as the memory bug got fixed

Modified:
    branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp
    branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h
    branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp
    branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h
    branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp
    branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp
    branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp
    branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -1339,6 +1339,7 @@
                 // controller reported error
                 //
                 DPRINT1("CStatus %x\n", CStatus);
+                ASSERT(FALSE);
             }
 
             //

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -148,7 +148,7 @@
     
     //Software
     ULONG PhysicalAddr;
-    LIST_ENTRY LinkedDescriptors;
+    LIST_ENTRY DescriptorEntry;
     ULONG TotalBytesToTransfer;
 } QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
 
@@ -216,9 +216,21 @@
     //Software
     ULONG PhysicalAddr;
     LIST_ENTRY LinkedQueueHeads;
+    LIST_ENTRY TransferDescriptorListHead;
     PVOID Request;
 } QUEUE_HEAD, *PQUEUE_HEAD;
 
+C_ASSERT(sizeof(END_POINT_CHARACTERISTICS) == 4);
+C_ASSERT(sizeof(END_POINT_CAPABILITIES) == 4);
+
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, HorizontalLinkPointer) == 0x00);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCharacteristics) == 0x04);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCapabilities) == 0x08);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, CurrentLinkPointer) == 0xC);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, NextPointer) == 0x10);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, AlternateNextPointer) == 0x14);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, Token) == 0x18);
+C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, BufferPointer) == 0x1C);
 C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x30);
 
 
@@ -292,3 +304,4 @@
     ULONG PortChange;
 }EHCI_PORT_STATUS;
 
+

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -70,6 +70,9 @@
     NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
 
     friend VOID StatusChangeEndpointCallBack(PVOID Context);
 
@@ -1675,12 +1678,21 @@
     //
     // initialize setup packet
     //
-    CtrlSetup.bmRequestType.B = 0xa2; //FIXME: Const.
+    CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const.
     CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
     CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
     CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
     CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
 
+    if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+    {
+        //
+        // data direction is device to host
+        //
+        CtrlSetup.bmRequestType.B |= 0x80;
+    }
+
+
     //
     // issue request
     //
@@ -1697,6 +1709,185 @@
     //
     return Status;
 }
+
+NTSTATUS
+CHubController::HandleSyncResetAndClearStall(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PUSB_ENDPOINT EndpointDescriptor;
+    ULONG Type;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get type
+    //
+    Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
+    if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
+    {
+        //
+        // clear stall
+        //
+        Status = HandleClearStall(Irp, Urb);
+    }
+    DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
+
+    //
+    // reset data toggle
+    //
+    ASSERT(NT_SUCCESS(Status));
+    EndpointDescriptor->DataToggle = 0x0;
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CHubController::HandleAbortPipe(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+    //
+    // issue request
+    //
+    Status = UsbDevice->AbortPipe(EndpointDescriptor);
+    DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleClearStall(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+    DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
+
+    //
+    // initialize setup packet
+    //
+    CtrlSetup.bmRequestType.B = 0x02;
+    CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
+    CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
+    CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
+    CtrlSetup.wLength = 0;
+    CtrlSetup.wValue.W = 0;
+
+    //
+    // issue request
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
+
+    DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
+
+    //
+    // done
+    //
+    return Status;
+}
+
 
 //-----------------------------------------------------------------------------------------
 NTSTATUS
@@ -1747,12 +1938,20 @@
     //
     // initialize setup packet
     //
-    CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const.
+    CtrlSetup.bmRequestType.B = 0x21;
     CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
     CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
     CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
     CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
 
+    if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+    {
+        //
+        // data direction is device to host
+        //
+        CtrlSetup.bmRequestType.B |= 0x80;
+    }
+
     //
     // issue request
     //
@@ -1761,8 +1960,13 @@
     //
     // assert on failure
     //
-    PC_ASSERT(NT_SUCCESS(Status));
-
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // display error
+        //
+        DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
+    }
 
     //
     // done
@@ -1806,6 +2010,16 @@
 
             switch (Urb->UrbHeader.Function)
             {
+                case URB_FUNCTION_SYNC_RESET_PIPE:
+                case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
+                    Status = HandleSyncResetAndClearStall(Irp, Urb);
+                    break;
+                case URB_FUNCTION_ABORT_PIPE:
+                    Status = HandleAbortPipe(Irp, Urb);
+                    break;
+                case URB_FUNCTION_SYNC_CLEAR_STALL:
+                    Status = HandleClearStall(Irp, Urb);
+                    break;
                 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
                     Status = HandleGetDescriptorFromInterface(Irp, Urb);
                     break;

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -379,6 +379,7 @@
 // 
 
 struct _QUEUE_HEAD;
+struct _USB_ENDPOINT;
 
 DECLARE_INTERFACE_(IUSBRequest, IUnknown)
 {
@@ -395,7 +396,7 @@
     virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
                                                IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
                                                IN UCHAR DeviceAddress,
-                                               IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+                                               IN OPTIONAL struct _USB_ENDPOINT *EndpointDescriptor,
                                                IN OUT ULONG TransferBufferLength,
                                                IN OUT PMDL TransferBuffer) = 0;
 
@@ -588,6 +589,15 @@
 // This function gets called by IUSBHardware after it the Interrupt on Async Advance bit has been set
 
     virtual VOID CompleteAsyncRequests() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// AbortDevicePipe
+//
+// Description: aborts all pending requsts of an device
+
+    virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0;
+
 };
 
 typedef IUSBQueue *PUSBQUEUE;
@@ -841,6 +851,15 @@
 
     virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
                                      IN OUT PUSBD_INTERFACE_INFORMATION Interface) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// AbortPipe
+//
+// Description: aborts all pending requsts
+
+    virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0;
+
 };
 
 typedef IUSBDevice *PUSBDEVICE;

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -10,24 +10,6 @@
 
 #define INITGUID
 #include "usbehci.h"
-
-typedef struct _USB_ENDPOINT
-{
-    USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
-} USB_ENDPOINT, *PUSB_ENDPOINT;
-
-typedef struct _USB_INTERFACE
-{
-    USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
-    USB_ENDPOINT *EndPoints;
-} USB_INTERFACE, *PUSB_INTERFACE;
-
-typedef struct _USB_CONFIGURATION
-{
-    USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
-    USB_INTERFACE *Interfaces;
-} USB_CONFIGURATION, *PUSB_CONFIGURATION;
-
 
 class CUSBDevice : public IUSBDevice
 {
@@ -70,10 +52,12 @@
     virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer);
     virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle);
     virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
+    virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
+
 
     // local function
     virtual NTSTATUS CommitIrp(PIRP Irp);
-    virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
+    virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
     virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex);
     virtual NTSTATUS CreateDeviceDescriptor();
     virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
@@ -537,7 +521,7 @@
 NTSTATUS
 CUSBDevice::CommitSetupPacket(
     IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
-    IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+    IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
     IN ULONG BufferLength, 
     IN OUT PMDL Mdl)
 {
@@ -1273,6 +1257,23 @@
     return Status;
 }
 
+NTSTATUS
+CUSBDevice::AbortPipe(
+    IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
+{
+    //
+    // let it handle usb queue
+    //
+    ASSERT(m_Queue);
+    ASSERT(m_DeviceAddress);
+
+    //
+    // done
+    //
+    return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
+}
+
+
 //----------------------------------------------------------------------------------------
 NTSTATUS
 CreateUSBDevice(

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -41,6 +41,8 @@
     virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
     virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
     virtual VOID CompleteAsyncRequests();
+    virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
+
 
     // constructor / destructor
     CUSBQueue(IUnknown *OuterUnknown){}
@@ -499,11 +501,6 @@
     // remove software link
     //
     RemoveEntryList(&QueueHead->LinkedQueueHeads);
-
-    //
-    // FIXME: clear failure 
-    //
-    QueueHead->Token.Bits.Halted = FALSE;
 }
 
 //
@@ -629,6 +626,7 @@
     //
     // walk async list 
     //
+    ASSERT(AsyncListQueueHead);
     Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
 
     while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
@@ -637,6 +635,7 @@
         // get queue head structure
         //
         QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+        ASSERT(QueueHead);
 
         //
         // sanity check
@@ -658,7 +657,7 @@
         //
         IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
 
-        DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
+        DPRINT("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
 
         //
         // check if queue head is complete
@@ -930,6 +929,16 @@
 }
 
 NTSTATUS
+CUSBQueue::AbortDevicePipe(
+    IN UCHAR DeviceAddress,
+    IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS
 CreateUSBQueue(
     PUSBQUEUE *OutUsbQueue)
 {
@@ -962,3 +971,4 @@
     //
     return STATUS_SUCCESS;
 }
+

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -36,7 +36,7 @@
     }
 
     // IUSBRequest interface functions
-    virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
+    virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
     virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
     virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode, IN struct _QUEUE_HEAD *QueueHead);
     virtual VOID CancelCallback(IN NTSTATUS NtStatusCode, IN struct _QUEUE_HEAD *QueueHead);
@@ -62,6 +62,10 @@
     NTSTATUS BuildSetupPacket();
     NTSTATUS BuildSetupPacketFromURB();
     ULONG InternalCalculateTransferLength();
+    NTSTATUS BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset);
+    VOID InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength);
+    VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead);
+
 
     // constructor / destructor
     CUSBRequest(IUnknown *OuterUnknown){}
@@ -118,17 +122,12 @@
     //
     // store end point address
     //
-    PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
+    PUSB_ENDPOINT m_EndpointDescriptor;
 
     //
     // DMA queue head
     //
     PQUEUE_HEAD m_QueueHead;
-
-    //
-    // DMA transfer descriptors linked to the queue head
-    //
-    PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[4];
 
     //
     // allocated setup packet from the DMA pool
@@ -141,6 +140,8 @@
     //
     NTSTATUS m_NtStatusCode;
     ULONG m_UrbStatusCode;
+
+    PVOID m_Base;
 
 };
 
@@ -160,7 +161,7 @@
     IN PDMAMEMORYMANAGER DmaManager,
     IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
     IN UCHAR DeviceAddress,
-    IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+    IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
     IN OUT ULONG TransferBufferLength,
     IN OUT PMDL TransferBuffer)
 {
@@ -321,7 +322,7 @@
                 //
                 // get endpoint descriptor
                 //
-                m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+                m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
 
             }
             break;
@@ -587,7 +588,7 @@
         //
         // end point is defined in the low byte of bmAttributes
         //
-        TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
+        TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
     }
     else
     {
@@ -595,6 +596,7 @@
         // initialized with setup packet, must be a control transfer
         //
         TransferType = USB_ENDPOINT_TYPE_CONTROL;
+        ASSERT(m_EndpointDescriptor == FALSE);
     }
 
     //
@@ -606,13 +608,243 @@
 UCHAR
 CUSBRequest::InternalGetPidDirection()
 {
-    ASSERT(m_Irp);
-    ASSERT(m_EndpointDescriptor);
-
-    //
-    // end point is defined in the low byte of bEndpointAddress
-    //
-    return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
+    if (m_EndpointDescriptor)
+    {
+        //
+        // end point direction is highest bit in bEndpointAddress
+        //
+        return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
+    }
+    else
+    {
+        //
+        // request arrives on the control pipe, extract direction from setup packet
+        //
+        ASSERT(m_DescriptorPacket);
+        return (m_DescriptorPacket->bmRequestType.B >> 7);
+    }
+}
+
+VOID
+CUSBRequest::InitDescriptor(
+    IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor,
+    IN PVOID TransferBuffer,
+    IN ULONG TransferBufferLength,
+    IN UCHAR PidCode,
+    IN UCHAR DataToggle,
+    OUT PULONG OutDescriptorLength)
+{
+    ULONG Index, Length = 0, PageOffset, BufferLength;
+
+    //
+    // init transfer descriptor
+    //
+    CurrentDescriptor->Token.Bits.PIDCode = PidCode;
+    CurrentDescriptor->Token.Bits.TotalBytesToTransfer = 0;
+    CurrentDescriptor->Token.Bits.DataToggle = DataToggle;
+
+    //
+    // sanity check
+    //
+    ASSERT(TransferBufferLength);
+
+    //
+    // store buffers
+    //
+    Index = 0;
+    do
+    {
+        //
+        // use physical address
+        //
+        CurrentDescriptor->BufferPointer[Index] = MmGetPhysicalAddress(TransferBuffer).LowPart;
+
+        //
+        // Get the offset from page size
+        //
+        PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]);
+        if (PageOffset != 0)
+        {
+           //
+           // move to next page
+           //
+           TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer);
+        }
+        else
+        {
+            //
+            // move to next page
+            //
+            TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE);
+        }
+
+        //
+        // calculate buffer length
+        //
+        BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset);
+
+        //
+        // increment transfer bytes
+        //
+        CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
+        CurrentDescriptor->TotalBytesToTransfer += BufferLength;
+        Length += BufferLength;
+        DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer);
+
+        //
+        // decrement available byte count
+        //
+        TransferBufferLength -= BufferLength;
+        if (TransferBufferLength == 0)
+        {
+            //
+            // end reached
+            //
+            break;
+        }
+
+        //
+        // sanity check
+        //
+        if (Index > 1)
+        {
+            //
+            // no equal buffers
+            //
+            ASSERT(CurrentDescriptor->BufferPointer[Index] != CurrentDescriptor->BufferPointer[Index-1]);
+        }
+
+        //
+        // next descriptor index
+        //
+        Index++;
+    }while(Index < 5);
+
+    //
+    // store result
+    //
+    *OutDescriptorLength = Length;
+}
+
+
+NTSTATUS
+CUSBRequest::BuildTransferDescriptorChain(
+    IN PQUEUE_HEAD QueueHead,
+    IN PVOID TransferBuffer,
+    IN ULONG TransferBufferLength,
+    IN UCHAR PidCode,
+    IN UCHAR InitialDataToggle,
+    OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor,
+    OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor,
+    OUT PUCHAR OutDataToggle,
+    OUT PULONG OutTransferBufferOffset)
+{
+    PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
+    NTSTATUS Status;
+    ULONG DescriptorLength, TransferBufferOffset  = 0;
+
+    do
+    {
+        //
+        // allocate transfer descriptor
+        //
+        Status = CreateDescriptor(&CurrentDescriptor);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to allocate transfer descriptor
+            //
+            ASSERT(FALSE);
+            return Status;
+        }
+
+        //
+        // now init the descriptor
+        //
+        InitDescriptor(CurrentDescriptor, 
+                       (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
+                       TransferBufferLength - TransferBufferOffset,
+                       PidCode,
+                       InitialDataToggle,
+                       &DescriptorLength);
+
+        //
+        // insert into queue head
+        //
+        InsertTailList(&QueueHead->TransferDescriptorListHead, &CurrentDescriptor->DescriptorEntry);
+
+        //
+        // adjust offset
+        //
+        TransferBufferOffset += DescriptorLength;
+
+        if (LastDescriptor)
+        {
+            //
+            // link to current descriptor
+            //
+            LastDescriptor->AlternateNextPointer = CurrentDescriptor->PhysicalAddr;
+            LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
+            LastDescriptor = CurrentDescriptor;
+        }
+        else
+        {
+            //
+            // first descriptor in chain
+            //
+            LastDescriptor = FirstDescriptor = CurrentDescriptor;
+        }
+
+        if(TransferBufferLength == TransferBufferOffset)
+        {
+            //
+            // end reached
+            //
+            break;
+        }
+    }while(TRUE);
+
+    if (OutFirstDescriptor)
+    {
+        //
+        // store first descriptor
+        //
+        *OutFirstDescriptor = FirstDescriptor;
+    }
+
+    if (OutLastDescriptor)
+    {
+        //
+        // store last descriptor
+        //
+        *OutLastDescriptor = CurrentDescriptor;
+    }
+
+    if (OutDataToggle)
+    {
+        //
+        // flip data toggle
+        //
+        InitialDataToggle = !InitialDataToggle;
+
+        //
+        // store result data toggle
+        //
+        *OutDataToggle = InitialDataToggle;
+    }
+
+    if (OutTransferBufferOffset)
+    {
+        //
+        // store offset
+        //
+        *OutTransferBufferOffset = TransferBufferOffset;
+    }
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
 }
 
 //----------------------------------------------------------------------------------------
@@ -621,8 +853,9 @@
     PQUEUE_HEAD * OutHead)
 {
     NTSTATUS Status;
-    ULONG NumTransferDescriptors, Index;
+    ULONG DescriptorChainLength;
     PQUEUE_HEAD QueueHead;
+    PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor;
 
     //
     // first allocate the queue head
@@ -650,30 +883,34 @@
         //
         // failed to allocate setup packet
         //
+        ASSERT(FALSE);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     //
-    // calculate num of transfer descriptors
-    //
-    NumTransferDescriptors = m_TransferBufferMDL != 0 ? 3 : 2;
-
-    //
-    // allocate transfer descriptors
-    //
-    for(Index = 0; Index < NumTransferDescriptors; Index++)
-    {
-        //
-        // allocate transfer descriptor
-        //
-        Status = CreateDescriptor(&m_TransferDescriptors[Index]);
-        if (!NT_SUCCESS(Status))
-        {
-            //
-            // failed to allocate transfer descriptor
-            //
-            return Status;
-        }
+    // create setup descriptor
+    //
+    Status = CreateDescriptor(&SetupDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to allocate transfer descriptor
+        //
+        ASSERT(FALSE);
+        return Status;
+    }
+
+    //
+    // create status descriptor
+    //
+    Status = CreateDescriptor(&StatusDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to allocate transfer descriptor
+        //
+        ASSERT(FALSE);
+        return Status;
     }
 
     //
@@ -686,102 +923,86 @@
         //
         // set endpoint address and max packet length
         //
-        QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F;
-        QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize;
-    }
-
-    //
-    // setup descriptors
-    //
-    m_TransferDescriptors[0]->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
-    m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
-    m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE;
-    m_TransferDescriptors[0]->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart);
-    m_TransferDescriptors[0]->NextPointer = m_TransferDescriptors[1]->PhysicalAddr;
-    m_TransferDescriptors[0]->AlternateNextPointer = m_TransferDescriptors[1]->PhysicalAddr;
-
-    if (m_TransferBufferMDL)
-    {
-        //
-        // setup in descriptor
-        //
-        m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
-        m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = m_TransferBufferLength;
-        m_TransferDescriptors[1]->NextPointer = m_TransferDescriptors[2]->PhysicalAddr;
-        m_TransferDescriptors[1]->Token.Bits.DataToggle = TRUE;
-        m_TransferDescriptors[1]->AlternateNextPointer = m_TransferDescriptors[2]->PhysicalAddr;
-
-        //
-        // FIXME: check if the request spawns over a page -> fill other members
-        //
-        PC_ASSERT(m_TransferBufferLength <= PAGE_SIZE);
-        m_TransferDescriptors[1]->BufferPointer[0] = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
-
-        //
-        // setup out descriptor
-        //
-        m_TransferDescriptors[2]->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN;
-        m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer = 0;
-        m_TransferDescriptors[2]->Token.Bits.DataToggle = TRUE;
-
-        //
-        // special case, setup alternative next descriptor in case of error
-        // HAIKU links to dead descriptor
-        //
-
-        //
-        // interrupt on completion
-        //
-        m_TransferDescriptors[2]->Token.Bits.InterruptOnComplete = TRUE;
+        QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
+        QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
+    }
+
+    //
+    // init setup descriptor
+    //
+    SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
+    SetupDescriptor->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
+    SetupDescriptor->Token.Bits.DataToggle = FALSE;
+    SetupDescriptor->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart);
+    InsertTailList(&QueueHead->TransferDescriptorListHead, &SetupDescriptor->DescriptorEntry);
+
+
+    //
+    // init status descriptor
+    //
+    StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0;
+    StatusDescriptor->Token.Bits.DataToggle = TRUE;
+    StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE;
+
+    //
+    // is there data
+    //
+    if (m_TransferBufferLength)
+    {
+        Status = BuildTransferDescriptorChain(QueueHead,
+                                              MmGetMdlVirtualAddress(m_TransferBufferMDL),
+                                              m_TransferBufferLength,
+                                              InternalGetPidDirection(),
+                                              TRUE,
+                                              &FirstDescriptor,
+                                              &LastDescriptor,
+                                              NULL,
+                                              &DescriptorChainLength);
+
+        //
+        // FIXME handle errors
+        //
+        ASSERT(Status == STATUS_SUCCESS);
+        ASSERT(DescriptorChainLength == m_TransferBufferLength);
+
+        //
+        // now link the descriptors
+        //
+        SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr;
+        SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr;
+        LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
+        LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
+
+
+        //
+        // pid code is flipped for ops with data stage
+        //
+        StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection();
     }
     else
     {
         //
-        // no buffer, setup in descriptor
-        //
-        m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
-        m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = 0;
-        m_TransferDescriptors[1]->Token.Bits.DataToggle = TRUE;
-
-        //
-        // interrupt on completion
-        //
-        m_TransferDescriptors[1]->Token.Bits.InterruptOnComplete = TRUE;
-    }
+        // direct link
+        //
+        SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
+        SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
+
+        //
+        // retrieve result of operation
+        //
+        StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
+    }
+
+    //
+    // insert status descriptor
+    //
+    InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry);
+
 
     //
     // link transfer descriptors to queue head
     //
-    QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
-
-    DPRINT("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr);
-    DPRINT("NumDescriptors %lu\n", NumTransferDescriptors);
-    DPRINT("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer);
-    DPRINT("QueueHead NextPointer %x\n", QueueHead->NextPointer);
-    DPRINT("m_DescriptorSetupPacket HiPart %x LoPart %x\n", m_DescriptorSetupPacket.HighPart, m_DescriptorSetupPacket.LowPart);
-
-
-    DPRINT("TransferDescriptor 0 Addr %x\n", m_TransferDescriptors[0]->PhysicalAddr);
-    DPRINT("TransferDescriptor 0 Next %x\n", m_TransferDescriptors[0]->NextPointer);
-    DPRINT("TransferDescriptor 0 AlternativeNext %x\n", m_TransferDescriptors[0]->AlternateNextPointer);
-    DPRINT("TransferDescriptor 0 Buffer Pointer %x\n", m_TransferDescriptors[0]->BufferPointer[0]);
-    DPRINT("TransferDescriptor 0 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer);
-
-    DPRINT("TransferDescriptor 1 Addr %x\n", m_TransferDescriptors[1]->PhysicalAddr);
-    DPRINT("TransferDescriptor 1 Next %x\n", m_TransferDescriptors[1]->NextPointer);
-    DPRINT("TransferDescriptor 1 AlternativeNext %x\n", m_TransferDescriptors[1]->AlternateNextPointer);
-    DPRINT("TransferDescriptor 1 Buffer Pointer %x\n", m_TransferDescriptors[1]->BufferPointer[0]);
-    DPRINT("TransferDescriptor 1 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer);
-
-    if (NumTransferDescriptors == 3)
-    {
-        DPRINT("TransferDescriptor 2 Addr %x\n", m_TransferDescriptors[2]->PhysicalAddr);
-        DPRINT("TransferDescriptor 2 Next %x\n", m_TransferDescriptors[2]->NextPointer);
-        DPRINT("TransferDescriptor 2 AlternativeNext %x\n", m_TransferDescriptors[2]->AlternateNextPointer);
-        DPRINT("TransferDescriptor 2 Buffer Pointer %x\n", m_TransferDescriptors[2]->BufferPointer[0]);
-        DPRINT("TransferDescriptor 2 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer);
-    }
-
+    QueueHead->NextPointer = SetupDescriptor->PhysicalAddr;
 
     //
     // store result
@@ -789,10 +1010,80 @@
     *OutHead = QueueHead;
 
     //
+    // displays the current request
+    //
+    //DumpQueueHead(QueueHead);
+
+    DPRINT1("BuildControlTransferQueueHead done\n");
+    //
     // done
     //
     return STATUS_SUCCESS;
 }
+
+VOID
+CUSBRequest::DumpQueueHead(
+    IN PQUEUE_HEAD QueueHead)
+{
+    PLIST_ENTRY Entry;
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+    ULONG Index = 0;
+
+    DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr);
+    DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer);
+    DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer);
+
+    DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCharacteristics.ControlEndPointFlag);
+    DPRINT1("QueueHead DeviceAddress %x\n", QueueHead->EndPointCharacteristics.DeviceAddress);
+    DPRINT1("QueueHead EndPointNumber %x\n", QueueHead->EndPointCharacteristics.EndPointNumber);
+    DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead->EndPointCharacteristics.EndPointSpeed);
+    DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead->EndPointCharacteristics.HeadOfReclamation);
+    DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead->EndPointCharacteristics.InactiveOnNextTransaction);
+    DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead->EndPointCharacteristics.MaximumPacketLength);
+    DPRINT1("QueueHead NakCountReload %x\n", QueueHead->EndPointCharacteristics.NakCountReload);
+    DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead->EndPointCharacteristics.QEDTDataToggleControl);
+    DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCapabilities.HubAddr);
+    DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead->EndPointCapabilities.InterruptScheduleMask);
+    DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame);
+    DPRINT1("QueueHead PortNumber %x\n", QueueHead->EndPointCapabilities.PortNumber);
+    DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead->EndPointCapabilities.SplitCompletionMask);
+
+    Entry = QueueHead->TransferDescriptorListHead.Flink;
+    while(Entry != &QueueHead->TransferDescriptorListHead)
+    {
+        //
+        // get transfer descriptor
+        //
+        Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
+
+        DPRINT1("TransferDescriptor %lu Addr %x\n", Index, Descriptor->PhysicalAddr);
+        DPRINT1("TransferDescriptor %lu Next %x\n", Index, Descriptor->NextPointer);
+        DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index, Descriptor->AlternateNextPointer);
+        DPRINT1("TransferDescriptor %lu Active %lu\n", Index, Descriptor->Token.Bits.Active);
+        DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index, Descriptor->Token.Bits.BabbleDetected);
+        DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index, Descriptor->Token.Bits.CurrentPage);
+        DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index, Descriptor->Token.Bits.DataBufferError);
+        DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index, Descriptor->Token.Bits.DataToggle);
+        DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index, Descriptor->Token.Bits.ErrorCounter);
+        DPRINT1("TransferDescriptor %lu Halted %lu\n", Index, Descriptor->Token.Bits.Halted);
+        DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index, Descriptor->Token.Bits.InterruptOnComplete);
+        DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index, Descriptor->Token.Bits.MissedMicroFrame);
+        DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index, Descriptor->Token.Bits.PIDCode);
+        DPRINT1("TransferDescriptor %lu PingState %lu\n", Index, Descriptor->Token.Bits.PingState);
+        DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index, Descriptor->Token.Bits.SplitTransactionState);
+        DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index, Descriptor->Token.Bits.TotalBytesToTransfer);
+        DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index, Descriptor->Token.Bits.TransactionError);
+
+        DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index, Descriptor->BufferPointer[0]);
+        DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index, Descriptor->BufferPointer[1]);
+        DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index, Descriptor->BufferPointer[2]);
+        DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index, Descriptor->BufferPointer[3]);
+        DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index, Descriptor->BufferPointer[4]);
+        Entry = Entry->Flink;
+        Index++;
+    }
+}
+
 
 //----------------------------------------------------------------------------------------
 NTSTATUS
@@ -801,11 +1092,9 @@
 {
     NTSTATUS Status;
     PQUEUE_HEAD QueueHead;
-    ULONG TransferDescriptorCount, Index;
-    ULONG BytesAvailable, BufferIndex;
     PVOID Base;
-    ULONG PageOffset, CurrentTransferBufferLength;
-    UCHAR DataToggle;
+    ULONG ChainDescriptorLength;
+    PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
 
     //
     // Allocate the queue head
@@ -826,279 +1115,81 @@
     PC_ASSERT(QueueHead);
     PC_ASSERT(m_TransferBufferLength);
 
-    //
-    // Max default of 3 descriptors
-    //
-    TransferDescriptorCount = 3;
-
-    //
-    // get virtual base of mdl
-    //
-    Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
+    if (!m_Base)
+    {
+        //
+        // get virtual base of mdl
+        //
+        m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
+    }
 
     //
     // Increase the size of last transfer, 0 in case this is the first
     //
-    Base = (PVOID)((ULONG_PTR)Base + m_TransferBufferLengthCompleted);
+    Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
 
     PC_ASSERT(m_EndpointDescriptor);
     PC_ASSERT(Base);
 
     //
-    // Get the offset from page size
-    //
-    PageOffset = BYTE_OFFSET(Base);
-
-    //
-    // PageOffset should only be > 0 if this is the  first transfer for this requests
-    //
-    if ((PageOffset != 0) && (m_TransferBufferLengthCompleted != 0))
-    {
-        ASSERT(FALSE);
-    }
-
-    //
-    // Calculate the size of this transfer
-    //
-    if ((PageOffset != 0) && ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= (PAGE_SIZE * 4) + PageOffset))
-    {
-        CurrentTransferBufferLength = (PAGE_SIZE * 4) + PageOffset;
-    }
-    else if ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= PAGE_SIZE * 5)
-    {
-        CurrentTransferBufferLength = PAGE_SIZE * 5;
-    }
-    else
-        CurrentTransferBufferLength = (m_TransferBufferLength - m_TransferBufferLengthCompleted);
-
-    //
-    // Add current transfer length to transfer length completed
-    //
-    m_TransferBufferLengthCompleted += CurrentTransferBufferLength;
-    BytesAvailable = CurrentTransferBufferLength;
-
-    DPRINT1("BuildBulkTransferQueueHead\n");
-    DPRINT("CurrentTransferBufferLength %x, m_TransferBufferLengthCompleted %x\n", CurrentTransferBufferLength, m_TransferBufferLengthCompleted);
-
-    DPRINT("EndPointAddress %x\n", m_EndpointDescriptor->bEndpointAddress);
-    DPRINT("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
-
-    DPRINT("Request %p Base Address %p TransferBytesLength %lu MDL %p\n", this, Base, BytesAvailable, m_TransferBufferMDL);
-    DPRINT("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->bEndpointAddress & 0x0F);
-    DPRINT("Irp %p QueueHead %p\n", m_Irp, QueueHead);
-
-    //PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
-
-    //
-    // DataToggle
-    //
-    DataToggle = FALSE;
-
-    //
-    // Allocated transfer descriptors
-    //
-    for (Index = 0; Index < TransferDescriptorCount; Index++)
-    {
-        Status = CreateDescriptor(&m_TransferDescriptors[Index]);
-        if (!NT_SUCCESS(Status))
-        {
-            //
-            // Failed to allocate transfer descriptors
-            //
-
-            //
-            // Free QueueHead
-            //
-            FreeQueueHead(QueueHead);
-
-            //
-            // Free Descriptors
-            // FIXME: Implement FreeDescriptors
-            //
-            return Status;
-        }
-
-        //
-        // sanity check
-        //
-        PC_ASSERT(BytesAvailable);
-
-        //
-        // now setup transfer buffers
-        //
-        for(BufferIndex = 0; BufferIndex < 5; BufferIndex++)
-        {
-            //
-            // If this is the first buffer of the first descriptor and there is a PageOffset
-            //
-            if ((BufferIndex == 0) && (PageOffset != 0) && (Index == 0))
-            {
-                //
-                // use physical address
-                //
-                m_TransferDescriptors[Index]->BufferPointer[0] = MmGetPhysicalAddress(Base).LowPart;
-
-                //
-                // move to next page
-                //
-                Base = (PVOID)ROUND_TO_PAGES(Base);
-
-                //
-                // increment transfer bytes
-                //
-                if (CurrentTransferBufferLength > PAGE_SIZE - PageOffset)
-                    m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = PAGE_SIZE - PageOffset;
-                else
-                    m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = CurrentTransferBufferLength;
-
-                //
-                // decrement available byte count
-                //
-                BytesAvailable -= m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer;
-
-                DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
-                    BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
-            }
-            else
-            {
-                //
-                // the following pages always start on byte zero of each page
-                //
-                PC_ASSERT(((ULONG_PTR)Base & (PAGE_SIZE-1)) == 0);
-
-                if (BytesAvailable >= PAGE_SIZE)
-                {
-                    //
-                    // store address
-                    //
-                    m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart;
-
-                    //
-                    // move to next page
-                    //
-                    Base = (PVOID)((ULONG_PTR)Base + PAGE_SIZE);
-
-                    //
-                    // increment transfer descriptor bytes
-                    //
-                    m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += PAGE_SIZE;
-
-                    //
-                    // decrement available byte count
-                    //
-                    BytesAvailable -= PAGE_SIZE;
-
-                    DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
-                            BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
-                }
-                else
-                {
-                    PC_ASSERT(BytesAvailable);
-
-                    if (BytesAvailable)
-                    {
-                        //
-                        // store address
-                        //
-                        m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart;
-
-                       //
-                       // increment transfer descriptor bytes
-                       //
-                       m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += BytesAvailable;
-
-                       //
-                       // decrement available byte count
-                       //
-                       BytesAvailable -= BytesAvailable;
-
-                       //
-                       // done as this is the last partial or full page
-                       //
-                    }
-                    DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
-                            BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
-
-                    break;
-                }
-            }
-
-            //
-            // Check if all bytes have been consumed
-            //
-            if (BytesAvailable == 0)
-                break;
-        }
-
-        //
-        // Go ahead and link descriptors
-        //
-        if (Index > 0)
-        {
-            m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr;
-        }
-
-
-        //
-        // status descriptor
-        //
-        m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE;
-
-        //
-        // FIXME: need status descriptor?
-        //
-
-        //
-        // setup direction
-        //
-        m_TransferDescriptors[Index]->Token.Bits.PIDCode = InternalGetPidDirection();
-
-        //
-        // set data toggle
-        //
-        m_TransferDescriptors[Index]->Token.Bits.DataToggle = DataToggle;
-        DataToggle = !DataToggle;
-
-        //
-        // Check if all bytes have been consumed
-        //
-        if (BytesAvailable == 0)
-            break;
-    }
-
-    //
-    // all bytes should have been consumed
-    //
-    PC_ASSERT(BytesAvailable == 0);
-
-    //
-    // Initialize the QueueHead
+    // sanity check
+    //
+    ASSERT(m_EndpointDescriptor);
+
+    //
+    // build bulk transfer descriptor chain
+    //
+    Status = BuildTransferDescriptorChain(QueueHead,
+                                          Base,
+                                          m_TransferBufferLength - m_TransferBufferLengthCompleted,
+                                          InternalGetPidDirection(),
+                                          m_EndpointDescriptor->DataToggle,
+                                          &FirstDescriptor,
+                                          &LastDescriptor,
+                                          &m_EndpointDescriptor->DataToggle,
+                                          &ChainDescriptorLength);
+
+    //
+    // FIXME: handle errors
+    //
+    ASSERT(ChainDescriptorLength == m_TransferBufferLength);
+
+    //
+    // move to next offset
+    //
+    m_TransferBufferLengthCompleted += ChainDescriptorLength;
+
+    ASSERT(Status == STATUS_SUCCESS);
+
+    //
+    // init queue head
     //
     QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
-
-    if (m_EndpointDescriptor)
-    {
-        //
-        // Set endpoint address and max packet length
-        //
-        QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F;
-        QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize;
-    }
-
-    //
-    // store number of transactions
-    //
-    QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = min(Index, 1);
-
-    //
-    // link descriptor with queue head
-    //
-    QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
+    QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
+    QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
+    QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
+    QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr;
+    QueueHead->AlternateNextPointer = TERMINATE_POINTER;
+
+    ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
+    ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
+    ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength);
+    ASSERT(QueueHead->NextPointer);
+
+    //
+    // interrupt on last descriptor
+    //
+    LastDescriptor->Token.Bits.InterruptOnComplete = TRUE;
 
     //
     // store result
     //
     *OutHead = QueueHead;
+
+    //
+    // dump status
+    //
+    //DumpQueueHead(QueueHead);
 
     //
     // done
@@ -1176,6 +1267,7 @@
     QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
     QueueHead->AlternateNextPointer = TERMINATE_POINTER;
     QueueHead->NextPointer = TERMINATE_POINTER;
+    InitializeListHead(&QueueHead->TransferDescriptorListHead);
 
     //
     // 1 for non high speed, 0 for high speed device
@@ -1536,12 +1628,50 @@
 CUSBRequest::FreeQueueHead(
     IN struct _QUEUE_HEAD * QueueHead)
 {
-    LONG DescriptorCount;
-
-    //
-    // FIXME: support chained queue heads
-    //
-    //PC_ASSERT(QueueHead == m_QueueHead);
+    PLIST_ENTRY Entry;
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+
+    //
+    // sanity checks
+    //
+    ASSERT(m_DmaManager);
+    ASSERT(QueueHead);
+    ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
+
+    do
+    {
+        //
+        // get transfer descriptors
+        //
+        Entry = RemoveHeadList(&QueueHead->TransferDescriptorListHead);
+        ASSERT(Entry);
+
+        //
+        // obtain descriptor from entry
+        //
+        Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
+        ASSERT(Descriptor);
+
+        //
+        // add transfer count
+        //
+        m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
+        DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor, Descriptor->PhysicalAddr, Descriptor->TotalBytesToTransfer, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
+
+        //
+        // release transfer descriptors
+        //
+        m_DmaManager->Release(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
+
+    }while(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
+
+    if (m_DescriptorPacket)
+    {
+        //
+        // release packet descriptor
+        //
+        m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    }
 
     //
     // release queue head
@@ -1549,57 +1679,10 @@
     m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
 
     //
-    // nullify pointer
+    // nullify pointers
     //
     m_QueueHead = 0;
-
-    //
-    // release transfer descriptors
-    //
-    for (DescriptorCount = 0; DescriptorCount < 3; DescriptorCount++)
-    {
-        if (m_TransferDescriptors[DescriptorCount])
-        {
-            //
-            // Calculate Total Bytes Transferred
-            // FIXME: Is this the correct method of determine bytes transferred?
-            //
-            if (USB_ENDPOINT_TYPE_BULK == GetTransferType())
-            {
-                //
-                // sanity check
-                //
-                ASSERT(m_EndpointDescriptor);
-
-                if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress))
-                {
-                    DPRINT("m_TotalBytesTransferred %x, %x - %x\n",
-                        m_TotalBytesTransferred,
-                        m_TransferDescriptors[DescriptorCount]->TotalBytesToTransfer,
-                        m_TransferDescriptors[DescriptorCount]->Token.Bits.TotalBytesToTransfer);
-
-                    m_TotalBytesTransferred +=
-                        m_TransferDescriptors[DescriptorCount]->TotalBytesToTransfer -
-                        m_TransferDescriptors[DescriptorCount]->Token.Bits.TotalBytesToTransfer;
-                }
-            }
-
-            //
-            // release transfer descriptors
-            //
-            m_DmaManager->Release(m_TransferDescriptors[DescriptorCount], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
-            m_TransferDescriptors[DescriptorCount] = 0;
-        }
-    }
-
-    if (m_DescriptorPacket)
-    {
-        //
-        // release packet descriptor
-        //
-        m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
-        m_DescriptorPacket = 0;
-    }
+    m_DescriptorPacket = 0;
 }
 
 //-----------------------------------------------------------------------------------------
@@ -1607,7 +1690,8 @@
 CUSBRequest::IsQueueHeadComplete(
     struct _QUEUE_HEAD * QueueHead)
 {
-    ULONG Index;
+    PLIST_ENTRY Entry;
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
 
     //
     // first check - is the queue head currently active
@@ -1617,39 +1701,50 @@
         //
         // queue head is active (currently processed)
         //
-        ASSERT(QueueHead->Token.Bits.Halted == FALSE);
-        //return FALSE;
-    }
-
-    //
-    // FIXME: support chained queue heads
-    //
-    for(Index = 0; Index < 3; Index++)
-    {
-        //
-        // check transfer descriptors for completion
-        //
-        if (m_TransferDescriptors[Index])
+        return FALSE;
+    }
+
+    if (QueueHead->Token.Bits.Halted)
+    {
+        //
+        // error occured
+        //
+        DPRINT1("Found halted queue head %p\n", QueueHead);
+        DumpQueueHead(QueueHead);
+        ASSERT(FALSE);
+        return TRUE;
+    }
+
+    //
+    // loop list and see if there are any active descriptors
+    //
+    Entry = QueueHead->TransferDescriptorListHead.Flink;
+    while(Entry != &QueueHead->TransferDescriptorListHead)
+    {
+        //
+        // obtain descriptor from entry
+        //
+        Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
+        ASSERT(Descriptor);
+        if (Descriptor->Token.Bits.Active)
         {
             //
-            // check for serious error
-            //
-            DPRINT("Descriptor Addr %x\n", m_TransferDescriptors[Index]->PhysicalAddr);
-            DPRINT("Descriptor BabbleDetected %x\n", m_TransferDescriptors[Index]->Token.Bits.BabbleDetected);
-            DPRINT("Descriptor DataBufferError %x\n", m_TransferDescriptors[Index]->Token.Bits.DataBufferError);
-            DPRINT("Descriptor DataToggle %x\n", m_TransferDescriptors[Index]->Token.Bits.DataToggle);
-            DPRINT("Descriptor ErrorCounter %x\n", m_TransferDescriptors[Index]->Token.Bits.ErrorCounter);
-            DPRINT("Descriptor TransactionError %x\n", m_TransferDescriptors[Index]->Token.Bits.TransactionError);
-
-
-            //
-            // the transfer descriptor should be in the same state as the queue head
-            //
-            //PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
+            // descriptor is still active
+            //
+            return FALSE;
         }
-    }
-    //ASSERT(FALSE);
-
+
+         //
+         // move to next entry
+         //
+         Entry = Entry->Flink;
+    }
+
+    DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr);
+
+    //
+    // no active descriptors found, queue head is finished
+    //
     return TRUE;
 }
 
@@ -1682,8 +1777,7 @@
     // sanity check
     //
     ASSERT(m_EndpointDescriptor);
-
-    if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress))
+    if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress))
     {
         //
         // bulk in request

Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h
URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h?rev=55530&r1=55529&r2=55530&view=diff
==============================================================================
--- branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h [iso-8859-1] (original)
+++ branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h [iso-8859-1] Fri Feb 10 20:15:39 2012
@@ -38,6 +38,28 @@
 #define C_PORT_SUSPEND      18
 #define C_PORT_OVER_CURRENT 19
 #define C_PORT_RESET        20
+
+typedef struct _USB_ENDPOINT
+{
+    USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
+    UCHAR HubAddress;
+    UCHAR HubPort;
+    UCHAR DataToggle;
+} USB_ENDPOINT, *PUSB_ENDPOINT;
+
+typedef struct _USB_INTERFACE
+{
+    USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+    USB_ENDPOINT *EndPoints;
+} USB_INTERFACE, *PUSB_INTERFACE;
+
+typedef struct _USB_CONFIGURATION
+{
+    USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+    USB_INTERFACE *Interfaces;
+} USB_CONFIGURATION, *PUSB_CONFIGURATION;
+
+
 
 typedef struct
 {




More information about the Ros-diffs mailing list