Author: janderwald
Date: Wed Apr 27 16:23:42 2011
New Revision: 51466

URL: http://svn.reactos.org/svn/reactos?rev=51466&view=rev
Log:
[USBEHCI_NEW]
- Return the physical address of the async queue head in 
CUSBHardwareDevice::GetAsyncListRegister
- Remove superflous entries from queue head structure, they are processed 
within IUSBRequest class
- Remove USBHI_GetPortHackFlags, this function has been deprecated
- Add interface functions for IUSBRequest / IUSBQueue
- Callback into IUSBQueue when a hardware interrupt arrives
- Implement callback function to check for completed queue heads / free 
completed queue head depending on the Async Advance interrupt bit

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

Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp [iso-8859-1] Wed 
Apr 27 16:23:42 2011
@@ -87,30 +87,39 @@
     virtual ~CUSBHardwareDevice(){}
 
 protected:
-    LONG m_Ref;
-    PDRIVER_OBJECT m_DriverObject;
-    PDEVICE_OBJECT m_PhysicalDeviceObject;
-    PDEVICE_OBJECT m_FunctionalDeviceObject;
-    PDEVICE_OBJECT m_NextDeviceObject;
-    KSPIN_LOCK m_Lock;
-    PKINTERRUPT m_Interrupt;
-    KDPC m_IntDpcObject;
-    PVOID VirtualBase;
-    PHYSICAL_ADDRESS PhysicalAddress;
-    PULONG m_Base;
-    PDMA_ADAPTER m_Adapter;
-    ULONG m_MapRegisters;
-    EHCI_CAPS m_Capabilities;
-    USHORT m_VendorID;
-    USHORT m_DeviceID;
-    PQUEUE_HEAD AsyncQueueHead;
-    PUSBQUEUE m_UsbQueue;
-    PDMAMEMORYMANAGER m_MemoryManager;
-    HD_INIT_CALLBACK* m_SCECallBack;
-    PVOID m_SCEContext;
+    LONG m_Ref;                                                                
        // reference count
+    PDRIVER_OBJECT m_DriverObject;                                             
        // driver object
+    PDEVICE_OBJECT m_PhysicalDeviceObject;                                     
        // pdo
+    PDEVICE_OBJECT m_FunctionalDeviceObject;                                   
        // fdo (hcd controller)
+    PDEVICE_OBJECT m_NextDeviceObject;                                         
        // lower device object
+    KSPIN_LOCK m_Lock;                                                         
        // hardware lock
+    PKINTERRUPT m_Interrupt;                                                   
        // interrupt object
+    KDPC m_IntDpcObject;                                                       
        // dpc object for deferred isr processing
+    PVOID VirtualBase;                                                         
        // virtual base for memory manager
+    PHYSICAL_ADDRESS PhysicalAddress;                                          
        // physical base for memory manager
+    PULONG m_Base;                                                             
        // EHCI operational port base registers
+    PDMA_ADAPTER m_Adapter;                                                    
        // dma adapter object
+    ULONG m_MapRegisters;                                                      
        // map registers count
+    EHCI_CAPS m_Capabilities;                                                  
        // EHCI caps
+    USHORT m_VendorID;                                                         
        // vendor id
+    USHORT m_DeviceID;                                                         
        // device id
+    PQUEUE_HEAD AsyncQueueHead;                                                
        // async queue head terminator
+    PUSBQUEUE m_UsbQueue;                                                      
        // usb request queue
+    PDMAMEMORYMANAGER m_MemoryManager;                                         
        // memory manager
+    HD_INIT_CALLBACK* m_SCECallBack;                                           
        // status change callback routine
+    PVOID m_SCEContext;                                                        
        // status change callback routine context
+    BOOLEAN m_DoorBellRingInProgress;                                          
        // door bell ring in progress
+
+    // set command
     VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
+
+    // get command
     VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
+
+    // read register
     ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset);
+
+    // write register
     VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value);
 };
 
@@ -315,6 +324,7 @@
                 m_Capabilities.HCCParamsLong = 
