}
// IUSBRequest interface functions
- virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, 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_DESCRIPTOR 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);
// local functions
ULONG InternalGetTransferType();
+ UCHAR InternalGetPidDirection();
NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
- ULONG GetDeviceAddress();
+ UCHAR GetDeviceAddress();
NTSTATUS BuildSetupPacket();
NTSTATUS BuildSetupPacketFromURB();
+ ULONG InternalCalculateTransferLength();
// constructor / destructor
CUSBRequest(IUnknown *OuterUnknown){}
//
ULONG m_TransferBufferLength;
+ //
+ // current transfer length
+ //
+ ULONG m_TransferBufferLengthCompleted;
+
+ //
+ // Total Transfer Length
+ //
+ ULONG m_TotalBytesTransferred;
+
//
// transfer buffer MDL
//
//
PKEVENT m_CompletionEvent;
+ //
+ // device address for callers who initialized it with device address
+ //
+ UCHAR m_DeviceAddress;
+
+ //
+ // store end point address
+ //
+ PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
+
//
// DMA queue head
//
CUSBRequest::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)
{
m_SetupPacket = SetupPacket;
m_TransferBufferLength = TransferBufferLength;
m_TransferBufferMDL = TransferBuffer;
+ m_DeviceAddress = DeviceAddress;
+ m_EndpointDescriptor = EndpointDescriptor;
+ m_TotalBytesTransferred = 0;
+
+ //
+ // Set Length Completed to 0
+ //
+ m_TransferBufferLengthCompleted = 0;
//
// allocate completion event
PC_ASSERT(DmaManager);
PC_ASSERT(Irp);
+ m_DmaManager = DmaManager;
+ m_TotalBytesTransferred = 0;
+
//
// get current irp stack location
//
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
//
- // bulk / interrupt transfer
+ // bulk interrupt transfer
//
if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
{
//
- // FIXME: it must have an MDL
+ // Check if there is a MDL
//
- PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
+ if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+ {
+ //
+ // sanity check
+ //
+ PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
+
+ //
+ // Create one using TransferBuffer
+ //
+ DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+ m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
+ Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (!m_TransferBufferMDL)
+ {
+ //
+ // failed to allocate mdl
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build mdl for non paged pool
+ // FIXME: Does hub driver already do this when passing MDL?
+ //
+ MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
+
+ //
+ // Keep that ehci created the MDL and needs to free it.
+ //
+ }
+ else
+ {
+ m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
+ }
//
- // get mdl buffer
+ // save buffer length
//
- m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+
+ //
+ // Set Length Completed to 0
+ //
+ m_TransferBufferLengthCompleted = 0;
+
+ //
+ // get endpoint descriptor
+ //
+ m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+
}
break;
}
//
Urb->UrbHeader.Status = UrbStatusCode;
+ //
+ // Check if the MDL was created
+ //
+ if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+ {
+ //
+ // Free Mdl
+ //
+ IoFreeMdl(m_TransferBufferMDL);
+ }
+
//
// check if the request was successfull
//
//
Urb->UrbHeader.Length = 0;
}
+ else
+ {
+ //
+ // calculate transfer length
+ //
+ Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = InternalCalculateTransferLength();
+ }
+
+ DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
//
// FIXME: check if the transfer was split
//
// store urb status
//
+ DPRINT1("Request Cancelled\n");
Urb->UrbHeader.Status = USBD_STATUS_CANCELED;
Urb->UrbHeader.Length = 0;
//
// FIXME: check if request was split
//
- UNIMPLEMENTED
+
+ //
+ // Check if the transfer was completed, only valid for Bulk Transfers
+ //
+ if ((m_TransferBufferLengthCompleted < m_TransferBufferLength)
+ && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
+ {
+ //
+ // Transfer not completed
+ //
+ return FALSE;
+ }
return TRUE;
}
//----------------------------------------------------------------------------------------
ULONG
CUSBRequest::InternalGetTransferType()
{
- PIO_STACK_LOCATION IoStack;
- PURB Urb;
- PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG TransferType;
//
//
if (m_Irp)
{
- //
- // get stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+ ASSERT(m_EndpointDescriptor);
//
- // get urb
+ // end point is defined in the low byte of bmAttributes
//
- Urb = (PURB)IoStack->Parameters.Others.Argument1;
-
- //
- // check if there is a handle
- //
- if (Urb->UrbBulkOrInterruptTransfer.PipeHandle)
- {
- //
- // cast to end point
- //
- EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
-
- //
- // end point is defined in the low byte of bmAttributes
- //
- TransferType = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
- }
- else
- {
- //
- // no pipe handle, assume it is a control transfer
- //
- TransferType = USB_ENDPOINT_TYPE_CONTROL;
- }
+ TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
}
else
{
return TransferType;
}
+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;
+}
+
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::BuildControlTransferQueueHead(
// now initialize the queue head
//
QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
-
- //if (PipeHandle)
- // QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
+
+ if (m_EndpointDescriptor)
+ {
+ //
+ // set endpoint address and max packet length
+ //
+ QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F;
+ QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize;
+ }
QueueHead->Token.Bits.DataToggle = TRUE;
CUSBRequest::BuildBulkTransferQueueHead(
PQUEUE_HEAD * OutHead)
{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PQUEUE_HEAD QueueHead;
+ ULONG TransferDescriptorCount, Index;
+ ULONG BytesAvailable, BufferIndex;
+ PVOID Base;
+ ULONG PageOffset, CurrentTransferBufferLength;
+
+ //
+ // Allocate the queue head
+ //
+ Status = CreateQueueHead(&QueueHead);
+
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate queue heads
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // sanity checks
+ //
+ PC_ASSERT(QueueHead);
+ PC_ASSERT(m_TransferBufferLength);
+
+ //
+ // Max default of 3 descriptors
+ //
+ TransferDescriptorCount = 3;
+
+ //
+ // get virtual base of mdl
+ //
+ 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);
+
+ 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;
+ 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));
+
+ //
+ // 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;
+
+ DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[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;
+
+ DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
+ BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
+ }
+ else
+ {
+ PC_ASSERT(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
+ //
+ DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[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;
+ }
+
+ //
+ // store transfer bytes of descriptor
+ //
+ m_TransferDescriptors[Index]->TotalBytesToTransfer = m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer;
+
+ //
+ // Go ahead and link descriptors
+ //
+ if (Index > 0)
+ {
+ m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr;
+ }
+
+ //
+ // setup direction
+ //
+ m_TransferDescriptors[Index]->Token.Bits.PIDCode = InternalGetPidDirection();
+
+ //
+ // FIXME: performance penality?
+ //
+ m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE;
+
+ //
+ // FIXME need dead queue transfer descriptor?
+ //
+
+ //
+ // Check if all bytes have been consumed
+ //
+ if (BytesAvailable == 0)
+ break;
+ }
+
+ //
+ // all bytes should have been consumed
+ //
+ PC_ASSERT(BytesAvailable == 0);
+
+ //
+ // Initialize the QueueHead
+ //
+ 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;
+ }
+
+ QueueHead->Token.Bits.DataToggle = TRUE;
+
+ //
+ // link descriptor with queue head
+ //
+ QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
+
+ //
+ // store result
+ //
+ *OutHead = QueueHead;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------------------
// allocate queue head
//
Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
+
if (!NT_SUCCESS(Status))
{
//
}
//----------------------------------------------------------------------------------------
-ULONG
+UCHAR
CUSBRequest::GetDeviceAddress()
{
PIO_STACK_LOCATION IoStack;
if (!m_Irp)
{
//
- // no irp is provided
- // assume it is for device address 0
- return 0;
+ // used provided address
+ //
+ return m_DeviceAddress;
}
//
CUSBRequest::FreeQueueHead(
IN struct _QUEUE_HEAD * QueueHead)
{
+ LONG DescriptorCount;
+
//
// FIXME: support chained queue heads
//
- PC_ASSERT(QueueHead == m_QueueHead);
+ //PC_ASSERT(QueueHead == m_QueueHead);
//
// release queue head
//
// release transfer descriptors
//
-
- if (m_TransferDescriptors[0])
+ for (DescriptorCount = 0; DescriptorCount < 3; DescriptorCount++)
{
- //
- // release transfer descriptors
- //
- m_DmaManager->Release(m_TransferDescriptors[0], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
- m_TransferDescriptors[0] = 0;
- }
+ 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;
+ }
+ }
- if (m_TransferDescriptors[1])
- {
- //
- // release transfer descriptors
- //
- m_DmaManager->Release(m_TransferDescriptors[1], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
- m_TransferDescriptors[1] = 0;
+ //
+ // release transfer descriptors
+ //
+ m_DmaManager->Release(m_TransferDescriptors[DescriptorCount], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
+ m_TransferDescriptors[DescriptorCount] = 0;
+ }
}
- if (m_TransferDescriptors[2])
+ if (m_DescriptorPacket)
{
//
- // release transfer descriptors
+ // release packet descriptor
//
- m_DmaManager->Release(m_TransferDescriptors[2], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
- m_TransferDescriptors[2] = 0;
+ m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+ m_DescriptorPacket = 0;
}
}
//
// check for serious error
//
- PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Halted == 0);
+ //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);
+ //PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
}
}
*OutMDL = m_TransferBufferMDL;
*TransferLength = m_TransferBufferLength;
}
+//-----------------------------------------------------------------------------------------
+ULONG
+CUSBRequest::InternalCalculateTransferLength()
+{
+ if (!m_Irp)
+ {
+ //
+ // FIXME: get length for control request
+ //
+ return m_TransferBufferLength;
+ }
+
+ //
+ // sanity check
+ //
+ ASSERT(m_EndpointDescriptor);
+
+ if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress))
+ {
+ //
+ // bulk in request
+ // HACK: Properly determine transfer length
+ //
+ return m_TransferBufferLength;//m_TotalBytesTransferred;
+ }
+
+ //
+ // bulk out transfer
+ //
+ return m_TransferBufferLength;
+}
//-----------------------------------------------------------------------------------------
NTSTATUS