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 IUSBRequest
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
39 virtual NTSTATUS
InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager
, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, IN UCHAR DeviceAddress
, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
, IN OUT ULONG TransferBufferLength
, IN OUT PMDL TransferBuffer
);
40 virtual NTSTATUS
InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager
, IN OUT PIRP Irp
);
41 virtual VOID
CompletionCallback(IN NTSTATUS NtStatusCode
, IN ULONG UrbStatusCode
, IN
struct _QUEUE_HEAD
*QueueHead
);
42 virtual VOID
CancelCallback(IN NTSTATUS NtStatusCode
, IN
struct _QUEUE_HEAD
*QueueHead
);
43 virtual NTSTATUS
GetQueueHead(struct _QUEUE_HEAD
** OutHead
);
44 virtual BOOLEAN
IsRequestComplete();
45 virtual ULONG
GetTransferType();
46 virtual VOID
GetResultStatus(OUT OPTIONAL NTSTATUS
*NtStatusCode
, OUT OPTIONAL PULONG UrbStatusCode
);
47 virtual BOOLEAN
IsRequestInitialized();
48 virtual BOOLEAN
ShouldReleaseRequestAfterCompletion();
49 virtual VOID
FreeQueueHead(struct _QUEUE_HEAD
* QueueHead
);
50 virtual VOID
GetTransferBuffer(OUT PMDL
* OutMDL
, OUT PULONG TransferLength
);
51 virtual BOOLEAN
IsQueueHeadComplete(struct _QUEUE_HEAD
* QueueHead
);
55 ULONG
InternalGetTransferType();
56 UCHAR
InternalGetPidDirection();
57 NTSTATUS
BuildControlTransferQueueHead(PQUEUE_HEAD
* OutHead
);
58 NTSTATUS
BuildBulkTransferQueueHead(PQUEUE_HEAD
* OutHead
);
59 NTSTATUS
CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
);
60 NTSTATUS
CreateQueueHead(PQUEUE_HEAD
*OutQueueHead
);
61 UCHAR
GetDeviceAddress();
62 NTSTATUS
BuildSetupPacket();
63 NTSTATUS
BuildSetupPacketFromURB();
64 ULONG
InternalCalculateTransferLength();
65 NTSTATUS
BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, IN UCHAR InitialDataToggle
, OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
, OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
, OUT PUCHAR OutDataToggle
, OUT PULONG OutTransferBufferOffset
);
66 VOID
InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, IN UCHAR DataToggle
, OUT PULONG OutDescriptorLength
);
67 VOID
DumpQueueHead(IN PQUEUE_HEAD QueueHead
);
70 // constructor / destructor
71 CUSBRequest(IUnknown
*OuterUnknown
){}
72 virtual ~CUSBRequest(){}
78 // memory manager for allocating setup packet / queue head / transfer descriptors
80 PDMAMEMORYMANAGER m_DmaManager
;
83 // caller provided irp packet containing URB request
88 // transfer buffer length
90 ULONG m_TransferBufferLength
;
93 // current transfer length
95 ULONG m_TransferBufferLengthCompleted
;
98 // Total Transfer Length
100 ULONG m_TotalBytesTransferred
;
103 // transfer buffer MDL
105 PMDL m_TransferBufferMDL
;
108 // caller provided setup packet
110 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
113 // completion event for callers who initialized request with setup packet
115 PKEVENT m_CompletionEvent
;
118 // device address for callers who initialized it with device address
120 UCHAR m_DeviceAddress
;
123 // store end point address
125 PUSB_ENDPOINT m_EndpointDescriptor
;
130 PQUEUE_HEAD m_QueueHead
;
133 // allocated setup packet from the DMA pool
135 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
136 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
139 // stores the result of the operation
141 NTSTATUS m_NtStatusCode
;
142 ULONG m_UrbStatusCode
;
148 //----------------------------------------------------------------------------------------
151 CUSBRequest::QueryInterface(
155 return STATUS_UNSUCCESSFUL
;
158 //----------------------------------------------------------------------------------------
160 CUSBRequest::InitializeWithSetupPacket(
161 IN PDMAMEMORYMANAGER DmaManager
,
162 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
163 IN UCHAR DeviceAddress
,
164 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
165 IN OUT ULONG TransferBufferLength
,
166 IN OUT PMDL TransferBuffer
)
171 PC_ASSERT(DmaManager
);
172 PC_ASSERT(SetupPacket
);
177 m_DmaManager
= DmaManager
;
178 m_SetupPacket
= SetupPacket
;
179 m_TransferBufferLength
= TransferBufferLength
;
180 m_TransferBufferMDL
= TransferBuffer
;
181 m_DeviceAddress
= DeviceAddress
;
182 m_EndpointDescriptor
= EndpointDescriptor
;
183 m_TotalBytesTransferred
= 0;
186 // Set Length Completed to 0
188 m_TransferBufferLengthCompleted
= 0;
191 // allocate completion event
193 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBEHCI
);
194 if (!m_CompletionEvent
)
197 // failed to allocate completion event
199 return STATUS_INSUFFICIENT_RESOURCES
;
203 // initialize completion event
205 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
210 return STATUS_SUCCESS
;
212 //----------------------------------------------------------------------------------------
214 CUSBRequest::InitializeWithIrp(
215 IN PDMAMEMORYMANAGER DmaManager
,
218 PIO_STACK_LOCATION IoStack
;
224 PC_ASSERT(DmaManager
);
227 m_DmaManager
= DmaManager
;
228 m_TotalBytesTransferred
= 0;
231 // get current irp stack location
233 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
238 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
239 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
240 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
245 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
253 // check function type
255 switch (Urb
->UrbHeader
.Function
)
258 // luckily those request have the same structure layout
260 case URB_FUNCTION_CLASS_INTERFACE
:
261 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
262 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
265 // bulk interrupt transfer
267 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
270 // Check if there is a MDL
272 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
277 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
280 // Create one using TransferBuffer
282 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
283 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
284 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
289 if (!m_TransferBufferMDL
)
292 // failed to allocate mdl
294 return STATUS_INSUFFICIENT_RESOURCES
;
298 // build mdl for non paged pool
299 // FIXME: Does hub driver already do this when passing MDL?
301 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
304 // Keep that ehci created the MDL and needs to free it.
309 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
313 // save buffer length
315 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
318 // Set Length Completed to 0
320 m_TransferBufferLengthCompleted
= 0;
323 // get endpoint descriptor
325 m_EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
331 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
338 return STATUS_SUCCESS
;
342 //----------------------------------------------------------------------------------------
344 CUSBRequest::CompletionCallback(
345 IN NTSTATUS NtStatusCode
,
346 IN ULONG UrbStatusCode
,
347 IN
struct _QUEUE_HEAD
*QueueHead
)
349 PIO_STACK_LOCATION IoStack
;
353 // FIXME: support linked queue heads
357 // store completion code
359 m_NtStatusCode
= NtStatusCode
;
360 m_UrbStatusCode
= UrbStatusCode
;
365 // set irp completion status
367 m_Irp
->IoStatus
.Status
= NtStatusCode
;
370 // get current irp stack location
372 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
377 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
382 Urb
->UrbHeader
.Status
= UrbStatusCode
;
385 // Check if the MDL was created
387 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
392 IoFreeMdl(m_TransferBufferMDL
);
396 // check if the request was successfull
398 if (!NT_SUCCESS(NtStatusCode
))
401 // set returned length to zero in case of error
403 Urb
->UrbHeader
.Length
= 0;
408 // calculate transfer length
410 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
= InternalCalculateTransferLength();
413 DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp
, NtStatusCode
, UrbStatusCode
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
416 // FIXME: check if the transfer was split
417 // if yes dont complete irp yet
419 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
424 // signal completion event
426 PC_ASSERT(m_CompletionEvent
);
427 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
430 //----------------------------------------------------------------------------------------
432 CUSBRequest::CancelCallback(
433 IN NTSTATUS NtStatusCode
,
434 IN
struct _QUEUE_HEAD
*QueueHead
)
436 PIO_STACK_LOCATION IoStack
;
440 // FIXME: support linked queue heads
444 // store cancelleation code
446 m_NtStatusCode
= NtStatusCode
;
451 // set irp completion status
453 m_Irp
->IoStatus
.Status
= NtStatusCode
;
456 // get current irp stack location
458 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
463 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
468 DPRINT1("Request Cancelled\n");
469 Urb
->UrbHeader
.Status
= USBD_STATUS_CANCELED
;
470 Urb
->UrbHeader
.Length
= 0;
473 // FIXME: check if the transfer was split
474 // if yes dont complete irp yet
476 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
481 // signal completion event
483 PC_ASSERT(m_CompletionEvent
);
484 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
487 //----------------------------------------------------------------------------------------
489 CUSBRequest::GetQueueHead(
490 struct _QUEUE_HEAD
** OutHead
)
496 // first get transfer type
498 TransferType
= InternalGetTransferType();
501 // build request depending on type
505 case USB_ENDPOINT_TYPE_CONTROL
:
506 Status
= BuildControlTransferQueueHead(OutHead
);
508 case USB_ENDPOINT_TYPE_BULK
:
509 Status
= BuildBulkTransferQueueHead(OutHead
);
511 case USB_ENDPOINT_TYPE_INTERRUPT
:
512 DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
513 Status
= STATUS_NOT_IMPLEMENTED
;
515 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
516 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
517 Status
= STATUS_NOT_IMPLEMENTED
;
521 Status
= STATUS_NOT_IMPLEMENTED
;
525 if (NT_SUCCESS(Status
))
530 m_QueueHead
= *OutHead
;
533 // store request object
535 (*OutHead
)->Request
= PVOID(this);
544 //----------------------------------------------------------------------------------------
546 CUSBRequest::IsRequestComplete()
549 // FIXME: check if request was split
553 // Check if the transfer was completed, only valid for Bulk Transfers
555 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
556 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
559 // Transfer not completed
565 //----------------------------------------------------------------------------------------
567 CUSBRequest::GetTransferType()
570 // call internal implementation
572 return InternalGetTransferType();
575 //----------------------------------------------------------------------------------------
577 CUSBRequest::InternalGetTransferType()
582 // check if an irp is provided
586 ASSERT(m_EndpointDescriptor
);
589 // end point is defined in the low byte of bmAttributes
591 TransferType
= (m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
596 // initialized with setup packet, must be a control transfer
598 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
599 ASSERT(m_EndpointDescriptor
== FALSE
);
609 CUSBRequest::InternalGetPidDirection()
611 if (m_EndpointDescriptor
)
614 // end point direction is highest bit in bEndpointAddress
616 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
621 // request arrives on the control pipe, extract direction from setup packet
623 ASSERT(m_DescriptorPacket
);
624 return (m_DescriptorPacket
->bmRequestType
.B
>> 7);
629 CUSBRequest::InitDescriptor(
630 IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
,
631 IN PVOID TransferBuffer
,
632 IN ULONG TransferBufferLength
,
635 OUT PULONG OutDescriptorLength
)
637 ULONG Index
, Length
= 0, PageOffset
, BufferLength
;
640 // init transfer descriptor
642 CurrentDescriptor
->Token
.Bits
.PIDCode
= PidCode
;
643 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
644 CurrentDescriptor
->Token
.Bits
.DataToggle
= DataToggle
;
649 ASSERT(TransferBufferLength
);
658 // use physical address
660 CurrentDescriptor
->BufferPointer
[Index
] = MmGetPhysicalAddress(TransferBuffer
).LowPart
;
663 // Get the offset from page size
665 PageOffset
= BYTE_OFFSET(CurrentDescriptor
->BufferPointer
[Index
]);
671 TransferBuffer
= (PVOID
)ROUND_TO_PAGES(TransferBuffer
);
678 TransferBuffer
= (PVOID
)((ULONG_PTR
)TransferBuffer
+ PAGE_SIZE
);
682 // calculate buffer length
684 BufferLength
= min(TransferBufferLength
, PAGE_SIZE
- PageOffset
);
687 // increment transfer bytes
689 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
+= BufferLength
;
690 CurrentDescriptor
->TotalBytesToTransfer
+= BufferLength
;
691 Length
+= BufferLength
;
692 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index
, TransferBufferLength
, PageOffset
, BufferLength
, CurrentDescriptor
->BufferPointer
[Index
], TransferBuffer
);
695 // decrement available byte count
697 TransferBufferLength
-= BufferLength
;
698 if (TransferBufferLength
== 0)
714 ASSERT(CurrentDescriptor
->BufferPointer
[Index
] != CurrentDescriptor
->BufferPointer
[Index
-1]);
718 // next descriptor index
726 *OutDescriptorLength
= Length
;
731 CUSBRequest::BuildTransferDescriptorChain(
732 IN PQUEUE_HEAD QueueHead
,
733 IN PVOID TransferBuffer
,
734 IN ULONG TransferBufferLength
,
736 IN UCHAR InitialDataToggle
,
737 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
,
738 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
,
739 OUT PUCHAR OutDataToggle
,
740 OUT PULONG OutTransferBufferOffset
)
742 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
= NULL
;
744 ULONG DescriptorLength
, TransferBufferOffset
= 0;
749 // allocate transfer descriptor
751 Status
= CreateDescriptor(&CurrentDescriptor
);
752 if (!NT_SUCCESS(Status
))
755 // failed to allocate transfer descriptor
762 // now init the descriptor
764 InitDescriptor(CurrentDescriptor
,
765 (PVOID
)((ULONG_PTR
)TransferBuffer
+ TransferBufferOffset
),
766 TransferBufferLength
- TransferBufferOffset
,
772 // insert into queue head
774 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &CurrentDescriptor
->DescriptorEntry
);
779 TransferBufferOffset
+= DescriptorLength
;
784 // link to current descriptor
786 LastDescriptor
->AlternateNextPointer
= CurrentDescriptor
->PhysicalAddr
;
787 LastDescriptor
->NextPointer
= CurrentDescriptor
->PhysicalAddr
;
788 LastDescriptor
= CurrentDescriptor
;
793 // first descriptor in chain
795 LastDescriptor
= FirstDescriptor
= CurrentDescriptor
;
798 if(TransferBufferLength
== TransferBufferOffset
)
807 if (OutFirstDescriptor
)
810 // store first descriptor
812 *OutFirstDescriptor
= FirstDescriptor
;
815 if (OutLastDescriptor
)
818 // store last descriptor
820 *OutLastDescriptor
= CurrentDescriptor
;
828 InitialDataToggle
= !InitialDataToggle
;
831 // store result data toggle
833 *OutDataToggle
= InitialDataToggle
;
836 if (OutTransferBufferOffset
)
841 *OutTransferBufferOffset
= TransferBufferOffset
;
847 return STATUS_SUCCESS
;
850 //----------------------------------------------------------------------------------------
852 CUSBRequest::BuildControlTransferQueueHead(
853 PQUEUE_HEAD
* OutHead
)
856 ULONG DescriptorChainLength
;
857 PQUEUE_HEAD QueueHead
;
858 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor
, StatusDescriptor
, FirstDescriptor
, LastDescriptor
;
861 // first allocate the queue head
863 Status
= CreateQueueHead(&QueueHead
);
864 if (!NT_SUCCESS(Status
))
867 // failed to allocate queue head
869 return STATUS_INSUFFICIENT_RESOURCES
;
875 PC_ASSERT(QueueHead
);
878 // create setup packet
880 Status
= BuildSetupPacket();
881 if (!NT_SUCCESS(Status
))
884 // failed to allocate setup packet
887 return STATUS_INSUFFICIENT_RESOURCES
;
891 // create setup descriptor
893 Status
= CreateDescriptor(&SetupDescriptor
);
894 if (!NT_SUCCESS(Status
))
897 // failed to allocate transfer descriptor
904 // create status descriptor
906 Status
= CreateDescriptor(&StatusDescriptor
);
907 if (!NT_SUCCESS(Status
))
910 // failed to allocate transfer descriptor
917 // now initialize the queue head
919 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
921 if (m_EndpointDescriptor
)
924 // set endpoint address and max packet length
926 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
927 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
931 // init setup descriptor
933 SetupDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_SETUP_TOKEN
;
934 SetupDescriptor
->Token
.Bits
.TotalBytesToTransfer
= sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
);
935 SetupDescriptor
->Token
.Bits
.DataToggle
= FALSE
;
936 SetupDescriptor
->BufferPointer
[0] = (ULONG
)PtrToUlong(m_DescriptorSetupPacket
.LowPart
);
937 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &SetupDescriptor
->DescriptorEntry
);
941 // init status descriptor
943 StatusDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
944 StatusDescriptor
->Token
.Bits
.DataToggle
= TRUE
;
945 StatusDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
950 if (m_TransferBufferLength
)
952 Status
= BuildTransferDescriptorChain(QueueHead
,
953 MmGetMdlVirtualAddress(m_TransferBufferMDL
),
954 m_TransferBufferLength
,
955 InternalGetPidDirection(),
960 &DescriptorChainLength
);
963 // FIXME handle errors
965 ASSERT(Status
== STATUS_SUCCESS
);
966 ASSERT(DescriptorChainLength
== m_TransferBufferLength
);
969 // now link the descriptors
971 SetupDescriptor
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
972 SetupDescriptor
->AlternateNextPointer
= FirstDescriptor
->PhysicalAddr
;
973 LastDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
974 LastDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
978 // pid code is flipped for ops with data stage
980 StatusDescriptor
->Token
.Bits
.PIDCode
= !InternalGetPidDirection();
987 SetupDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
988 SetupDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
991 // retrieve result of operation
993 StatusDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
997 // insert status descriptor
999 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &StatusDescriptor
->DescriptorEntry
);
1003 // link transfer descriptors to queue head
1005 QueueHead
->NextPointer
= SetupDescriptor
->PhysicalAddr
;
1010 *OutHead
= QueueHead
;
1013 // displays the current request
1015 //DumpQueueHead(QueueHead);
1017 DPRINT("BuildControlTransferQueueHead done\n");
1021 return STATUS_SUCCESS
;
1025 CUSBRequest::DumpQueueHead(
1026 IN PQUEUE_HEAD QueueHead
)
1029 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1032 DPRINT1("QueueHead %p Addr %x\n", QueueHead
, QueueHead
->PhysicalAddr
);
1033 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead
->AlternateNextPointer
);
1034 DPRINT1("QueueHead NextPointer %x\n", QueueHead
->NextPointer
);
1036 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
);
1037 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1038 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1039 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead
->EndPointCharacteristics
.EndPointSpeed
);
1040 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead
->EndPointCharacteristics
.HeadOfReclamation
);
1041 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead
->EndPointCharacteristics
.InactiveOnNextTransaction
);
1042 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1043 DPRINT1("QueueHead NakCountReload %x\n", QueueHead
->EndPointCharacteristics
.NakCountReload
);
1044 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
);
1045 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCapabilities
.HubAddr
);
1046 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead
->EndPointCapabilities
.InterruptScheduleMask
);
1047 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
);
1048 DPRINT1("QueueHead PortNumber %x\n", QueueHead
->EndPointCapabilities
.PortNumber
);
1049 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead
->EndPointCapabilities
.SplitCompletionMask
);
1051 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1052 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1055 // get transfer descriptor
1057 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1059 DPRINT1("TransferDescriptor %lu Addr %x\n", Index
, Descriptor
->PhysicalAddr
);
1060 DPRINT1("TransferDescriptor %lu Next %x\n", Index
, Descriptor
->NextPointer
);
1061 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index
, Descriptor
->AlternateNextPointer
);
1062 DPRINT1("TransferDescriptor %lu Active %lu\n", Index
, Descriptor
->Token
.Bits
.Active
);
1063 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index
, Descriptor
->Token
.Bits
.BabbleDetected
);
1064 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index
, Descriptor
->Token
.Bits
.CurrentPage
);
1065 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index
, Descriptor
->Token
.Bits
.DataBufferError
);
1066 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index
, Descriptor
->Token
.Bits
.DataToggle
);
1067 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index
, Descriptor
->Token
.Bits
.ErrorCounter
);
1068 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index
, Descriptor
->Token
.Bits
.Halted
);
1069 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index
, Descriptor
->Token
.Bits
.InterruptOnComplete
);
1070 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index
, Descriptor
->Token
.Bits
.MissedMicroFrame
);
1071 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index
, Descriptor
->Token
.Bits
.PIDCode
);
1072 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index
, Descriptor
->Token
.Bits
.PingState
);
1073 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index
, Descriptor
->Token
.Bits
.SplitTransactionState
);
1074 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index
, Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1075 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index
, Descriptor
->Token
.Bits
.TransactionError
);
1077 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index
, Descriptor
->BufferPointer
[0]);
1078 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index
, Descriptor
->BufferPointer
[1]);
1079 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index
, Descriptor
->BufferPointer
[2]);
1080 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index
, Descriptor
->BufferPointer
[3]);
1081 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index
, Descriptor
->BufferPointer
[4]);
1082 Entry
= Entry
->Flink
;
1088 //----------------------------------------------------------------------------------------
1090 CUSBRequest::BuildBulkTransferQueueHead(
1091 PQUEUE_HEAD
* OutHead
)
1094 PQUEUE_HEAD QueueHead
;
1096 ULONG ChainDescriptorLength
;
1097 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
, LastDescriptor
;
1100 // Allocate the queue head
1102 Status
= CreateQueueHead(&QueueHead
);
1104 if (!NT_SUCCESS(Status
))
1107 // failed to allocate queue heads
1109 return STATUS_INSUFFICIENT_RESOURCES
;
1115 PC_ASSERT(QueueHead
);
1116 PC_ASSERT(m_TransferBufferLength
);
1121 // get virtual base of mdl
1123 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1127 // Increase the size of last transfer, 0 in case this is the first
1129 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1131 PC_ASSERT(m_EndpointDescriptor
);
1137 ASSERT(m_EndpointDescriptor
);
1140 // build bulk transfer descriptor chain
1142 Status
= BuildTransferDescriptorChain(QueueHead
,
1144 m_TransferBufferLength
- m_TransferBufferLengthCompleted
,
1145 InternalGetPidDirection(),
1146 m_EndpointDescriptor
->DataToggle
,
1149 &m_EndpointDescriptor
->DataToggle
,
1150 &ChainDescriptorLength
);
1153 // FIXME: handle errors
1155 ASSERT(ChainDescriptorLength
== m_TransferBufferLength
);
1158 // move to next offset
1160 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1162 ASSERT(Status
== STATUS_SUCCESS
);
1167 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
1168 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
1169 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
1170 QueueHead
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1171 QueueHead
->CurrentLinkPointer
= FirstDescriptor
->PhysicalAddr
;
1172 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1174 ASSERT(QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1175 ASSERT(QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1176 ASSERT(QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1177 ASSERT(QueueHead
->NextPointer
);
1180 // interrupt on last descriptor
1182 LastDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
1187 *OutHead
= QueueHead
;
1192 //DumpQueueHead(QueueHead);
1197 return STATUS_SUCCESS
;
1200 //----------------------------------------------------------------------------------------
1202 CUSBRequest::CreateDescriptor(
1203 PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
)
1205 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1207 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress
;
1210 // allocate descriptor
1212 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR
), (PVOID
*)&Descriptor
, &TransferDescriptorPhysicalAddress
);
1213 if (!NT_SUCCESS(Status
))
1216 // failed to allocate transfer descriptor
1218 return STATUS_INSUFFICIENT_RESOURCES
;
1222 // initialize transfer descriptor
1224 Descriptor
->NextPointer
= TERMINATE_POINTER
;
1225 Descriptor
->AlternateNextPointer
= TERMINATE_POINTER
;
1226 Descriptor
->Token
.Bits
.DataToggle
= TRUE
;
1227 Descriptor
->Token
.Bits
.ErrorCounter
= 0x03;
1228 Descriptor
->Token
.Bits
.Active
= TRUE
;
1229 Descriptor
->PhysicalAddr
= TransferDescriptorPhysicalAddress
.LowPart
;
1234 *OutDescriptor
= Descriptor
;
1242 //----------------------------------------------------------------------------------------
1244 CUSBRequest::CreateQueueHead(
1245 PQUEUE_HEAD
*OutQueueHead
)
1247 PQUEUE_HEAD QueueHead
;
1248 PHYSICAL_ADDRESS QueueHeadPhysicalAddress
;
1252 // allocate queue head
1254 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_HEAD
), (PVOID
*)&QueueHead
, &QueueHeadPhysicalAddress
);
1256 if (!NT_SUCCESS(Status
))
1259 // failed to allocate queue head
1261 return STATUS_INSUFFICIENT_RESOURCES
;
1265 // initialize queue head
1267 QueueHead
->HorizontalLinkPointer
= TERMINATE_POINTER
;
1268 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1269 QueueHead
->NextPointer
= TERMINATE_POINTER
;
1270 InitializeListHead(&QueueHead
->TransferDescriptorListHead
);
1273 // 1 for non high speed, 0 for high speed device
1275 QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
= 0;
1276 QueueHead
->EndPointCharacteristics
.HeadOfReclamation
= FALSE
;
1277 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= 64;
1280 // Set NakCountReload to max value possible
1282 QueueHead
->EndPointCharacteristics
.NakCountReload
= 0xF;
1285 // Get the Initial Data Toggle from the QEDT
1287 QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
= TRUE
;
1290 // FIXME: check if High Speed Device
1292 QueueHead
->EndPointCharacteristics
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
1293 QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
= 0x03;
1294 QueueHead
->Token
.DWord
= 0;
1295 QueueHead
->Token
.Bits
.InterruptOnComplete
= FALSE
;
1298 // FIXME check if that is really needed
1300 QueueHead
->PhysicalAddr
= QueueHeadPhysicalAddress
.LowPart
;
1303 // output queue head
1305 *OutQueueHead
= QueueHead
;
1310 return STATUS_SUCCESS
;
1313 //----------------------------------------------------------------------------------------
1315 CUSBRequest::GetDeviceAddress()
1317 PIO_STACK_LOCATION IoStack
;
1319 PUSBDEVICE UsbDevice
;
1322 // check if there is an irp provided
1327 // used provided address
1329 return m_DeviceAddress
;
1333 // get current stack location
1335 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1338 // get contained urb
1340 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1343 // check if there is a pipe handle provided
1345 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
1348 // there is a device handle provided
1350 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
1353 // return device address
1355 return UsbDevice
->GetDeviceAddress();
1359 // no device handle provided, it is the host root bus
1364 //----------------------------------------------------------------------------------------
1366 CUSBRequest::BuildSetupPacket()
1371 // allocate common buffer setup packet
1373 Status
= m_DmaManager
->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), (PVOID
*)&m_DescriptorPacket
, &m_DescriptorSetupPacket
);
1374 if (!NT_SUCCESS(Status
))
1385 // copy setup packet
1387 RtlCopyMemory(m_DescriptorPacket
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1392 // build setup packet from urb
1394 Status
= BuildSetupPacketFromURB();
1405 CUSBRequest::BuildSetupPacketFromURB()
1407 PIO_STACK_LOCATION IoStack
;
1409 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1415 PC_ASSERT(m_DescriptorPacket
);
1418 // get stack location
1420 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1425 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1428 // zero descriptor packet
1430 RtlZeroMemory(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1433 switch (Urb
->UrbHeader
.Function
)
1436 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
1437 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
1438 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
1443 case URB_FUNCTION_GET_CONFIGURATION
:
1444 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1445 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1446 m_DescriptorPacket
->wLength
= 1;
1449 /* GET DESCRIPTOR */
1450 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1451 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1452 m_DescriptorPacket
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1453 m_DescriptorPacket
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1454 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1455 m_DescriptorPacket
->wLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1456 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1460 case URB_FUNCTION_GET_INTERFACE
:
1461 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1462 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1463 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1464 m_DescriptorPacket
->wLength
= 1;
1468 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1469 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1470 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1471 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1472 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1473 m_DescriptorPacket
->wLength
= 2;
1476 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
1477 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1478 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1479 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1480 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1481 m_DescriptorPacket
->wLength
= 2;
1484 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
1485 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1486 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1487 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1488 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1489 m_DescriptorPacket
->wLength
= 2;
1495 case URB_FUNCTION_SELECT_CONFIGURATION
:
1496 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1497 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
1498 m_DescriptorPacket
->wIndex
.W
= 0;
1499 m_DescriptorPacket
->wLength
= 0;
1500 m_DescriptorPacket
->bmRequestType
.B
= 0x00;
1503 /* SET DESCRIPTOR */
1504 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
1505 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
1506 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
1511 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
1512 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1513 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1514 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1515 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1518 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
1519 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1520 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1521 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1522 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1525 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
1526 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1527 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1528 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1529 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1533 case URB_FUNCTION_SELECT_INTERFACE
:
1534 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_INTERFACE
;
1535 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
1536 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
1537 m_DescriptorPacket
->wLength
= 0;
1538 m_DescriptorPacket
->bmRequestType
.B
= 0x01;
1542 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
1553 //----------------------------------------------------------------------------------------
1555 CUSBRequest::GetResultStatus(
1556 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1557 OUT OPTIONAL PULONG UrbStatusCode
)
1562 PC_ASSERT(m_CompletionEvent
);
1565 // wait for the operation to complete
1567 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1574 *NtStatusCode
= m_NtStatusCode
;
1582 *UrbStatusCode
= m_UrbStatusCode
;
1588 //-----------------------------------------------------------------------------------------
1590 CUSBRequest::IsRequestInitialized()
1592 if (m_Irp
|| m_SetupPacket
)
1595 // request is initialized
1601 // request is not initialized
1606 //-----------------------------------------------------------------------------------------
1608 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1613 // the request is completed, release it
1620 // created with an setup packet, don't release
1626 //-----------------------------------------------------------------------------------------
1628 CUSBRequest::FreeQueueHead(
1629 IN
struct _QUEUE_HEAD
* QueueHead
)
1632 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1637 ASSERT(m_DmaManager
);
1639 ASSERT(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1644 // get transfer descriptors
1646 Entry
= RemoveHeadList(&QueueHead
->TransferDescriptorListHead
);
1650 // obtain descriptor from entry
1652 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1656 // add transfer count
1658 m_TotalBytesTransferred
+= (Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1659 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
);
1662 // release transfer descriptors
1664 m_DmaManager
->Release(Descriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
1666 }while(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1668 if (m_DescriptorPacket
)
1671 // release packet descriptor
1673 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1677 // release queue head
1679 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1685 m_DescriptorPacket
= 0;
1688 //-----------------------------------------------------------------------------------------
1690 CUSBRequest::IsQueueHeadComplete(
1691 struct _QUEUE_HEAD
* QueueHead
)
1694 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1697 // first check - is the queue head currently active
1699 if (QueueHead
->Token
.Bits
.Active
)
1702 // queue head is active (currently processed)
1707 if (QueueHead
->Token
.Bits
.Halted
)
1712 DPRINT1("Found halted queue head %p\n", QueueHead
);
1713 DumpQueueHead(QueueHead
);
1719 // loop list and see if there are any active descriptors
1721 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1722 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1725 // obtain descriptor from entry
1727 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1729 if (Descriptor
->Token
.Bits
.Active
)
1732 // descriptor is still active
1738 // move to next entry
1740 Entry
= Entry
->Flink
;
1743 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead
, QueueHead
->PhysicalAddr
);
1746 // no active descriptors found, queue head is finished
1751 //-----------------------------------------------------------------------------------------
1753 CUSBRequest::GetTransferBuffer(
1755 OUT PULONG TransferLength
)
1759 PC_ASSERT(TransferLength
);
1761 *OutMDL
= m_TransferBufferMDL
;
1762 *TransferLength
= m_TransferBufferLength
;
1764 //-----------------------------------------------------------------------------------------
1766 CUSBRequest::InternalCalculateTransferLength()
1771 // FIXME: get length for control request
1773 return m_TransferBufferLength
;
1779 ASSERT(m_EndpointDescriptor
);
1780 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
1784 // HACK: Properly determine transfer length
1786 return m_TransferBufferLength
;//m_TotalBytesTransferred;
1790 // bulk out transfer
1792 return m_TransferBufferLength
;
1795 //-----------------------------------------------------------------------------------------
1797 InternalCreateUSBRequest(
1798 PUSBREQUEST
*OutRequest
)
1803 // allocate requests
1805 This
= new(NonPagedPool
, TAG_USBEHCI
) CUSBRequest(0);
1809 // failed to allocate
1811 return STATUS_INSUFFICIENT_RESOURCES
;
1815 // add reference count
1822 *OutRequest
= (PUSBREQUEST
)This
;
1827 return STATUS_SUCCESS
;