READ_REGISTER_ULONG((PULONG)((ULONG)ResourceBase + 8));
 
                 DPRINT1("Controller has %d Ports\n", 
m_Capabilities.HCSParams.PortCount);
+                DPRINT1("Controller EHCI Version %x\n", 
m_Capabilities.HCIVersion);
                 if (m_Capabilities.HCSParams.PortRouteRules)
                 {
                     for (Count = 0; Count < 
m_Capabilities.HCSParams.PortCount; Count++)
@@ -850,7 +860,7 @@
 ULONG
 CUSBHardwareDevice::GetAsyncListRegister()
 {
-    return PhysicalAddress.LowPart;
+    return AsyncQueueHead->PhysicalAddr;
 }
 
 ULONG CUSBHardwareDevice::GetPeriodicListRegister()
@@ -946,10 +956,85 @@
     IN PVOID SystemArgument2)
 {
     CUSBHardwareDevice *This;
-    ULONG CStatus, PortStatus, PortCount, i;
+    ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell;
+    NTSTATUS Status = STATUS_SUCCESS;
+    EHCI_USBCMD_CONTENT UsbCmd;
 
     This = (CUSBHardwareDevice*) SystemArgument1;
     CStatus = (ULONG) SystemArgument2;
+
+
+    //
+    // check for completion of async schedule
+    //
+    if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT))
+    {
+        if (CStatus & EHCI_ERROR_INT)
+        {
+            //
+            // controller reported error
+            //
+            Status = STATUS_UNSUCCESSFUL;
+        }
+
+        //
+        // check if there is a door bell ring in progress
+        //
+        if (This->m_DoorBellRingInProgress == FALSE)
+        {
+            //
+            // inform IUSBQueue of a completed queue head
+            //
+            This->m_UsbQueue->InterruptCallback(Status, &ShouldRingDoorBell);
+
+            //
+            // was a queue head completed?
+            //
+             if (ShouldRingDoorBell)
+             {
+                 //
+                 // set door ring bell in progress status flag
+                 //
+                 This->m_DoorBellRingInProgress = TRUE;
+
+                 //
+                 // get command register
+                 //
+                 This->GetCommandRegister(&UsbCmd);
+
+                 //
+                 // set door rang bell bit
+                 //
+                 UsbCmd.DoorBell = TRUE;
+
+                 //
+                 // update command status
+                 //
+                 This->SetCommandRegister(&UsbCmd);
+             }
+        }
+    }
+
+    //
+    // check if the controller has acknowledged the door bell 
+    //
+    if (CStatus & EHCI_STS_IAA)
+    {
+        //
+        // controller has acknowledged, assert we rang the bell
+        //
+        PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
+
+        //
+        // now notify IUSBQueue that it can free completed requests
+        //
+        This->m_UsbQueue->CompleteAsyncRequests();
+
+        //
+        // door ring bell completed
+        //
+        This->m_DoorBellRingInProgress = FALSE;
+    }
 
     This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
     if (CStatus & EHCI_STS_PCD)

Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.h
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/hardware.h?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] Wed 
Apr 27 16:23:42 2011
@@ -190,10 +190,6 @@
     //Software
     ULONG PhysicalAddr;
     LIST_ENTRY LinkedQueueHeads;
-    PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor;
-    PIRP IrpToComplete;
-    PMDL Mdl;
-    PKEVENT Event;
     PVOID Request;
 } QUEUE_HEAD, *PQUEUE_HEAD;
 

Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp 
[iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp 
[iso-8859-1] Wed Apr 27 16:23:42 2011
@@ -1988,16 +1988,6 @@
 
 NTSTATUS
 USB_BUSIFFN
-USBHI_GetPortHackFlags(
-    PVOID BusContext,
-    PULONG Flags)
-{
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-USB_BUSIFFN
 USBHI_QueryDeviceInformation(
     PVOID BusContext,
     PUSB_DEVICE_HANDLE DeviceHandle,
@@ -2565,7 +2555,6 @@
             InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
             InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
             InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
-            InterfaceHub->GetPortHackFlags = USBHI_GetPortHackFlags;
             InterfaceHub->QueryDeviceInformation = 
USBHI_QueryDeviceInformation;
         }
 

Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Wed 
Apr 27 16:23:42 2011
@@ -482,7 +482,26 @@
 // Description: frees the queue head with the associated transfer descriptors
 
     virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead) = 0;
+
+//---------------------------------------------------------------------------------------
+//
+// GetTransferBuffer
+//
+// Description: this function returns the transfer buffer mdl and length
+// Used by IUSBQueue for mapping buffer contents with DMA
+
+    virtual VOID GetTransferBuffer(OUT PMDL * OutMDL,
+                                   OUT PULONG TransferLength) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// IsQueueHeadComplete
+//
+// Description: returns true when the queue head which was passed as a 
parameter has been completed
+
+    virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead) = 0;
 };
+
 
 typedef IUSBRequest *PUSBREQUEST;
 
@@ -539,6 +558,24 @@
 // Description: creates an usb request
 
     virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// InterruptCallback
