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_queue.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 class CUSBQueue
: public IUSBQueue
17 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
19 STDMETHODIMP_(ULONG
) AddRef()
21 InterlockedIncrement(&m_Ref
);
24 STDMETHODIMP_(ULONG
) Release()
26 InterlockedDecrement(&m_Ref
);
36 virtual NTSTATUS
Initialize(IN PUSBHARDWAREDEVICE Hardware
, PDMA_ADAPTER AdapterObject
, IN PDMAMEMORYMANAGER MemManager
, IN OPTIONAL PKSPIN_LOCK Lock
);
37 virtual ULONG
GetPendingRequestCount();
38 virtual NTSTATUS
AddUSBRequest(IUSBRequest
* Request
);
39 virtual NTSTATUS
CancelRequests();
40 virtual NTSTATUS
CreateUSBRequest(IUSBRequest
**OutRequest
);
42 // constructor / destructor
43 CUSBQueue(IUnknown
*OuterUnknown
){}
44 virtual ~CUSBQueue(){}
47 LONG m_Ref
; // reference count
48 KSPIN_LOCK m_Lock
; // list lock
49 PUSBHARDWAREDEVICE m_Hardware
; // hardware
50 POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor
; // bulk head descriptor
51 POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor
; // control head descriptor
54 //=================================================================================================
59 CUSBQueue::QueryInterface(
63 if (IsEqualGUIDAligned(refiid
, IID_IUnknown
))
65 *Output
= PVOID(PUNKNOWN(this));
66 PUNKNOWN(*Output
)->AddRef();
67 return STATUS_SUCCESS
;
70 return STATUS_UNSUCCESSFUL
;
74 CUSBQueue::Initialize(
75 IN PUSBHARDWAREDEVICE Hardware
,
76 IN PDMA_ADAPTER AdapterObject
,
77 IN PDMAMEMORYMANAGER MemManager
,
78 IN OPTIONAL PKSPIN_LOCK Lock
)
81 // get bulk endpoint descriptor
83 Hardware
->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor
);
86 // get control endpoint descriptor
88 Hardware
->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor
);
91 // initialize spinlock
93 KeInitializeSpinLock(&m_Lock
);
98 m_Hardware
= Hardware
;
100 return STATUS_SUCCESS
;
104 CUSBQueue::GetPendingRequestCount()
107 // Loop through the pending list and iterrate one for each QueueHead that
108 // has a IRP to complete.
115 CUSBQueue::AddUSBRequest(
116 IUSBRequest
* Request
)
121 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
;
122 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
124 DPRINT1("CUSBQueue::AddUSBRequest\n");
129 ASSERT(Request
!= NULL
);
134 Type
= Request
->GetTransferType();
137 // check if supported
141 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
142 case USB_ENDPOINT_TYPE_INTERRUPT
:
143 /* NOT IMPLEMENTED IN QUEUE */
144 Status
= STATUS_NOT_SUPPORTED
;
146 case USB_ENDPOINT_TYPE_BULK
:
147 case USB_ENDPOINT_TYPE_CONTROL
:
148 Status
= STATUS_SUCCESS
;
153 Status
= STATUS_NOT_SUPPORTED
;
159 if (!NT_SUCCESS(Status
))
162 // request not supported, please try later
168 // add extra reference which is released when the request is completed
173 // get transfer descriptors
175 Status
= Request
->GetEndpointDescriptor(&Descriptor
);
176 if (!NT_SUCCESS(Status
))
179 // failed to get transfer descriptor
181 DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status
);
193 if (Type
== USB_ENDPOINT_TYPE_BULK
)
196 // get head descriptor
198 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
200 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
203 // get head descriptor
205 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
211 Descriptor
->NextPhysicalEndpoint
= HeadDescriptor
->NextPhysicalEndpoint
;
212 Descriptor
->NextDescriptor
= HeadDescriptor
->NextDescriptor
;
214 HeadDescriptor
->NextPhysicalEndpoint
= Descriptor
->PhysicalAddress
.LowPart
;
215 HeadDescriptor
->NextDescriptor
= Descriptor
;
218 // set descriptor active
220 Descriptor
->Flags
&= ~OHCI_ENDPOINT_SKIP
;
223 // notify hardware of our request
225 m_Hardware
->HeadEndpointDescriptorModified(Type
);
227 DPRINT1("Request added to queue\n");
230 return STATUS_SUCCESS
;
234 CUSBQueue::CancelRequests()
237 return STATUS_NOT_IMPLEMENTED
;
241 CUSBQueue::CreateUSBRequest(
242 IUSBRequest
**OutRequest
)
244 PUSBREQUEST UsbRequest
;
248 Status
= InternalCreateUSBRequest(&UsbRequest
);
250 if (NT_SUCCESS(Status
))
252 *OutRequest
= UsbRequest
;
261 PUSBQUEUE
*OutUsbQueue
)
266 // allocate controller
268 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBQueue(0);
272 // failed to allocate
274 return STATUS_INSUFFICIENT_RESOURCES
;
278 // add reference count
285 *OutUsbQueue
= (PUSBQUEUE
)This
;
290 return STATUS_SUCCESS
;