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
);
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
;
141 //----------------------------------------------------------------------------------------
144 CUSBRequest::QueryInterface(
148 return STATUS_UNSUCCESSFUL
;
151 //----------------------------------------------------------------------------------------
153 CUSBRequest::InitializeWithSetupPacket(
154 IN PDMAMEMORYMANAGER DmaManager
,
155 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
156 IN UCHAR DeviceAddress
,
157 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
158 IN OUT ULONG TransferBufferLength
,
159 IN OUT PMDL TransferBuffer
)
164 PC_ASSERT(DmaManager
);
165 PC_ASSERT(SetupPacket
);
170 m_DmaManager
= DmaManager
;
171 m_SetupPacket
= SetupPacket
;
172 m_TransferBufferLength
= TransferBufferLength
;
173 m_TransferBufferMDL
= TransferBuffer
;
174 m_DeviceAddress
= DeviceAddress
;
175 m_EndpointDescriptor
= EndpointDescriptor
;
176 m_TotalBytesTransferred
= 0;
179 // Set Length Completed to 0
181 m_TransferBufferLengthCompleted
= 0;
184 // allocate completion event
186 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBOHCI
);
187 if (!m_CompletionEvent
)
190 // failed to allocate completion event
192 return STATUS_INSUFFICIENT_RESOURCES
;
196 // initialize completion event
198 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
203 return STATUS_SUCCESS
;
205 //----------------------------------------------------------------------------------------
207 CUSBRequest::InitializeWithIrp(
208 IN PDMAMEMORYMANAGER DmaManager
,
211 PIO_STACK_LOCATION IoStack
;
217 PC_ASSERT(DmaManager
);
220 m_DmaManager
= DmaManager
;
221 m_TotalBytesTransferred
= 0;
224 // get current irp stack location
226 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
231 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
232 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
233 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
238 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
246 // check function type
248 switch (Urb
->UrbHeader
.Function
)
250 case URB_FUNCTION_ISOCH_TRANSFER
:
253 // there must be at least one packet
255 ASSERT(Urb
->UrbIsochronousTransfer
.NumberOfPackets
);
258 // is there data to be transferred
260 if (Urb
->UrbIsochronousTransfer
.TransferBufferLength
)
263 // Check if there is a MDL
265 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
270 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
273 // Create one using TransferBuffer
275 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
276 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
277 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
282 if (!m_TransferBufferMDL
)
285 // failed to allocate mdl
287 return STATUS_INSUFFICIENT_RESOURCES
;
291 // build mdl for non paged pool
292 // FIXME: Does hub driver already do this when passing MDL?
294 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
301 m_TransferBufferMDL
= Urb
->UrbIsochronousTransfer
.TransferBufferMDL
;
306 // save buffer length
308 m_TransferBufferLength
= Urb
->UrbIsochronousTransfer
.TransferBufferLength
;
311 // Set Length Completed to 0
313 m_TransferBufferLengthCompleted
= 0;
316 // get endpoint descriptor
318 m_EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
321 // completed initialization
326 // luckily those request have the same structure layout
328 case URB_FUNCTION_CLASS_INTERFACE
:
329 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
330 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
333 // bulk interrupt transfer
335 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
338 // Check if there is a MDL
340 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
345 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
348 // Create one using TransferBuffer
350 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
351 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
352 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
357 if (!m_TransferBufferMDL
)
360 // failed to allocate mdl
362 return STATUS_INSUFFICIENT_RESOURCES
;
366 // build mdl for non paged pool
367 // FIXME: Does hub driver already do this when passing MDL?
369 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
372 // Keep that ehci created the MDL and needs to free it.
377 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
381 // save buffer length
383 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
386 // Set Length Completed to 0
388 m_TransferBufferLengthCompleted
= 0;
391 // get endpoint descriptor
393 m_EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
399 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
406 return STATUS_SUCCESS
;
410 //----------------------------------------------------------------------------------------
412 CUSBRequest::IsRequestComplete()
415 // FIXME: check if request was split
419 // Check if the transfer was completed, only valid for Bulk Transfers
421 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
422 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
425 // Transfer not completed
431 //----------------------------------------------------------------------------------------
433 CUSBRequest::GetTransferType()
436 // call internal implementation
438 return InternalGetTransferType();
442 CUSBRequest::GetMaxPacketSize()
444 if (!m_EndpointDescriptor
)
453 ASSERT(m_EndpointDescriptor
);
456 // return max packet size
458 return m_EndpointDescriptor
->wMaxPacketSize
;
462 CUSBRequest::GetInterval()
464 ASSERT(m_EndpointDescriptor
);
465 ASSERT((m_EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
468 // return interrupt interval
470 return m_EndpointDescriptor
->bInterval
;
474 CUSBRequest::GetEndpointAddress()
476 if (!m_EndpointDescriptor
)
485 ASSERT(m_EndpointDescriptor
);
488 // endpoint number is between 1-15
490 return (m_EndpointDescriptor
->bEndpointAddress
& 0xF);
493 //----------------------------------------------------------------------------------------
495 CUSBRequest::InternalGetTransferType()
500 // check if an irp is provided
504 ASSERT(m_EndpointDescriptor
);
507 // end point is defined in the low byte of bmAttributes
509 TransferType
= (m_EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
514 // initialized with setup packet, must be a control transfer
516 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
526 CUSBRequest::InternalGetPidDirection()
529 ASSERT(m_EndpointDescriptor
);
532 // end point is defined in the low byte of bEndpointAddress
534 return (m_EndpointDescriptor
->bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
538 //----------------------------------------------------------------------------------------
540 CUSBRequest::GetDeviceAddress()
542 PIO_STACK_LOCATION IoStack
;
544 PUSBDEVICE UsbDevice
;
547 // check if there is an irp provided
552 // used provided address
554 return m_DeviceAddress
;
558 // get current stack location
560 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
565 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
568 // check if there is a pipe handle provided
570 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
573 // there is a device handle provided
575 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
578 // return device address
580 return UsbDevice
->GetDeviceAddress();
584 // no device handle provided, it is the host root bus
590 CUSBRequest::FreeDescriptor(
591 POHCI_GENERAL_TD Descriptor
)
593 if (Descriptor
->BufferSize
)
598 m_DmaManager
->Release(Descriptor
->BufferLogical
, Descriptor
->BufferSize
);
602 // release descriptor
604 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
608 //----------------------------------------------------------------------------------------
610 CUSBRequest::CreateIsochronousTransferDescriptor(
611 POHCI_ISO_TD
* OutDescriptor
,
614 POHCI_ISO_TD Descriptor
;
615 PHYSICAL_ADDRESS DescriptorAddress
;
619 // allocate transfer descriptor
621 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ISO_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
622 if (!NT_SUCCESS(Status
))
631 // initialize descriptor, hardware part
633 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);
634 Descriptor
->BufferPhysical
= 0;
635 Descriptor
->NextPhysicalDescriptor
= 0;
636 Descriptor
->LastPhysicalByteAddress
= 0;
641 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
642 Descriptor
->NextLogicalDescriptor
= 0;
647 *OutDescriptor
= Descriptor
;
652 return STATUS_SUCCESS
;
656 CUSBRequest::BuildIsochronousEndpoint(
657 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
659 POHCI_ISO_TD FirstDescriptor
= NULL
, PreviousDescriptor
= NULL
, CurrentDescriptor
= NULL
;
660 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
661 ULONG Index
= 0, SubIndex
, NumberOfPackets
, PageOffset
, Page
;
664 PIO_STACK_LOCATION IoStack
;
666 PHYSICAL_ADDRESS Address
;
669 // get current irp stack location
671 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
676 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
677 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
678 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
683 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
687 // allocate endpoint descriptor
689 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
690 if (!NT_SUCCESS(Status
))
693 // failed to create setup descriptor
702 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
706 // FIXME: support requests which spans serveral pages
708 ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL
), MmGetMdlByteCount(m_TransferBufferMDL
)) <= 2);
710 Status
= m_DmaManager
->Allocate(m_TransferBufferLength
, &Buffer
, &Address
);
711 ASSERT(Status
== STATUS_SUCCESS
);
714 while(Index
< Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
717 // get number of packets remaining
719 NumberOfPackets
= min(Urb
->UrbIsochronousTransfer
.NumberOfPackets
- Index
, OHCI_ITD_NOFFSET
);
721 // allocate iso descriptor
723 Status
= CreateIsochronousTransferDescriptor(&CurrentDescriptor
, NumberOfPackets
);
724 if (!NT_SUCCESS(Status
))
728 // failed to allocate descriptor
737 Page
= MmGetPhysicalAddress(Buffer
).LowPart
;
742 PageOffset
= BYTE_OFFSET(Page
);
745 // initialize descriptor
747 CurrentDescriptor
->BufferPhysical
= Page
- PageOffset
;
749 for(SubIndex
= 0; SubIndex
< NumberOfPackets
; SubIndex
++)
752 // store buffer offset
754 CurrentDescriptor
->Offset
[SubIndex
] = Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
+ PageOffset
;
755 DPRINT1("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex
+Index
, Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
+SubIndex
].Offset
, CurrentDescriptor
->Offset
[SubIndex
]);
759 // increment packet offset
761 Index
+= NumberOfPackets
;
764 // check if this is the last descriptor
766 if (Index
== Urb
->UrbIsochronousTransfer
.NumberOfPackets
)
771 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ m_TransferBufferLength
- 1;
776 // use start address of next packet - 1
778 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ PageOffset
+ Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
- 1;
782 // is there a previous descriptor
784 if (PreviousDescriptor
)
789 PreviousDescriptor
->NextLogicalDescriptor
= CurrentDescriptor
;
790 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
797 FirstDescriptor
= CurrentDescriptor
;
801 // store as previous descriptor
803 PreviousDescriptor
= CurrentDescriptor
;
804 DPRINT1("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor
, CurrentDescriptor
->PhysicalAddress
.LowPart
, CurrentDescriptor
->BufferPhysical
, CurrentDescriptor
->LastPhysicalByteAddress
);
807 // fire interrupt as soon transfer is finished
809 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
813 // clear interrupt mask for last transfer descriptor
815 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
818 // fire interrupt as soon transfer is finished
820 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
823 // set isochronous type
825 EndpointDescriptor
->Flags
|= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
;
828 // now link descriptor to endpoint
830 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
831 EndpointDescriptor
->TailPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
832 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
837 *OutEndpointDescriptor
= EndpointDescriptor
;
842 return STATUS_SUCCESS
;
845 //----------------------------------------------------------------------------------------
847 CUSBRequest::CreateGeneralTransferDescriptor(
848 POHCI_GENERAL_TD
* OutDescriptor
,
851 POHCI_GENERAL_TD Descriptor
;
852 PHYSICAL_ADDRESS DescriptorAddress
;
856 // allocate transfer descriptor
858 Status
= m_DmaManager
->Allocate(sizeof(OHCI_GENERAL_TD
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
859 if (!NT_SUCCESS(Status
))
868 // initialize descriptor, hardware part
870 Descriptor
->Flags
= 0;
871 Descriptor
->BufferPhysical
= 0;
872 Descriptor
->NextPhysicalDescriptor
= 0;
873 Descriptor
->LastPhysicalByteAddress
= 0;
878 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
879 Descriptor
->BufferSize
= BufferSize
;
884 // allocate buffer from dma
886 Status
= m_DmaManager
->Allocate(BufferSize
, &Descriptor
->BufferLogical
, &DescriptorAddress
);
887 if (!NT_SUCCESS(Status
))
892 m_DmaManager
->Release(Descriptor
, sizeof(OHCI_GENERAL_TD
));
897 // set physical address of buffer
899 Descriptor
->BufferPhysical
= DescriptorAddress
.LowPart
;
900 Descriptor
->LastPhysicalByteAddress
= Descriptor
->BufferPhysical
+ BufferSize
- 1;
906 *OutDescriptor
= Descriptor
;
911 return STATUS_SUCCESS
;
915 CUSBRequest::AllocateEndpointDescriptor(
916 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
)
918 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
919 PHYSICAL_ADDRESS DescriptorAddress
;
923 // allocate descriptor
925 Status
= m_DmaManager
->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
926 if (!NT_SUCCESS(Status
))
929 // failed to allocate descriptor
935 // intialize descriptor
937 Descriptor
->Flags
= OHCI_ENDPOINT_SKIP
;
940 // append device address and endpoint number
942 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
943 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
944 Descriptor
->Flags
|= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
946 DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor
->Flags
, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
949 // is there an endpoint descriptor
951 if (m_EndpointDescriptor
)
956 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->bEndpointAddress
))
961 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_OUT
;
968 Descriptor
->Flags
|= OHCI_ENDPOINT_DIRECTION_IN
;
974 // FIXME: detect type
976 Descriptor
->Flags
|= OHCI_ENDPOINT_FULL_SPEED
;
978 Descriptor
->HeadPhysicalDescriptor
= 0;
979 Descriptor
->NextPhysicalEndpoint
= 0;
980 Descriptor
->TailPhysicalDescriptor
= 0;
981 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
986 *OutDescriptor
= Descriptor
;
991 return STATUS_SUCCESS
;
995 CUSBRequest::BuildBulkInterruptEndpoint(
996 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
998 POHCI_GENERAL_TD FirstDescriptor
, PreviousDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
;
999 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1000 ULONG BufferSize
, CurrentSize
, Direction
, MaxLengthInPage
;
1005 // allocate endpoint descriptor
1007 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1008 if (!NT_SUCCESS(Status
))
1011 // failed to create setup descriptor
1017 // allocate transfer descriptor for last descriptor
1019 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
1020 if (!NT_SUCCESS(Status
))
1023 // failed to create transfer descriptor
1025 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1032 BufferSize
= m_TransferBufferLength
;
1034 ASSERT(m_TransferBufferMDL
);
1039 Buffer
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1042 if (InternalGetPidDirection())
1047 Direction
= OHCI_TD_DIRECTION_PID_IN
;
1054 Direction
= OHCI_TD_DIRECTION_PID_OUT
;
1060 // get current buffersize
1062 CurrentSize
= min(8192, BufferSize
);
1067 MaxLengthInPage
= PAGE_SIZE
- BYTE_OFFSET(Buffer
);
1070 // get minimum from current page size
1072 CurrentSize
= min(CurrentSize
, MaxLengthInPage
);
1073 ASSERT(CurrentSize
);
1076 // allocate transfer descriptor
1078 Status
= CreateGeneralTransferDescriptor(&CurrentDescriptor
, 0);
1079 if (!NT_SUCCESS(Status
))
1082 // failed to create transfer descriptor
1086 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1087 FreeDescriptor(LastDescriptor
);
1092 // initialize descriptor
1094 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
;
1097 // store physical address of buffer
1099 CurrentDescriptor
->BufferPhysical
= MmGetPhysicalAddress(Buffer
).LowPart
;
1100 CurrentDescriptor
->LastPhysicalByteAddress
= CurrentDescriptor
->BufferPhysical
+ CurrentSize
- 1;
1103 // is there a previous descriptor
1105 if (PreviousDescriptor
)
1110 PreviousDescriptor
->NextLogicalDescriptor
= (PVOID
)CurrentDescriptor
;
1111 PreviousDescriptor
->NextPhysicalDescriptor
= CurrentDescriptor
->PhysicalAddress
.LowPart
;
1116 // it is the first descriptor
1118 FirstDescriptor
= CurrentDescriptor
;
1121 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
);
1124 // set previous descriptor
1126 PreviousDescriptor
= CurrentDescriptor
;
1129 // subtract buffer size
1131 BufferSize
-= CurrentSize
;
1134 // increment buffer offset
1136 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
1141 // first descriptor has no carry bit
1143 FirstDescriptor
->Flags
&= ~OHCI_TD_TOGGLE_CARRY
;
1148 FirstDescriptor
->Flags
|= OHCI_TD_TOGGLE_0
;
1151 // clear interrupt mask for last transfer descriptor
1153 CurrentDescriptor
->Flags
&= ~OHCI_TD_INTERRUPT_MASK
;
1156 // fire interrupt as soon transfer is finished
1158 CurrentDescriptor
->Flags
|= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE
);
1161 // link last data descriptor to last descriptor
1163 CurrentDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1164 CurrentDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1167 // now link descriptor to endpoint
1169 EndpointDescriptor
->HeadPhysicalDescriptor
= FirstDescriptor
->PhysicalAddress
.LowPart
;
1170 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1171 EndpointDescriptor
->HeadLogicalDescriptor
= FirstDescriptor
;
1176 *OutEndpointDescriptor
= EndpointDescriptor
;
1181 return STATUS_SUCCESS
;
1186 CUSBRequest::BuildControlTransferDescriptor(
1187 POHCI_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
1189 POHCI_GENERAL_TD SetupDescriptor
, StatusDescriptor
, DataDescriptor
= NULL
, LastDescriptor
;
1190 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1194 // allocate endpoint descriptor
1196 Status
= AllocateEndpointDescriptor(&EndpointDescriptor
);
1197 if (!NT_SUCCESS(Status
))
1200 // failed to create setup descriptor
1206 // first allocate setup descriptor
1208 Status
= CreateGeneralTransferDescriptor(&SetupDescriptor
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1209 if (!NT_SUCCESS(Status
))
1212 // failed to create setup descriptor
1214 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1219 // now create the status descriptor
1221 Status
= CreateGeneralTransferDescriptor(&StatusDescriptor
, 0);
1222 if (!NT_SUCCESS(Status
))
1225 // failed to create status descriptor
1227 FreeDescriptor(SetupDescriptor
);
1228 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1233 // finally create the last descriptor
1235 Status
= CreateGeneralTransferDescriptor(&LastDescriptor
, 0);
1236 if (!NT_SUCCESS(Status
))
1239 // failed to create status descriptor
1241 FreeDescriptor(SetupDescriptor
);
1242 FreeDescriptor(StatusDescriptor
);
1243 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1247 if (m_TransferBufferLength
)
1250 // FIXME: support more than one data descriptor
1252 ASSERT(m_TransferBufferLength
< 8192);
1255 // now create the data descriptor
1257 Status
= CreateGeneralTransferDescriptor(&DataDescriptor
, 0);
1258 if (!NT_SUCCESS(Status
))
1261 // failed to create status descriptor
1263 m_DmaManager
->Release(EndpointDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1264 FreeDescriptor(SetupDescriptor
);
1265 FreeDescriptor(StatusDescriptor
);
1266 FreeDescriptor(LastDescriptor
);
1271 // initialize data descriptor
1273 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
;
1275 if (m_EndpointDescriptor
)
1277 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor
->bEndpointAddress
))
1282 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_OUT
;
1289 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1295 // no end point address provided - assume its an in direction
1297 DataDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1301 // FIXME verify short packets are ok
1303 //DataDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
1306 // store physical address of buffer
1308 DataDescriptor
->BufferPhysical
= MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL
)).LowPart
;
1309 DataDescriptor
->LastPhysicalByteAddress
= DataDescriptor
->BufferPhysical
+ m_TransferBufferLength
- 1;
1314 // initialize setup descriptor
1316 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
);
1321 // copy setup packet
1323 RtlCopyMemory(SetupDescriptor
->BufferLogical
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1328 // generate setup packet from urb
1334 // initialize status descriptor
1336 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
);
1337 if (m_TransferBufferLength
== 0)
1340 // input direction is flipped for the status descriptor
1342 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_IN
;
1347 // output direction is flipped for the status descriptor
1349 StatusDescriptor
->Flags
|= OHCI_TD_DIRECTION_PID_OUT
;
1353 // now link the descriptors
1355 if (m_TransferBufferLength
)
1358 // link setup descriptor to data descriptor
1360 SetupDescriptor
->NextPhysicalDescriptor
= DataDescriptor
->PhysicalAddress
.LowPart
;
1361 SetupDescriptor
->NextLogicalDescriptor
= DataDescriptor
;
1364 // link data descriptor to status descriptor
1365 // FIXME: check if there are more data descriptors
1367 DataDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1368 DataDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1371 // link status descriptor to last descriptor
1373 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1374 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1379 // link setup descriptor to status descriptor
1381 SetupDescriptor
->NextPhysicalDescriptor
= StatusDescriptor
->PhysicalAddress
.LowPart
;
1382 SetupDescriptor
->NextLogicalDescriptor
= StatusDescriptor
;
1385 // link status descriptor to last descriptor
1387 StatusDescriptor
->NextPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1388 StatusDescriptor
->NextLogicalDescriptor
= LastDescriptor
;
1392 // now link descriptor to endpoint
1394 EndpointDescriptor
->HeadPhysicalDescriptor
= SetupDescriptor
->PhysicalAddress
.LowPart
;
1395 EndpointDescriptor
->TailPhysicalDescriptor
= LastDescriptor
->PhysicalAddress
.LowPart
;
1396 EndpointDescriptor
->HeadLogicalDescriptor
= SetupDescriptor
;
1401 *OutEndpointDescriptor
= EndpointDescriptor
;
1406 return STATUS_SUCCESS
;
1409 //----------------------------------------------------------------------------------------
1411 CUSBRequest::GetEndpointDescriptor(
1412 struct _OHCI_ENDPOINT_DESCRIPTOR
** OutDescriptor
)
1418 // get transfer type
1420 TransferType
= InternalGetTransferType();
1423 // build request depending on type
1425 switch(TransferType
)
1427 case USB_ENDPOINT_TYPE_CONTROL
:
1428 Status
= BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1430 case USB_ENDPOINT_TYPE_BULK
:
1431 case USB_ENDPOINT_TYPE_INTERRUPT
:
1432 Status
= BuildBulkInterruptEndpoint(OutDescriptor
);
1434 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
1435 Status
= BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR
*)OutDescriptor
);
1439 Status
= STATUS_NOT_IMPLEMENTED
;
1443 if (NT_SUCCESS(Status
))
1448 //m_QueueHead = *OutDescriptor;
1451 // store request object
1453 (*OutDescriptor
)->Request
= PVOID(this);
1462 //----------------------------------------------------------------------------------------
1464 CUSBRequest::GetResultStatus(
1465 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1466 OUT OPTIONAL PULONG UrbStatusCode
)
1471 PC_ASSERT(m_CompletionEvent
);
1474 // wait for the operation to complete
1476 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1483 *NtStatusCode
= m_NtStatusCode
;
1491 *UrbStatusCode
= m_UrbStatusCode
;
1497 CUSBRequest::FreeEndpointDescriptor(
1498 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1500 POHCI_GENERAL_TD TransferDescriptor
, NextTransferDescriptor
;
1501 POHCI_ISO_TD IsoTransferDescriptor
, IsoNextTransferDescriptor
;
1502 ULONG Index
, PacketCount
;
1504 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1506 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1509 // get first iso transfer descriptor
1511 IsoTransferDescriptor
= (POHCI_ISO_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1514 // release endpoint descriptor
1516 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1518 while(IsoTransferDescriptor
)
1523 IsoNextTransferDescriptor
= IsoTransferDescriptor
->NextLogicalDescriptor
;
1528 PacketCount
= OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor
->Flags
);
1530 DPRINT1("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor
, IsoTransferDescriptor
->PhysicalAddress
.LowPart
, IsoTransferDescriptor
->BufferPhysical
, IsoTransferDescriptor
->LastPhysicalByteAddress
, PacketCount
);
1532 for(Index
= 0; Index
< PacketCount
; Index
++)
1534 DPRINT1("PSW Index %lu Value %x\n", Index
, IsoTransferDescriptor
->Offset
[Index
]);
1538 // release descriptor
1540 m_DmaManager
->Release(IsoTransferDescriptor
, sizeof(OHCI_ISO_TD
));
1545 IsoTransferDescriptor
= IsoNextTransferDescriptor
;
1551 // get first general transfer descriptor
1553 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1556 // release endpoint descriptor
1558 m_DmaManager
->Release(OutDescriptor
, sizeof(OHCI_ENDPOINT_DESCRIPTOR
));
1560 while(TransferDescriptor
)
1565 NextTransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1568 // is there a buffer associated
1570 if (TransferDescriptor
->BufferSize
)
1575 m_DmaManager
->Release(TransferDescriptor
->BufferLogical
, TransferDescriptor
->BufferSize
);
1578 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor
, TransferDescriptor
->PhysicalAddress
.LowPart
, TransferDescriptor
->BufferPhysical
, TransferDescriptor
->LastPhysicalByteAddress
);
1581 // release descriptor
1583 m_DmaManager
->Release(TransferDescriptor
, sizeof(OHCI_GENERAL_TD
));
1588 TransferDescriptor
= NextTransferDescriptor
;
1595 CUSBRequest::CheckError(
1596 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1598 POHCI_GENERAL_TD TransferDescriptor
;
1599 ULONG ConditionCode
;
1601 PIO_STACK_LOCATION IoStack
;
1607 m_NtStatusCode
= STATUS_SUCCESS
;
1608 m_UrbStatusCode
= USBD_STATUS_SUCCESS
;
1611 if (OutDescriptor
->Flags
& OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
)
1614 // FIXME: handle isochronous support
1621 // get first general transfer descriptor
1623 TransferDescriptor
= (POHCI_GENERAL_TD
)OutDescriptor
->HeadLogicalDescriptor
;
1625 while(TransferDescriptor
)
1628 // the descriptor must have been processed
1630 ASSERT(OHCI_TD_GET_CONDITION_CODE(TransferDescriptor
->Flags
) != OHCI_TD_CONDITION_NOT_ACCESSED
);
1633 // get condition code
1635 ConditionCode
= OHCI_TD_GET_CONDITION_CODE(TransferDescriptor
->Flags
);
1636 if (ConditionCode
!= OHCI_TD_CONDITION_NO_ERROR
)
1639 // FIXME status code
1641 m_NtStatusCode
= STATUS_UNSUCCESSFUL
;
1643 switch(ConditionCode
)
1645 case OHCI_TD_CONDITION_CRC_ERROR
:
1646 DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1647 m_UrbStatusCode
= USBD_STATUS_CRC
;
1649 case OHCI_TD_CONDITION_BIT_STUFFING
:
1650 DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1651 m_UrbStatusCode
= USBD_STATUS_BTSTUFF
;
1653 case OHCI_TD_CONDITION_TOGGLE_MISMATCH
:
1654 DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1655 m_UrbStatusCode
= USBD_STATUS_DATA_TOGGLE_MISMATCH
;
1657 case OHCI_TD_CONDITION_STALL
:
1658 DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1659 m_UrbStatusCode
= USBD_STATUS_STALL_PID
;
1661 case OHCI_TD_CONDITION_NO_RESPONSE
:
1662 DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1663 m_UrbStatusCode
= USBD_STATUS_DEV_NOT_RESPONDING
;
1665 case OHCI_TD_CONDITION_PID_CHECK_FAILURE
:
1666 DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1667 m_UrbStatusCode
= USBD_STATUS_PID_CHECK_FAILURE
;
1669 case OHCI_TD_CONDITION_UNEXPECTED_PID
:
1670 DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1671 m_UrbStatusCode
= USBD_STATUS_UNEXPECTED_PID
;
1673 case OHCI_TD_CONDITION_DATA_OVERRUN
:
1674 DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1675 m_UrbStatusCode
= USBD_STATUS_DATA_OVERRUN
;
1677 case OHCI_TD_CONDITION_DATA_UNDERRUN
:
1681 // get current irp stack location
1683 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1688 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1690 if(Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1693 // short packets are ok
1695 ASSERT(Urb
->UrbHeader
.Function
== URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
);
1696 m_NtStatusCode
= STATUS_SUCCESS
;
1700 DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1701 m_UrbStatusCode
= USBD_STATUS_DATA_UNDERRUN
;
1703 case OHCI_TD_CONDITION_BUFFER_OVERRUN
:
1704 DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1705 m_UrbStatusCode
= USBD_STATUS_BUFFER_OVERRUN
;
1707 case OHCI_TD_CONDITION_BUFFER_UNDERRUN
:
1708 DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor
);
1709 m_UrbStatusCode
= USBD_STATUS_BUFFER_UNDERRUN
;
1717 TransferDescriptor
= (POHCI_GENERAL_TD
)TransferDescriptor
->NextLogicalDescriptor
;
1723 CUSBRequest::CompletionCallback(
1724 struct _OHCI_ENDPOINT_DESCRIPTOR
* OutDescriptor
)
1726 PIO_STACK_LOCATION IoStack
;
1729 DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor
, OutDescriptor
->PhysicalAddress
.LowPart
);
1734 CheckError(OutDescriptor
);
1739 // set irp completion status
1741 m_Irp
->IoStatus
.Status
= m_NtStatusCode
;
1744 // get current irp stack location
1746 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1751 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1756 Urb
->UrbHeader
.Status
= m_UrbStatusCode
;
1759 // Check if the MDL was created
1761 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
1766 IoFreeMdl(m_TransferBufferMDL
);
1770 // FIXME: support status and calculate length
1774 // FIXME: check if the transfer was split
1775 // if yes dont complete irp yet
1777 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
1782 // signal completion event
1784 PC_ASSERT(m_CompletionEvent
);
1785 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
1790 //-----------------------------------------------------------------------------------------
1792 CUSBRequest::IsRequestInitialized()
1794 if (m_Irp
|| m_SetupPacket
)
1797 // request is initialized
1803 // request is not initialized
1808 //-----------------------------------------------------------------------------------------
1810 CUSBRequest::IsQueueHeadComplete(
1811 struct _QUEUE_HEAD
* QueueHead
)
1819 //-----------------------------------------------------------------------------------------
1821 InternalCreateUSBRequest(
1822 PUSBREQUEST
*OutRequest
)
1827 // allocate requests
1829 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBRequest(0);
1833 // failed to allocate
1835 return STATUS_INSUFFICIENT_RESOURCES
;
1839 // add reference count
1846 *OutRequest
= (PUSBREQUEST
)This
;
1851 return STATUS_SUCCESS
;