+//
+// Description: callback when the periodic / asynchronous queue has been 
completed / queue head been completed
+
+    virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG 
ShouldRingDoorBell) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// CompleteAsyncRequests
+//
+// Description: once a request has been completed it is moved to pending 
queue. Since a queue head should only be freed
+// after a door bell ring, this needs some synchronization.
+// This function gets called by IUSBHardware after it the Interrupt on Async 
Advance bit has been set
+
+    virtual VOID CompleteAsyncRequests() = 0;
 };
 
 typedef IUSBQueue *PUSBQUEUE;

Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] Wed 
Apr 27 16:23:42 2011
@@ -33,12 +33,14 @@
         return m_Ref;
     }
 
-    NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER 
AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock);
-    ULONG GetPendingRequestCount();
-    NTSTATUS AddUSBRequest(PURB Urb);
-    NTSTATUS AddUSBRequest(IUSBRequest * Request);
-    NTSTATUS CancelRequests();
-    NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
+    virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER 
AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock);
+    virtual ULONG GetPendingRequestCount();
+    virtual NTSTATUS AddUSBRequest(PURB Urb);
+    virtual NTSTATUS AddUSBRequest(IUSBRequest * Request);
+    virtual NTSTATUS CancelRequests();
+    virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
+    virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG 
ShouldRingDoorBell);
+    virtual VOID CompleteAsyncRequests();
 
     // constructor / destructor
     CUSBQueue(IUnknown *OuterUnknown){}
@@ -50,6 +52,7 @@
     PDMA_ADAPTER m_Adapter;
     PQUEUE_HEAD AsyncListQueueHead;
     PQUEUE_HEAD PendingListQueueHead;
+    LIST_ENTRY m_CompletedRequestAsyncList;
 
     // queue head manipulation functions
     VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
@@ -57,8 +60,11 @@
     VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD 
NewQueueHead);
     PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
 
+    // processes the async list
+    VOID ProcessAsyncList(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
+
     // called for each completed queue head
-    NTSTATUS QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
+    VOID QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
 
     // called when the completion queue is cleaned up
     VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead);
@@ -120,6 +126,17 @@
     //
     InitializeListHead(&PendingListQueueHead->LinkedQueueHeads);
 
+    //
+    // fake the queue head as the first queue head
+    //
+    PendingListQueueHead->PhysicalAddr = ((ULONG_PTR)AsyncListQueueHead | 
QH_TYPE_QH);
+
+    //
+    // Initialize completed async list head
+    //
+    InitializeListHead(&m_CompletedRequestAsyncList);
+
+
     return Status;
 }
 
@@ -234,13 +251,44 @@
     PQUEUE_HEAD PreviousQH, NextQH;
     PLIST_ENTRY Entry;
 
+    //
+    // sanity check: there must be at least one queue head with halted bit set
+    //
+    PC_ASSERT(QueueHead->Token.Bits.Halted == 0);
+
+    //
+    // get previous link
+    //
     Entry = QueueHead->LinkedQueueHeads.Blink;
+
+    //
+    // get queue head structure
+    //
     PreviousQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+    //
+    // get next link
+    //
     Entry = QueueHead->LinkedQueueHeads.Flink;
+
+    //
+    // get queue head structure
+    //
     NextQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+    //
+    // sanity check
+    //
     ASSERT(QueueHead->HorizontalLinkPointer == (NextQH->PhysicalAddr | 
QH_TYPE_QH));
+
+    //
+    // remove queue head from linked list
+    //
     PreviousQH->HorizontalLinkPointer = NextQH->PhysicalAddr | QH_TYPE_QH;
 
+    //
+    // remove software link
+    //
     RemoveEntryList(&QueueHead->LinkedQueueHeads);
 }
 
@@ -326,7 +374,7 @@
     return FirstQueueHead;
 }
 
-NTSTATUS
+VOID
 CUSBQueue::QueueHeadCompletion(
     PQUEUE_HEAD CurrentQH,
     NTSTATUS Status)
