Author: janderwald
Date: Wed Feb 22 17:24:43 2012
New Revision: 55809

URL: http://svn.reactos.org/svn/reactos?rev=55809&view=rev
Log:
[USBUHCI]
- Queue dpc when the interrupt indicates completion of a transfer or an error 
interrupt
- Implement checking if a queue head is complete
- Free queue heads and associated endpoint descriptors

Modified:
    trunk/reactos/drivers/usb/usbuhci/hardware.cpp
    trunk/reactos/drivers/usb/usbuhci/hardware.h
    trunk/reactos/drivers/usb/usbuhci/interfaces.h
    trunk/reactos/drivers/usb/usbuhci/usb_queue.cpp
    trunk/reactos/drivers/usb/usbuhci/usb_request.cpp

Modified: trunk/reactos/drivers/usb/usbuhci/hardware.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbuhci/hardware.cpp?rev=55809&r1=55808&r2=55809&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbuhci/hardware.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbuhci/hardware.cpp [iso-8859-1] Wed Feb 22 
17:24:43 2012
@@ -686,7 +686,7 @@
         m_QueueHead[Index]->PhysicalAddress = Address.LowPart;
         m_QueueHead[Index]->ElementPhysical = QH_TERMINATE;
 
-        if (Index > 1)
+        if (Index > 0)
         {
             //
             // link queue heads
@@ -696,6 +696,48 @@
         }
     }
 
+            DPRINT1("Index %lu QueueHead %p LinkPhysical %x ElementPhysical %x 
PhysicalAddress %x Request %x NextElementDescriptor %x\n",
+                0,
+                m_QueueHead[0], 
+                m_QueueHead[0]->LinkPhysical,
+                m_QueueHead[0]->ElementPhysical,
+                m_QueueHead[0]->PhysicalAddress, 
+                m_QueueHead[0]->Request, 
+                m_QueueHead[0]->NextElementDescriptor);
+            DPRINT1("Index %lu QueueHead %p LinkPhysical %x ElementPhysical %x 
PhysicalAddress %x Request %x NextElementDescriptor %x\n",
+                1,
+                m_QueueHead[1], 
+                m_QueueHead[1]->LinkPhysical,
+                m_QueueHead[1]->ElementPhysical,
+                m_QueueHead[1]->PhysicalAddress, 
+                m_QueueHead[1]->Request, 
+                m_QueueHead[1]->NextElementDescriptor);
+
+            DPRINT1("Index %lu QueueHead %p LinkPhysical %x ElementPhysical %x 
PhysicalAddress %x Request %x NextElementDescriptor %x\n",
+                2,
+                m_QueueHead[2], 
+                m_QueueHead[2]->LinkPhysical,
+                m_QueueHead[2]->ElementPhysical,
+                m_QueueHead[2]->PhysicalAddress, 
+                m_QueueHead[2]->Request, 
+                m_QueueHead[2]->NextElementDescriptor);
+            DPRINT1("Index %lu QueueHead %p LinkPhysical %x ElementPhysical %x 
PhysicalAddress %x Request %x NextElementDescriptor %x\n",
+                3,
+                m_QueueHead[3], 
+                m_QueueHead[3]->LinkPhysical,
+                m_QueueHead[3]->ElementPhysical,
+                m_QueueHead[3]->PhysicalAddress, 
+                m_QueueHead[3]->Request, 
+                m_QueueHead[3]->NextElementDescriptor);
+            DPRINT1("Index %lu QueueHead %p LinkPhysical %x ElementPhysical %x 
PhysicalAddress %x Request %x NextElementDescriptor %x\n",
+                4,
+                m_QueueHead[4], 
+                m_QueueHead[4]->LinkPhysical,
+                m_QueueHead[4]->ElementPhysical,
+                m_QueueHead[4]->PhysicalAddress, 
+                m_QueueHead[4]->Request, 
+                m_QueueHead[4]->NextElementDescriptor);
+
     //
     // terminate last queue head with stray descriptor
     //
@@ -708,7 +750,7 @@
         DPRINT1("[USBUHCI] Failed to allocate queue head %x Index %x\n", 
Status, Index);
         return Status;
     }
-
+#if 0
     //
     // init stray descriptor
     //
