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/usbohci/usb_request.cpp
5 * PURPOSE: USB OHCI 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_DESCRIPTOR EndpointDescriptor
, IN USB_DEVICE_SPEED DeviceSpeed
, IN OUT ULONG TransferBufferLength
, IN OUT PMDL TransferBuffer
);
40 virtual NTSTATUS
InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager
, IN OUT PIRP Irp
, IN USB_DEVICE_SPEED DeviceSpeed
);
41 virtual BOOLEAN
IsRequestComplete();
42 virtual ULONG
GetTransferType();
43 virtual NTSTATUS
GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR
** OutEndpointDescriptor
);
44 virtual VOID
GetResultStatus(OUT OPTIONAL NTSTATUS
*NtStatusCode
, OUT OPTIONAL PULONG UrbStatusCode
);
45 virtual BOOLEAN
IsRequestInitialized();
46 virtual BOOLEAN
IsQueueHeadComplete(struct _QUEUE_HEAD
* QueueHead
);
47 virtual VOID
CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
);
48 virtual VOID
FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
);
49 virtual UCHAR
GetInterval();
53 ULONG
InternalGetTransferType();
54 UCHAR
InternalGetPidDirection();
55 UCHAR
GetDeviceAddress();
56 NTSTATUS
BuildSetupPacket();
57 NTSTATUS
BuildSetupPacketFromURB();
58 NTSTATUS
BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
59 NTSTATUS
BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
60 NTSTATUS
BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
61 NTSTATUS
CreateGeneralTransferDescriptor(POHCI_GENERAL_TD
* OutDescriptor
, ULONG BufferSize
);
62 VOID
FreeDescriptor(POHCI_GENERAL_TD Descriptor
);
63 NTSTATUS
AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
);
64 NTSTATUS
CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD
*OutDescriptor
, ULONG FrameCount
);
65 UCHAR
GetEndpointAddress();
66 USHORT
GetMaxPacketSize();
67 VOID
CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
);
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_DESCRIPTOR m_EndpointDescriptor
;
128 // allocated setup packet from the DMA pool
130 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
131 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
134 // stores the result of the operation
136 NTSTATUS m_NtStatusCode
;
137 ULONG m_UrbStatusCode
;
142 USB_DEVICE_SPEED m_DeviceSpeed
;
150 //----------------------------------------------------------------------------------------
153 CUSBRequest::QueryInterface(
157 return STATUS_UNSUCCESSFUL
;
160 //----------------------------------------------------------------------------------------
162 CUSBRequest::InitializeWithSetupPacket(
163 IN PDMAMEMORYMANAGER DmaManager
,
164 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
165 IN UCHAR DeviceAddress
,
166 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
167 IN USB_DEVICE_SPEED DeviceSpeed
,
168 IN OUT ULONG TransferBufferLength
,
169 IN OUT PMDL TransferBuffer
)
174 PC_ASSERT(DmaManager
);
175 PC_ASSERT(SetupPacket
);
180 m_DmaManager
= DmaManager
;
181 m_SetupPacket
= SetupPacket
;
182 m_TransferBufferLength
= TransferBufferLength
;
183 m_TransferBufferMDL
= TransferBuffer
;
184 m_DeviceAddress
= DeviceAddress
;
185 m_EndpointDescriptor
= EndpointDescriptor
;
186 m_TotalBytesTransferred
= 0;
187 m_DeviceSpeed
= DeviceSpeed
;
190 // Set Length Completed to 0
192 m_TransferBufferLengthCompleted
= 0;
195 // allocate completion event
197 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBOHCI
);
198 if (!m_CompletionEvent
)
201 // failed to allocate completion event
203 return STATUS_INSUFFICIENT_RESOURCES
;
207 // initialize completion event
209 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
214 return STATUS_SUCCESS
;
216 //----------------------------------------------------------------------------------------
218 CUSBRequest::InitializeWithIrp(
219 IN PDMAMEMORYMANAGER DmaManager
,
221 IN USB_DEVICE_SPEED DeviceSpeed
)
223 PIO_STACK_LOCATION IoStack
;
228 PC_ASSERT(DmaManager
);
231 m_DmaManager
= DmaManager
;
232 m_TotalBytesTransferred
= 0;
235 // get current irp stack location
237 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
242 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
243 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
244 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
249 m_Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
259 m_DeviceSpeed
= DeviceSpeed
;
262 // check function type
264 switch (m_Urb
->UrbHeader
.Function
)
266 case URB_FUNCTION_ISOCH_TRANSFER
:
269 // there must be at least one packet
271 ASSERT(m_Urb
->UrbIsochronousTransfer
.NumberOfPackets
);
274 // is there data to be transferred
276 if (m_Urb
->UrbIsochronousTransfer
.TransferBufferLength
)
279 // Check if there is a MDL
281 if (!m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
286 PC_ASSERT(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
289 // Create one using TransferBuffer
291 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
292 m_TransferBufferMDL
= IoAllocateMdl(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
293 m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
298 if (!m_TransferBufferMDL
)
301 // failed to allocate mdl
303 return STATUS_INSUFFICIENT_RESOURCES
;
307 // build mdl for non paged pool
308 // FIXME: Does hub driver already do this when passing MDL?
310 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
317 m_TransferBufferMDL
= m_Urb
->UrbIsochronousTransfer
.TransferBufferMDL
;
322 // save buffer length
324 m_TransferBufferLength
= m_Urb
->UrbIsochronousTransfer
.TransferBufferLength
;
327 // Set Length Completed to 0
329 m_TransferBufferLengthCompleted
= 0;
332 // get endpoint descriptor
334 m_EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)m_Urb
->UrbIsochronousTransfer
.PipeHandle
;
337 // completed initialization
342 // luckily those request have the same structure layout
344 case URB_FUNCTION_CLASS_INTERFACE
:
345 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
346 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
349 // bulk interrupt transfer
351 if (m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
354 // Check if there is a MDL
356 if (!m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
361 PC_ASSERT(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
364 // Create one using TransferBuffer
366 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
367 m_TransferBufferMDL
= IoAllocateMdl(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
368 m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
373 if (!m_TransferBufferMDL
)
376 // failed to allocate mdl
378 return STATUS_INSUFFICIENT_RESOURCES
;
382 // build mdl for non paged pool
383 // FIXME: Does hub driver already do this when passing MDL?
385 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
388 // Keep that ehci created the MDL and needs to free it.
393 m_TransferBufferMDL
= m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
397 // save buffer length
399 m_TransferBufferLength
= m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
402 // Set Length Completed to 0
404 m_TransferBufferLengthCompleted
= 0;
407 // get endpoint descriptor
409 m_EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)m_Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
415 DPRINT1("URB Function: not supported %x\n", m_Urb
->UrbHeader
.Function
);
422 return STATUS_SUCCESS
;
426 //----------------------------------------------------------------------------------------
428 CUSBRequest::IsRequestComplete()
431 // FIXME: check if request was split
435 // Check if the transfer was completed, only valid for Bulk Transfers
437 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
438 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
441 // Transfer not completed
447 //----------------------------------------------------------------------------------------
449 CUSBRequest::GetTransferType()
452 // call internal implementation
454 return InternalGetTransferType();
458 CUSBRequest::GetMaxPacketSize()
460 if (!m_EndpointDescriptor
)
469 ASSERT(m_EndpointDescriptor
);
472 // return max packet size
474 return m_EndpointDescriptor
->wMaxPacketSize
;
478 CUSBRequest::GetInterval()
480 ASSERT(m_EndpointDescriptor
);
481 ASSERT((m_EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
484 // return interrupt interval
486 return m_EndpointDescriptor
->bInterval
;
490 CUSBRequest::GetEndpointAddress()
492 if (!m_EndpointDescriptor
)
501 ASSERT(m_EndpointDescriptor
);
504 // endpoint number is between 1-15
506 return (m_EndpointDescriptor
->bEndpointAddress
& 0xF);
509 //----------------------------------------------------------------------------------------
511 CUSBRequest::InternalGetTransferType()
516 // check if an irp is provided
520 ASSERT(m_EndpointDescriptor
);
523 // end point is defined in the low byte of bmAttributes
525 TransferType
= (m_EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
530 // initialized with setup packet, must be a control transfer
532 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
542 CUSBRequest::InternalGetPidDirection()
545 ASSERT(m_EndpointDescriptor
);
548 // end point is defined in the low byte of bEndpointAddress
550 return (m_EndpointDescriptor
->bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
554 //----------------------------------------------------------------------------------------
556 CUSBRequest::GetDeviceAddress()
558 PIO_STACK_LOCATION IoStack
;
560 PUSBDEVICE UsbDevice
;
563 // check if there is an irp provided
568 // used provided address
570 return m_DeviceAddress
;
574 // get current stack location
576 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
581 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
584 // check if there is a pipe handle provided
586 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
589 // there is a device handle provided
591 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
594 // return device address
596 return UsbDevice
->GetDeviceAddress();
600 // no device handle provided, it is the host root bus
606 CUSBRequest::FreeDescriptor(
607 POHCI_GENERAL_TD Descriptor
)
609 if (Descriptor
->BufferSize
)
614 m_DmaManager
->Release(Descriptor
->BufferLogical
, Descriptor
->BufferSize
);
618 // release descriptor
620 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
624 //----------------------------------------------------------------------------------------
626 CUSBRequest::CreateIsochronousTransferDescriptor(
627 POHCI_ISO_TD
* OutDescriptor
,
630 POHCI_ISO_TD Descriptor
;
631 PHYSICAL_ADDRESS DescriptorAddress
;
635 // allocate transfer descriptor
637 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ISO_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
638 if (!NT_SUCCESS(Status
))
647 // initialize descriptor, hardware part
649 Descriptor
->Flags
= OHCI_ITD_SET_FRAME_COUNT(FrameCount
) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE
);// | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
650 Descriptor
->BufferPhysical
= 0;
651 Descriptor
->NextPhysicalDescriptor
= 0;
652 Descriptor
->LastPhysicalByteAddress
= 0;
657 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
658 Descriptor
->NextLogicalDescriptor
= 0;
663 *OutDescriptor
= Descriptor
;
668 return STATUS_SUCCESS
;
672 CUSBRequest::BuildIsochronousEndpoint(
673 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
675 POHCI_ISO_TD FirstDescriptor
= NULL
, PreviousDescriptor
= NULL
, CurrentDescriptor
= NULL
;
676 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
677 ULONG Index
= 0, SubIndex
, NumberOfPackets
, PageOffset
, Page
;
680 PIO_STACK_LOCATION IoStack
;
682 PHYSICAL_ADDRESS Address
;
685 // get current irp stack location
687 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
692 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
693 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
694 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
699 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
703 // allocate endpoint descriptor
705 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
706 if (!NT_SUCCESS(Status
))
709 // failed to create setup descriptor
718 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
722 // FIXME: support requests which spans serveral pages
724 ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL
), MmGetMdlByteCount(m_TransferBufferMDL
)) <= 2);
726 Status
= m_DmaManager
->Allocate(m_TransferBufferLength
, &Buffer
, &Address
);
727 ASSERT(Status
== STATUS_SUCCESS
);
730 while(Index
< Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
733 // get number of packets remaining
735 NumberOfPackets
= min(Urb
->UrbIsochronousTransfer
.NumberOfPackets
- Index
, OHCI_ITD_NOFFSET
);
737 // allocate iso descriptor
739 Status
= CreateIsochronousTransferDescriptor(&CurrentDescriptor
, NumberOfPackets
);
740 if (!NT_SUCCESS(Status
))
744 // failed to allocate descriptor
753 Page
= MmGetPhysicalAddress(Buffer
).LowPart
;
758 PageOffset
= BYTE_OFFSET(Page
);
761 // initialize descriptor
763 CurrentDescriptor
->BufferPhysical
= Page
- PageOffset
;
765 for(SubIndex
= 0; SubIndex
< NumberOfPackets
; SubIndex
++)
768 // store buffer offset
770 CurrentDescriptor
->Offset
[SubIndex
] = Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
+ PageOffset
;
771 DPRINT("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex
+Index
, Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
, CurrentDescriptor
->Offset
[SubIndex
]);
775 // increment packet offset
777 Index
+= NumberOfPackets
;
780 // check if this is the last descriptor
782 if (Index
== Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
787 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ m_TransferBufferLength
- 1;
792 // use start address of next packet - 1
794 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
- 1;
798 // is there a previous descriptor
800 if (PreviousDescriptor
)
805 PreviousDescriptor
->NextLogicalDescriptor
= CurrentDescriptor
;
806 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
813 FirstDescriptor
= CurrentDescriptor
;
817 // store as previous descriptor
819 PreviousDescriptor
= CurrentDescriptor
;
820 DPRINT("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor
, CurrentDescriptor
->PhysicalAddress
.LowPart
, CurrentDescriptor
->BufferPhysical
, CurrentDescriptor
->LastPhysicalByteAddress
);
823 // fire interrupt as soon transfer is finished
825 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
829 // clear interrupt mask for last transfer descriptor
831 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
834 // fire interrupt as soon transfer is finished
836 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
839 // set isochronous type
841 EndpointDescriptor
->Flags
|= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
;
844 // now link descriptor to endpoint
846 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
847 EndpointDescriptor
->TailPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
848 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
853 *OutEndpointDescriptor
= EndpointDescriptor
;
858 return STATUS_SUCCESS
;
861 //----------------------------------------------------------------------------------------
863 CUSBRequest::CreateGeneralTransferDescriptor(
864 POHCI_GENERAL_TD
* OutDescriptor
,
867 POHCI_GENERAL_TD Descriptor
;
868 PHYSICAL_ADDRESS DescriptorAddress
;
872 // allocate transfer descriptor
874 Status
= m_DmaManager
->Allocate(sizeof(OHCI_GENERAL_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
875 if (!NT_SUCCESS(Status
))
884 // initialize descriptor, hardware part
886 Descriptor
->Flags
= 0;
887 Descriptor
->BufferPhysical
= 0;
888 Descriptor
->NextPhysicalDescriptor
= 0;
889 Descriptor
->LastPhysicalByteAddress
= 0;
894 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
895 Descriptor
->BufferSize
= BufferSize
;
900 // allocate buffer from dma
902 Status
= m_DmaManager
->Allocate(BufferSize
, &Descriptor
->BufferLogical
, &DescriptorAddress
);
903 if (!NT_SUCCESS(Status
))
908 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
913 // set physical address of buffer
915 Descriptor
->BufferPhysical
= DescriptorAddress
.LowPart
;
916 Descriptor
->LastPhysicalByteAddress
= Descriptor
->BufferPhysical
+ BufferSize
- 1;
922 *OutDescriptor
= Descriptor
;
927 return STATUS_SUCCESS
;
931 CUSBRequest::AllocateEndpointDescriptor(
932 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
)
934 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
935 PHYSICAL_ADDRESS DescriptorAddress
;
939 // allocate descriptor
941 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
942 if (!NT_SUCCESS(Status
))
945 // failed to allocate descriptor
951 // intialize descriptor
953 Descriptor
->Flags
= OHCI_ENDPOINT_SKIP
;
956 // append device address and endpoint number
958 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
959 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
960 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
962 DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor
->Flags
, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
965 // is there an endpoint descriptor
967 if (m_EndpointDescriptor
)
972 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->bEndpointAddress
))
977 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_OUT
;
984 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_IN
;
992 if (m_DeviceSpeed
== UsbFullSpeed
)
995 // device is full speed
997 Descriptor
->Flags
|= OHCI_ENDPOINT_FULL_SPEED
;
999 else if (m_DeviceSpeed
== UsbLowSpeed
)
1002 // device is full speed
1004 Descriptor
->Flags
|= OHCI_ENDPOINT_LOW_SPEED
;
1014 Descriptor
->HeadPhysicalDescriptor
= 0;
1015 Descriptor
->NextPhysicalEndpoint
= 0;
1016 Descriptor
->TailPhysicalDescriptor
= 0;
1017 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
1022 *OutDescriptor
= Descriptor
;
1027 return STATUS_SUCCESS
;
1031 CUSBRequest::BuildBulkInterruptEndpoint(
1032 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
1034 POHCI_GENERAL_TD FirstDescriptor
, PreviousDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
;
1035 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1036 ULONG BufferSize
, CurrentSize
, Direction
, MaxLengthInPage
;
1041 // allocate endpoint descriptor
1043 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1044 if (!NT_SUCCESS(Status
))
1047 // failed to create setup descriptor
1053 // allocate transfer descriptor for last descriptor
1055 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
1056 if (!NT_SUCCESS(Status
))
1059 // failed to create transfer descriptor
1061 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1068 BufferSize
= m_TransferBufferLength
;
1070 ASSERT(m_TransferBufferMDL
);
1075 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1078 if (InternalGetPidDirection())
1083 Direction
= OHCI_TD_DIRECTION_PID_IN
;
1090 Direction
= OHCI_TD_DIRECTION_PID_OUT
;
1096 // get current buffersize
1098 CurrentSize
= min(8192, BufferSize
);
1103 MaxLengthInPage
= PAGE_SIZE
- BYTE_OFFSET(Buffer
);
1106 // get minimum from current page size
1108 CurrentSize
= min(CurrentSize
, MaxLengthInPage
);
1109 ASSERT(CurrentSize
);
1112 // allocate transfer descriptor
1114 Status
= CreateGeneralTransferDescriptor(&CurrentDescriptor
, 0);
1115 if (!NT_SUCCESS(Status
))
1118 // failed to create transfer descriptor
1122 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1123 FreeDescriptor(LastDescriptor
);
1128 // initialize descriptor
1130 CurrentDescriptor
->Flags
= Direction
| OHCI_TD_BUFFER_ROUNDING
| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED
) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE
) | OHCI_TD_TOGGLE_CARRY
;
1133 // store physical address of buffer
1135 CurrentDescriptor
->BufferPhysical
= MmGetPhysicalAddress(Buffer
).LowPart
;
1136 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ CurrentSize
- 1;
1141 if (m_Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1144 // indicate short packet support
1146 CurrentDescriptor
->Flags
|= OHCI_TD_BUFFER_ROUNDING
;
1152 // is there a previous descriptor
1154 if (PreviousDescriptor
)
1159 PreviousDescriptor
->NextLogicalDescriptor
= (PVOID
)CurrentDescriptor
;
1160 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
1165 // it is the first descriptor
1167 FirstDescriptor
= CurrentDescriptor
;
1170 DPRINT("PreviousDescriptor %p CurrentDescriptor %p Logical %x Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor
, CurrentDescriptor
, CurrentDescriptor
->PhysicalAddress
.LowPart
, CurrentDescriptor
->BufferLogical
, CurrentDescriptor
->BufferPhysical
, CurrentDescriptor
->LastPhysicalByteAddress
, CurrentSize
);
1173 // set previous descriptor
1175 PreviousDescriptor
= CurrentDescriptor
;
1178 // subtract buffer size
1180 BufferSize
-= CurrentSize
;
1183 // increment buffer offset
1185 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
1190 // first descriptor has no carry bit
1192 FirstDescriptor
->Flags
&= ~OHCI_TD_TOGGLE_CARRY
;
1197 FirstDescriptor
->Flags
|= OHCI_TD_TOGGLE_0
;
1200 // clear interrupt mask for last transfer descriptor
1202 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
1205 // fire interrupt as soon transfer is finished
1207 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
1210 // link last data descriptor to last descriptor
1212 CurrentDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1213 CurrentDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1216 // now link descriptor to endpoint
1218 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
1219 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1220 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
1225 *OutEndpointDescriptor
= EndpointDescriptor
;
1230 return STATUS_SUCCESS
;
1235 CUSBRequest::BuildControlTransferDescriptor(
1236 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
1238 POHCI_GENERAL_TD SetupDescriptor
, StatusDescriptor
, DataDescriptor
= NULL
, LastDescriptor
;
1239 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1243 // allocate endpoint descriptor
1245 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1246 if (!NT_SUCCESS(Status
))
1249 // failed to create setup descriptor
1255 // first allocate setup descriptor
1257 Status
= CreateGeneralTransferDescriptor(&SetupDescriptor
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1258 if (!NT_SUCCESS(Status
))
1261 // failed to create setup descriptor
1263 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1268 // now create the status descriptor
1270 Status
= CreateGeneralTransferDescriptor(&StatusDescriptor
, 0);
1271 if (!NT_SUCCESS(Status
))
1274 // failed to create status descriptor
1276 FreeDescriptor(SetupDescriptor
);
1277 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1282 // finally create the last descriptor
1284 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
1285 if (!NT_SUCCESS(Status
))
1288 // failed to create status descriptor
1290 FreeDescriptor(SetupDescriptor
);
1291 FreeDescriptor(StatusDescriptor
);
1292 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1296 if (m_TransferBufferLength
)
1299 // FIXME: support more than one data descriptor
1301 ASSERT(m_TransferBufferLength
< 8192);
1304 // now create the data descriptor
1306 Status
= CreateGeneralTransferDescriptor(&DataDescriptor
, 0);
1307 if (!NT_SUCCESS(Status
))
1310 // failed to create status descriptor
1312 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1313 FreeDescriptor(SetupDescriptor
);
1314 FreeDescriptor(StatusDescriptor
);
1315 FreeDescriptor(LastDescriptor
);
1320 // initialize data descriptor
1322 DataDescriptor
->Flags
= OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED
) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE
) | OHCI_TD_TOGGLE_CARRY
| OHCI_TD_TOGGLE_1
;
1324 if (m_EndpointDescriptor
)
1326 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->bEndpointAddress
))
1331 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_OUT
;
1338 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1344 // no end point address provided - assume its an in direction
1346 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1350 // use short packets
1352 DataDescriptor
->Flags
|= OHCI_TD_BUFFER_ROUNDING
;
1355 // store physical address of buffer
1357 DataDescriptor
->BufferPhysical
= MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL
)).LowPart
;
1358 DataDescriptor
->LastPhysicalByteAddress
= DataDescriptor
->BufferPhysical
+ m_TransferBufferLength
- 1;
1362 // initialize setup descriptor
1364 SetupDescriptor
->Flags
= OHCI_TD_BUFFER_ROUNDING
| OHCI_TD_DIRECTION_PID_SETUP
| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED
) | OHCI_TD_TOGGLE_0
| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE
);
1369 // copy setup packet
1371 RtlCopyMemory(SetupDescriptor
->BufferLogical
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1376 // generate setup packet from urb
1382 // initialize status descriptor
1384 StatusDescriptor
->Flags
= OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED
) | OHCI_TD_TOGGLE_1
| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
1385 if (m_TransferBufferLength
== 0)
1388 // input direction is flipped for the status descriptor
1390 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1395 // output direction is flipped for the status descriptor
1397 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_OUT
;
1401 // now link the descriptors
1403 if (m_TransferBufferLength
)
1406 // link setup descriptor to data descriptor
1408 SetupDescriptor
->NextPhysicalDescriptor
= DataDescriptor
->PhysicalAddress
.LowPart
;
1409 SetupDescriptor
->NextLogicalDescriptor
= DataDescriptor
;
1412 // link data descriptor to status descriptor
1413 // FIXME: check if there are more data descriptors
1415 DataDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1416 DataDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1419 // link status descriptor to last descriptor
1421 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1422 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1427 // link setup descriptor to status descriptor
1429 SetupDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1430 SetupDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1433 // link status descriptor to last descriptor
1435 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1436 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1440 // now link descriptor to endpoint
1442 EndpointDescriptor
->HeadPhysicalDescriptor
= SetupDescriptor
->PhysicalAddress
.LowPart
;
1443 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1444 EndpointDescriptor
->HeadLogicalDescriptor
= SetupDescriptor
;
1449 *OutEndpointDescriptor
= EndpointDescriptor
;
1454 return STATUS_SUCCESS
;
1457 //----------------------------------------------------------------------------------------
1459 CUSBRequest::GetEndpointDescriptor(
1460 struct _OHCI_ENDPOINT_DESCRIPTOR
** OutDescriptor
)
1466 // get transfer type
1468 TransferType
= InternalGetTransferType();
1471 // build request depending on type
1473 switch(TransferType
)
1475 case USB_ENDPOINT_TYPE_CONTROL
:
1476 Status
= BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1478 case USB_ENDPOINT_TYPE_BULK
:
1479 case USB_ENDPOINT_TYPE_INTERRUPT
:
1480 Status
= BuildBulkInterruptEndpoint(OutDescriptor
);
1482 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
1483 Status
= BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1487 Status
= STATUS_NOT_IMPLEMENTED
;
1491 if (NT_SUCCESS(Status
))
1496 //m_QueueHead = *OutDescriptor;
1499 // store request object
1501 (*OutDescriptor
)->Request
= PVOID(this);
1510 //----------------------------------------------------------------------------------------
1512 CUSBRequest::GetResultStatus(
1513 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1514 OUT OPTIONAL PULONG UrbStatusCode
)
1519 PC_ASSERT(m_CompletionEvent
);
1522 // wait for the operation to complete
1524 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1531 *NtStatusCode
= m_NtStatusCode
;
1539 *UrbStatusCode
= m_UrbStatusCode
;
1545 CUSBRequest::FreeEndpointDescriptor(
1546 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1548 POHCI_GENERAL_TD TransferDescriptor
, NextTransferDescriptor
;
1549 POHCI_ISO_TD IsoTransferDescriptor
, IsoNextTransferDescriptor
;
1550 ULONG Index
, PacketCount
;
1552 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1554 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1557 // get first iso transfer descriptor
1559 IsoTransferDescriptor
= (POHCI_ISO_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1562 // release endpoint descriptor
1564 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1566 while(IsoTransferDescriptor
)
1571 IsoNextTransferDescriptor
= IsoTransferDescriptor
->NextLogicalDescriptor
;
1576 PacketCount
= OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor
->Flags
);
1578 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor
, IsoTransferDescriptor
->PhysicalAddress
.LowPart
, IsoTransferDescriptor
->BufferPhysical
, IsoTransferDescriptor
->LastPhysicalByteAddress
, PacketCount
);
1580 for(Index
= 0; Index
< PacketCount
; Index
++)
1582 DPRINT("PSW Index %lu Value %x\n", Index
, IsoTransferDescriptor
->Offset
[Index
]);
1586 // release descriptor
1588 m_DmaManager
->Release(IsoTransferDescriptor
, sizeof(OHCI_ISO_TD
));
1593 IsoTransferDescriptor
= IsoNextTransferDescriptor
;
1599 // get first general transfer descriptor
1601 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1604 // release endpoint descriptor
1606 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1608 while(TransferDescriptor
)
1613 NextTransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1616 // is there a buffer associated
1618 if (TransferDescriptor
->BufferSize
)
1623 m_DmaManager
->Release(TransferDescriptor
->BufferLogical
, TransferDescriptor
->BufferSize
);
1626 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor
, TransferDescriptor
->PhysicalAddress
.LowPart
, TransferDescriptor
->BufferPhysical
, TransferDescriptor
->LastPhysicalByteAddress
);
1629 // release descriptor
1631 m_DmaManager
->Release(TransferDescriptor
, sizeof(OHCI_GENERAL_TD
));
1636 TransferDescriptor
= NextTransferDescriptor
;
1643 CUSBRequest::CheckError(
1644 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1646 POHCI_GENERAL_TD TransferDescriptor
;
1647 ULONG ConditionCode
;
1649 PIO_STACK_LOCATION IoStack
;
1655 m_NtStatusCode
= STATUS_SUCCESS
;
1656 m_UrbStatusCode
= USBD_STATUS_SUCCESS
;
1659 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1662 // FIXME: handle isochronous support
1669 // get first general transfer descriptor
1671 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1673 while(TransferDescriptor
)
1676 // get condition code
1678 ConditionCode
= OHCI_TD_GET_CONDITION_CODE(TransferDescriptor
->Flags
);
1679 if (ConditionCode
!= OHCI_TD_CONDITION_NO_ERROR
)
1682 // FIXME status code
1684 m_NtStatusCode
= STATUS_UNSUCCESSFUL
;
1686 switch(ConditionCode
)
1688 case OHCI_TD_CONDITION_CRC_ERROR
:
1689 DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1690 m_UrbStatusCode
= USBD_STATUS_CRC
;
1692 case OHCI_TD_CONDITION_BIT_STUFFING
:
1693 DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1694 m_UrbStatusCode
= USBD_STATUS_BTSTUFF
;
1696 case OHCI_TD_CONDITION_TOGGLE_MISMATCH
:
1697 DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1698 m_UrbStatusCode
= USBD_STATUS_DATA_TOGGLE_MISMATCH
;
1700 case OHCI_TD_CONDITION_STALL
:
1701 DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1702 m_UrbStatusCode
= USBD_STATUS_STALL_PID
;
1704 case OHCI_TD_CONDITION_NO_RESPONSE
:
1705 DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1706 m_UrbStatusCode
= USBD_STATUS_DEV_NOT_RESPONDING
;
1708 case OHCI_TD_CONDITION_PID_CHECK_FAILURE
:
1709 DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1710 m_UrbStatusCode
= USBD_STATUS_PID_CHECK_FAILURE
;
1712 case OHCI_TD_CONDITION_UNEXPECTED_PID
:
1713 DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1714 m_UrbStatusCode
= USBD_STATUS_UNEXPECTED_PID
;
1716 case OHCI_TD_CONDITION_DATA_OVERRUN
:
1717 DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1718 m_UrbStatusCode
= USBD_STATUS_DATA_OVERRUN
;
1720 case OHCI_TD_CONDITION_DATA_UNDERRUN
:
1724 // get current irp stack location
1726 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1731 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1733 if(Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1736 // short packets are ok
1738 ASSERT(Urb
->UrbHeader
.Function
== URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
);
1739 m_NtStatusCode
= STATUS_SUCCESS
;
1743 DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1744 m_UrbStatusCode
= USBD_STATUS_DATA_UNDERRUN
;
1746 case OHCI_TD_CONDITION_BUFFER_OVERRUN
:
1747 DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1748 m_UrbStatusCode
= USBD_STATUS_BUFFER_OVERRUN
;
1750 case OHCI_TD_CONDITION_BUFFER_UNDERRUN
:
1751 DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1752 m_UrbStatusCode
= USBD_STATUS_BUFFER_UNDERRUN
;
1760 TransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1766 CUSBRequest::CompletionCallback(
1767 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1769 PIO_STACK_LOCATION IoStack
;
1772 DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1777 CheckError(OutDescriptor
);
1782 // set irp completion status
1784 m_Irp
->IoStatus
.Status
= m_NtStatusCode
;
1787 // get current irp stack location
1789 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1794 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1799 Urb
->UrbHeader
.Status
= m_UrbStatusCode
;
1802 // Check if the MDL was created
1804 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
1809 IoFreeMdl(m_TransferBufferMDL
);
1813 // FIXME: support status and calculate length
1817 // FIXME: check if the transfer was split
1818 // if yes dont complete irp yet
1820 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
1825 // signal completion event
1827 PC_ASSERT(m_CompletionEvent
);
1828 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
1833 //-----------------------------------------------------------------------------------------
1835 CUSBRequest::IsRequestInitialized()
1837 if (m_Irp
|| m_SetupPacket
)
1840 // request is initialized
1846 // request is not initialized
1851 //-----------------------------------------------------------------------------------------
1853 CUSBRequest::IsQueueHeadComplete(
1854 struct _QUEUE_HEAD
* QueueHead
)
1862 //-----------------------------------------------------------------------------------------
1864 InternalCreateUSBRequest(
1865 PUSBREQUEST
*OutRequest
)
1870 // allocate requests
1872 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBRequest(0);
1876 // failed to allocate
1878 return STATUS_INSUFFICIENT_RESOURCES
;
1882 // add reference count
1889 *OutRequest
= (PUSBREQUEST
)This
;
1894 return STATUS_SUCCESS
;