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 OUT ULONG TransferBufferLength
, IN OUT PMDL TransferBuffer
);
40 virtual NTSTATUS
InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager
, IN OUT PIRP Irp
);
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
);
51 ULONG
InternalGetTransferType();
52 UCHAR
InternalGetPidDirection();
53 UCHAR
GetDeviceAddress();
54 NTSTATUS
BuildSetupPacket();
55 NTSTATUS
BuildSetupPacketFromURB();
56 NTSTATUS
BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
57 NTSTATUS
BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
58 NTSTATUS
CreateGeneralTransferDescriptor(POHCI_GENERAL_TD
* OutDescriptor
, ULONG BufferSize
);
59 VOID
FreeDescriptor(POHCI_GENERAL_TD Descriptor
);
60 NTSTATUS
AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
);
61 UCHAR
GetEndpointAddress();
62 USHORT
GetMaxPacketSize();
64 // constructor / destructor
65 CUSBRequest(IUnknown
*OuterUnknown
){}
66 virtual ~CUSBRequest(){}
72 // memory manager for allocating setup packet / queue head / transfer descriptors
74 PDMAMEMORYMANAGER m_DmaManager
;
77 // caller provided irp packet containing URB request
82 // transfer buffer length
84 ULONG m_TransferBufferLength
;
87 // current transfer length
89 ULONG m_TransferBufferLengthCompleted
;
92 // Total Transfer Length
94 ULONG m_TotalBytesTransferred
;
97 // transfer buffer MDL
99 PMDL m_TransferBufferMDL
;
102 // caller provided setup packet
104 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
107 // completion event for callers who initialized request with setup packet
109 PKEVENT m_CompletionEvent
;
112 // device address for callers who initialized it with device address
114 UCHAR m_DeviceAddress
;
117 // store end point address
119 PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor
;
122 // allocated setup packet from the DMA pool
124 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
125 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
128 // stores the result of the operation
130 NTSTATUS m_NtStatusCode
;
131 ULONG m_UrbStatusCode
;
135 //----------------------------------------------------------------------------------------
138 CUSBRequest::QueryInterface(
142 return STATUS_UNSUCCESSFUL
;
145 //----------------------------------------------------------------------------------------
147 CUSBRequest::InitializeWithSetupPacket(
148 IN PDMAMEMORYMANAGER DmaManager
,
149 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
150 IN UCHAR DeviceAddress
,
151 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
152 IN OUT ULONG TransferBufferLength
,
153 IN OUT PMDL TransferBuffer
)
158 PC_ASSERT(DmaManager
);
159 PC_ASSERT(SetupPacket
);
164 m_DmaManager
= DmaManager
;
165 m_SetupPacket
= SetupPacket
;
166 m_TransferBufferLength
= TransferBufferLength
;
167 m_TransferBufferMDL
= TransferBuffer
;
168 m_DeviceAddress
= DeviceAddress
;
169 m_EndpointDescriptor
= EndpointDescriptor
;
170 m_TotalBytesTransferred
= 0;
173 // Set Length Completed to 0
175 m_TransferBufferLengthCompleted
= 0;
178 // allocate completion event
180 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBOHCI
);
181 if (!m_CompletionEvent
)
184 // failed to allocate completion event
186 return STATUS_INSUFFICIENT_RESOURCES
;
190 // initialize completion event
192 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
197 return STATUS_SUCCESS
;
199 //----------------------------------------------------------------------------------------
201 CUSBRequest::InitializeWithIrp(
202 IN PDMAMEMORYMANAGER DmaManager
,
205 PIO_STACK_LOCATION IoStack
;
211 PC_ASSERT(DmaManager
);
214 m_DmaManager
= DmaManager
;
215 m_TotalBytesTransferred
= 0;
218 // get current irp stack location
220 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
225 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
226 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
227 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
232 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
240 // check function type
242 switch (Urb
->UrbHeader
.Function
)
245 // luckily those request have the same structure layout
247 case URB_FUNCTION_CLASS_INTERFACE
:
248 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
249 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
252 // bulk interrupt transfer
254 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
257 // Check if there is a MDL
259 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
264 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
267 // Create one using TransferBuffer
269 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
270 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
271 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
276 if (!m_TransferBufferMDL
)
279 // failed to allocate mdl
281 return STATUS_INSUFFICIENT_RESOURCES
;
285 // build mdl for non paged pool
286 // FIXME: Does hub driver already do this when passing MDL?
288 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
291 // Keep that ehci created the MDL and needs to free it.
296 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
300 // save buffer length
302 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
305 // Set Length Completed to 0
307 m_TransferBufferLengthCompleted
= 0;
310 // get endpoint descriptor
312 m_EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
318 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
325 return STATUS_SUCCESS
;
329 //----------------------------------------------------------------------------------------
331 CUSBRequest::IsRequestComplete()
334 // FIXME: check if request was split
338 // Check if the transfer was completed, only valid for Bulk Transfers
340 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
341 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
344 // Transfer not completed
350 //----------------------------------------------------------------------------------------
352 CUSBRequest::GetTransferType()
355 // call internal implementation
357 return InternalGetTransferType();
361 CUSBRequest::GetMaxPacketSize()
363 if (!m_EndpointDescriptor
)
372 ASSERT(m_EndpointDescriptor
);
375 // return max packet size
377 return m_EndpointDescriptor
->wMaxPacketSize
;
381 CUSBRequest::GetEndpointAddress()
383 if (!m_EndpointDescriptor
)
392 ASSERT(m_EndpointDescriptor
);
395 // endpoint number is between 1-15
397 return (m_EndpointDescriptor
->bEndpointAddress
& 0xF);
400 //----------------------------------------------------------------------------------------
402 CUSBRequest::InternalGetTransferType()
407 // check if an irp is provided
411 ASSERT(m_EndpointDescriptor
);
414 // end point is defined in the low byte of bmAttributes
416 TransferType
= (m_EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
421 // initialized with setup packet, must be a control transfer
423 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
433 CUSBRequest::InternalGetPidDirection()
436 ASSERT(m_EndpointDescriptor
);
439 // end point is defined in the low byte of bEndpointAddress
441 return (m_EndpointDescriptor
->bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
445 //----------------------------------------------------------------------------------------
447 CUSBRequest::GetDeviceAddress()
449 PIO_STACK_LOCATION IoStack
;
451 PUSBDEVICE UsbDevice
;
454 // check if there is an irp provided
459 // used provided address
461 return m_DeviceAddress
;
465 // get current stack location
467 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
472 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
475 // check if there is a pipe handle provided
477 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
480 // there is a device handle provided
482 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
485 // return device address
487 return UsbDevice
->GetDeviceAddress();
491 // no device handle provided, it is the host root bus
497 CUSBRequest::FreeDescriptor(
498 POHCI_GENERAL_TD Descriptor
)
500 if (Descriptor
->BufferSize
)
505 m_DmaManager
->Release(Descriptor
->BufferLogical
, Descriptor
->BufferSize
);
509 // release descriptor
511 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
514 //----------------------------------------------------------------------------------------
516 CUSBRequest::CreateGeneralTransferDescriptor(
517 POHCI_GENERAL_TD
* OutDescriptor
,
520 POHCI_GENERAL_TD Descriptor
;
521 PHYSICAL_ADDRESS DescriptorAddress
;
525 // allocate transfer descriptor
527 Status
= m_DmaManager
->Allocate(sizeof(OHCI_GENERAL_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
528 if (!NT_SUCCESS(Status
))
537 // initialize descriptor, hardware part
539 Descriptor
->Flags
= 0;
540 Descriptor
->BufferPhysical
= 0;
541 Descriptor
->NextPhysicalDescriptor
= 0;
542 Descriptor
->LastPhysicalByteAddress
= 0;
547 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
548 Descriptor
->BufferSize
= BufferSize
;
553 // allocate buffer from dma
555 Status
= m_DmaManager
->Allocate(BufferSize
, &Descriptor
->BufferLogical
, &DescriptorAddress
);
556 if (!NT_SUCCESS(Status
))
561 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
566 // set physical address of buffer
568 Descriptor
->BufferPhysical
= DescriptorAddress
.LowPart
;
569 Descriptor
->LastPhysicalByteAddress
= Descriptor
->BufferPhysical
+ BufferSize
- 1;
575 *OutDescriptor
= Descriptor
;
580 return STATUS_SUCCESS
;
584 CUSBRequest::AllocateEndpointDescriptor(
585 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
)
587 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
588 PHYSICAL_ADDRESS DescriptorAddress
;
592 // allocate descriptor
594 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
595 if (!NT_SUCCESS(Status
))
598 // failed to allocate descriptor
604 // intialize descriptor
606 Descriptor
->Flags
= OHCI_ENDPOINT_SKIP
;
609 // append device address and endpoint number
611 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
612 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
613 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
616 // is there an endpoint descriptor
618 if (m_EndpointDescriptor
)
623 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->bEndpointAddress
))
628 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_OUT
;
635 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_IN
;
642 // FIXME: detect type
644 Descriptor
->Flags
|= OHCI_ENDPOINT_FULL_SPEED
;
646 Descriptor
->HeadPhysicalDescriptor
= 0;
647 Descriptor
->NextPhysicalEndpoint
= 0;
648 Descriptor
->TailPhysicalDescriptor
= 0;
649 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
654 *OutDescriptor
= Descriptor
;
659 return STATUS_SUCCESS
;
663 CUSBRequest::BuildBulkInterruptEndpoint(
664 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
666 POHCI_GENERAL_TD FirstDescriptor
, PreviousDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
;
667 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
668 ULONG BufferSize
, CurrentSize
, Direction
, MaxLengthInPage
;
673 // allocate endpoint descriptor
675 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
676 if (!NT_SUCCESS(Status
))
679 // failed to create setup descriptor
685 // allocate transfer descriptor for last descriptor
687 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
688 if (!NT_SUCCESS(Status
))
691 // failed to create transfer descriptor
693 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
700 BufferSize
= m_TransferBufferLength
;
702 ASSERT(m_TransferBufferMDL
);
707 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
710 if (InternalGetPidDirection())
715 Direction
= OHCI_TD_DIRECTION_PID_IN
;
722 Direction
= OHCI_TD_DIRECTION_PID_OUT
;
728 // get current buffersize
730 CurrentSize
= min(8192, BufferSize
);
735 MaxLengthInPage
= PAGE_SIZE
- BYTE_OFFSET(Buffer
);
738 // get minimum from current page size
740 CurrentSize
= min(CurrentSize
, MaxLengthInPage
);
744 // allocate transfer descriptor
746 Status
= CreateGeneralTransferDescriptor(&CurrentDescriptor
, 0);
747 if (!NT_SUCCESS(Status
))
750 // failed to create transfer descriptor
754 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
755 FreeDescriptor(LastDescriptor
);
760 // initialize descriptor
762 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
;
765 // store physical address of buffer
767 CurrentDescriptor
->BufferPhysical
= MmGetPhysicalAddress(Buffer
).LowPart
;
768 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ CurrentSize
- 1;
771 // is there a previous descriptor
773 if (PreviousDescriptor
)
778 PreviousDescriptor
->NextLogicalDescriptor
= (PVOID
)CurrentDescriptor
;
779 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
784 // it is the first descriptor
786 FirstDescriptor
= CurrentDescriptor
;
789 DPRINT("PreviousDescriptor %p CurrentDescriptor %p Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor
, CurrentDescriptor
, CurrentDescriptor
->BufferLogical
, CurrentDescriptor
->BufferPhysical
, CurrentDescriptor
->LastPhysicalByteAddress
, CurrentSize
);
792 // set previous descriptor
794 PreviousDescriptor
= CurrentDescriptor
;
797 // subtract buffer size
799 BufferSize
-= CurrentSize
;
802 // increment buffer offset
804 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
809 // first descriptor has no carry bit
811 FirstDescriptor
->Flags
&= ~OHCI_TD_TOGGLE_CARRY
;
816 FirstDescriptor
->Flags
|= OHCI_TD_TOGGLE_0
;
819 // clear interrupt mask for last transfer descriptor
821 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
824 // fire interrupt as soon transfer is finished
826 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
829 // link last data descriptor to last descriptor
831 CurrentDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
832 CurrentDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
835 // now link descriptor to endpoint
837 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
838 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
839 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
844 *OutEndpointDescriptor
= EndpointDescriptor
;
849 return STATUS_SUCCESS
;
855 CUSBRequest::BuildControlTransferDescriptor(
856 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
858 POHCI_GENERAL_TD SetupDescriptor
, StatusDescriptor
, DataDescriptor
= NULL
, LastDescriptor
;
859 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
863 // allocate endpoint descriptor
865 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
866 if (!NT_SUCCESS(Status
))
869 // failed to create setup descriptor
875 // first allocate setup descriptor
877 Status
= CreateGeneralTransferDescriptor(&SetupDescriptor
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
878 if (!NT_SUCCESS(Status
))
881 // failed to create setup descriptor
883 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
888 // now create the status descriptor
890 Status
= CreateGeneralTransferDescriptor(&StatusDescriptor
, 0);
891 if (!NT_SUCCESS(Status
))
894 // failed to create status descriptor
896 FreeDescriptor(SetupDescriptor
);
897 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
902 // finally create the last descriptor
904 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
905 if (!NT_SUCCESS(Status
))
908 // failed to create status descriptor
910 FreeDescriptor(SetupDescriptor
);
911 FreeDescriptor(StatusDescriptor
);
912 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
916 if (m_TransferBufferLength
)
919 // FIXME: support more than one data descriptor
921 ASSERT(m_TransferBufferLength
< 8192);
924 // now create the data descriptor
926 Status
= CreateGeneralTransferDescriptor(&DataDescriptor
, 0);
927 if (!NT_SUCCESS(Status
))
930 // failed to create status descriptor
932 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
933 FreeDescriptor(SetupDescriptor
);
934 FreeDescriptor(StatusDescriptor
);
935 FreeDescriptor(LastDescriptor
);
940 // initialize data descriptor
942 DataDescriptor
->Flags
= 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
| OHCI_TD_DIRECTION_PID_IN
;
945 // store physical address of buffer
947 DataDescriptor
->BufferPhysical
= MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL
)).LowPart
;
948 DataDescriptor
->LastPhysicalByteAddress
= DataDescriptor
->BufferPhysical
+ m_TransferBufferLength
- 1;
953 // initialize setup descriptor
955 SetupDescriptor
->Flags
= 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
);
962 RtlCopyMemory(SetupDescriptor
->BufferLogical
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
967 // generate setup packet from urb
973 // initialize status descriptor
975 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
);
976 if (m_TransferBufferLength
== 0)
979 // input direction is flipped for the status descriptor
981 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
986 // output direction is flipped for the status descriptor
988 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_OUT
;
992 // now link the descriptors
994 if (m_TransferBufferLength
)
997 // link setup descriptor to data descriptor
999 SetupDescriptor
->NextPhysicalDescriptor
= DataDescriptor
->PhysicalAddress
.LowPart
;
1000 SetupDescriptor
->NextLogicalDescriptor
= DataDescriptor
;
1003 // link data descriptor to status descriptor
1004 // FIXME: check if there are more data descriptors
1006 DataDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1007 DataDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1010 // link status descriptor to last descriptor
1012 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1013 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1018 // link setup descriptor to status descriptor
1020 SetupDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1021 SetupDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1024 // link status descriptor to last descriptor
1026 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1027 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1031 // now link descriptor to endpoint
1033 EndpointDescriptor
->HeadPhysicalDescriptor
= SetupDescriptor
->PhysicalAddress
.LowPart
;
1034 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1035 EndpointDescriptor
->HeadLogicalDescriptor
= SetupDescriptor
;
1040 *OutEndpointDescriptor
= EndpointDescriptor
;
1045 return STATUS_SUCCESS
;
1048 //----------------------------------------------------------------------------------------
1050 CUSBRequest::GetEndpointDescriptor(
1051 struct _OHCI_ENDPOINT_DESCRIPTOR
** OutDescriptor
)
1057 // get transfer type
1059 TransferType
= InternalGetTransferType();
1062 // build request depending on type
1064 switch(TransferType
)
1066 case USB_ENDPOINT_TYPE_CONTROL
:
1067 Status
= BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1069 case USB_ENDPOINT_TYPE_BULK
:
1070 case USB_ENDPOINT_TYPE_INTERRUPT
:
1071 Status
= BuildBulkInterruptEndpoint(OutDescriptor
);
1073 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
1074 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
1075 Status
= STATUS_NOT_IMPLEMENTED
;
1079 Status
= STATUS_NOT_IMPLEMENTED
;
1083 if (NT_SUCCESS(Status
))
1088 //m_QueueHead = *OutDescriptor;
1091 // store request object
1093 (*OutDescriptor
)->Request
= PVOID(this);
1102 //----------------------------------------------------------------------------------------
1104 CUSBRequest::GetResultStatus(
1105 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1106 OUT OPTIONAL PULONG UrbStatusCode
)
1111 PC_ASSERT(m_CompletionEvent
);
1114 // wait for the operation to complete
1116 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1123 *NtStatusCode
= m_NtStatusCode
;
1131 *UrbStatusCode
= m_UrbStatusCode
;
1137 CUSBRequest::FreeEndpointDescriptor(
1138 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1140 POHCI_GENERAL_TD TransferDescriptor
, NextTransferDescriptor
;
1142 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1145 // get first general transfer descriptor
1147 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1150 // release endpoint descriptor
1152 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1154 while(TransferDescriptor
)
1159 NextTransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1162 // is there a buffer associated
1164 if (TransferDescriptor
->BufferSize
)
1169 m_DmaManager
->Release(TransferDescriptor
->BufferLogical
, TransferDescriptor
->BufferSize
);
1172 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor
, TransferDescriptor
->PhysicalAddress
.LowPart
, TransferDescriptor
->BufferPhysical
, TransferDescriptor
->LastPhysicalByteAddress
);
1175 // release descriptor
1177 m_DmaManager
->Release(TransferDescriptor
, sizeof(OHCI_GENERAL_TD
));
1182 TransferDescriptor
= NextTransferDescriptor
;
1188 CUSBRequest::CompletionCallback(
1189 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1191 POHCI_GENERAL_TD TransferDescriptor
, NextTransferDescriptor
;
1192 PIO_STACK_LOCATION IoStack
;
1195 DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1200 m_NtStatusCode
= STATUS_SUCCESS
;
1201 m_UrbStatusCode
= USBD_STATUS_SUCCESS
;
1206 // set irp completion status
1208 m_Irp
->IoStatus
.Status
= STATUS_SUCCESS
; //FIXME
1211 // get current irp stack location
1213 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1218 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1223 Urb
->UrbHeader
.Status
= USBD_STATUS_SUCCESS
; //FIXME
1226 // Check if the MDL was created
1228 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
1233 IoFreeMdl(m_TransferBufferMDL
);
1237 // FIXME: support status and calculate length
1241 // FIXME: check if the transfer was split
1242 // if yes dont complete irp yet
1244 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
1249 // signal completion event
1251 PC_ASSERT(m_CompletionEvent
);
1252 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
1257 //-----------------------------------------------------------------------------------------
1259 CUSBRequest::IsRequestInitialized()
1261 if (m_Irp
|| m_SetupPacket
)
1264 // request is initialized
1270 // request is not initialized
1275 //-----------------------------------------------------------------------------------------
1277 CUSBRequest::IsQueueHeadComplete(
1278 struct _QUEUE_HEAD
* QueueHead
)
1286 //-----------------------------------------------------------------------------------------
1288 InternalCreateUSBRequest(
1289 PUSBREQUEST
*OutRequest
)
1294 // allocate requests
1296 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBRequest(0);
1300 // failed to allocate
1302 return STATUS_INSUFFICIENT_RESOURCES
;
1306 // add reference count
1313 *OutRequest
= (PUSBREQUEST
)This
;
1318 return STATUS_SUCCESS
;