@@ -415,14 +463,94 @@
     else
     {
         //
-        // FIXME: put queue head into completed queue head list
-        //
-    }
-
-    //
-    // done
-    //
-    return STATUS_SUCCESS;
+        // put queue head into completed queue head list
+        //
+        InsertTailList(&m_CompletedRequestAsyncList, 
&CurrentQH->LinkedQueueHeads);
+    }
+}
+
+VOID
+CUSBQueue::ProcessAsyncList(
+    IN NTSTATUS Status,
+    OUT PULONG ShouldRingDoorBell)
+{
+    KIRQL OldLevel;
+    PLIST_ENTRY Entry;
+    PQUEUE_HEAD QueueHead;
+    IUSBRequest * Request;
+
+    //
+    // lock completed async list
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // walk async list 
+    //
+    Entry = PendingListQueueHead->LinkedQueueHeads.Flink;
+
+    while(Entry != &PendingListQueueHead->LinkedQueueHeads)
+    {
+        //
+        // get queue head structure
+        //
+        QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, 
LinkedQueueHeads);
+
+        //
+        // sanity check
+        //
+        PC_ASSERT(QueueHead->Request);
+
+        //
+        // get IUSBRequest interface
+        //
+        Request = (IUSBRequest*)QueueHead->Request;
+
+
+        //
+        // move to next entry
+        //
+        Entry = Entry->Flink;
+
+        //
+        // check if queue head is complete
+        //
+        if (Request->IsQueueHeadComplete(QueueHead))
+        {
+            //
+            // current queue head is complete
+            //
+            QueueHeadCompletion(QueueHead, Status);
+
+            //
+            // ring door bell is going to be necessary
+            //
+            *ShouldRingDoorBell = TRUE;
+        }
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+}
+
+
+VOID
+CUSBQueue::InterruptCallback(
+    IN NTSTATUS Status, 
+    OUT PULONG ShouldRingDoorBell)
+{
+    //
+    // iterate asynchronous list
+    //
+    *ShouldRingDoorBell = FALSE;
+    ProcessAsyncList(Status, ShouldRingDoorBell);
+
+    //
+    // TODO: implement periodic schedule processing
+    //
 }
 
 VOID
@@ -472,6 +600,47 @@
     //
     // request is now released
     //
+}
+
+VOID
+CUSBQueue::CompleteAsyncRequests()
+{
+    KIRQL OldLevel;
+    PLIST_ENTRY Entry;
+    PQUEUE_HEAD CurrentQH;
+
+    //
+    // first acquire request lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // the list should not be empty
+    //
+    PC_ASSERT(!IsListEmpty(&m_CompletedRequestAsyncList));
+
+    while(!IsListEmpty(&m_CompletedRequestAsyncList))
+    {
+        //
+        // remove first entry
+        //
+        Entry = RemoveHeadList(&m_CompletedRequestAsyncList);
+
+        //
+        // get queue head structure
+        //
+        CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, 
LinkedQueueHeads);
+
+        //
+        // complete request now
+        //
+        QueueHeadCleanup(CurrentQH);
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
 }
 
 NTSTATUS

Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp?rev=51466&r1=51465&r2=51466&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] 
Wed Apr 27 16:23:42 2011
@@ -47,6 +47,9 @@
     virtual BOOLEAN IsRequestInitialized();
     virtual BOOLEAN ShouldReleaseRequestAfterCompletion();
     virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead);
+    virtual VOID GetTransferBuffer(OUT PMDL * OutMDL, OUT PULONG 
TransferLength);
+    virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
+
 
     // local functions
     ULONG InternalGetTransferType();
@@ -641,12 +644,6 @@
     }
 
     //
-    // Control Transfers have only one in or out buffer if one at all. Put in 
the QueueHead the
-    // same as BulkTransfers. USBQueue will use the Mdl to fill in the 
BufferPointers
-    //
-    QueueHead->Mdl = m_TransferBufferMDL;
-
-    //
     // link setup packet into buffer - Physical Address!!!
     //
     m_TransferDescriptors[0]->BufferPointer[0] = 
(ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart);
@@ -1149,6 +1146,64 @@
     }
 }
 
+//-----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBRequest::IsQueueHeadComplete(
+    struct _QUEUE_HEAD * QueueHead)
+{
+    ULONG Index;
+
+    //
+    // first check - is the queue head currently active
+    //
+    if (QueueHead->Token.Bits.Active)
+    {
+        //
+        // queue head is active (currently processed)
+        //
+        return FALSE;
+    }
+
+    //
+    // FIXME: support chained queue heads
+    //
+    for(Index = 0; Index < 3; Index++)
+    {
+        //
+        // check transfer descriptors for completion
+        //
+        if (m_TransferDescriptors[Index])
+        {
+            //
+            // check for serious error
+            //
+            PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Halted == 0);
+
+            //
+            // the transfer descriptor should be in the same state as the 
queue head
+            //
+            PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
+        }
+    }
+
+    return TRUE;
+}
+
+//-----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::GetTransferBuffer(
+    OUT PMDL * OutMDL,
+    OUT PULONG TransferLength)
+{
+    // sanity checks
+    PC_ASSERT(OutMDL);
+    PC_ASSERT(TransferLength);
+
+    *OutMDL = m_TransferBufferMDL;
+    *TransferLength = m_TransferBufferLength;
+}
+
+//-----------------------------------------------------------------------------------------
 NTSTATUS
 InternalCreateUSBRequest(
     PUSBREQUEST *OutRequest)


Reply via email to