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
, IN PQUEUE_TRANSFER_DESCRIPTOR AlternativeDescriptor
, 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
);
69 // constructor / destructor
70 CUSBRequest(IUnknown
*OuterUnknown
){}
71 virtual ~CUSBRequest(){}
77 // memory manager for allocating setup packet / queue head / transfer descriptors
79 PDMAMEMORYMANAGER m_DmaManager
;
82 // caller provided irp packet containing URB request
87 // transfer buffer length
89 ULONG m_TransferBufferLength
;
92 // current transfer length
94 ULONG m_TransferBufferLengthCompleted
;
97 // Total Transfer Length
99 ULONG m_TotalBytesTransferred
;
102 // transfer buffer MDL
104 PMDL m_TransferBufferMDL
;
107 // caller provided setup packet
109 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
112 // completion event for callers who initialized request with setup packet
114 PKEVENT m_CompletionEvent
;
117 // device address for callers who initialized it with device address
119 UCHAR m_DeviceAddress
;
122 // store end point address
124 PUSB_ENDPOINT m_EndpointDescriptor
;
129 PQUEUE_HEAD m_QueueHead
;
132 // allocated setup packet from the DMA pool
134 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
135 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
138 // stores the result of the operation
140 NTSTATUS m_NtStatusCode
;
141 ULONG m_UrbStatusCode
;
147 //----------------------------------------------------------------------------------------
150 CUSBRequest::QueryInterface(
154 return STATUS_UNSUCCESSFUL
;
157 //----------------------------------------------------------------------------------------
159 CUSBRequest::InitializeWithSetupPacket(
160 IN PDMAMEMORYMANAGER DmaManager
,
161 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
162 IN UCHAR DeviceAddress
,
163 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
164 IN OUT ULONG TransferBufferLength
,
165 IN OUT PMDL TransferBuffer
)
170 PC_ASSERT(DmaManager
);
171 PC_ASSERT(SetupPacket
);
176 m_DmaManager
= DmaManager
;
177 m_SetupPacket
= SetupPacket
;
178 m_TransferBufferLength
= TransferBufferLength
;
179 m_TransferBufferMDL
= TransferBuffer
;
180 m_DeviceAddress
= DeviceAddress
;
181 m_EndpointDescriptor
= EndpointDescriptor
;
182 m_TotalBytesTransferred
= 0;
185 // Set Length Completed to 0
187 m_TransferBufferLengthCompleted
= 0;
190 // allocate completion event
192 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBEHCI
);
193 if (!m_CompletionEvent
)
196 // failed to allocate completion event
198 return STATUS_INSUFFICIENT_RESOURCES
;
202 // initialize completion event
204 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
209 return STATUS_SUCCESS
;
211 //----------------------------------------------------------------------------------------
213 CUSBRequest::InitializeWithIrp(
214 IN PDMAMEMORYMANAGER DmaManager
,
217 PIO_STACK_LOCATION IoStack
;
223 PC_ASSERT(DmaManager
);
226 m_DmaManager
= DmaManager
;
227 m_TotalBytesTransferred
= 0;
230 // get current irp stack location
232 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
237 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
238 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
239 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
244 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
252 // check function type
254 switch (Urb
->UrbHeader
.Function
)
257 // luckily those request have the same structure layout
259 case URB_FUNCTION_CLASS_INTERFACE
:
260 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
261 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
264 // bulk interrupt transfer
266 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
269 // Check if there is a MDL
271 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
276 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
279 // Create one using TransferBuffer
281 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
282 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
283 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
288 if (!m_TransferBufferMDL
)
291 // failed to allocate mdl
293 return STATUS_INSUFFICIENT_RESOURCES
;
297 // build mdl for non paged pool
298 // FIXME: Does hub driver already do this when passing MDL?
300 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
303 // Keep that ehci created the MDL and needs to free it.
308 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
312 // save buffer length
314 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
317 // Set Length Completed to 0
319 m_TransferBufferLengthCompleted
= 0;
322 // get endpoint descriptor
324 m_EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
330 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
337 return STATUS_SUCCESS
;
341 //----------------------------------------------------------------------------------------
343 CUSBRequest::CompletionCallback(
344 IN NTSTATUS NtStatusCode
,
345 IN ULONG UrbStatusCode
,
346 IN
struct _QUEUE_HEAD
*QueueHead
)
348 PIO_STACK_LOCATION IoStack
;
352 // FIXME: support linked queue heads
356 // store completion code
358 m_NtStatusCode
= NtStatusCode
;
359 m_UrbStatusCode
= UrbStatusCode
;
364 // set irp completion status
366 m_Irp
->IoStatus
.Status
= NtStatusCode
;
369 // get current irp stack location
371 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
376 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
381 Urb
->UrbHeader
.Status
= UrbStatusCode
;
384 // Check if the MDL was created
386 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
391 IoFreeMdl(m_TransferBufferMDL
);
395 // check if the request was successfull
397 if (!NT_SUCCESS(NtStatusCode
))
400 // set returned length to zero in case of error
402 Urb
->UrbHeader
.Length
= 0;
407 // calculate transfer length
409 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
= InternalCalculateTransferLength();
412 DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp
, NtStatusCode
, UrbStatusCode
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
415 // FIXME: check if the transfer was split
416 // if yes dont complete irp yet
418 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
423 // signal completion event
425 PC_ASSERT(m_CompletionEvent
);
426 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
429 //----------------------------------------------------------------------------------------
431 CUSBRequest::CancelCallback(
432 IN NTSTATUS NtStatusCode
,
433 IN
struct _QUEUE_HEAD
*QueueHead
)
435 PIO_STACK_LOCATION IoStack
;
439 // FIXME: support linked queue heads
443 // store cancelleation code
445 m_NtStatusCode
= NtStatusCode
;
450 // set irp completion status
452 m_Irp
->IoStatus
.Status
= NtStatusCode
;
455 // get current irp stack location
457 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
462 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
467 DPRINT1("Request Cancelled\n");
468 Urb
->UrbHeader
.Status
= USBD_STATUS_CANCELED
;
469 Urb
->UrbHeader
.Length
= 0;
472 // FIXME: check if the transfer was split
473 // if yes dont complete irp yet
475 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
480 // signal completion event
482 PC_ASSERT(m_CompletionEvent
);
483 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
486 //----------------------------------------------------------------------------------------
488 CUSBRequest::GetQueueHead(
489 struct _QUEUE_HEAD
** OutHead
)
495 // first get transfer type
497 TransferType
= InternalGetTransferType();
500 // build request depending on type
504 case USB_ENDPOINT_TYPE_CONTROL
:
505 Status
= BuildControlTransferQueueHead(OutHead
);
507 case USB_ENDPOINT_TYPE_BULK
:
508 Status
= BuildBulkTransferQueueHead(OutHead
);
510 case USB_ENDPOINT_TYPE_INTERRUPT
:
511 DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
512 Status
= STATUS_NOT_IMPLEMENTED
;
514 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
515 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
516 Status
= STATUS_NOT_IMPLEMENTED
;
520 Status
= STATUS_NOT_IMPLEMENTED
;
524 if (NT_SUCCESS(Status
))
529 m_QueueHead
= *OutHead
;
532 // store request object
534 (*OutHead
)->Request
= PVOID(this);
543 //----------------------------------------------------------------------------------------
545 CUSBRequest::IsRequestComplete()
548 // FIXME: check if request was split
552 // Check if the transfer was completed, only valid for Bulk Transfers
554 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
555 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
558 // Transfer not completed
564 //----------------------------------------------------------------------------------------
566 CUSBRequest::GetTransferType()
569 // call internal implementation
571 return InternalGetTransferType();
574 //----------------------------------------------------------------------------------------
576 CUSBRequest::InternalGetTransferType()
581 // check if an irp is provided
585 ASSERT(m_EndpointDescriptor
);
588 // end point is defined in the low byte of bmAttributes
590 TransferType
= (m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
595 // initialized with setup packet, must be a control transfer
597 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
598 ASSERT(m_EndpointDescriptor
== FALSE
);
608 CUSBRequest::InternalGetPidDirection()
610 if (m_EndpointDescriptor
)
613 // end point direction is highest bit in bEndpointAddress
615 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
620 // request arrives on the control pipe, extract direction from setup packet
622 ASSERT(m_DescriptorPacket
);
623 return (m_DescriptorPacket
->bmRequestType
.B
>> 7);
628 CUSBRequest::InitDescriptor(
629 IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
,
630 IN PVOID TransferBuffer
,
631 IN ULONG TransferBufferLength
,
634 OUT PULONG OutDescriptorLength
)
636 ULONG Index
, Length
= 0, PageOffset
, BufferLength
;
637 PHYSICAL_ADDRESS Address
;
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
);
660 Address
= MmGetPhysicalAddress(TransferBuffer
);
663 // use physical address
665 CurrentDescriptor
->BufferPointer
[Index
] = Address
.LowPart
;
666 CurrentDescriptor
->ExtendedBufferPointer
[Index
] = Address
.HighPart
;
669 // Get the offset from page size
671 PageOffset
= BYTE_OFFSET(CurrentDescriptor
->BufferPointer
[Index
]);
677 TransferBuffer
= (PVOID
)ROUND_TO_PAGES(TransferBuffer
);
684 TransferBuffer
= (PVOID
)((ULONG_PTR
)TransferBuffer
+ PAGE_SIZE
);
688 // calculate buffer length
690 BufferLength
= min(TransferBufferLength
, PAGE_SIZE
- PageOffset
);
693 // increment transfer bytes
695 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
+= BufferLength
;
696 CurrentDescriptor
->TotalBytesToTransfer
+= BufferLength
;
697 Length
+= BufferLength
;
698 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index
, TransferBufferLength
, PageOffset
, BufferLength
, CurrentDescriptor
->BufferPointer
[Index
], TransferBuffer
);
701 // decrement available byte count
703 TransferBufferLength
-= BufferLength
;
704 if (TransferBufferLength
== 0)
720 ASSERT(CurrentDescriptor
->BufferPointer
[Index
] != CurrentDescriptor
->BufferPointer
[Index
-1]);
724 // next descriptor index
732 *OutDescriptorLength
= Length
;
736 CUSBRequest::BuildTransferDescriptorChain(
737 IN PQUEUE_HEAD QueueHead
,
738 IN PVOID TransferBuffer
,
739 IN ULONG TransferBufferLength
,
741 IN UCHAR InitialDataToggle
,
742 IN PQUEUE_TRANSFER_DESCRIPTOR AlternativeDescriptor
,
743 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
,
744 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
,
745 OUT PUCHAR OutDataToggle
,
746 OUT PULONG OutTransferBufferOffset
)
748 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
= NULL
;
750 ULONG DescriptorLength
, TransferBufferOffset
= 0;
751 ULONG MaxPacketSize
= 0, TransferSize
;
754 // is there an endpoint descriptor
756 if (m_EndpointDescriptor
)
759 // use endpoint packet size
761 MaxPacketSize
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
767 // allocate transfer descriptor
769 Status
= CreateDescriptor(&CurrentDescriptor
);
770 if (!NT_SUCCESS(Status
))
773 // failed to allocate transfer descriptor
775 return STATUS_INSUFFICIENT_RESOURCES
;
781 // transfer size is minimum available buffer or endpoint size
783 TransferSize
= min(TransferBufferLength
- TransferBufferOffset
, MaxPacketSize
);
788 // use available buffer
790 TransferSize
= TransferBufferLength
- TransferBufferOffset
;
794 // now init the descriptor
796 InitDescriptor(CurrentDescriptor
,
797 (PVOID
)((ULONG_PTR
)TransferBuffer
+ TransferBufferOffset
),
804 // insert into queue head
806 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &CurrentDescriptor
->DescriptorEntry
);
811 TransferBufferOffset
+= DescriptorLength
;
816 // link to current descriptor
818 LastDescriptor
->NextPointer
= CurrentDescriptor
->PhysicalAddr
;
819 LastDescriptor
= CurrentDescriptor
;
821 if (AlternativeDescriptor
)
824 // link to alternative next pointer
826 LastDescriptor
->AlternateNextPointer
= AlternativeDescriptor
->PhysicalAddr
;
833 // first descriptor in chain
835 LastDescriptor
= FirstDescriptor
= CurrentDescriptor
;
841 InitialDataToggle
= !InitialDataToggle
;
843 if(TransferBufferLength
== TransferBufferOffset
)
853 if (OutFirstDescriptor
)
856 // store first descriptor
858 *OutFirstDescriptor
= FirstDescriptor
;
861 if (OutLastDescriptor
)
864 // store last descriptor
866 *OutLastDescriptor
= CurrentDescriptor
;
872 // store result data toggle
874 *OutDataToggle
= InitialDataToggle
;
877 if (OutTransferBufferOffset
)
882 *OutTransferBufferOffset
= TransferBufferOffset
;
888 return STATUS_SUCCESS
;
891 //----------------------------------------------------------------------------------------
893 CUSBRequest::BuildControlTransferQueueHead(
894 PQUEUE_HEAD
* OutHead
)
897 ULONG DescriptorChainLength
;
898 PQUEUE_HEAD QueueHead
;
899 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor
, StatusDescriptor
, FirstDescriptor
, LastDescriptor
;
902 // first allocate the queue head
904 Status
= CreateQueueHead(&QueueHead
);
905 if (!NT_SUCCESS(Status
))
908 // failed to allocate queue head
910 return STATUS_INSUFFICIENT_RESOURCES
;
916 PC_ASSERT(QueueHead
);
919 // create setup packet
921 Status
= BuildSetupPacket();
922 if (!NT_SUCCESS(Status
))
925 // failed to allocate setup packet
928 return STATUS_INSUFFICIENT_RESOURCES
;
932 // create setup descriptor
934 Status
= CreateDescriptor(&SetupDescriptor
);
935 if (!NT_SUCCESS(Status
))
938 // failed to allocate transfer descriptor
945 // create status descriptor
947 Status
= CreateDescriptor(&StatusDescriptor
);
948 if (!NT_SUCCESS(Status
))
951 // failed to allocate transfer descriptor
958 // now initialize the queue head
960 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
962 ASSERT(m_EndpointDescriptor
== FALSE
);
965 // init setup descriptor
967 SetupDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_SETUP_TOKEN
;
968 SetupDescriptor
->Token
.Bits
.TotalBytesToTransfer
= sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
);
969 SetupDescriptor
->Token
.Bits
.DataToggle
= FALSE
;
970 SetupDescriptor
->BufferPointer
[0] = m_DescriptorSetupPacket
.LowPart
;
971 SetupDescriptor
->ExtendedBufferPointer
[0] = m_DescriptorSetupPacket
.HighPart
;
972 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &SetupDescriptor
->DescriptorEntry
);
976 // init status descriptor
978 StatusDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
979 StatusDescriptor
->Token
.Bits
.DataToggle
= TRUE
;
980 StatusDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
985 if (m_TransferBufferLength
)
987 Status
= BuildTransferDescriptorChain(QueueHead
,
988 MmGetMdlVirtualAddress(m_TransferBufferMDL
),
989 m_TransferBufferLength
,
990 InternalGetPidDirection(),
996 &DescriptorChainLength
);
999 // FIXME handle errors
1001 ASSERT(Status
== STATUS_SUCCESS
);
1002 ASSERT(DescriptorChainLength
== m_TransferBufferLength
);
1005 // now link the descriptors
1007 SetupDescriptor
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1008 SetupDescriptor
->AlternateNextPointer
= FirstDescriptor
->PhysicalAddr
;
1009 LastDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
1010 LastDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
1014 // pid code is flipped for ops with data stage
1016 StatusDescriptor
->Token
.Bits
.PIDCode
= !InternalGetPidDirection();
1023 SetupDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
1024 SetupDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
1027 // retrieve result of operation
1029 StatusDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
1033 // insert status descriptor
1035 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &StatusDescriptor
->DescriptorEntry
);
1039 // link transfer descriptors to queue head
1041 QueueHead
->NextPointer
= SetupDescriptor
->PhysicalAddr
;
1046 *OutHead
= QueueHead
;
1049 // displays the current request
1051 //DumpQueueHead(QueueHead);
1053 DPRINT("BuildControlTransferQueueHead done\n");
1057 return STATUS_SUCCESS
;
1061 CUSBRequest::DumpQueueHead(
1062 IN PQUEUE_HEAD QueueHead
)
1065 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1068 DPRINT1("QueueHead %p Addr %x\n", QueueHead
, QueueHead
->PhysicalAddr
);
1069 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead
->AlternateNextPointer
);
1070 DPRINT1("QueueHead NextPointer %x\n", QueueHead
->NextPointer
);
1072 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
);
1073 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1074 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1075 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead
->EndPointCharacteristics
.EndPointSpeed
);
1076 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead
->EndPointCharacteristics
.HeadOfReclamation
);
1077 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead
->EndPointCharacteristics
.InactiveOnNextTransaction
);
1078 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1079 DPRINT1("QueueHead NakCountReload %x\n", QueueHead
->EndPointCharacteristics
.NakCountReload
);
1080 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
);
1081 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCapabilities
.HubAddr
);
1082 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead
->EndPointCapabilities
.InterruptScheduleMask
);
1083 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
);
1084 DPRINT1("QueueHead PortNumber %x\n", QueueHead
->EndPointCapabilities
.PortNumber
);
1085 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead
->EndPointCapabilities
.SplitCompletionMask
);
1087 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1088 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1091 // get transfer descriptor
1093 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1095 DPRINT1("TransferDescriptor %lu Addr %x\n", Index
, Descriptor
->PhysicalAddr
);
1096 DPRINT1("TransferDescriptor %lu Next %x\n", Index
, Descriptor
->NextPointer
);
1097 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index
, Descriptor
->AlternateNextPointer
);
1098 DPRINT1("TransferDescriptor %lu Active %lu\n", Index
, Descriptor
->Token
.Bits
.Active
);
1099 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index
, Descriptor
->Token
.Bits
.BabbleDetected
);
1100 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index
, Descriptor
->Token
.Bits
.CurrentPage
);
1101 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index
, Descriptor
->Token
.Bits
.DataBufferError
);
1102 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index
, Descriptor
->Token
.Bits
.DataToggle
);
1103 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index
, Descriptor
->Token
.Bits
.ErrorCounter
);
1104 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index
, Descriptor
->Token
.Bits
.Halted
);
1105 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index
, Descriptor
->Token
.Bits
.InterruptOnComplete
);
1106 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index
, Descriptor
->Token
.Bits
.MissedMicroFrame
);
1107 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index
, Descriptor
->Token
.Bits
.PIDCode
);
1108 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index
, Descriptor
->Token
.Bits
.PingState
);
1109 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index
, Descriptor
->Token
.Bits
.SplitTransactionState
);
1110 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index
, Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1111 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index
, Descriptor
->Token
.Bits
.TransactionError
);
1113 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index
, Descriptor
->BufferPointer
[0]);
1114 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index
, Descriptor
->BufferPointer
[1]);
1115 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index
, Descriptor
->BufferPointer
[2]);
1116 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index
, Descriptor
->BufferPointer
[3]);
1117 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index
, Descriptor
->BufferPointer
[4]);
1118 Entry
= Entry
->Flink
;
1124 //----------------------------------------------------------------------------------------
1126 CUSBRequest::BuildBulkTransferQueueHead(
1127 PQUEUE_HEAD
* OutHead
)
1130 PQUEUE_HEAD QueueHead
;
1132 ULONG ChainDescriptorLength
;
1133 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
, LastDescriptor
;
1136 // Allocate the queue head
1138 Status
= CreateQueueHead(&QueueHead
);
1140 if (!NT_SUCCESS(Status
))
1143 // failed to allocate queue heads
1145 return STATUS_INSUFFICIENT_RESOURCES
;
1151 PC_ASSERT(QueueHead
);
1152 PC_ASSERT(m_TransferBufferLength
);
1157 // get virtual base of mdl
1159 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1163 // Increase the size of last transfer, 0 in case this is the first
1165 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1167 PC_ASSERT(m_EndpointDescriptor
);
1173 ASSERT(m_EndpointDescriptor
);
1176 // use 4 * PAGE_SIZE at max for each new request
1178 ULONG MaxTransferLength
= min(4 * PAGE_SIZE
, m_TransferBufferLength
- m_TransferBufferLengthCompleted
);
1181 // build bulk transfer descriptor chain
1183 Status
= BuildTransferDescriptorChain(QueueHead
,
1186 InternalGetPidDirection(),
1187 m_EndpointDescriptor
->DataToggle
,
1191 &m_EndpointDescriptor
->DataToggle
,
1192 &ChainDescriptorLength
);
1195 // move to next offset
1197 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1199 ASSERT(Status
== STATUS_SUCCESS
);
1204 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
1205 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
1206 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
1207 QueueHead
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1208 QueueHead
->CurrentLinkPointer
= FirstDescriptor
->PhysicalAddr
;
1209 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1211 ASSERT(QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1212 ASSERT(QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1213 ASSERT(QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1214 ASSERT(QueueHead
->NextPointer
);
1217 // interrupt on last descriptor
1219 LastDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
1224 *OutHead
= QueueHead
;
1229 //DumpQueueHead(QueueHead);
1234 return STATUS_SUCCESS
;
1237 //----------------------------------------------------------------------------------------
1239 CUSBRequest::CreateDescriptor(
1240 PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
)
1242 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1244 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress
;
1247 // allocate descriptor
1249 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR
), (PVOID
*)&Descriptor
, &TransferDescriptorPhysicalAddress
);
1250 if (!NT_SUCCESS(Status
))
1253 // failed to allocate transfer descriptor
1255 return STATUS_INSUFFICIENT_RESOURCES
;
1259 // initialize transfer descriptor
1261 Descriptor
->NextPointer
= TERMINATE_POINTER
;
1262 Descriptor
->AlternateNextPointer
= TERMINATE_POINTER
;
1263 Descriptor
->Token
.Bits
.DataToggle
= TRUE
;
1264 Descriptor
->Token
.Bits
.ErrorCounter
= 0x03;
1265 Descriptor
->Token
.Bits
.Active
= TRUE
;
1266 Descriptor
->PhysicalAddr
= TransferDescriptorPhysicalAddress
.LowPart
;
1271 *OutDescriptor
= Descriptor
;
1279 //----------------------------------------------------------------------------------------
1281 CUSBRequest::CreateQueueHead(
1282 PQUEUE_HEAD
*OutQueueHead
)
1284 PQUEUE_HEAD QueueHead
;
1285 PHYSICAL_ADDRESS QueueHeadPhysicalAddress
;
1289 // allocate queue head
1291 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_HEAD
), (PVOID
*)&QueueHead
, &QueueHeadPhysicalAddress
);
1293 if (!NT_SUCCESS(Status
))
1296 // failed to allocate queue head
1298 return STATUS_INSUFFICIENT_RESOURCES
;
1302 // initialize queue head
1304 QueueHead
->HorizontalLinkPointer
= TERMINATE_POINTER
;
1305 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1306 QueueHead
->NextPointer
= TERMINATE_POINTER
;
1307 InitializeListHead(&QueueHead
->TransferDescriptorListHead
);
1310 // 1 for non high speed, 0 for high speed device
1312 QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
= 0;
1313 QueueHead
->EndPointCharacteristics
.HeadOfReclamation
= FALSE
;
1314 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= 64;
1317 // Set NakCountReload to max value possible
1319 QueueHead
->EndPointCharacteristics
.NakCountReload
= 0x3;
1322 // Get the Initial Data Toggle from the QEDT
1324 QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
= TRUE
;
1327 // FIXME: check if High Speed Device
1329 QueueHead
->EndPointCharacteristics
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
1330 QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
= 0x01;
1331 QueueHead
->Token
.DWord
= 0;
1332 QueueHead
->Token
.Bits
.InterruptOnComplete
= FALSE
;
1337 QueueHead
->PhysicalAddr
= QueueHeadPhysicalAddress
.LowPart
;
1340 // output queue head
1342 *OutQueueHead
= QueueHead
;
1347 return STATUS_SUCCESS
;
1350 //----------------------------------------------------------------------------------------
1352 CUSBRequest::GetDeviceAddress()
1354 PIO_STACK_LOCATION IoStack
;
1356 PUSBDEVICE UsbDevice
;
1359 // check if there is an irp provided
1364 // used provided address
1366 return m_DeviceAddress
;
1370 // get current stack location
1372 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1375 // get contained urb
1377 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1380 // check if there is a pipe handle provided
1382 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
1385 // there is a device handle provided
1387 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
1390 // return device address
1392 return UsbDevice
->GetDeviceAddress();
1396 // no device handle provided, it is the host root bus
1401 //----------------------------------------------------------------------------------------
1403 CUSBRequest::BuildSetupPacket()
1408 // allocate common buffer setup packet
1410 Status
= m_DmaManager
->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), (PVOID
*)&m_DescriptorPacket
, &m_DescriptorSetupPacket
);
1411 if (!NT_SUCCESS(Status
))
1422 // copy setup packet
1424 RtlCopyMemory(m_DescriptorPacket
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1429 // build setup packet from urb
1431 Status
= BuildSetupPacketFromURB();
1442 CUSBRequest::BuildSetupPacketFromURB()
1444 PIO_STACK_LOCATION IoStack
;
1446 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1452 PC_ASSERT(m_DescriptorPacket
);
1455 // get stack location
1457 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1462 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1465 // zero descriptor packet
1467 RtlZeroMemory(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1470 switch (Urb
->UrbHeader
.Function
)
1473 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
1474 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
1475 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
1480 case URB_FUNCTION_GET_CONFIGURATION
:
1481 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1482 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1483 m_DescriptorPacket
->wLength
= 1;
1486 /* GET DESCRIPTOR */
1487 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1488 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1489 m_DescriptorPacket
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1490 m_DescriptorPacket
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1491 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1492 m_DescriptorPacket
->wLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1493 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1497 case URB_FUNCTION_GET_INTERFACE
:
1498 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1499 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1500 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1501 m_DescriptorPacket
->wLength
= 1;
1505 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1506 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1507 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1508 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1509 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1510 m_DescriptorPacket
->wLength
= 2;
1513 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
1514 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1515 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1516 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1517 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1518 m_DescriptorPacket
->wLength
= 2;
1521 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
1522 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1523 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1524 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1525 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1526 m_DescriptorPacket
->wLength
= 2;
1532 case URB_FUNCTION_SELECT_CONFIGURATION
:
1533 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1534 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
1535 m_DescriptorPacket
->wIndex
.W
= 0;
1536 m_DescriptorPacket
->wLength
= 0;
1537 m_DescriptorPacket
->bmRequestType
.B
= 0x00;
1540 /* SET DESCRIPTOR */
1541 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
1542 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
1543 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
1548 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
1549 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1550 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1551 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1552 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1555 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
1556 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1557 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1558 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1559 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1562 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
1563 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1564 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1565 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1566 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1570 case URB_FUNCTION_SELECT_INTERFACE
:
1571 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_INTERFACE
;
1572 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
1573 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
1574 m_DescriptorPacket
->wLength
= 0;
1575 m_DescriptorPacket
->bmRequestType
.B
= 0x01;
1579 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
1590 //----------------------------------------------------------------------------------------
1592 CUSBRequest::GetResultStatus(
1593 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1594 OUT OPTIONAL PULONG UrbStatusCode
)
1599 PC_ASSERT(m_CompletionEvent
);
1602 // wait for the operation to complete
1604 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1611 *NtStatusCode
= m_NtStatusCode
;
1619 *UrbStatusCode
= m_UrbStatusCode
;
1625 //-----------------------------------------------------------------------------------------
1627 CUSBRequest::IsRequestInitialized()
1629 if (m_Irp
|| m_SetupPacket
)
1632 // request is initialized
1638 // request is not initialized
1643 //-----------------------------------------------------------------------------------------
1645 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1650 // the request is completed, release it
1657 // created with an setup packet, don't release
1663 //-----------------------------------------------------------------------------------------
1665 CUSBRequest::FreeQueueHead(
1666 IN
struct _QUEUE_HEAD
* QueueHead
)
1669 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1674 ASSERT(m_DmaManager
);
1676 ASSERT(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1681 // get transfer descriptors
1683 Entry
= RemoveHeadList(&QueueHead
->TransferDescriptorListHead
);
1687 // obtain descriptor from entry
1689 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1693 // add transfer count
1695 m_TotalBytesTransferred
+= (Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1696 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
);
1699 // release transfer descriptors
1701 m_DmaManager
->Release(Descriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
1703 }while(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1705 if (m_DescriptorPacket
)
1708 // release packet descriptor
1710 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1714 // release queue head
1716 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1722 m_DescriptorPacket
= 0;
1725 //-----------------------------------------------------------------------------------------
1727 CUSBRequest::IsQueueHeadComplete(
1728 struct _QUEUE_HEAD
* QueueHead
)
1731 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1734 // first check - is the queue head currently active
1736 if (QueueHead
->Token
.Bits
.Active
)
1739 // queue head is active (currently processed)
1744 if (QueueHead
->Token
.Bits
.Halted
)
1749 DPRINT1("Found halted queue head %p\n", QueueHead
);
1750 DumpQueueHead(QueueHead
);
1756 // loop list and see if there are any active descriptors
1758 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1759 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1762 // obtain descriptor from entry
1764 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1766 if (Descriptor
->Token
.Bits
.Active
)
1769 // descriptor is still active
1775 // move to next entry
1777 Entry
= Entry
->Flink
;
1780 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead
, QueueHead
->PhysicalAddr
);
1783 // no active descriptors found, queue head is finished
1788 //-----------------------------------------------------------------------------------------
1790 CUSBRequest::GetTransferBuffer(
1792 OUT PULONG TransferLength
)
1796 PC_ASSERT(TransferLength
);
1798 *OutMDL
= m_TransferBufferMDL
;
1799 *TransferLength
= m_TransferBufferLength
;
1801 //-----------------------------------------------------------------------------------------
1803 CUSBRequest::InternalCalculateTransferLength()
1808 // FIXME: get length for control request
1810 return m_TransferBufferLength
;
1816 ASSERT(m_EndpointDescriptor
);
1817 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
1821 // HACK: Properly determine transfer length
1823 return m_TransferBufferLength
;//m_TotalBytesTransferred;
1827 // bulk out transfer
1829 return m_TransferBufferLength
;
1832 //-----------------------------------------------------------------------------------------
1834 InternalCreateUSBRequest(
1835 PUSBREQUEST
*OutRequest
)
1840 // allocate requests
1842 This
= new(NonPagedPool
, TAG_USBEHCI
) CUSBRequest(0);
1846 // failed to allocate
1848 return STATUS_INSUFFICIENT_RESOURCES
;
1852 // add reference count
1859 *OutRequest
= (PUSBREQUEST
)This
;
1864 return STATUS_SUCCESS
;