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 DPRINT1("[EHCI] Failed to create queue head\n");
852 PC_ASSERT(QueueHead
);
855 // create setup packet
857 Status
= BuildSetupPacket();
858 if (!NT_SUCCESS(Status
))
860 // failed to create setup packet
861 DPRINT1("[EHCI] Failed to create setup packet\n");
863 // release queue head
864 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
869 // create setup descriptor
871 Status
= CreateDescriptor(&SetupDescriptor
);
872 if (!NT_SUCCESS(Status
))
874 // failed to create setup transfer descriptor
875 DPRINT1("[EHCI] Failed to create setup descriptor\n");
877 if (m_DescriptorPacket
)
879 // release packet descriptor
880 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
883 // release queue head
884 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
889 // create status descriptor
891 Status
= CreateDescriptor(&StatusDescriptor
);
892 if (!NT_SUCCESS(Status
))
894 // failed to create status transfer descriptor
895 DPRINT1("[EHCI] Failed to create status descriptor\n");
897 // release setup transfer descriptor
898 m_DmaManager
->Release(SetupDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
900 if (m_DescriptorPacket
)
902 // release packet descriptor
903 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
906 // release queue head
907 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
912 // now initialize the queue head
914 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
916 ASSERT(m_EndpointDescriptor
== NULL
);
919 // init setup descriptor
921 SetupDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_SETUP_TOKEN
;
922 SetupDescriptor
->Token
.Bits
.TotalBytesToTransfer
= sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
);
923 SetupDescriptor
->Token
.Bits
.DataToggle
= FALSE
;
924 SetupDescriptor
->BufferPointer
[0] = m_DescriptorSetupPacket
.LowPart
;
925 SetupDescriptor
->ExtendedBufferPointer
[0] = m_DescriptorSetupPacket
.HighPart
;
926 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &SetupDescriptor
->DescriptorEntry
);
930 // init status descriptor
932 StatusDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
933 StatusDescriptor
->Token
.Bits
.DataToggle
= TRUE
;
934 StatusDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
939 if (m_TransferBufferLength
)
941 Status
= BuildTransferDescriptorChain(QueueHead
,
942 MmGetMdlVirtualAddress(m_TransferBufferMDL
),
943 m_TransferBufferLength
,
944 InternalGetPidDirection(),
949 &DescriptorChainLength
);
950 if (!NT_SUCCESS(Status
))
952 // failed to create descriptor chain
953 DPRINT1("[EHCI] Failed to create descriptor chain\n");
955 // release status transfer descriptor
956 m_DmaManager
->Release(StatusDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
958 // release setup transfer descriptor
959 m_DmaManager
->Release(SetupDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
961 if (m_DescriptorPacket
)
963 // release packet descriptor
964 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
967 // release queue head
968 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
972 if (m_TransferBufferLength
!= DescriptorChainLength
)
974 DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength
);
975 DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength
);
980 // now link the descriptors
982 SetupDescriptor
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
983 SetupDescriptor
->AlternateNextPointer
= FirstDescriptor
->PhysicalAddr
;
984 LastDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
985 LastDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
989 // pid code is flipped for ops with data stage
991 StatusDescriptor
->Token
.Bits
.PIDCode
= !InternalGetPidDirection();
998 SetupDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
999 SetupDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
1002 // retrieve result of operation
1004 StatusDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
1008 // insert status descriptor
1010 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &StatusDescriptor
->DescriptorEntry
);
1014 // link transfer descriptors to queue head
1016 QueueHead
->NextPointer
= SetupDescriptor
->PhysicalAddr
;
1021 *OutHead
= QueueHead
;
1024 // displays the current request
1026 //DumpQueueHead(QueueHead);
1028 DPRINT("BuildControlTransferQueueHead done\n");
1032 return STATUS_SUCCESS
;
1036 CUSBRequest::DumpQueueHead(
1037 IN PQUEUE_HEAD QueueHead
)
1040 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1043 DPRINT1("QueueHead %p Addr %x\n", QueueHead
, QueueHead
->PhysicalAddr
);
1044 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead
->AlternateNextPointer
);
1045 DPRINT1("QueueHead NextPointer %x\n", QueueHead
->NextPointer
);
1047 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
);
1048 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1049 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1050 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead
->EndPointCharacteristics
.EndPointSpeed
);
1051 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead
->EndPointCharacteristics
.HeadOfReclamation
);
1052 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead
->EndPointCharacteristics
.InactiveOnNextTransaction
);
1053 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1054 DPRINT1("QueueHead NakCountReload %x\n", QueueHead
->EndPointCharacteristics
.NakCountReload
);
1055 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
);
1056 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCapabilities
.HubAddr
);
1057 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead
->EndPointCapabilities
.InterruptScheduleMask
);
1058 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
);
1059 DPRINT1("QueueHead PortNumber %x\n", QueueHead
->EndPointCapabilities
.PortNumber
);
1060 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead
->EndPointCapabilities
.SplitCompletionMask
);
1062 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1063 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1066 // get transfer descriptor
1068 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1070 DPRINT1("TransferDescriptor %lu Addr %x\n", Index
, Descriptor
->PhysicalAddr
);
1071 DPRINT1("TransferDescriptor %lu Next %x\n", Index
, Descriptor
->NextPointer
);
1072 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index
, Descriptor
->AlternateNextPointer
);
1073 DPRINT1("TransferDescriptor %lu Active %lu\n", Index
, Descriptor
->Token
.Bits
.Active
);
1074 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index
, Descriptor
->Token
.Bits
.BabbleDetected
);
1075 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index
, Descriptor
->Token
.Bits
.CurrentPage
);
1076 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index
, Descriptor
->Token
.Bits
.DataBufferError
);
1077 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index
, Descriptor
->Token
.Bits
.DataToggle
);
1078 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index
, Descriptor
->Token
.Bits
.ErrorCounter
);
1079 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index
, Descriptor
->Token
.Bits
.Halted
);
1080 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index
, Descriptor
->Token
.Bits
.InterruptOnComplete
);
1081 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index
, Descriptor
->Token
.Bits
.MissedMicroFrame
);
1082 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index
, Descriptor
->Token
.Bits
.PIDCode
);
1083 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index
, Descriptor
->Token
.Bits
.PingState
);
1084 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index
, Descriptor
->Token
.Bits
.SplitTransactionState
);
1085 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index
, Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1086 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index
, Descriptor
->Token
.Bits
.TransactionError
);
1088 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index
, Descriptor
->BufferPointer
[0]);
1089 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index
, Descriptor
->BufferPointer
[1]);
1090 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index
, Descriptor
->BufferPointer
[2]);
1091 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index
, Descriptor
->BufferPointer
[3]);
1092 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index
, Descriptor
->BufferPointer
[4]);
1093 Entry
= Entry
->Flink
;
1099 //----------------------------------------------------------------------------------------
1101 CUSBRequest::BuildBulkInterruptTransferQueueHead(
1102 PQUEUE_HEAD
* OutHead
)
1105 PQUEUE_HEAD QueueHead
;
1107 ULONG ChainDescriptorLength
;
1108 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
, LastDescriptor
;
1111 // Allocate the queue head
1113 Status
= CreateQueueHead(&QueueHead
);
1114 if (!NT_SUCCESS(Status
))
1117 // failed to allocate queue head
1119 DPRINT1("[EHCI] Failed to create queue head\n");
1126 PC_ASSERT(QueueHead
);
1127 PC_ASSERT(m_TransferBufferLength
);
1132 // get virtual base of mdl
1134 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1138 // Increase the size of last transfer, 0 in case this is the first
1140 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1142 PC_ASSERT(m_EndpointDescriptor
);
1148 ASSERT(m_EndpointDescriptor
);
1151 // use 4 * PAGE_SIZE at max for each new request
1153 ULONG MaxTransferLength
= min(4 * PAGE_SIZE
, m_TransferBufferLength
- m_TransferBufferLengthCompleted
);
1156 // build bulk transfer descriptor chain
1158 Status
= BuildTransferDescriptorChain(QueueHead
,
1161 InternalGetPidDirection(),
1162 m_EndpointDescriptor
->DataToggle
,
1165 &m_EndpointDescriptor
->DataToggle
,
1166 &ChainDescriptorLength
);
1167 if (!NT_SUCCESS(Status
))
1170 // failed to build transfer descriptor chain
1172 DPRINT1("[EHCI] Failed to create descriptor chain\n");
1173 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1178 // move to next offset
1180 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1185 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
1186 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
1187 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
1188 QueueHead
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1189 QueueHead
->CurrentLinkPointer
= FirstDescriptor
->PhysicalAddr
;
1190 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1192 ASSERT(QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1193 ASSERT(QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1194 ASSERT(QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1195 ASSERT(QueueHead
->NextPointer
);
1198 // interrupt on last descriptor
1200 LastDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
1205 *OutHead
= QueueHead
;
1210 //DumpQueueHead(QueueHead);
1215 return STATUS_SUCCESS
;
1218 //----------------------------------------------------------------------------------------
1221 CUSBRequest::CreateDescriptor(
1222 PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
)
1224 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1226 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress
;
1229 // allocate descriptor
1231 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR
), (PVOID
*)&Descriptor
, &TransferDescriptorPhysicalAddress
);
1232 if (!NT_SUCCESS(Status
))
1235 // failed to allocate transfer descriptor
1237 return STATUS_INSUFFICIENT_RESOURCES
;
1241 // initialize transfer descriptor
1243 Descriptor
->NextPointer
= TERMINATE_POINTER
;
1244 Descriptor
->AlternateNextPointer
= TERMINATE_POINTER
;
1245 Descriptor
->Token
.Bits
.DataToggle
= TRUE
;
1246 Descriptor
->Token
.Bits
.ErrorCounter
= 0x03;
1247 Descriptor
->Token
.Bits
.Active
= TRUE
;
1248 Descriptor
->PhysicalAddr
= TransferDescriptorPhysicalAddress
.LowPart
;
1253 *OutDescriptor
= Descriptor
;
1261 //----------------------------------------------------------------------------------------
1263 CUSBRequest::CreateQueueHead(
1264 PQUEUE_HEAD
*OutQueueHead
)
1266 PQUEUE_HEAD QueueHead
;
1267 PHYSICAL_ADDRESS QueueHeadPhysicalAddress
;
1271 // allocate queue head
1273 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_HEAD
), (PVOID
*)&QueueHead
, &QueueHeadPhysicalAddress
);
1274 if (!NT_SUCCESS(Status
))
1277 // failed to allocate queue head
1279 return STATUS_INSUFFICIENT_RESOURCES
;
1283 // initialize queue head
1285 QueueHead
->HorizontalLinkPointer
= TERMINATE_POINTER
;
1286 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1287 QueueHead
->NextPointer
= TERMINATE_POINTER
;
1288 InitializeListHead(&QueueHead
->TransferDescriptorListHead
);
1291 // 1 for non high speed, 0 for high speed device
1293 QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
= 0;
1294 QueueHead
->EndPointCharacteristics
.HeadOfReclamation
= FALSE
;
1295 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= 64;
1298 // Set NakCountReload to max value possible
1300 QueueHead
->EndPointCharacteristics
.NakCountReload
= 0x3;
1303 // Get the Initial Data Toggle from the QEDT
1305 QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
= TRUE
;
1308 // FIXME: check if High Speed Device
1310 QueueHead
->EndPointCharacteristics
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
1311 QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
= 0x01;
1312 QueueHead
->Token
.DWord
= 0;
1313 QueueHead
->Token
.Bits
.InterruptOnComplete
= FALSE
;
1318 QueueHead
->PhysicalAddr
= QueueHeadPhysicalAddress
.LowPart
;
1321 // output queue head
1323 *OutQueueHead
= QueueHead
;
1328 return STATUS_SUCCESS
;
1331 //----------------------------------------------------------------------------------------
1334 CUSBRequest::GetDeviceAddress()
1336 PIO_STACK_LOCATION IoStack
;
1338 PUSBDEVICE UsbDevice
;
1341 // check if there is an irp provided
1346 // used provided address
1348 return m_DeviceAddress
;
1352 // get current stack location
1354 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1357 // get contained urb
1359 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1362 // check if there is a pipe handle provided
1364 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
1367 // there is a device handle provided
1369 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
1372 // return device address
1374 return UsbDevice
->GetDeviceAddress();
1378 // no device handle provided, it is the host root bus
1383 //----------------------------------------------------------------------------------------
1385 CUSBRequest::BuildSetupPacket()
1390 // allocate common buffer setup packet
1392 Status
= m_DmaManager
->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), (PVOID
*)&m_DescriptorPacket
, &m_DescriptorSetupPacket
);
1393 if (!NT_SUCCESS(Status
))
1404 // copy setup packet
1406 RtlCopyMemory(m_DescriptorPacket
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1411 // build setup packet from urb
1413 Status
= BuildSetupPacketFromURB();
1424 CUSBRequest::BuildSetupPacketFromURB()
1426 PIO_STACK_LOCATION IoStack
;
1428 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1434 PC_ASSERT(m_DescriptorPacket
);
1437 // get stack location
1439 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1444 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1447 // zero descriptor packet
1449 RtlZeroMemory(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1452 switch (Urb
->UrbHeader
.Function
)
1455 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
1456 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
1457 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
1462 case URB_FUNCTION_GET_CONFIGURATION
:
1463 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1464 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1465 m_DescriptorPacket
->wLength
= 1;
1468 /* GET DESCRIPTOR */
1469 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1470 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1471 m_DescriptorPacket
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1472 m_DescriptorPacket
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1473 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1474 m_DescriptorPacket
->wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1475 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1479 case URB_FUNCTION_GET_INTERFACE
:
1480 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1481 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1482 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1483 m_DescriptorPacket
->wLength
= 1;
1487 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1488 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1489 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1490 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1491 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1492 m_DescriptorPacket
->wLength
= 2;
1495 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
1496 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1497 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1498 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1499 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1500 m_DescriptorPacket
->wLength
= 2;
1503 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
1504 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1505 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1506 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1507 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1508 m_DescriptorPacket
->wLength
= 2;
1514 case URB_FUNCTION_SELECT_CONFIGURATION
:
1515 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1516 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
1517 m_DescriptorPacket
->wIndex
.W
= 0;
1518 m_DescriptorPacket
->wLength
= 0;
1519 m_DescriptorPacket
->bmRequestType
.B
= 0x00;
1522 /* SET DESCRIPTOR */
1523 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
1524 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
1525 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
1530 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
1531 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1532 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1533 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1534 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1537 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
1538 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1539 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1540 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1541 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1544 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
1545 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1546 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1547 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1548 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1552 case URB_FUNCTION_SELECT_INTERFACE
:
1553 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_INTERFACE
;
1554 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
1555 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
1556 m_DescriptorPacket
->wLength
= 0;
1557 m_DescriptorPacket
->bmRequestType
.B
= 0x01;
1561 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
1572 //----------------------------------------------------------------------------------------
1575 CUSBRequest::GetResultStatus(
1576 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1577 OUT OPTIONAL PULONG UrbStatusCode
)
1582 PC_ASSERT(m_CompletionEvent
);
1585 // wait for the operation to complete
1587 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1594 *NtStatusCode
= m_NtStatusCode
;
1602 *UrbStatusCode
= m_UrbStatusCode
;
1607 //-----------------------------------------------------------------------------------------
1610 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1615 // the request is completed, release it
1622 // created with an setup packet, don't release
1628 //-----------------------------------------------------------------------------------------
1631 CUSBRequest::FreeQueueHead(
1632 IN
struct _QUEUE_HEAD
* QueueHead
)
1635 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1640 ASSERT(m_DmaManager
);
1642 ASSERT(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1647 // get transfer descriptors
1649 Entry
= RemoveHeadList(&QueueHead
->TransferDescriptorListHead
);
1653 // obtain descriptor from entry
1655 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1659 // add transfer count
1661 m_TotalBytesTransferred
+= (Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1662 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
);
1665 // release transfer descriptors
1667 m_DmaManager
->Release(Descriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
1669 }while(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1671 if (m_DescriptorPacket
)
1674 // release packet descriptor
1676 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1680 // release queue head
1682 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1688 m_DescriptorPacket
= 0;
1691 //-----------------------------------------------------------------------------------------
1694 CUSBRequest::IsQueueHeadComplete(
1695 struct _QUEUE_HEAD
* QueueHead
)
1698 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1701 // first check - is the queue head currently active
1703 if (QueueHead
->Token
.Bits
.Active
)
1706 // queue head is active (currently processed)
1711 if (QueueHead
->Token
.Bits
.Halted
)
1716 DPRINT1("Found halted queue head %p\n", QueueHead
);
1717 DumpQueueHead(QueueHead
);
1723 // loop list and see if there are any active descriptors
1725 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1726 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1729 // obtain descriptor from entry
1731 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1733 if (Descriptor
->Token
.Bits
.Active
)
1736 // descriptor is still active
1742 // move to next entry
1744 Entry
= Entry
->Flink
;
1747 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead
, QueueHead
->PhysicalAddr
);
1750 // no active descriptors found, queue head is finished
1755 //-----------------------------------------------------------------------------------------
1757 CUSBRequest::InternalCalculateTransferLength()
1762 // FIXME: get length for control request
1764 return m_TransferBufferLength
;
1770 ASSERT(m_EndpointDescriptor
);
1771 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
1775 // HACK: Properly determine transfer length
1777 return m_TransferBufferLength
;//m_TotalBytesTransferred;
1781 // bulk out transfer
1783 return m_TransferBufferLength
;
1787 CUSBRequest::GetSpeed()
1793 CUSBRequest::GetInterval()
1795 if (!m_EndpointDescriptor
)
1798 return m_EndpointDescriptor
->EndPointDescriptor
.bInterval
;
1801 //-----------------------------------------------------------------------------------------
1804 InternalCreateUSBRequest(
1805 PUSBREQUEST
*OutRequest
)
1810 // allocate requests
1812 This
= new(NonPagedPool
, TAG_USBEHCI
) CUSBRequest(0);
1816 // failed to allocate
1818 return STATUS_INSUFFICIENT_RESOURCES
;
1822 // add reference count
1829 *OutRequest
= (PUSBREQUEST
)This
;
1834 return STATUS_SUCCESS
;