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 IOHCIRequest
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
43 ULONG
InternalGetTransferType();
44 UCHAR
InternalGetPidDirection();
45 UCHAR STDMETHODCALLTYPE
GetDeviceAddress();
46 NTSTATUS
BuildSetupPacket();
47 NTSTATUS
BuildSetupPacketFromURB();
48 NTSTATUS
BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
49 NTSTATUS
BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
50 NTSTATUS
BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
);
51 NTSTATUS
CreateGeneralTransferDescriptor(POHCI_GENERAL_TD
* OutDescriptor
, ULONG BufferSize
);
52 VOID
FreeDescriptor(POHCI_GENERAL_TD Descriptor
);
53 NTSTATUS
AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
);
54 NTSTATUS
CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD
*OutDescriptor
, ULONG FrameCount
);
55 UCHAR
GetEndpointAddress();
56 USHORT
GetMaxPacketSize();
57 VOID
CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
);
58 VOID
DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR
*Descriptor
);
59 NTSTATUS
BuildTransferDescriptorChain(IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, OUT POHCI_GENERAL_TD
* OutFirstDescriptor
, OUT POHCI_GENERAL_TD
* OutLastDescriptor
, OUT PULONG OutTransferBufferOffset
);
60 VOID
InitDescriptor(IN POHCI_GENERAL_TD CurrentDescriptor
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
);
63 // constructor / destructor
64 CUSBRequest(IUnknown
*OuterUnknown
){}
65 virtual ~CUSBRequest(){}
71 // memory manager for allocating setup packet / queue head / transfer descriptors
73 PDMAMEMORYMANAGER m_DmaManager
;
76 // caller provided irp packet containing URB request
81 // transfer buffer length
83 ULONG m_TransferBufferLength
;
86 // current transfer length
88 ULONG m_TransferBufferLengthCompleted
;
91 // Total Transfer Length
93 ULONG m_TotalBytesTransferred
;
96 // transfer buffer MDL
98 PMDL m_TransferBufferMDL
;
101 // caller provided setup packet
103 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
106 // completion event for callers who initialized request with setup packet
108 PKEVENT m_CompletionEvent
;
111 // device address for callers who initialized it with device address
113 UCHAR m_DeviceAddress
;
116 // store endpoint descriptor
118 PUSB_ENDPOINT m_EndpointDescriptor
;
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
;
135 USB_DEVICE_SPEED m_DeviceSpeed
;
148 //----------------------------------------------------------------------------------------
151 CUSBRequest::QueryInterface(
155 return STATUS_UNSUCCESSFUL
;
158 //----------------------------------------------------------------------------------------
161 CUSBRequest::InitializeWithSetupPacket(
162 IN PDMAMEMORYMANAGER DmaManager
,
163 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
164 IN PUSBDEVICE Device
,
165 IN OPTIONAL
struct _USB_ENDPOINT
* EndpointDescriptor
,
166 IN OUT ULONG TransferBufferLength
,
167 IN OUT PMDL TransferBuffer
)
172 PC_ASSERT(DmaManager
);
173 PC_ASSERT(SetupPacket
);
178 m_DmaManager
= DmaManager
;
179 m_SetupPacket
= SetupPacket
;
180 m_TransferBufferLength
= TransferBufferLength
;
181 m_TransferBufferMDL
= TransferBuffer
;
182 m_DeviceAddress
= Device
->GetDeviceAddress();
183 m_EndpointDescriptor
= EndpointDescriptor
;
184 m_TotalBytesTransferred
= 0;
185 m_DeviceSpeed
= Device
->GetSpeed();
188 // Set Length Completed to 0
190 m_TransferBufferLengthCompleted
= 0;
193 // allocate completion event
195 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBOHCI
);
196 if (!m_CompletionEvent
)
199 // failed to allocate completion event
201 return STATUS_INSUFFICIENT_RESOURCES
;
205 // initialize completion event
207 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
212 return STATUS_SUCCESS
;
214 //----------------------------------------------------------------------------------------
217 CUSBRequest::InitializeWithIrp(
218 IN PDMAMEMORYMANAGER DmaManager
,
219 IN
struct IUSBDevice
* Device
,
222 PIO_STACK_LOCATION IoStack
;
227 PC_ASSERT(DmaManager
);
230 m_DmaManager
= DmaManager
;
231 m_TotalBytesTransferred
= 0;
234 // get current irp stack location
236 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
241 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
242 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
243 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
248 m_Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
258 m_DeviceSpeed
= Device
->GetSpeed();
261 // check function type
263 switch (m_Urb
->UrbHeader
.Function
)
265 case URB_FUNCTION_ISOCH_TRANSFER
:
268 // there must be at least one packet
270 ASSERT(m_Urb
->UrbIsochronousTransfer
.NumberOfPackets
);
273 // is there data to be transferred
275 if (m_Urb
->UrbIsochronousTransfer
.TransferBufferLength
)
278 // Check if there is a MDL
280 if (!m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
285 PC_ASSERT(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
288 // Create one using TransferBuffer
290 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
291 m_TransferBufferMDL
= IoAllocateMdl(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
292 m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
297 if (!m_TransferBufferMDL
)
300 // failed to allocate mdl
302 return STATUS_INSUFFICIENT_RESOURCES
;
306 // build mdl for non paged pool
307 // FIXME: Does hub driver already do this when passing MDL?
309 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
316 m_TransferBufferMDL
= m_Urb
->UrbIsochronousTransfer
.TransferBufferMDL
;
321 // save buffer length
323 m_TransferBufferLength
= m_Urb
->UrbIsochronousTransfer
.TransferBufferLength
;
326 // Set Length Completed to 0
328 m_TransferBufferLengthCompleted
= 0;
331 // get endpoint descriptor
333 m_EndpointDescriptor
= (PUSB_ENDPOINT
)m_Urb
->UrbIsochronousTransfer
.PipeHandle
;
336 // completed initialization
341 // luckily those request have the same structure layout
343 case URB_FUNCTION_CLASS_INTERFACE
:
344 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
345 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
348 // bulk interrupt transfer
350 if (m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
353 // Check if there is a MDL
355 if (!m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
360 PC_ASSERT(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
363 // Create one using TransferBuffer
365 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
366 m_TransferBufferMDL
= IoAllocateMdl(m_Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
367 m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
372 if (!m_TransferBufferMDL
)
375 // failed to allocate mdl
377 return STATUS_INSUFFICIENT_RESOURCES
;
381 // build mdl for non paged pool
382 // FIXME: Does hub driver already do this when passing MDL?
384 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
387 // Keep that ehci created the MDL and needs to free it.
392 m_TransferBufferMDL
= m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
396 // save buffer length
398 m_TransferBufferLength
= m_Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
401 // Set Length Completed to 0
403 m_TransferBufferLengthCompleted
= 0;
406 // get endpoint descriptor
408 m_EndpointDescriptor
= (PUSB_ENDPOINT
)m_Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
414 DPRINT1("URB Function: not supported %x\n", m_Urb
->UrbHeader
.Function
);
421 return STATUS_SUCCESS
;
425 //----------------------------------------------------------------------------------------
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 //----------------------------------------------------------------------------------------
450 CUSBRequest::GetTransferType()
453 // call internal implementation
455 return InternalGetTransferType();
459 CUSBRequest::GetMaxPacketSize()
461 if (!m_EndpointDescriptor
)
463 if (m_DeviceSpeed
== UsbLowSpeed
)
466 // control pipes use 8 bytes packets
473 // must be full speed
475 ASSERT(m_DeviceSpeed
== UsbFullSpeed
);
481 ASSERT(m_EndpointDescriptor
);
484 // return max packet size
486 return m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
491 CUSBRequest::GetInterval()
493 ASSERT(m_EndpointDescriptor
);
494 ASSERT((m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
497 // return interrupt interval
499 return m_EndpointDescriptor
->EndPointDescriptor
.bInterval
;
503 CUSBRequest::GetEndpointAddress()
505 if (!m_EndpointDescriptor
)
514 ASSERT(m_EndpointDescriptor
);
517 // endpoint number is between 1-15
519 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0xF);
522 //----------------------------------------------------------------------------------------
524 CUSBRequest::InternalGetTransferType()
529 // check if an irp is provided
533 ASSERT(m_EndpointDescriptor
);
536 // end point is defined in the low byte of bmAttributes
538 TransferType
= (m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
543 // initialized with setup packet, must be a control transfer
545 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
555 CUSBRequest::InternalGetPidDirection()
557 if (m_EndpointDescriptor
)
560 // end point direction is highest bit in bEndpointAddress
562 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
567 // request arrives on the control pipe, extract direction from setup packet
569 ASSERT(m_SetupPacket
);
570 return (m_SetupPacket
->bmRequestType
.B
>> 7);
574 //----------------------------------------------------------------------------------------
577 CUSBRequest::GetDeviceAddress()
579 PIO_STACK_LOCATION IoStack
;
581 PUSBDEVICE UsbDevice
;
584 // check if there is an irp provided
589 // used provided address
591 return m_DeviceAddress
;
595 // get current stack location
597 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
602 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
605 // check if there is a pipe handle provided
607 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
610 // there is a device handle provided
612 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
615 // return device address
617 return UsbDevice
->GetDeviceAddress();
621 // no device handle provided, it is the host root bus
627 CUSBRequest::FreeDescriptor(
628 POHCI_GENERAL_TD Descriptor
)
630 if (Descriptor
->BufferSize
)
635 m_DmaManager
->Release(Descriptor
->BufferLogical
, Descriptor
->BufferSize
);
639 // release descriptor
641 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
645 //----------------------------------------------------------------------------------------
647 CUSBRequest::CreateIsochronousTransferDescriptor(
648 POHCI_ISO_TD
* OutDescriptor
,
651 POHCI_ISO_TD Descriptor
;
652 PHYSICAL_ADDRESS DescriptorAddress
;
656 // allocate transfer descriptor
658 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ISO_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
659 if (!NT_SUCCESS(Status
))
668 // initialize descriptor, hardware part
670 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);
671 Descriptor
->BufferPhysical
= 0;
672 Descriptor
->NextPhysicalDescriptor
= 0;
673 Descriptor
->LastPhysicalByteAddress
= 0;
678 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
679 Descriptor
->NextLogicalDescriptor
= 0;
684 *OutDescriptor
= Descriptor
;
689 return STATUS_SUCCESS
;
693 CUSBRequest::BuildIsochronousEndpoint(
694 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
696 POHCI_ISO_TD FirstDescriptor
= NULL
, PreviousDescriptor
= NULL
, CurrentDescriptor
= NULL
;
697 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
698 ULONG Index
= 0, SubIndex
, NumberOfPackets
, PageOffset
, Page
;
701 PIO_STACK_LOCATION IoStack
;
703 PHYSICAL_ADDRESS Address
;
706 // get current irp stack location
708 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
713 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
714 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
715 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
720 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
724 // allocate endpoint descriptor
726 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
727 if (!NT_SUCCESS(Status
))
730 // failed to create setup descriptor
739 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
743 // FIXME: support requests which spans several pages
745 ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL
), MmGetMdlByteCount(m_TransferBufferMDL
)) <= 2);
747 Status
= m_DmaManager
->Allocate(m_TransferBufferLength
, &Buffer
, &Address
);
748 ASSERT(Status
== STATUS_SUCCESS
);
751 while(Index
< Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
754 // get number of packets remaining
756 NumberOfPackets
= min(Urb
->UrbIsochronousTransfer
.NumberOfPackets
- Index
, OHCI_ITD_NOFFSET
);
758 // allocate iso descriptor
760 Status
= CreateIsochronousTransferDescriptor(&CurrentDescriptor
, NumberOfPackets
);
761 if (!NT_SUCCESS(Status
))
765 // failed to allocate descriptor
774 Page
= MmGetPhysicalAddress(Buffer
).LowPart
;
779 PageOffset
= BYTE_OFFSET(Page
);
782 // initialize descriptor
784 CurrentDescriptor
->BufferPhysical
= Page
- PageOffset
;
786 for(SubIndex
= 0; SubIndex
< NumberOfPackets
; SubIndex
++)
789 // store buffer offset
791 CurrentDescriptor
->Offset
[SubIndex
] = Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
+ PageOffset
;
792 DPRINT("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex
+Index
, Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
, CurrentDescriptor
->Offset
[SubIndex
]);
796 // increment packet offset
798 Index
+= NumberOfPackets
;
801 // check if this is the last descriptor
803 if (Index
== Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
808 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ m_TransferBufferLength
- 1;
813 // use start address of next packet - 1
815 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
- 1;
819 // is there a previous descriptor
821 if (PreviousDescriptor
)
826 PreviousDescriptor
->NextLogicalDescriptor
= CurrentDescriptor
;
827 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
834 FirstDescriptor
= CurrentDescriptor
;
838 // store as previous descriptor
840 PreviousDescriptor
= CurrentDescriptor
;
841 DPRINT("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor
, CurrentDescriptor
->PhysicalAddress
.LowPart
, CurrentDescriptor
->BufferPhysical
, CurrentDescriptor
->LastPhysicalByteAddress
);
844 // fire interrupt as soon transfer is finished
846 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
850 // clear interrupt mask for last transfer descriptor
852 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
855 // fire interrupt as soon transfer is finished
857 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
860 // set isochronous type
862 EndpointDescriptor
->Flags
|= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
;
865 // now link descriptor to endpoint
867 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
868 EndpointDescriptor
->TailPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
869 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
874 *OutEndpointDescriptor
= EndpointDescriptor
;
879 return STATUS_SUCCESS
;
882 //----------------------------------------------------------------------------------------
884 CUSBRequest::CreateGeneralTransferDescriptor(
885 POHCI_GENERAL_TD
* OutDescriptor
,
888 POHCI_GENERAL_TD Descriptor
;
889 PHYSICAL_ADDRESS DescriptorAddress
;
893 // allocate transfer descriptor
895 Status
= m_DmaManager
->Allocate(sizeof(OHCI_GENERAL_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
896 if (!NT_SUCCESS(Status
))
905 // initialize descriptor, hardware part
907 Descriptor
->Flags
= 0;
908 Descriptor
->BufferPhysical
= 0;
909 Descriptor
->NextPhysicalDescriptor
= 0;
910 Descriptor
->LastPhysicalByteAddress
= 0;
915 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
916 Descriptor
->BufferSize
= BufferSize
;
921 // allocate buffer from dma
923 Status
= m_DmaManager
->Allocate(BufferSize
, &Descriptor
->BufferLogical
, &DescriptorAddress
);
924 if (!NT_SUCCESS(Status
))
929 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
934 // set physical address of buffer
936 Descriptor
->BufferPhysical
= DescriptorAddress
.LowPart
;
937 Descriptor
->LastPhysicalByteAddress
= Descriptor
->BufferPhysical
+ BufferSize
- 1;
943 *OutDescriptor
= Descriptor
;
948 return STATUS_SUCCESS
;
952 CUSBRequest::AllocateEndpointDescriptor(
953 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
)
955 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
956 PHYSICAL_ADDRESS DescriptorAddress
;
960 // allocate descriptor
962 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
963 if (!NT_SUCCESS(Status
))
966 // failed to allocate descriptor
972 // initialize descriptor
974 Descriptor
->Flags
= OHCI_ENDPOINT_SKIP
;
977 // append device address and endpoint number
979 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
980 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
981 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
983 DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %lu\n", Descriptor
->Flags
, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
986 // is there an endpoint descriptor
988 if (m_EndpointDescriptor
)
993 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
998 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_OUT
;
1005 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_IN
;
1011 // get it from transfer descriptor
1013 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR
;
1019 if (m_DeviceSpeed
== UsbFullSpeed
)
1022 // device is full speed
1024 Descriptor
->Flags
|= OHCI_ENDPOINT_FULL_SPEED
;
1026 else if (m_DeviceSpeed
== UsbLowSpeed
)
1029 // device is full speed
1031 Descriptor
->Flags
|= OHCI_ENDPOINT_LOW_SPEED
;
1041 Descriptor
->HeadPhysicalDescriptor
= 0;
1042 Descriptor
->NextPhysicalEndpoint
= 0;
1043 Descriptor
->TailPhysicalDescriptor
= 0;
1044 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
1049 *OutDescriptor
= Descriptor
;
1054 return STATUS_SUCCESS
;
1058 CUSBRequest::InitDescriptor(
1059 IN POHCI_GENERAL_TD CurrentDescriptor
,
1060 IN PVOID TransferBuffer
,
1061 IN ULONG TransferBufferLength
,
1062 IN UCHAR PidDirection
)
1071 Direction
= OHCI_TD_DIRECTION_PID_IN
;
1078 Direction
= OHCI_TD_DIRECTION_PID_OUT
;
1083 // initialize descriptor
1085 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
;
1088 // store physical address of buffer
1090 CurrentDescriptor
->BufferPhysical
= MmGetPhysicalAddress(TransferBuffer
).LowPart
;
1091 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ TransferBufferLength
- 1;
1093 DPRINT("CurrentDescriptor %p Addr %x TransferBufferLength %lu\n", CurrentDescriptor
, CurrentDescriptor
->PhysicalAddress
.LowPart
, TransferBufferLength
);
1097 CUSBRequest::BuildTransferDescriptorChain(
1098 IN PVOID TransferBuffer
,
1099 IN ULONG TransferBufferLength
,
1100 IN UCHAR PidDirection
,
1101 OUT POHCI_GENERAL_TD
* OutFirstDescriptor
,
1102 OUT POHCI_GENERAL_TD
* OutLastDescriptor
,
1103 OUT PULONG OutTransferBufferOffset
)
1105 POHCI_GENERAL_TD FirstDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
= NULL
;
1107 ULONG MaxLengthInPage
, TransferBufferOffset
= 0;
1108 ULONG MaxPacketSize
= 0, TransferSize
, CurrentSize
;
1111 // for now use one page as maximum size
1113 MaxPacketSize
= PAGE_SIZE
;
1118 // allocate transfer descriptor
1120 Status
= CreateGeneralTransferDescriptor(&CurrentDescriptor
, 0);
1121 if (!NT_SUCCESS(Status
))
1124 // failed to allocate transfer descriptor
1126 return STATUS_INSUFFICIENT_RESOURCES
;
1132 // transfer size is minimum available buffer or endpoint size
1134 TransferSize
= min(TransferBufferLength
- TransferBufferOffset
, MaxPacketSize
);
1139 // use available buffer
1141 TransferSize
= TransferBufferLength
- TransferBufferOffset
;
1147 MaxLengthInPage
= PAGE_SIZE
- BYTE_OFFSET(TransferBuffer
);
1150 // get minimum from current page size
1152 CurrentSize
= min(TransferSize
, MaxLengthInPage
);
1153 ASSERT(CurrentSize
);
1156 // now init the descriptor
1158 InitDescriptor(CurrentDescriptor
,
1159 (PVOID
)((ULONG_PTR
)TransferBuffer
+ TransferBufferOffset
),
1166 TransferBufferOffset
+= CurrentSize
;
1169 // is there a previous descriptor
1176 LastDescriptor
->NextLogicalDescriptor
= (PVOID
)CurrentDescriptor
;
1177 LastDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
1182 // it is the first descriptor
1184 FirstDescriptor
= CurrentDescriptor
;
1187 if(TransferBufferLength
== TransferBufferOffset
)
1197 if (OutFirstDescriptor
)
1200 // store first descriptor
1202 *OutFirstDescriptor
= FirstDescriptor
;
1205 if (OutLastDescriptor
)
1208 // store last descriptor
1210 *OutLastDescriptor
= CurrentDescriptor
;
1213 if (OutTransferBufferOffset
)
1218 *OutTransferBufferOffset
= TransferBufferOffset
;
1224 return STATUS_SUCCESS
;
1229 CUSBRequest::BuildBulkInterruptEndpoint(
1230 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
1232 POHCI_GENERAL_TD FirstDescriptor
, LastDescriptor
;
1233 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1236 ULONG ChainDescriptorLength
;
1241 ASSERT(m_EndpointDescriptor
);
1244 // allocate endpoint descriptor
1246 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1247 if (!NT_SUCCESS(Status
))
1250 // failed to create setup descriptor
1255 ASSERT(m_TransferBufferMDL
);
1262 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1266 // Increase the size of last transfer, 0 in case this is the first
1268 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1273 ASSERT(m_EndpointDescriptor
);
1277 // use 2 * PAGE_SIZE at max for each new request
1279 ULONG MaxTransferLength
= min(1 * PAGE_SIZE
, m_TransferBufferLength
- m_TransferBufferLengthCompleted
);
1280 DPRINT("m_TransferBufferLength %lu m_TransferBufferLengthCompleted %lu DataToggle %x\n", m_TransferBufferLength
, m_TransferBufferLengthCompleted
, m_EndpointDescriptor
->DataToggle
);
1283 // build bulk transfer descriptor chain
1285 Status
= BuildTransferDescriptorChain(Base
,
1287 InternalGetPidDirection(),
1290 &ChainDescriptorLength
);
1291 if (!NT_SUCCESS(Status
))
1294 // failed to build transfer descriptor chain
1296 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1301 // move to next offset
1303 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1306 // first descriptor has no carry bit
1308 FirstDescriptor
->Flags
&= ~OHCI_TD_TOGGLE_CARRY
;
1311 // apply data toggle
1313 FirstDescriptor
->Flags
|= (m_EndpointDescriptor
->DataToggle
? OHCI_TD_TOGGLE_1
: OHCI_TD_TOGGLE_0
);
1316 // clear interrupt mask for last transfer descriptor
1318 LastDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
1322 // fire interrupt as soon transfer is finished
1324 LastDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
1327 // now link descriptor to endpoint
1329 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
1330 EndpointDescriptor
->TailPhysicalDescriptor
= (FirstDescriptor
== LastDescriptor
? 0 : LastDescriptor
->PhysicalAddress
.LowPart
);
1331 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
1334 // dump descriptor list
1336 //DumpEndpointDescriptor(EndpointDescriptor);
1341 *OutEndpointDescriptor
= EndpointDescriptor
;
1346 return STATUS_SUCCESS
;
1350 CUSBRequest::DumpEndpointDescriptor(
1351 POHCI_ENDPOINT_DESCRIPTOR Descriptor
)
1354 POHCI_GENERAL_TD GeneralDescriptor
;
1356 DPRINT1("EndpointDescriptor %p Addr %x\n", Descriptor
, Descriptor
->PhysicalAddress
.LowPart
);
1357 DPRINT1("EndpointDescriptor HeadPhysicalDescriptor %x HeadLogicalDescriptor %p\n", Descriptor
->HeadPhysicalDescriptor
, Descriptor
->HeadLogicalDescriptor
);
1358 DPRINT1("EndpointDescriptor TailPhysicalDescriptor %x\n", Descriptor
->TailPhysicalDescriptor
);
1359 DPRINT1("EndpointDescriptor NextDescriptor %p\n", Descriptor
->NextDescriptor
);
1360 DPRINT1("EndpointDescriptor NextPhysicalEndpoint %x\n", Descriptor
->NextPhysicalEndpoint
);
1361 DPRINT1("EndpointDescriptor Flags %x\n", Descriptor
->Flags
);
1364 GeneralDescriptor
= (POHCI_GENERAL_TD
)Descriptor
->HeadLogicalDescriptor
;
1365 while(GeneralDescriptor
)
1367 DPRINT1("Descriptor %lu Address %p Addr %x\n", Count
, GeneralDescriptor
, GeneralDescriptor
->PhysicalAddress
);
1368 DPRINT1("Descriptor %lu BufferLogical %p BufferPhysical %x\n", Count
, GeneralDescriptor
->BufferLogical
, GeneralDescriptor
->BufferPhysical
);
1369 DPRINT1("Descriptor %lu BufferSize %lu\n", Count
, GeneralDescriptor
->BufferSize
);
1370 DPRINT1("Descriptor %lu LastPhysicalByteAddress %x\n", Count
, GeneralDescriptor
->LastPhysicalByteAddress
);
1371 DPRINT1("Descriptor %lu Flags %x\n", Count
, GeneralDescriptor
->Flags
);
1372 DPRINT1("Descriptor %lu NextLogicalDescriptor %p NextPhysicalDescriptor %x\n", Count
, GeneralDescriptor
->NextLogicalDescriptor
, GeneralDescriptor
->NextPhysicalDescriptor
);
1375 GeneralDescriptor
= (POHCI_GENERAL_TD
)GeneralDescriptor
->NextLogicalDescriptor
;
1380 CUSBRequest::BuildControlTransferDescriptor(
1381 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
1383 POHCI_GENERAL_TD SetupDescriptor
, StatusDescriptor
, DataDescriptor
= NULL
, LastDescriptor
;
1384 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1388 // allocate endpoint descriptor
1390 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1391 if (!NT_SUCCESS(Status
))
1394 // failed to create setup descriptor
1400 // first allocate setup descriptor
1402 Status
= CreateGeneralTransferDescriptor(&SetupDescriptor
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1403 if (!NT_SUCCESS(Status
))
1406 // failed to create setup descriptor
1408 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1413 // now create the status descriptor
1415 Status
= CreateGeneralTransferDescriptor(&StatusDescriptor
, 0);
1416 if (!NT_SUCCESS(Status
))
1419 // failed to create status descriptor
1421 FreeDescriptor(SetupDescriptor
);
1422 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1427 // finally create the last descriptor
1429 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
1430 if (!NT_SUCCESS(Status
))
1433 // failed to create status descriptor
1435 FreeDescriptor(SetupDescriptor
);
1436 FreeDescriptor(StatusDescriptor
);
1437 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1442 // initialize setup descriptor
1444 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
);
1447 // initialize status descriptor
1449 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
);
1454 // copy setup packet
1456 RtlCopyMemory(SetupDescriptor
->BufferLogical
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1461 // generate setup packet from urb
1466 if (m_TransferBufferLength
)
1469 // FIXME: support more than one data descriptor
1471 ASSERT(m_TransferBufferLength
< 8192);
1474 // now create the data descriptor
1476 Status
= CreateGeneralTransferDescriptor(&DataDescriptor
, 0);
1477 if (!NT_SUCCESS(Status
))
1480 // failed to create status descriptor
1482 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1483 FreeDescriptor(SetupDescriptor
);
1484 FreeDescriptor(StatusDescriptor
);
1489 // initialize data descriptor
1491 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
;
1494 // setup pid direction
1496 DataDescriptor
->Flags
|= InternalGetPidDirection() == TRUE
? OHCI_TD_DIRECTION_PID_IN
: OHCI_TD_DIRECTION_PID_OUT
;
1499 // use short packets
1501 DataDescriptor
->Flags
|= OHCI_TD_BUFFER_ROUNDING
;
1504 // store physical address of buffer
1506 DataDescriptor
->BufferPhysical
= MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL
)).LowPart
;
1507 DataDescriptor
->LastPhysicalByteAddress
= DataDescriptor
->BufferPhysical
+ m_TransferBufferLength
- 1;
1510 // flip status pid direction
1512 StatusDescriptor
->Flags
|= InternalGetPidDirection() == TRUE
? OHCI_TD_DIRECTION_PID_OUT
: OHCI_TD_DIRECTION_PID_IN
;
1515 // link setup descriptor to data descriptor
1517 SetupDescriptor
->NextPhysicalDescriptor
= DataDescriptor
->PhysicalAddress
.LowPart
;
1518 SetupDescriptor
->NextLogicalDescriptor
= DataDescriptor
;
1521 // link data descriptor to status descriptor
1522 // FIXME: check if there are more data descriptors
1524 DataDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1525 DataDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1528 // link status descriptor to last descriptor
1530 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1531 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1536 // status descriptor is always in
1538 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1541 // link setup descriptor to status descriptor
1543 SetupDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1544 SetupDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1546 // link status descriptor to last descriptor
1548 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1549 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1553 // now link descriptor to endpoint
1555 EndpointDescriptor
->HeadPhysicalDescriptor
= SetupDescriptor
->PhysicalAddress
.LowPart
;
1556 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1557 EndpointDescriptor
->HeadLogicalDescriptor
= SetupDescriptor
;
1562 *OutEndpointDescriptor
= EndpointDescriptor
;
1567 //DumpEndpointDescriptor(EndpointDescriptor);
1572 return STATUS_SUCCESS
;
1575 //----------------------------------------------------------------------------------------
1578 CUSBRequest::GetEndpointDescriptor(
1579 struct _OHCI_ENDPOINT_DESCRIPTOR
** OutDescriptor
)
1586 // get transfer type
1588 TransferType
= InternalGetTransferType();
1591 // build request depending on type
1593 switch(TransferType
)
1595 case USB_ENDPOINT_TYPE_CONTROL
:
1596 Status
= BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1598 case USB_ENDPOINT_TYPE_BULK
:
1599 case USB_ENDPOINT_TYPE_INTERRUPT
:
1600 Status
= BuildBulkInterruptEndpoint(OutDescriptor
);
1602 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
1603 Status
= BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1607 Status
= STATUS_NOT_IMPLEMENTED
;
1613 if (NT_SUCCESS(Status
))
1618 //m_QueueHead = *OutDescriptor;
1621 // store request object
1623 (*OutDescriptor
)->Request
= PVOID(this);
1632 //----------------------------------------------------------------------------------------
1635 CUSBRequest::GetResultStatus(
1636 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1637 OUT OPTIONAL PULONG UrbStatusCode
)
1642 PC_ASSERT(m_CompletionEvent
);
1645 // wait for the operation to complete
1647 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1654 *NtStatusCode
= m_NtStatusCode
;
1662 *UrbStatusCode
= m_UrbStatusCode
;
1669 CUSBRequest::FreeEndpointDescriptor(
1670 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1672 POHCI_GENERAL_TD TransferDescriptor
, NextTransferDescriptor
;
1673 POHCI_ISO_TD IsoTransferDescriptor
, IsoNextTransferDescriptor
;
1674 ULONG Index
, PacketCount
;
1676 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1681 CheckError(OutDescriptor
);
1684 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1687 // get first iso transfer descriptor
1689 IsoTransferDescriptor
= (POHCI_ISO_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1692 // release endpoint descriptor
1694 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1696 while(IsoTransferDescriptor
)
1701 IsoNextTransferDescriptor
= IsoTransferDescriptor
->NextLogicalDescriptor
;
1706 PacketCount
= OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor
->Flags
);
1708 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor
, IsoTransferDescriptor
->PhysicalAddress
.LowPart
, IsoTransferDescriptor
->BufferPhysical
, IsoTransferDescriptor
->LastPhysicalByteAddress
, PacketCount
);
1710 for(Index
= 0; Index
< PacketCount
; Index
++)
1712 DPRINT("PSW Index %lu Value %x\n", Index
, IsoTransferDescriptor
->Offset
[Index
]);
1716 // release descriptor
1718 m_DmaManager
->Release(IsoTransferDescriptor
, sizeof(OHCI_ISO_TD
));
1723 IsoTransferDescriptor
= IsoNextTransferDescriptor
;
1729 // get first general transfer descriptor
1731 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1734 // release endpoint descriptor
1736 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1738 while(TransferDescriptor
)
1743 NextTransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1746 // is there a buffer associated
1748 if (TransferDescriptor
->BufferSize
)
1753 m_DmaManager
->Release(TransferDescriptor
->BufferLogical
, TransferDescriptor
->BufferSize
);
1756 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor
, TransferDescriptor
->PhysicalAddress
.LowPart
, TransferDescriptor
->BufferPhysical
, TransferDescriptor
->LastPhysicalByteAddress
);
1759 // release descriptor
1761 m_DmaManager
->Release(TransferDescriptor
, sizeof(OHCI_GENERAL_TD
));
1766 TransferDescriptor
= NextTransferDescriptor
;
1773 CUSBRequest::CheckError(
1774 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1776 POHCI_GENERAL_TD TransferDescriptor
;
1777 ULONG ConditionCode
;
1779 PIO_STACK_LOCATION IoStack
;
1785 m_NtStatusCode
= STATUS_SUCCESS
;
1786 m_UrbStatusCode
= USBD_STATUS_SUCCESS
;
1789 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1792 // FIXME: handle isochronous support
1799 // get first general transfer descriptor
1801 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1803 if (m_EndpointDescriptor
!= NULL
)
1806 // update data toggle
1808 m_EndpointDescriptor
->DataToggle
= (OutDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_TOGGLE_CARRY
);
1811 while(TransferDescriptor
)
1814 // get condition code
1816 ConditionCode
= OHCI_TD_GET_CONDITION_CODE(TransferDescriptor
->Flags
);
1817 if (ConditionCode
!= OHCI_TD_CONDITION_NO_ERROR
)
1820 // FIXME status code
1822 m_NtStatusCode
= STATUS_UNSUCCESSFUL
;
1824 switch(ConditionCode
)
1826 case OHCI_TD_CONDITION_CRC_ERROR
:
1827 DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1828 m_UrbStatusCode
= USBD_STATUS_CRC
;
1830 case OHCI_TD_CONDITION_BIT_STUFFING
:
1831 DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1832 m_UrbStatusCode
= USBD_STATUS_BTSTUFF
;
1834 case OHCI_TD_CONDITION_TOGGLE_MISMATCH
:
1835 DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1836 m_UrbStatusCode
= USBD_STATUS_DATA_TOGGLE_MISMATCH
;
1838 case OHCI_TD_CONDITION_STALL
:
1839 DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1840 m_UrbStatusCode
= USBD_STATUS_STALL_PID
;
1842 case OHCI_TD_CONDITION_NO_RESPONSE
:
1843 DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1844 m_UrbStatusCode
= USBD_STATUS_DEV_NOT_RESPONDING
;
1846 case OHCI_TD_CONDITION_PID_CHECK_FAILURE
:
1847 DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1848 m_UrbStatusCode
= USBD_STATUS_PID_CHECK_FAILURE
;
1850 case OHCI_TD_CONDITION_UNEXPECTED_PID
:
1851 DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1852 m_UrbStatusCode
= USBD_STATUS_UNEXPECTED_PID
;
1854 case OHCI_TD_CONDITION_DATA_OVERRUN
:
1855 DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1856 m_UrbStatusCode
= USBD_STATUS_DATA_OVERRUN
;
1858 case OHCI_TD_CONDITION_DATA_UNDERRUN
:
1862 // get current irp stack location
1864 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1869 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1871 if(Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1874 // short packets are ok
1876 ASSERT(Urb
->UrbHeader
.Function
== URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
);
1877 m_NtStatusCode
= STATUS_SUCCESS
;
1881 DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1882 m_UrbStatusCode
= USBD_STATUS_DATA_UNDERRUN
;
1884 case OHCI_TD_CONDITION_BUFFER_OVERRUN
:
1885 DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1886 m_UrbStatusCode
= USBD_STATUS_BUFFER_OVERRUN
;
1888 case OHCI_TD_CONDITION_BUFFER_UNDERRUN
:
1889 DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1890 m_UrbStatusCode
= USBD_STATUS_BUFFER_UNDERRUN
;
1898 TransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1905 CUSBRequest::CompletionCallback()
1907 PIO_STACK_LOCATION IoStack
;
1910 DPRINT("CUSBRequest::CompletionCallback\n");
1915 // set irp completion status
1917 m_Irp
->IoStatus
.Status
= m_NtStatusCode
;
1920 // get current irp stack location
1922 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1927 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1932 Urb
->UrbHeader
.Status
= m_UrbStatusCode
;
1935 // Check if the MDL was created
1937 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
1942 IoFreeMdl(m_TransferBufferMDL
);
1946 // FIXME calculate length
1952 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
1957 // signal completion event
1959 PC_ASSERT(m_CompletionEvent
);
1960 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
1964 //-----------------------------------------------------------------------------------------
1967 InternalCreateUSBRequest(
1968 PUSBREQUEST
*OutRequest
)
1973 // allocate requests
1975 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBRequest(0);
1979 // failed to allocate
1981 return STATUS_INSUFFICIENT_RESOURCES
;
1985 // add reference count
1992 *OutRequest
= (PUSBREQUEST
)This
;
1997 return STATUS_SUCCESS
;