2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/usb_request.cpp
5 * PURPOSE: USB EHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 class CUSBRequest
: public IEHCIRequest
19 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
21 STDMETHODIMP_(ULONG
) AddRef()
23 InterlockedIncrement(&m_Ref
);
26 STDMETHODIMP_(ULONG
) Release()
28 InterlockedDecrement(&m_Ref
);
38 // IUSBRequest interface functions
40 // IEHCI Request interface functions
44 ULONG
InternalGetTransferType();
45 UCHAR
InternalGetPidDirection();
46 NTSTATUS
BuildControlTransferQueueHead(PQUEUE_HEAD
* OutHead
);
47 NTSTATUS
BuildBulkInterruptTransferQueueHead(PQUEUE_HEAD
* OutHead
);
48 NTSTATUS STDMETHODCALLTYPE
CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
);
49 NTSTATUS
CreateQueueHead(PQUEUE_HEAD
*OutQueueHead
);
50 UCHAR STDMETHODCALLTYPE
GetDeviceAddress();
51 NTSTATUS
BuildSetupPacket();
52 NTSTATUS
BuildSetupPacketFromURB();
53 ULONG
InternalCalculateTransferLength();
54 NTSTATUS STDMETHODCALLTYPE
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
);
55 VOID STDMETHODCALLTYPE
InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, IN UCHAR DataToggle
, OUT PULONG OutDescriptorLength
);
56 VOID
DumpQueueHead(IN PQUEUE_HEAD QueueHead
);
58 // constructor / destructor
59 CUSBRequest(IUnknown
*OuterUnknown
){}
60 virtual ~CUSBRequest(){}
66 // memory manager for allocating setup packet / queue head / transfer descriptors
68 PDMAMEMORYMANAGER m_DmaManager
;
71 // caller provided irp packet containing URB request
76 // transfer buffer length
78 ULONG m_TransferBufferLength
;
81 // current transfer length
83 ULONG m_TransferBufferLengthCompleted
;
86 // Total Transfer Length
88 ULONG m_TotalBytesTransferred
;
91 // transfer buffer MDL
93 PMDL m_TransferBufferMDL
;
96 // caller provided setup packet
98 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
101 // completion event for callers who initialized request with setup packet
103 PKEVENT m_CompletionEvent
;
106 // device address for callers who initialized it with device address
108 UCHAR m_DeviceAddress
;
111 // store end point address
113 PUSB_ENDPOINT m_EndpointDescriptor
;
118 PQUEUE_HEAD m_QueueHead
;
121 // allocated setup packet from the DMA pool
123 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
124 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
127 // stores the result of the operation
129 NTSTATUS m_NtStatusCode
;
130 ULONG m_UrbStatusCode
;
132 // buffer base address
136 USB_DEVICE_SPEED m_Speed
;
140 //----------------------------------------------------------------------------------------
143 CUSBRequest::QueryInterface(
147 return STATUS_UNSUCCESSFUL
;
150 //----------------------------------------------------------------------------------------
153 CUSBRequest::InitializeWithSetupPacket(
154 IN PDMAMEMORYMANAGER DmaManager
,
155 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
156 IN PUSBDEVICE Device
,
157 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
158 IN OUT ULONG TransferBufferLength
,
159 IN OUT PMDL TransferBuffer
)
164 PC_ASSERT(DmaManager
);
165 PC_ASSERT(SetupPacket
);
170 m_DmaManager
= DmaManager
;
171 m_SetupPacket
= SetupPacket
;
172 m_TransferBufferLength
= TransferBufferLength
;
173 m_TransferBufferMDL
= TransferBuffer
;
174 m_DeviceAddress
= Device
->GetDeviceAddress();
175 m_Speed
= Device
->GetSpeed();
176 m_EndpointDescriptor
= EndpointDescriptor
;
177 m_TotalBytesTransferred
= 0;
180 // Set Length Completed to 0
182 m_TransferBufferLengthCompleted
= 0;
185 // allocate completion event
187 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBEHCI
);
188 if (!m_CompletionEvent
)
191 // failed to allocate completion event
193 return STATUS_INSUFFICIENT_RESOURCES
;
197 // initialize completion event
199 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
204 return STATUS_SUCCESS
;
206 //----------------------------------------------------------------------------------------
209 CUSBRequest::InitializeWithIrp(
210 IN PDMAMEMORYMANAGER DmaManager
,
211 IN PUSBDEVICE Device
,
214 PIO_STACK_LOCATION IoStack
;
220 PC_ASSERT(DmaManager
);
223 m_DmaManager
= DmaManager
;
224 m_TotalBytesTransferred
= 0;
225 m_Speed
= Device
->GetSpeed();
228 // get current irp stack location
230 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
235 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
236 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
237 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
242 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
250 // check function type
252 switch (Urb
->UrbHeader
.Function
)
255 // luckily those request have the same structure layout
257 case URB_FUNCTION_CLASS_INTERFACE
:
258 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
259 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
262 // bulk interrupt transfer
264 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
267 // Check if there is a MDL
269 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
274 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
277 // Create one using TransferBuffer
279 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
280 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
281 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
286 if (!m_TransferBufferMDL
)
289 // failed to allocate mdl
291 return STATUS_INSUFFICIENT_RESOURCES
;
295 // build mdl for non paged pool
296 // FIXME: Does hub driver already do this when passing MDL?
298 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
301 // Keep that ehci created the MDL and needs to free it.
306 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
310 // save buffer length
312 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
315 // Set Length Completed to 0
317 m_TransferBufferLengthCompleted
= 0;
320 // get endpoint descriptor
322 m_EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
328 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
335 return STATUS_SUCCESS
;
339 //----------------------------------------------------------------------------------------
342 CUSBRequest::CompletionCallback(
343 IN NTSTATUS NtStatusCode
,
344 IN ULONG UrbStatusCode
,
345 IN
struct _QUEUE_HEAD
*QueueHead
)
347 PIO_STACK_LOCATION IoStack
;
351 // FIXME: support linked queue heads
355 // store completion code
357 m_NtStatusCode
= NtStatusCode
;
358 m_UrbStatusCode
= UrbStatusCode
;
363 // set irp completion status
365 m_Irp
->IoStatus
.Status
= NtStatusCode
;
368 // get current irp stack location
370 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
375 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
380 Urb
->UrbHeader
.Status
= UrbStatusCode
;
383 // Check if the MDL was created
385 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
390 IoFreeMdl(m_TransferBufferMDL
);
394 // check if the request was successfull
396 if (!NT_SUCCESS(NtStatusCode
))
399 // set returned length to zero in case of error
401 Urb
->UrbHeader
.Length
= 0;
406 // calculate transfer length
408 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
= InternalCalculateTransferLength();
411 DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp
, NtStatusCode
, UrbStatusCode
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
414 // FIXME: check if the transfer was split
415 // if yes dont complete irp yet
417 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
422 // signal completion event
424 PC_ASSERT(m_CompletionEvent
);
425 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
429 //----------------------------------------------------------------------------------------
432 CUSBRequest::GetQueueHead(
433 struct _QUEUE_HEAD
** OutHead
)
439 // first get transfer type
441 TransferType
= InternalGetTransferType();
444 // build request depending on type
448 case USB_ENDPOINT_TYPE_CONTROL
:
449 Status
= BuildControlTransferQueueHead(OutHead
);
451 case USB_ENDPOINT_TYPE_INTERRUPT
:
452 case USB_ENDPOINT_TYPE_BULK
:
453 Status
= BuildBulkInterruptTransferQueueHead(OutHead
);
455 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
456 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
457 Status
= STATUS_NOT_IMPLEMENTED
;
461 Status
= STATUS_NOT_IMPLEMENTED
;
465 if (NT_SUCCESS(Status
))
470 m_QueueHead
= *OutHead
;
473 // store request object
475 (*OutHead
)->Request
= PVOID(this);
484 //----------------------------------------------------------------------------------------
487 CUSBRequest::IsRequestComplete()
490 // FIXME: check if request was split
494 // Check if the transfer was completed, only valid for Bulk Transfers
496 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
497 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
500 // Transfer not completed
506 //----------------------------------------------------------------------------------------
509 CUSBRequest::GetTransferType()
512 // call internal implementation
514 return InternalGetTransferType();
517 //----------------------------------------------------------------------------------------
519 CUSBRequest::InternalGetTransferType()
524 // check if an irp is provided
528 ASSERT(m_EndpointDescriptor
);
531 // end point is defined in the low byte of bmAttributes
533 TransferType
= (m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
538 // initialized with setup packet, must be a control transfer
540 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
541 ASSERT(m_EndpointDescriptor
== NULL
);
551 CUSBRequest::InternalGetPidDirection()
553 if (m_EndpointDescriptor
)
556 // end point direction is highest bit in bEndpointAddress
558 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
563 // request arrives on the control pipe, extract direction from setup packet
565 ASSERT(m_DescriptorPacket
);
566 return (m_DescriptorPacket
->bmRequestType
.B
>> 7);
572 CUSBRequest::InitDescriptor(
573 IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
,
574 IN PVOID TransferBuffer
,
575 IN ULONG TransferBufferLength
,
578 OUT PULONG OutDescriptorLength
)
580 ULONG Index
, Length
= 0, PageOffset
, BufferLength
;
581 PHYSICAL_ADDRESS Address
;
584 // init transfer descriptor
586 CurrentDescriptor
->Token
.Bits
.PIDCode
= PidCode
;
587 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
588 CurrentDescriptor
->Token
.Bits
.DataToggle
= DataToggle
;
593 ASSERT(TransferBufferLength
);
604 Address
= MmGetPhysicalAddress(TransferBuffer
);
607 // use physical address
609 CurrentDescriptor
->BufferPointer
[Index
] = Address
.LowPart
;
610 CurrentDescriptor
->ExtendedBufferPointer
[Index
] = Address
.HighPart
;
613 // Get the offset from page size
615 PageOffset
= BYTE_OFFSET(CurrentDescriptor
->BufferPointer
[Index
]);
621 TransferBuffer
= (PVOID
)ROUND_TO_PAGES(TransferBuffer
);
628 TransferBuffer
= (PVOID
)((ULONG_PTR
)TransferBuffer
+ PAGE_SIZE
);
632 // calculate buffer length
634 BufferLength
= min(TransferBufferLength
, PAGE_SIZE
- PageOffset
);
637 // increment transfer bytes
639 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
+= BufferLength
;
640 CurrentDescriptor
->TotalBytesToTransfer
+= BufferLength
;
641 Length
+= BufferLength
;
642 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index
, TransferBufferLength
, PageOffset
, BufferLength
, CurrentDescriptor
->BufferPointer
[Index
], TransferBuffer
);
645 // decrement available byte count
647 TransferBufferLength
-= BufferLength
;
648 if (TransferBufferLength
== 0)
664 ASSERT(CurrentDescriptor
->BufferPointer
[Index
] != CurrentDescriptor
->BufferPointer
[Index
-1]);
668 // next descriptor index
676 *OutDescriptorLength
= Length
;
681 CUSBRequest::BuildTransferDescriptorChain(
682 IN PQUEUE_HEAD QueueHead
,
683 IN PVOID TransferBuffer
,
684 IN ULONG TransferBufferLength
,
686 IN UCHAR InitialDataToggle
,
687 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
,
688 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
,
689 OUT PUCHAR OutDataToggle
,
690 OUT PULONG OutTransferBufferOffset
)
692 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
= NULL
;
694 ULONG DescriptorLength
, TransferBufferOffset
= 0;
695 ULONG MaxPacketSize
= 0, TransferSize
;
698 // is there an endpoint descriptor
700 if (m_EndpointDescriptor
)
703 // use endpoint packet size
705 MaxPacketSize
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
711 // allocate transfer descriptor
713 Status
= CreateDescriptor(&CurrentDescriptor
);
714 if (!NT_SUCCESS(Status
))
717 // failed to allocate transfer descriptor
719 return STATUS_INSUFFICIENT_RESOURCES
;
725 // transfer size is minimum available buffer or endpoint size
727 TransferSize
= min(TransferBufferLength
- TransferBufferOffset
, MaxPacketSize
);
732 // use available buffer
734 TransferSize
= TransferBufferLength
- TransferBufferOffset
;
738 // now init the descriptor
740 InitDescriptor(CurrentDescriptor
,
741 (PVOID
)((ULONG_PTR
)TransferBuffer
+ TransferBufferOffset
),
748 // insert into queue head
750 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &CurrentDescriptor
->DescriptorEntry
);
755 TransferBufferOffset
+= DescriptorLength
;
760 // link to current descriptor
762 LastDescriptor
->NextPointer
= CurrentDescriptor
->PhysicalAddr
;
763 LastDescriptor
= CurrentDescriptor
;
768 // first descriptor in chain
770 LastDescriptor
= FirstDescriptor
= CurrentDescriptor
;
776 InitialDataToggle
= !InitialDataToggle
;
778 if(TransferBufferLength
== TransferBufferOffset
)
788 if (OutFirstDescriptor
)
791 // store first descriptor
793 *OutFirstDescriptor
= FirstDescriptor
;
796 if (OutLastDescriptor
)
799 // store last descriptor
801 *OutLastDescriptor
= CurrentDescriptor
;
807 // store result data toggle
809 *OutDataToggle
= InitialDataToggle
;
812 if (OutTransferBufferOffset
)
817 *OutTransferBufferOffset
= TransferBufferOffset
;
823 return STATUS_SUCCESS
;
826 //----------------------------------------------------------------------------------------
828 CUSBRequest::BuildControlTransferQueueHead(
829 PQUEUE_HEAD
* OutHead
)
832 ULONG DescriptorChainLength
;
833 PQUEUE_HEAD QueueHead
;
834 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor
, StatusDescriptor
, FirstDescriptor
, LastDescriptor
;
837 // first allocate the queue head
839 Status
= CreateQueueHead(&QueueHead
);
840 if (!NT_SUCCESS(Status
))
843 // failed to allocate queue head
845 return STATUS_INSUFFICIENT_RESOURCES
;
851 PC_ASSERT(QueueHead
);
854 // create setup packet
856 Status
= BuildSetupPacket();
857 if (!NT_SUCCESS(Status
))
860 // failed to allocate setup packet
863 return STATUS_INSUFFICIENT_RESOURCES
;
867 // create setup descriptor
869 Status
= CreateDescriptor(&SetupDescriptor
);
870 if (!NT_SUCCESS(Status
))
873 // failed to allocate transfer descriptor
880 // create status descriptor
882 Status
= CreateDescriptor(&StatusDescriptor
);
883 if (!NT_SUCCESS(Status
))
886 // failed to allocate transfer descriptor
893 // now initialize the queue head
895 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
897 ASSERT(m_EndpointDescriptor
== FALSE
);
900 // init setup descriptor
902 SetupDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_SETUP_TOKEN
;
903 SetupDescriptor
->Token
.Bits
.TotalBytesToTransfer
= sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
);
904 SetupDescriptor
->Token
.Bits
.DataToggle
= FALSE
;
905 SetupDescriptor
->BufferPointer
[0] = m_DescriptorSetupPacket
.LowPart
;
906 SetupDescriptor
->ExtendedBufferPointer
[0] = m_DescriptorSetupPacket
.HighPart
;
907 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &SetupDescriptor
->DescriptorEntry
);
911 // init status descriptor
913 StatusDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
914 StatusDescriptor
->Token
.Bits
.DataToggle
= TRUE
;
915 StatusDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
920 if (m_TransferBufferLength
)
922 Status
= BuildTransferDescriptorChain(QueueHead
,
923 MmGetMdlVirtualAddress(m_TransferBufferMDL
),
924 m_TransferBufferLength
,
925 InternalGetPidDirection(),
930 &DescriptorChainLength
);
933 // FIXME handle errors
935 ASSERT(Status
== STATUS_SUCCESS
);
936 if (m_TransferBufferLength
!= DescriptorChainLength
)
938 DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength
);
939 DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength
);
944 // now link the descriptors
946 SetupDescriptor
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
947 SetupDescriptor
->AlternateNextPointer
= FirstDescriptor
->PhysicalAddr
;
948 LastDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
949 LastDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
953 // pid code is flipped for ops with data stage
955 StatusDescriptor
->Token
.Bits
.PIDCode
= !InternalGetPidDirection();
962 SetupDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
963 SetupDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
966 // retrieve result of operation
968 StatusDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
972 // insert status descriptor
974 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &StatusDescriptor
->DescriptorEntry
);
978 // link transfer descriptors to queue head
980 QueueHead
->NextPointer
= SetupDescriptor
->PhysicalAddr
;
985 *OutHead
= QueueHead
;
988 // displays the current request
990 //DumpQueueHead(QueueHead);
992 DPRINT("BuildControlTransferQueueHead done\n");
996 return STATUS_SUCCESS
;
1000 CUSBRequest::DumpQueueHead(
1001 IN PQUEUE_HEAD QueueHead
)
1004 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1007 DPRINT1("QueueHead %p Addr %x\n", QueueHead
, QueueHead
->PhysicalAddr
);
1008 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead
->AlternateNextPointer
);
1009 DPRINT1("QueueHead NextPointer %x\n", QueueHead
->NextPointer
);
1011 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
);
1012 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1013 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1014 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead
->EndPointCharacteristics
.EndPointSpeed
);
1015 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead
->EndPointCharacteristics
.HeadOfReclamation
);
1016 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead
->EndPointCharacteristics
.InactiveOnNextTransaction
);
1017 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1018 DPRINT1("QueueHead NakCountReload %x\n", QueueHead
->EndPointCharacteristics
.NakCountReload
);
1019 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
);
1020 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCapabilities
.HubAddr
);
1021 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead
->EndPointCapabilities
.InterruptScheduleMask
);
1022 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
);
1023 DPRINT1("QueueHead PortNumber %x\n", QueueHead
->EndPointCapabilities
.PortNumber
);
1024 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead
->EndPointCapabilities
.SplitCompletionMask
);
1026 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1027 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1030 // get transfer descriptor
1032 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1034 DPRINT1("TransferDescriptor %lu Addr %x\n", Index
, Descriptor
->PhysicalAddr
);
1035 DPRINT1("TransferDescriptor %lu Next %x\n", Index
, Descriptor
->NextPointer
);
1036 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index
, Descriptor
->AlternateNextPointer
);
1037 DPRINT1("TransferDescriptor %lu Active %lu\n", Index
, Descriptor
->Token
.Bits
.Active
);
1038 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index
, Descriptor
->Token
.Bits
.BabbleDetected
);
1039 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index
, Descriptor
->Token
.Bits
.CurrentPage
);
1040 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index
, Descriptor
->Token
.Bits
.DataBufferError
);
1041 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index
, Descriptor
->Token
.Bits
.DataToggle
);
1042 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index
, Descriptor
->Token
.Bits
.ErrorCounter
);
1043 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index
, Descriptor
->Token
.Bits
.Halted
);
1044 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index
, Descriptor
->Token
.Bits
.InterruptOnComplete
);
1045 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index
, Descriptor
->Token
.Bits
.MissedMicroFrame
);
1046 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index
, Descriptor
->Token
.Bits
.PIDCode
);
1047 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index
, Descriptor
->Token
.Bits
.PingState
);
1048 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index
, Descriptor
->Token
.Bits
.SplitTransactionState
);
1049 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index
, Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1050 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index
, Descriptor
->Token
.Bits
.TransactionError
);
1052 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index
, Descriptor
->BufferPointer
[0]);
1053 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index
, Descriptor
->BufferPointer
[1]);
1054 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index
, Descriptor
->BufferPointer
[2]);
1055 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index
, Descriptor
->BufferPointer
[3]);
1056 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index
, Descriptor
->BufferPointer
[4]);
1057 Entry
= Entry
->Flink
;
1063 //----------------------------------------------------------------------------------------
1065 CUSBRequest::BuildBulkInterruptTransferQueueHead(
1066 PQUEUE_HEAD
* OutHead
)
1069 PQUEUE_HEAD QueueHead
;
1071 ULONG ChainDescriptorLength
;
1072 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
, LastDescriptor
;
1075 // Allocate the queue head
1077 Status
= CreateQueueHead(&QueueHead
);
1079 if (!NT_SUCCESS(Status
))
1082 // failed to allocate queue heads
1084 return STATUS_INSUFFICIENT_RESOURCES
;
1090 PC_ASSERT(QueueHead
);
1091 PC_ASSERT(m_TransferBufferLength
);
1096 // get virtual base of mdl
1098 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1102 // Increase the size of last transfer, 0 in case this is the first
1104 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1106 PC_ASSERT(m_EndpointDescriptor
);
1112 ASSERT(m_EndpointDescriptor
);
1115 // use 4 * PAGE_SIZE at max for each new request
1117 ULONG MaxTransferLength
= min(4 * PAGE_SIZE
, m_TransferBufferLength
- m_TransferBufferLengthCompleted
);
1120 // build bulk transfer descriptor chain
1122 Status
= BuildTransferDescriptorChain(QueueHead
,
1125 InternalGetPidDirection(),
1126 m_EndpointDescriptor
->DataToggle
,
1129 &m_EndpointDescriptor
->DataToggle
,
1130 &ChainDescriptorLength
);
1133 // move to next offset
1135 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1137 ASSERT(Status
== STATUS_SUCCESS
);
1142 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
1143 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
1144 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
1145 QueueHead
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1146 QueueHead
->CurrentLinkPointer
= FirstDescriptor
->PhysicalAddr
;
1147 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1149 ASSERT(QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1150 ASSERT(QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1151 ASSERT(QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1152 ASSERT(QueueHead
->NextPointer
);
1155 // interrupt on last descriptor
1157 LastDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
1162 *OutHead
= QueueHead
;
1167 //DumpQueueHead(QueueHead);
1172 return STATUS_SUCCESS
;
1175 //----------------------------------------------------------------------------------------
1178 CUSBRequest::CreateDescriptor(
1179 PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
)
1181 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1183 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress
;
1186 // allocate descriptor
1188 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR
), (PVOID
*)&Descriptor
, &TransferDescriptorPhysicalAddress
);
1189 if (!NT_SUCCESS(Status
))
1192 // failed to allocate transfer descriptor
1194 return STATUS_INSUFFICIENT_RESOURCES
;
1198 // initialize transfer descriptor
1200 Descriptor
->NextPointer
= TERMINATE_POINTER
;
1201 Descriptor
->AlternateNextPointer
= TERMINATE_POINTER
;
1202 Descriptor
->Token
.Bits
.DataToggle
= TRUE
;
1203 Descriptor
->Token
.Bits
.ErrorCounter
= 0x03;
1204 Descriptor
->Token
.Bits
.Active
= TRUE
;
1205 Descriptor
->PhysicalAddr
= TransferDescriptorPhysicalAddress
.LowPart
;
1210 *OutDescriptor
= Descriptor
;
1218 //----------------------------------------------------------------------------------------
1220 CUSBRequest::CreateQueueHead(
1221 PQUEUE_HEAD
*OutQueueHead
)
1223 PQUEUE_HEAD QueueHead
;
1224 PHYSICAL_ADDRESS QueueHeadPhysicalAddress
;
1228 // allocate queue head
1230 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_HEAD
), (PVOID
*)&QueueHead
, &QueueHeadPhysicalAddress
);
1232 if (!NT_SUCCESS(Status
))
1235 // failed to allocate queue head
1237 return STATUS_INSUFFICIENT_RESOURCES
;
1241 // initialize queue head
1243 QueueHead
->HorizontalLinkPointer
= TERMINATE_POINTER
;
1244 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1245 QueueHead
->NextPointer
= TERMINATE_POINTER
;
1246 InitializeListHead(&QueueHead
->TransferDescriptorListHead
);
1249 // 1 for non high speed, 0 for high speed device
1251 QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
= 0;
1252 QueueHead
->EndPointCharacteristics
.HeadOfReclamation
= FALSE
;
1253 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= 64;
1256 // Set NakCountReload to max value possible
1258 QueueHead
->EndPointCharacteristics
.NakCountReload
= 0x3;
1261 // Get the Initial Data Toggle from the QEDT
1263 QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
= TRUE
;
1266 // FIXME: check if High Speed Device
1268 QueueHead
->EndPointCharacteristics
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
1269 QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
= 0x01;
1270 QueueHead
->Token
.DWord
= 0;
1271 QueueHead
->Token
.Bits
.InterruptOnComplete
= FALSE
;
1276 QueueHead
->PhysicalAddr
= QueueHeadPhysicalAddress
.LowPart
;
1279 // output queue head
1281 *OutQueueHead
= QueueHead
;
1286 return STATUS_SUCCESS
;
1289 //----------------------------------------------------------------------------------------
1292 CUSBRequest::GetDeviceAddress()
1294 PIO_STACK_LOCATION IoStack
;
1296 PUSBDEVICE UsbDevice
;
1299 // check if there is an irp provided
1304 // used provided address
1306 return m_DeviceAddress
;
1310 // get current stack location
1312 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1315 // get contained urb
1317 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1320 // check if there is a pipe handle provided
1322 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
1325 // there is a device handle provided
1327 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
1330 // return device address
1332 return UsbDevice
->GetDeviceAddress();
1336 // no device handle provided, it is the host root bus
1341 //----------------------------------------------------------------------------------------
1343 CUSBRequest::BuildSetupPacket()
1348 // allocate common buffer setup packet
1350 Status
= m_DmaManager
->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), (PVOID
*)&m_DescriptorPacket
, &m_DescriptorSetupPacket
);
1351 if (!NT_SUCCESS(Status
))
1362 // copy setup packet
1364 RtlCopyMemory(m_DescriptorPacket
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1369 // build setup packet from urb
1371 Status
= BuildSetupPacketFromURB();
1382 CUSBRequest::BuildSetupPacketFromURB()
1384 PIO_STACK_LOCATION IoStack
;
1386 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1392 PC_ASSERT(m_DescriptorPacket
);
1395 // get stack location
1397 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1402 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1405 // zero descriptor packet
1407 RtlZeroMemory(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1410 switch (Urb
->UrbHeader
.Function
)
1413 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
1414 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
1415 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
1420 case URB_FUNCTION_GET_CONFIGURATION
:
1421 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1422 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1423 m_DescriptorPacket
->wLength
= 1;
1426 /* GET DESCRIPTOR */
1427 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1428 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1429 m_DescriptorPacket
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1430 m_DescriptorPacket
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1431 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1432 m_DescriptorPacket
->wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1433 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1437 case URB_FUNCTION_GET_INTERFACE
:
1438 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1439 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1440 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1441 m_DescriptorPacket
->wLength
= 1;
1445 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1446 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1447 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1448 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1449 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1450 m_DescriptorPacket
->wLength
= 2;
1453 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
1454 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1455 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1456 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1457 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1458 m_DescriptorPacket
->wLength
= 2;
1461 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
1462 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1463 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1464 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1465 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1466 m_DescriptorPacket
->wLength
= 2;
1472 case URB_FUNCTION_SELECT_CONFIGURATION
:
1473 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1474 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
1475 m_DescriptorPacket
->wIndex
.W
= 0;
1476 m_DescriptorPacket
->wLength
= 0;
1477 m_DescriptorPacket
->bmRequestType
.B
= 0x00;
1480 /* SET DESCRIPTOR */
1481 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
1482 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
1483 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
1488 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
1489 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1490 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1491 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1492 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1495 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
1496 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1497 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1498 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1499 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1502 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
1503 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1504 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1505 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1506 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1510 case URB_FUNCTION_SELECT_INTERFACE
:
1511 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_INTERFACE
;
1512 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
1513 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
1514 m_DescriptorPacket
->wLength
= 0;
1515 m_DescriptorPacket
->bmRequestType
.B
= 0x01;
1519 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
1530 //----------------------------------------------------------------------------------------
1533 CUSBRequest::GetResultStatus(
1534 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1535 OUT OPTIONAL PULONG UrbStatusCode
)
1540 PC_ASSERT(m_CompletionEvent
);
1543 // wait for the operation to complete
1545 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1552 *NtStatusCode
= m_NtStatusCode
;
1560 *UrbStatusCode
= m_UrbStatusCode
;
1565 //-----------------------------------------------------------------------------------------
1568 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1573 // the request is completed, release it
1580 // created with an setup packet, don't release
1586 //-----------------------------------------------------------------------------------------
1589 CUSBRequest::FreeQueueHead(
1590 IN
struct _QUEUE_HEAD
* QueueHead
)
1593 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1598 ASSERT(m_DmaManager
);
1600 ASSERT(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1605 // get transfer descriptors
1607 Entry
= RemoveHeadList(&QueueHead
->TransferDescriptorListHead
);
1611 // obtain descriptor from entry
1613 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1617 // add transfer count
1619 m_TotalBytesTransferred
+= (Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1620 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
);
1623 // release transfer descriptors
1625 m_DmaManager
->Release(Descriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
1627 }while(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1629 if (m_DescriptorPacket
)
1632 // release packet descriptor
1634 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1638 // release queue head
1640 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1646 m_DescriptorPacket
= 0;
1649 //-----------------------------------------------------------------------------------------
1652 CUSBRequest::IsQueueHeadComplete(
1653 struct _QUEUE_HEAD
* QueueHead
)
1656 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1659 // first check - is the queue head currently active
1661 if (QueueHead
->Token
.Bits
.Active
)
1664 // queue head is active (currently processed)
1669 if (QueueHead
->Token
.Bits
.Halted
)
1674 DPRINT1("Found halted queue head %p\n", QueueHead
);
1675 DumpQueueHead(QueueHead
);
1681 // loop list and see if there are any active descriptors
1683 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1684 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1687 // obtain descriptor from entry
1689 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1691 if (Descriptor
->Token
.Bits
.Active
)
1694 // descriptor is still active
1700 // move to next entry
1702 Entry
= Entry
->Flink
;
1705 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead
, QueueHead
->PhysicalAddr
);
1708 // no active descriptors found, queue head is finished
1713 //-----------------------------------------------------------------------------------------
1715 CUSBRequest::InternalCalculateTransferLength()
1720 // FIXME: get length for control request
1722 return m_TransferBufferLength
;
1728 ASSERT(m_EndpointDescriptor
);
1729 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
1733 // HACK: Properly determine transfer length
1735 return m_TransferBufferLength
;//m_TotalBytesTransferred;
1739 // bulk out transfer
1741 return m_TransferBufferLength
;
1745 CUSBRequest::GetSpeed()
1751 CUSBRequest::GetInterval()
1753 if (!m_EndpointDescriptor
)
1756 return m_EndpointDescriptor
->EndPointDescriptor
.bInterval
;
1759 //-----------------------------------------------------------------------------------------
1762 InternalCreateUSBRequest(
1763 PUSBREQUEST
*OutRequest
)
1768 // allocate requests
1770 This
= new(NonPagedPool
, TAG_USBEHCI
) CUSBRequest(0);
1774 // failed to allocate
1776 return STATUS_INSUFFICIENT_RESOURCES
;
1780 // add reference count
1787 *OutRequest
= (PUSBREQUEST
)This
;
1792 return STATUS_SUCCESS
;