@@ -722,7 +764,7 @@
     //
     m_QueueHead[4]->LinkPhysical = m_StrayDescriptor->PhysicalAddress;
     m_QueueHead[4]->NextLogicalDescriptor = m_StrayDescriptor;
-
+#endif
 
     //
     // allocate frame bandwidth array
@@ -1271,7 +1313,14 @@
     if (Acknowledge)
     {
         //
+        // acknowledge interrupt
+        //
         This->WriteRegister16(UHCI_USBSTS, Acknowledge);
+
+        //
+        // queue dpc
+        //
+        KeInsertQueueDpc(&This->m_IntDpcObject, UlongToPtr(Status), NULL);
     }
 
     //
@@ -1356,6 +1405,7 @@
     IN PVOID SystemArgument2)
 {
     CUSBHardwareDevice *This;
+    ULONG Status;
 
     //
     // get parameters
@@ -1363,8 +1413,24 @@
     This = (CUSBHardwareDevice*)DeferredContext;
 
     DPRINT("OhciDefferedRoutine\n");
-    ASSERT(FALSE);
-
+
+    //
+    // get status
+    //
+    Status = PtrToUlong(SystemArgument1);
+    if (Status & (UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT))
+    {
+        //
+        // a transfer finished, inform the queue
+        //
+        This->m_UsbQueue->TransferInterrupt(Status & UHCI_USBSTS_USBINT);
+        return;
+    }
+
+    //
+    // other event
+    //
+    DPRINT1("[USBUHCI] Status %x not handled\n", Status);
 }
 
 VOID

Modified: trunk/reactos/drivers/usb/usbuhci/hardware.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbuhci/hardware.h?rev=55809&r1=55808&r2=55809&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbuhci/hardware.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbuhci/hardware.h [iso-8859-1] Wed Feb 22 
17:24:43 2012
@@ -92,10 +92,11 @@
     ULONG BufferPhysical;   // pointer to the buffer
 
     // Software part
-    ULONG  PhysicalAddress;           // Physical address of this descriptor
+    ULONG PhysicalAddress;           // Physical address of this descriptor
     PVOID NextLogicalDescriptor;
-    ULONG  BufferSize;                // Size of the buffer
-    PVOID    BufferLogical;            // Logical pointer to the buffer
+    ULONG BufferSize;                // Size of the buffer
+    PVOID BufferLogical;            // Logical pointer to the buffer
+    PVOID UserBuffer;
 }UHCI_TRANSFER_DESCRIPTOR, *PUHCI_TRANSFER_DESCRIPTOR;
 
 #define        TD_NEXT_IS_QH                           0x02

Modified: trunk/reactos/drivers/usb/usbuhci/interfaces.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbuhci/interfaces.h?rev=55809&r1=55808&r2=55809&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbuhci/interfaces.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbuhci/interfaces.h [iso-8859-1] Wed Feb 22 
17:24:43 2012
@@ -437,6 +437,22 @@
 // Description: returns device speed
 
     virtual USB_DEVICE_SPEED GetDeviceSpeed() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// CompletionCallback
+//
+// Description: notifies request that the endpoint descriptor is complete
+
+    virtual VOID CompletionCallback() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// FreeEndpointDescriptor
+//
+// Description: frees the associated endpoint descriptor and its general 
descriptors
+
+    virtual VOID FreeEndpointDescriptor(struct _UHCI_QUEUE_HEAD * 
OutDescriptor) = 0;
 };
 
 
@@ -505,6 +521,14 @@
 // Description: aborts all pending requsts of an device
 
     virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN struct 
_USB_ENDPOINT * EndpointDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// TransferInterrupt
+//
+// Description: informs the queue that a interrupt completed
+
+    virtual VOID TransferInterrupt(UCHAR ErrorInterrupt) = 0;
 
 };
 

Modified: trunk/reactos/drivers/usb/usbuhci/usb_queue.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbuhci/usb_queue.cpp?rev=55809&r1=55808&r2=55809&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbuhci/usb_queue.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbuhci/usb_queue.cpp [iso-8859-1] Wed Feb 22 
17:24:43 2012
@@ -40,10 +40,16 @@
     virtual NTSTATUS CancelRequests();
     virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
     virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN struct 
_USB_ENDPOINT * EndpointDescriptor);
+    virtual VOID TransferInterrupt(UCHAR ErrorInterrupt);
 
 
     // local
     VOID LinkQueueHead(PUHCI_QUEUE_HEAD QueueHead, PUHCI_QUEUE_HEAD 
NextQueueHead);
+    VOID UnLinkQueueHead(PUHCI_QUEUE_HEAD PreviousQueueHead, PUHCI_QUEUE_HEAD 
NextQueueHead);
+    BOOLEAN IsQueueHeadComplete(PUHCI_QUEUE_HEAD QueueHead);
+    NTSTATUS AddQueueHead(PUHCI_QUEUE_HEAD NewQueueHead);
+    VOID QueueHeadCleanup(IN PUHCI_QUEUE_HEAD QueueHead, IN PUHCI_QUEUE_HEAD 
PreviousQueueHead, OUT PUHCI_QUEUE_HEAD *NextQueueHead);
+
 
     // constructor / destructor
     CUSBQueue(IUnknown *OuterUnknown){}
@@ -53,6 +59,7 @@
     LONG m_Ref;                                                                
         // reference count
     KSPIN_LOCK m_Lock;                                                         
         // list lock
     PUSBHARDWAREDEVICE m_Hardware;                                             
         // hardware
+    
 };
 
 
//=================================================================================================
@@ -106,25 +113,23 @@
 }
 
 NTSTATUS
-CUSBQueue::AddUSBRequest(
-    IUSBRequest * Request)
-{
-    PUHCI_QUEUE_HEAD NewQueueHead, QueueHead = NULL;
-    NTSTATUS Status;
-
-    DPRINT("CUSBQueue::AddUSBRequest\n");
-
-    //
-    // get queue head
-    //
-    Status = Request->GetEndpointDescriptor(&NewQueueHead);
-    if (!NT_SUCCESS(Status))
-    {
-        //
-        // failed to create queue head
-        //
-        DPRINT1("[USBUHCI] Failed to create queue head %x\n", Status);
-        return Status;
+CUSBQueue::AddQueueHead(
+    PUHCI_QUEUE_HEAD NewQueueHead)
+{
+    PUSBREQUEST Request;
+    PUHCI_QUEUE_HEAD QueueHead = NULL;
+
+
+    //
+    // get request
+    //
+    Request = (PUSBREQUEST)NewQueueHead->Request;
+    if (!Request)
+    {
+        //
+        // no request
+        //
+        return STATUS_INVALID_PARAMETER;
     }
 
     if (Request->GetTransferType() == USB_ENDPOINT_TYPE_CONTROL)
@@ -184,6 +189,40 @@
     //
     LinkQueueHead(QueueHead, NewQueueHead);
     return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+CUSBQueue::AddUSBRequest(
+    IUSBRequest * Request)
+{
+    PUHCI_QUEUE_HEAD NewQueueHead;
+    NTSTATUS Status;
+
+    //
+    // get queue head
+    //
+    Status = Request->GetEndpointDescriptor(&NewQueueHead);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create queue head
+        //
+        DPRINT1("[USBUHCI] Failed to create queue head %x\n", Status);
+        return Status;
+    }
+
+    //
+    // sanity check
+    //
+    ASSERT(PVOID(Request) == NewQueueHead->Request);
+
+    //
+    // add queue head
+    //
+    DPRINT1("AddUSBRequest Request %p\n", Request);
+    DPRINT1("NewQueueHead %p\n", NewQueueHead);
+    return AddQueueHead(NewQueueHead);
 }
 
 VOID
@@ -198,6 +237,17 @@
     QueueHead->NextLogicalDescriptor = (PVOID)NextQueueHead;
 }
 
+
+VOID
+CUSBQueue::UnLinkQueueHead(
+    PUHCI_QUEUE_HEAD QueueHeadToRemove,
+    PUHCI_QUEUE_HEAD PreviousQueueHead)
+{
+    PreviousQueueHead->LinkPhysical = QueueHeadToRemove->LinkPhysical;
+    PreviousQueueHead->NextLogicalDescriptor = 
QueueHeadToRemove->NextLogicalDescriptor;
+}
+
+
 NTSTATUS
 CUSBQueue::CancelRequests()
 {
@@ -233,6 +283,218 @@
     return Status;
 }
 
+BOOLEAN
+CUSBQueue::IsQueueHeadComplete(
+    IN PUHCI_QUEUE_HEAD QueueHead)
+{
+    PUHCI_TRANSFER_DESCRIPTOR Descriptor;
+    ULONG ErrorCount;
+
+    if (QueueHead->NextElementDescriptor == NULL)
+    {
+        //
+        // empty queue head
+        //
+        DPRINT1("QueueHead %p empty element physical\n", QueueHead);
+        return FALSE;
+    }
+
+    //
+    // check all descriptors
+    //
+    Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)QueueHead->NextElementDescriptor;
+    while(Descriptor)
+    {
+        if (Descriptor->Status & TD_STATUS_ACTIVE)
+        {
+            //
+            // descriptor is still active
+            //
+            DPRINT1("Descriptor %p is active Status %x BufferSize %lu\n", 
Descriptor, Descriptor->Status, Descriptor->BufferSize);
+            return FALSE;
+        }
+
+        if (Descriptor->Status & TD_ERROR_MASK)
+        {
+            //
+            // error happened
+            //
+            DPRINT1("[USBUHCI] Error detected at descriptor %p Physical %x\n", 
Descriptor, Descriptor->PhysicalAddress);
+
+            //
+            // get error count
+            //
+            ErrorCount = (Descriptor->Status >> TD_ERROR_COUNT_SHIFT) & 
TD_ERROR_COUNT_MASK;
+            if (ErrorCount == 0)
+            {
+                 //
+                 // error retry count elapsed
+                 //
+                 DPRINT1("[USBUHCI] ErrorBuffer %x TimeOut %x Nak %x BitStuff 
%x\n",
+                         Descriptor->Status & TD_STATUS_ERROR_BUFFER,
+                         Descriptor->Status & TD_STATUS_ERROR_TIMEOUT,
+                         Descriptor->Status & TD_STATUS_ERROR_NAK,
+                         Descriptor->Status & TD_STATUS_ERROR_BITSTUFF);
+                 return TRUE;
+            }
+            else if (Descriptor->Status & TD_STATUS_ERROR_BABBLE)
+            {
+                 //
+                 // babble error
+                 //
+                 DPRINT1("[USBUHCI] Babble detected\n");
+                 return TRUE;
+            }
+            else
+            {
+                //
+                // stall detected
+                //
+                DPRINT1("[USBUHCI] Stall detected\n");
+            }
+        }
+
+        //
+        // move to next descriptor
+        //
+        Descriptor = 
(PUHCI_TRANSFER_DESCRIPTOR)Descriptor->NextLogicalDescriptor;
+    }
+
+    //
+    // request is complete
+    //
+    return TRUE;
+}
+
+VOID
+CUSBQueue::QueueHeadCleanup(
+    IN PUHCI_QUEUE_HEAD QueueHead,
+    IN PUHCI_QUEUE_HEAD PreviousQueueHead,
+    OUT PUHCI_QUEUE_HEAD *NextQueueHead)
+{
+    PUSBREQUEST Request;
+    PUHCI_QUEUE_HEAD NewQueueHead;
+    NTSTATUS Status;
+
+    //
+    // unlink queue head
+    //
+    UnLinkQueueHead(QueueHead, PreviousQueueHead);
+
+    //
+    // get next queue head
+    //
+    *NextQueueHead = 
(PUHCI_QUEUE_HEAD)PreviousQueueHead->NextLogicalDescriptor;
+    ASSERT(*NextQueueHead != QueueHead);
+
+    //
+    // the queue head is complete, is the transfer now completed?
+    //
+    Request = (PUSBREQUEST)QueueHead->Request;
+    ASSERT(Request);
+
+    //
+    // free queue head
+    //
+    DPRINT1("Request %p\n", Request);
+    Request->FreeEndpointDescriptor(QueueHead);
+
+    //
+    // check if transfer is complete
+    //
+    if (Request->IsRequestComplete())
+    {
+        //
+        // the transfer is complete
+        //
+        Request->CompletionCallback();
+        Request->Release();
+        return;
+    }
+
+    //
+    // grab new queue head
+    //
+    Status = Request->GetEndpointDescriptor(&NewQueueHead);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to get new queue head
+        //
+        DPRINT1("[USBUHCI] Failed to get new queue head with %x\n", Status);
+        Request->CompletionCallback();
+        Request->Release();
+        return;
+    }
+
+    //
+    // Link queue head
+    //
+    Status = AddQueueHead(NewQueueHead);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to get new queue head
+        //
+        DPRINT1("[USBUHCI] Failed to add queue head with %x\n", Status);
+        Request->CompletionCallback();
+        Request->Release();
+        return;
+    }
+
+}
+
+VOID
+CUSBQueue::TransferInterrupt(
+    UCHAR ErrorInterrupt)
+{
+    KIRQL OldLevel;
+    PUHCI_QUEUE_HEAD QueueHead, PreviousQueueHead = NULL;
+    BOOLEAN IsComplete;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // get queue head
+    //
+    m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead);
+
+    while(QueueHead)
+    {
+        //
+        // is queue head complete
+        //
+        DPRINT1("QueueHead %p\n", QueueHead);
+        IsComplete = IsQueueHeadComplete(QueueHead);
+        if (IsComplete)
+        {
+            //
+            // cleanup queue head
+            //
+            QueueHeadCleanup(QueueHead, PreviousQueueHead, &QueueHead);
+            continue;
+        }
+
+        //
+        // backup previous queue head
+        //
+        PreviousQueueHead = QueueHead;
+
+        //
+        // get next queue head
+        //
+        QueueHead = (PUHCI_QUEUE_HEAD)QueueHead->NextLogicalDescriptor;
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+
 NTSTATUS
 CreateUSBQueue(
     PUSBQUEUE *OutUsbQueue)

Modified: trunk/reactos/drivers/usb/usbuhci/usb_request.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbuhci/usb_request.cpp?rev=55809&r1=55808&r2=55809&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbuhci/usb_request.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbuhci/usb_request.cpp [iso-8859-1] Wed Feb 22 
17:24:43 2012
@@ -46,7 +46,8 @@
     virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
     virtual UCHAR GetInterval();
     virtual USB_DEVICE_SPEED GetDeviceSpeed();
-
+    virtual VOID CompletionCallback();
+    virtual VOID FreeEndpointDescriptor(struct _UHCI_QUEUE_HEAD * 
OutDescriptor);
 
     // local functions
     ULONG InternalGetTransferType();
@@ -829,7 +830,7 @@
     //
     // FIXME FIXME FIXME FIXME FIXME 
     //
-    MaxPacketSize = 1280;
+    MaxPacketSize = 64; //1280;
 
     do
     {
@@ -857,7 +858,14 @@
              //
              // copy buffer
              //
-             RtlCopyMemory(CurrentDescriptor->BufferLogical, TransferBuffer, 
CurrentBufferSize);
+             RtlCopyMemory(CurrentDescriptor->BufferLogical, 
(PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), CurrentBufferSize);
+        }
+        else
+        {
+            //
+            // store user buffer
+            //
+            CurrentDescriptor->UserBuffer = (PVOID)((ULONG_PTR)TransferBuffer 
+ TransferBufferOffset);
         }
 
         if (!FirstDescriptor)
@@ -1075,7 +1083,7 @@
         Status = 
BuildTransferDescriptorChain(MmGetMdlVirtualAddress(m_TransferBufferMDL),
                                               m_TransferBufferLength,
                                               Direction ? TD_TOKEN_IN : 
TD_TOKEN_OUT,
-                                              FALSE,
+                                              TRUE,
                                               &FirstDescriptor,
                                               &LastDescriptor,
                                               &ChainDescriptorLength,
@@ -1131,6 +1139,173 @@
     return m_DeviceSpeed;
 }
 
+VOID
+CUSBRequest::FreeEndpointDescriptor(
+     struct _UHCI_QUEUE_HEAD * OutDescriptor)
+{
+    PUHCI_TRANSFER_DESCRIPTOR Descriptor, NextDescriptor;
+    ULONG ErrorCount;
+
+    //
+    // grab first transfer descriptor
+    //
+    Descriptor = 
(PUHCI_TRANSFER_DESCRIPTOR)OutDescriptor->NextElementDescriptor;
+    while(Descriptor)
+    {
+        if (Descriptor->Status & TD_ERROR_MASK)
+        {
+            //
+            // error happened
+            //
+            DPRINT1("[USBUHCI] Error detected at descriptor %p Physical %x\n", 
Descriptor, Descriptor->PhysicalAddress);
+
+            //
+            // get error count
+            //
+            ErrorCount = (Descriptor->Status >> TD_ERROR_COUNT_SHIFT) & 
TD_ERROR_COUNT_MASK;
+            if (ErrorCount == 0)
+            {
+                 //
+                 // error retry count elapsed
+                 //
+                 m_NtStatusCode = STATUS_UNSUCCESSFUL;
+
+                 if (Descriptor->Status & TD_STATUS_ERROR_BUFFER)
+                 {
+                     DPRINT1("[USBUHCI] Buffer Error detected in descriptor 
%p\n", Descriptor);
+                     m_UrbStatusCode = USBD_STATUS_DATA_BUFFER_ERROR;
+                 }
+                 else if (Descriptor->Status & TD_STATUS_ERROR_TIMEOUT)
+                 {
+                     DPRINT1("[USBUHCI] Timeout detected in descriptor %p\n", 
Descriptor);
+                     m_UrbStatusCode = USBD_STATUS_TIMEOUT;
+                 }
+                 else if (Descriptor->Status & TD_STATUS_ERROR_NAK)
+                 {
+                     DPRINT1("[USBUHCI] Unexpected pid detected in descriptor 
%p\n", Descriptor);
+                     m_UrbStatusCode = USBD_STATUS_UNEXPECTED_PID;
+                 }
+                 else if (Descriptor->Status & TD_STATUS_ERROR_BITSTUFF)
+                 {
+                     DPRINT1("[USBUHCI] BitStuff detected in descriptor %p\n", 
Descriptor);
+                     m_UrbStatusCode = USBD_STATUS_BTSTUFF;
+                 }
+            }
+            else if (Descriptor->Status & TD_STATUS_ERROR_BABBLE)
+            {
+                 //
+                 // babble error
+                 //
+                 DPRINT1("[USBUHCI] Babble detected in descriptor %p\n", 
Descriptor);
+                 m_UrbStatusCode = USBD_STATUS_BABBLE_DETECTED;
+            }
+            else
+            {
+                //
+                // stall detected
+                //
+                DPRINT1("[USBUHCI] Stall detected\n");
+                m_UrbStatusCode = USBD_STATUS_STALL_PID;
+            }
+        }
+        else
+        {
+            //
+            // FIXME detect actual length
+            //
+            if (Descriptor->UserBuffer)
+            {
+                //
+                // copy contents back
+                //
+                RtlCopyMemory(Descriptor->UserBuffer, 
Descriptor->BufferLogical, Descriptor->BufferSize);
+            }
+        }
+        //
+        // move to next descriptor
+        //
+        NextDescriptor = 
(PUHCI_TRANSFER_DESCRIPTOR)Descriptor->NextLogicalDescriptor;
+
+        //
+        // free endpoint descriptor
+        //
+        FreeDescriptor(Descriptor);
+
+        //
+        // move to next
+        //
+        Descriptor = NextDescriptor;
+    }
+
+    //
+    // now free queue head
+    //
+    m_DmaManager->Release(OutDescriptor, sizeof(UHCI_QUEUE_HEAD));
+
+}
+
+VOID
+CUSBRequest::CompletionCallback()
+{
+    PIO_STACK_LOCATION IoStack;
+    PURB Urb;
+
+    DPRINT("CUSBRequest::CompletionCallback\n");
+
+    if (m_Irp)
+    {
+        //
+        // set irp completion status
+        //
+        m_Irp->IoStatus.Status = m_NtStatusCode;
+
+        //
+        // get current irp stack location
+        //
+        IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+        //
+        // get urb
+        //
+        Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+        //
+        // store urb status
+        //
+        Urb->UrbHeader.Status = m_UrbStatusCode;
+
+        //
+        // Check if the MDL was created
+        //
+        if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+        {
+            //
+            // Free Mdl
+            //
+            IoFreeMdl(m_TransferBufferMDL);
+        }
+
+        //
+        // FIXME calculate length
+        //
+
+        //
+        // complete request
+        //
+        IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+    }
+    else
+    {
+        //
+        // signal completion event
+        //
+        PC_ASSERT(m_CompletionEvent);
+        KeSetEvent(m_CompletionEvent, 0, FALSE);
+    }
+
+}
+
+
 
//-----------------------------------------------------------------------------------------
 NTSTATUS
 InternalCreateUSBRequest(


Reply via email to