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/usbehci/hub_controller.cpp
5 * PURPOSE: USB EHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 VOID
StatusChangeEndpointCallBack(
17 class CHubController
: public IHubController
,
21 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
23 STDMETHODIMP_(ULONG
) AddRef()
25 InterlockedIncrement(&m_Ref
);
28 STDMETHODIMP_(ULONG
) Release()
30 InterlockedDecrement(&m_Ref
);
40 // IHubController interface functions
41 virtual NTSTATUS
Initialize(IN PDRIVER_OBJECT DriverObject
, IN PHCDCONTROLLER Controller
, IN PUSBHARDWAREDEVICE Device
, IN BOOLEAN IsRootHubDevice
, IN ULONG DeviceAddress
);
42 virtual NTSTATUS
GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
);
43 virtual NTSTATUS
GetHubControllerSymbolicLink(ULONG BufferLength
, PVOID Buffer
, PULONG RequiredLength
);
45 // IDispatchIrp interface functions
46 virtual NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
47 virtual NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
48 virtual NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
51 NTSTATUS
HandleQueryInterface(PIO_STACK_LOCATION IoStack
);
52 NTSTATUS
SetDeviceInterface(BOOLEAN bEnable
);
53 NTSTATUS
CreatePDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
54 PUSBHARDWAREDEVICE
GetUsbHardware();
55 ULONG
AcquireDeviceAddress();
56 VOID
ReleaseDeviceAddress(ULONG DeviceAddress
);
57 BOOLEAN
ValidateUsbDevice(PUSBDEVICE UsbDevice
);
58 NTSTATUS
AddUsbDevice(PUSBDEVICE UsbDevice
);
59 NTSTATUS
RemoveUsbDevice(PUSBDEVICE UsbDevice
);
60 VOID
SetNotification(PVOID CallbackContext
, PRH_INIT_CALLBACK CallbackRoutine
);
61 // internal ioctl routines
62 NTSTATUS
HandleGetDescriptor(IN OUT PIRP Irp
, PURB Urb
);
63 NTSTATUS
HandleGetDescriptorFromInterface(IN OUT PIRP Irp
, PURB Urb
);
64 NTSTATUS
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
65 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
70 NTSTATUS
HandleClassEndpoint(IN OUT PIRP Irp
, PURB Urb
);
71 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
72 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
73 NTSTATUS
HandleClearStall(IN OUT PIRP Irp
, PURB Urb
);
74 NTSTATUS
HandleSyncResetAndClearStall(IN OUT PIRP Irp
, PURB Urb
);
75 NTSTATUS
HandleAbortPipe(IN OUT PIRP Irp
, PURB Urb
);
77 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
79 // constructor / destructor
80 CHubController(IUnknown
*OuterUnknown
){}
81 virtual ~CHubController(){}
85 PHCDCONTROLLER m_Controller
;
86 PUSBHARDWAREDEVICE m_Hardware
;
87 BOOLEAN m_IsRootHubDevice
;
88 ULONG m_DeviceAddress
;
90 BOOLEAN m_InterfaceEnabled
;
91 UNICODE_STRING m_HubDeviceInterfaceString
;
93 PDEVICE_OBJECT m_HubControllerDeviceObject
;
94 PDRIVER_OBJECT m_DriverObject
;
96 PVOID m_HubCallbackContext
;
97 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
99 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
102 RTL_BITMAP m_DeviceAddressBitmap
;
103 PULONG m_DeviceAddressBitmapBuffer
;
104 LIST_ENTRY m_UsbDeviceList
;
105 PIRP m_PendingSCEIrp
;
108 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
115 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
117 /* Lifted from Linux with slight changes */
118 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
121 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
122 0x00, 0x20, /* bcdUSB; v1.1 */
123 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
124 0x01, /* bDeviceSubClass; */
125 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
126 0x08, /* bMaxPacketSize0; 8 Bytes */
127 /* Fill Vendor and Product in when init root hub */
128 0x00, 0x00, /* idVendor; */
129 0x00, 0x00, /* idProduct; */
130 0x00, 0x00, /* bcdDevice */
131 0x00, /* iManufacturer; */
132 0x00, /* iProduct; */
133 0x00, /* iSerialNumber; */
134 0x01 /* bNumConfigurations; */
138 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
140 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
141 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
142 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
146 0x40, /* self powered */
150 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
152 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
153 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
154 0, /* bInterfaceNumber; */
155 0, /* bAlternateSetting; */
156 0x1, /* bNumEndpoints; */
157 0x09, /* bInterfaceClass; HUB_CLASSCODE */
158 0x01, /* bInterfaceSubClass; */
159 0x00, /* bInterfaceProtocol: */
160 0x00, /* iInterface; */
163 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
165 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
166 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
167 0x81, /* bEndPointAddress */
168 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
169 0x01, /* wMaxPacketSize */
173 //----------------------------------------------------------------------------------------
176 CHubController::QueryInterface(
180 return STATUS_UNSUCCESSFUL
;
182 //----------------------------------------------------------------------------------------
184 CHubController::Initialize(
185 IN PDRIVER_OBJECT DriverObject
,
186 IN PHCDCONTROLLER Controller
,
187 IN PUSBHARDWAREDEVICE Device
,
188 IN BOOLEAN IsRootHubDevice
,
189 IN ULONG DeviceAddress
)
192 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
193 USHORT VendorID
, DeviceID
;
196 DPRINT1("CHubController::Initialize\n");
199 // initialize members
201 m_Controller
= Controller
;
203 m_IsRootHubDevice
= IsRootHubDevice
;
204 m_DeviceAddress
= DeviceAddress
;
205 m_DriverObject
= DriverObject
;
206 KeInitializeSpinLock(&m_Lock
);
207 InitializeListHead(&m_UsbDeviceList
);
210 // allocate device address bitmap buffer
212 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBEHCI
);
213 if (!m_DeviceAddressBitmapBuffer
)
218 return STATUS_INSUFFICIENT_RESOURCES
;
222 // initialize device address bitmap
224 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
225 RtlClearAllBits(&m_DeviceAddressBitmap
);
231 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
232 if (!NT_SUCCESS(Status
))
235 // failed to create hub device object
241 // get device extension
243 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
246 // initialize device extension
248 DeviceExtension
->IsFDO
= FALSE
;
249 DeviceExtension
->IsHub
= TRUE
; //FIXME
250 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
253 // intialize device descriptor
255 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
256 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
258 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
261 // update device descriptor
263 m_DeviceDescriptor
.idVendor
= VendorID
;
264 m_DeviceDescriptor
.idProduct
= DeviceID
;
265 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
269 // Set the SCE Callback that the Hardware Device will call on port status change
271 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
276 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
278 return STATUS_SUCCESS
;
282 // Queries the ports to see if there has been a device connected or removed.
285 CHubController::QueryStatusChageEndpoint(
288 ULONG PortCount
, PortId
;
289 PIO_STACK_LOCATION IoStack
;
290 USHORT PortStatus
, PortChange
;
292 PUCHAR TransferBuffer
;
293 UCHAR Changed
= FALSE
;
296 // get current stack location
298 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
304 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
308 // Get the number of ports and check each one for device connected
310 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
311 DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
, Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
313 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
318 for (PortId
= 0; PortId
< PortCount
; PortId
++)
320 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
322 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
326 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
330 DPRINT1("Change state on port %d\n", PortId
);
331 // Set the value for the port number
332 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
340 //-----------------------------------------------------------------------------------------
342 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
345 // store controller object
347 *HubDeviceObject
= m_HubControllerDeviceObject
;
349 return STATUS_SUCCESS
;
351 //-----------------------------------------------------------------------------------------
353 CHubController::GetHubControllerSymbolicLink(
356 PULONG RequiredLength
)
358 if (!m_InterfaceEnabled
)
361 // device interface not yet enabled
363 return STATUS_UNSUCCESSFUL
;
366 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
370 // length is without '\??\'
372 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
377 return STATUS_BUFFER_OVERFLOW
;
381 // copy symbolic link
383 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
386 // store length, length is without '\??\'
388 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
393 return STATUS_SUCCESS
;
396 //-----------------------------------------------------------------------------------------
398 CHubController::HandlePnp(
399 IN PDEVICE_OBJECT DeviceObject
,
402 PIO_STACK_LOCATION IoStack
;
403 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
404 PDEVICE_CAPABILITIES DeviceCapabilities
;
405 PPNP_BUS_INFORMATION BusInformation
;
406 PDEVICE_RELATIONS DeviceRelations
;
408 ULONG Index
= 0, Length
;
409 USHORT VendorID
, DeviceID
;
410 ULONG HiSpeed
, NumPorts
;
415 // get device extension
417 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
422 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
425 // get current stack location
427 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
429 switch(IoStack
->MinorFunction
)
431 case IRP_MN_START_DEVICE
:
433 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
435 // register device interface
437 Status
= SetDeviceInterface(TRUE
);
440 case IRP_MN_QUERY_STOP_DEVICE
:
441 case IRP_MN_QUERY_REMOVE_DEVICE
:
446 Status
= STATUS_SUCCESS
;
449 case IRP_MN_QUERY_ID
:
451 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
453 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
460 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
462 if (HiSpeed
== 0x200)
467 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
474 swprintf(Buffer
, L
"USB\\ROOT_HUB");
477 DPRINT1("Name %S\n", Buffer
);
482 Length
= (wcslen(Buffer
) + 1);
487 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBEHCI
);
494 Status
= STATUS_INSUFFICIENT_RESOURCES
;
501 wcscpy(DeviceName
, Buffer
);
506 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
507 Status
= STATUS_SUCCESS
;
510 Status
= STATUS_UNSUCCESSFUL
;
515 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
522 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
524 if (!NT_SUCCESS(Status
))
526 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
531 if (HiSpeed
== 0x200)
536 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
537 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
538 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
545 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
546 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
547 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
550 Buffer
[Index
] = UNICODE_NULL
;
554 DPRINT1("Name %S\n", Buffer
);
559 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBEHCI
);
566 Status
= STATUS_INSUFFICIENT_RESOURCES
;
573 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
578 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
579 Status
= STATUS_SUCCESS
;
583 Status
= STATUS_SUCCESS
;
586 case IRP_MN_QUERY_CAPABILITIES
:
588 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
590 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
592 DeviceCapabilities
->LockSupported
= FALSE
;
593 DeviceCapabilities
->EjectSupported
= FALSE
;
594 DeviceCapabilities
->Removable
= FALSE
;
595 DeviceCapabilities
->DockDevice
= FALSE
;
596 DeviceCapabilities
->UniqueID
= FALSE
;
597 DeviceCapabilities
->SilentInstall
= FALSE
;
598 DeviceCapabilities
->RawDeviceOK
= FALSE
;
599 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
600 DeviceCapabilities
->Address
= 0;
601 DeviceCapabilities
->UINumber
= 0;
602 DeviceCapabilities
->DeviceD2
= 1;
605 DeviceCapabilities
->HardwareDisabled
= FALSE
;
606 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
607 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
608 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
609 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
610 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
611 DeviceCapabilities
->D1Latency
= 0;
612 DeviceCapabilities
->D2Latency
= 0;
613 DeviceCapabilities
->D3Latency
= 0;
615 Status
= STATUS_SUCCESS
;
618 case IRP_MN_QUERY_INTERFACE
:
620 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
623 // handle device interface requests
625 Status
= HandleQueryInterface(IoStack
);
628 case IRP_MN_REMOVE_DEVICE
:
630 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
633 // deactivate device interface for BUS PDO
635 SetDeviceInterface(FALSE
);
638 // complete the request first
640 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
641 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
646 IoDeleteDevice(m_HubControllerDeviceObject
);
651 m_HubControllerDeviceObject
= 0;
656 return STATUS_SUCCESS
;
658 case IRP_MN_QUERY_DEVICE_RELATIONS
:
660 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
662 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
665 // allocate device relations
667 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBEHCI
);
668 if (!DeviceRelations
)
673 Status
= STATUS_INSUFFICIENT_RESOURCES
;
678 // initialize device relations
680 DeviceRelations
->Count
= 1;
681 DeviceRelations
->Objects
[0] = DeviceObject
;
682 ObReferenceObject(DeviceObject
);
687 Status
= STATUS_SUCCESS
;
688 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
695 Status
= Irp
->IoStatus
.Status
;
699 case IRP_MN_QUERY_BUS_INFORMATION
:
701 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
704 // allocate buffer for bus information
706 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
712 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
717 BusInformation
->LegacyBusType
= PNPBus
;
718 BusInformation
->BusNumber
= 0;
720 Status
= STATUS_SUCCESS
;
721 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
728 Status
= STATUS_INSUFFICIENT_RESOURCES
;
732 case IRP_MN_STOP_DEVICE
:
734 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
738 Status
= STATUS_SUCCESS
;
744 // ignore request with default status
746 Status
= Irp
->IoStatus
.Status
;
754 Irp
->IoStatus
.Status
= Status
;
755 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
763 //-----------------------------------------------------------------------------------------
765 CHubController::HandlePower(
766 IN PDEVICE_OBJECT DeviceObject
,
770 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
771 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
772 return STATUS_NOT_IMPLEMENTED
;
775 //-----------------------------------------------------------------------------------------
777 CHubController::HandleIsochronousTransfer(
781 PUSBDEVICE UsbDevice
;
782 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
785 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
787 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
791 DPRINT1("No EndpointDesc\n");
792 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
793 return STATUS_INVALID_PARAMETER
;
799 ASSERT(EndPointDesc
);
800 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
803 // check if this is a valid usb device handle
805 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
807 DPRINT1("HandleIsochronousTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
810 // invalid device handle
812 return STATUS_DEVICE_NOT_CONNECTED
;
818 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
820 return UsbDevice
->SubmitIrp(Irp
);
823 //-----------------------------------------------------------------------------------------
825 CHubController::HandleBulkOrInterruptTransfer(
829 PUSBDEVICE UsbDevice
;
830 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
832 // First check if the request is for the Status Change Endpoint
836 // Is the Request for the root hub
838 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
840 ASSERT(m_PendingSCEIrp
== NULL
);
841 if (QueryStatusChageEndpoint(Irp
))
843 StatusChangeEndpointCallBack(this);
844 return STATUS_SUCCESS
;
848 // Else pend the IRP, to be completed when a device connects or disconnects.
850 DPRINT1("Pending SCE Irp\n");;
851 m_PendingSCEIrp
= Irp
;
852 IoMarkIrpPending(Irp
);
853 return STATUS_PENDING
;
857 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
859 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
864 ASSERT(EndPointDesc
);
865 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
868 // check if this is a valid usb device handle
870 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
872 DPRINT1("HandleBulkOrInterruptTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
875 // invalid device handle
877 return STATUS_DEVICE_NOT_CONNECTED
;
883 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
885 return UsbDevice
->SubmitIrp(Irp
);
888 //-----------------------------------------------------------------------------------------
890 CHubController::HandleClassOther(
894 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
895 USHORT PortStatus
= 0, PortChange
= 0;
900 DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
903 // get number of ports available
905 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
906 PC_ASSERT(Status
== STATUS_SUCCESS
);
911 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
914 // port range reported start from 1 -n
915 // convert back port id so it matches the hardware
917 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
920 // check request code
922 switch(Urb
->UrbControlVendorClassRequest
.Request
)
924 case USB_REQUEST_GET_STATUS
:
929 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
930 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
935 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
937 if (NT_SUCCESS(Status
))
940 // request contains buffer of 2 ushort which are used from submitting port status and port change status
942 DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId
, PortStatus
, PortChange
);
943 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
946 // store status, then port change
948 *Buffer
= PortStatus
;
950 *Buffer
= PortChange
;
958 case USB_REQUEST_CLEAR_FEATURE
:
960 switch (Urb
->UrbControlVendorClassRequest
.Value
)
962 case C_PORT_CONNECTION
:
963 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
966 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
969 DPRINT("Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
973 Status
= STATUS_SUCCESS
;
976 case USB_REQUEST_SET_FEATURE
:
979 // request set feature
981 switch(Urb
->UrbControlVendorClassRequest
.Value
)
986 // port enable is a no-op for EHCI
988 Status
= STATUS_SUCCESS
;
995 // set suspend port feature
997 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
1003 // set power feature on port
1005 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1012 // reset port feature
1014 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1015 PC_ASSERT(Status
== STATUS_SUCCESS
);
1019 DPRINT1("Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1025 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1027 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1032 //-----------------------------------------------------------------------------------------
1034 CHubController::HandleSelectConfiguration(
1038 PUSBDEVICE UsbDevice
;
1039 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1042 // is the request for the Root Hub
1044 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1047 // FIXME: support setting device to unconfigured state
1049 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1052 // set device handle
1054 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1057 // copy interface info
1059 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1061 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1062 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1063 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1064 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1065 InterfaceInfo
->Reserved
= 0;
1070 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1075 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1076 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1077 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1078 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1079 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1081 return STATUS_SUCCESS
;
1086 // check if this is a valid usb device handle
1088 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1090 DPRINT1("HandleSelectConfiguration invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1093 // invalid device handle
1095 return STATUS_DEVICE_NOT_CONNECTED
;
1101 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1104 // select configuration
1106 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1110 //-----------------------------------------------------------------------------------------
1112 CHubController::HandleSelectInterface(
1116 PUSBDEVICE UsbDevice
;
1121 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1124 // is the request for the Root Hub
1126 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1129 // no op for root hub
1131 return STATUS_SUCCESS
;
1136 // check if this is a valid usb device handle
1138 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1140 DPRINT1("HandleSelectInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1143 // invalid device handle
1145 return STATUS_DEVICE_NOT_CONNECTED
;
1151 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1156 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1160 //-----------------------------------------------------------------------------------------
1162 CHubController::HandleGetStatusFromDevice(
1166 PUSHORT DeviceStatus
;
1167 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1169 PUSBDEVICE UsbDevice
;
1174 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1175 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1176 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1179 // get status buffer
1181 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1184 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1187 // FIXME need more flags ?
1189 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1190 return STATUS_SUCCESS
;
1194 // check if this is a valid usb device handle
1196 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1198 DPRINT1("HandleGetStatusFromDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1201 // invalid device handle
1203 return STATUS_DEVICE_NOT_CONNECTED
;
1209 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1213 // generate setup packet
1215 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1216 CtrlSetup
.wValue
.LowByte
= 0;
1217 CtrlSetup
.wValue
.HiByte
= 0;
1218 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1219 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1220 CtrlSetup
.bmRequestType
.B
= 0x80;
1223 // submit setup packet
1225 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1226 ASSERT(Status
== STATUS_SUCCESS
);
1227 DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1235 //-----------------------------------------------------------------------------------------
1237 CHubController::HandleClassDevice(
1241 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1242 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1243 ULONG PortCount
, Dummy2
;
1245 PUSBDEVICE UsbDevice
;
1246 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1248 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1251 // check class request type
1253 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1255 case USB_REQUEST_GET_STATUS
:
1258 // check if this is a valid usb device handle
1260 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1262 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1265 // invalid device handle
1267 return STATUS_DEVICE_NOT_CONNECTED
;
1273 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1277 // generate setup packet
1279 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1280 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlVendorClassRequest
.Index
;
1281 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1282 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1283 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1284 CtrlSetup
.bmRequestType
.B
= 0xA0;
1287 // submit setup packet
1289 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1290 ASSERT(Status
== STATUS_SUCCESS
);
1293 case USB_REQUEST_GET_DESCRIPTOR
:
1295 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1297 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1298 case USB_DEVICE_CLASS_HUB
:
1303 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1304 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1307 // get hub descriptor
1309 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1312 // one hub is handled
1314 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1315 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1318 // type should 0x29 according to msdn
1320 UsbHubDescriptor
->bDescriptorType
= 0x29;
1325 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1326 PC_ASSERT(Status
== STATUS_SUCCESS
);
1329 // FIXME: retrieve values
1331 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1332 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1333 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1334 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1339 Status
= STATUS_SUCCESS
;
1343 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1349 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1355 //-----------------------------------------------------------------------------------------
1357 CHubController::HandleGetDescriptorFromInterface(
1361 PUSBDEVICE UsbDevice
;
1362 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1368 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1369 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1372 // check if this is a valid usb device handle
1374 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1376 DPRINT1("HandleGetDescriptorFromInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1379 // invalid device handle
1381 return STATUS_DEVICE_NOT_CONNECTED
;
1387 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1390 // generate setup packet
1392 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1393 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1394 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1395 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1396 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1397 CtrlSetup
.bmRequestType
.B
= 0x81;
1400 // submit setup packet
1402 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1403 ASSERT(Status
== STATUS_SUCCESS
);
1411 //-----------------------------------------------------------------------------------------
1413 CHubController::HandleGetDescriptor(
1417 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1418 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1419 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1421 PUSBDEVICE UsbDevice
;
1424 DPRINT("CHubController::HandleGetDescriptor\n");
1427 // check descriptor type
1429 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1431 case USB_DEVICE_DESCRIPTOR_TYPE
:
1436 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1437 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1439 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1442 // copy root hub device descriptor
1444 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1445 Status
= STATUS_SUCCESS
;
1450 // check if this is a valid usb device handle
1452 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1454 DPRINT1("HandleGetDescriptor invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1457 // invalid device handle
1459 return STATUS_DEVICE_NOT_CONNECTED
;
1465 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1468 // retrieve device descriptor from device
1470 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1471 Status
= STATUS_SUCCESS
;
1475 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1480 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1481 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1483 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1486 // request is for the root bus controller
1488 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1491 // get configuration descriptor, very retarded!
1493 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1496 // check if buffer can hold interface and endpoint descriptor
1498 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1503 Status
= STATUS_SUCCESS
;
1509 // copy interface descriptor template
1511 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1512 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1515 // copy end point descriptor template
1517 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1518 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1523 Status
= STATUS_SUCCESS
;
1529 // check if this is a valid usb device handle
1531 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1533 DPRINT1("USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1536 // invalid device handle
1538 return STATUS_DEVICE_NOT_CONNECTED
;
1544 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1546 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1551 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1556 Status
= STATUS_SUCCESS
;
1561 // perform work in IUSBDevice
1563 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1568 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= Length
);
1571 // store result size
1573 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1574 Status
= STATUS_SUCCESS
;
1578 case USB_STRING_DESCRIPTOR_TYPE
:
1583 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1584 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1588 // check if this is a valid usb device handle
1590 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1592 DPRINT1("USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1595 // invalid device handle
1597 return STATUS_DEVICE_NOT_CONNECTED
;
1603 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1606 // generate setup packet
1608 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1609 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1610 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1611 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1612 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1613 CtrlSetup
.bmRequestType
.B
= 0x80;
1616 // submit setup packet
1618 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1622 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1632 //-----------------------------------------------------------------------------------------
1634 CHubController::HandleClassEndpoint(
1638 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1640 PUSBDEVICE UsbDevice
;
1645 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1646 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1647 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1650 // check if this is a valid usb device handle
1652 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1654 DPRINT1("HandleClassEndpoint invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1657 // invalid device handle
1659 return STATUS_DEVICE_NOT_CONNECTED
;
1665 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1668 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1669 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1670 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1671 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1672 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1673 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1674 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1675 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1676 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1679 // initialize setup packet
1681 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1682 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1683 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1684 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1685 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1687 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1690 // data direction is device to host
1692 CtrlSetup
.bmRequestType
.B
|= 0x80;
1699 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1702 // assert on failure
1704 PC_ASSERT(NT_SUCCESS(Status
));
1714 CHubController::HandleSyncResetAndClearStall(
1718 NTSTATUS Status
= STATUS_SUCCESS
;
1719 PUSB_ENDPOINT EndpointDescriptor
;
1725 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1726 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1727 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1730 // check if this is a valid usb device handle
1732 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1734 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1737 // invalid device handle
1739 return STATUS_DEVICE_NOT_CONNECTED
;
1743 // get endpoint descriptor
1745 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1750 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1751 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1756 Status
= HandleClearStall(Irp
, Urb
);
1758 DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status
);
1761 // reset data toggle
1763 ASSERT(NT_SUCCESS(Status
));
1764 EndpointDescriptor
->DataToggle
= 0x0;
1773 CHubController::HandleAbortPipe(
1778 PUSBDEVICE UsbDevice
;
1779 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1784 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1785 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1786 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1789 // check if this is a valid usb device handle
1791 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1793 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1796 // invalid device handle
1798 return STATUS_DEVICE_NOT_CONNECTED
;
1802 // get endpoint descriptor
1804 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1809 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1815 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
1816 DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status
);
1825 //-----------------------------------------------------------------------------------------
1827 CHubController::HandleClearStall(
1831 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1833 PUSBDEVICE UsbDevice
;
1834 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1840 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1841 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1842 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1845 // check if this is a valid usb device handle
1847 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1849 DPRINT1("HandleClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1852 // invalid device handle
1854 return STATUS_DEVICE_NOT_CONNECTED
;
1858 // get endpoint descriptor
1860 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1865 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1866 DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
1869 // initialize setup packet
1871 CtrlSetup
.bmRequestType
.B
= 0x02;
1872 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
1873 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
1874 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
1875 CtrlSetup
.wLength
= 0;
1876 CtrlSetup
.wValue
.W
= 0;
1881 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
1883 DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status
);
1892 //-----------------------------------------------------------------------------------------
1894 CHubController::HandleClassInterface(
1898 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1900 PUSBDEVICE UsbDevice
;
1905 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1906 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1907 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1910 // check if this is a valid usb device handle
1912 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1914 DPRINT1("HandleClassInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1917 // invalid device handle
1919 return STATUS_DEVICE_NOT_CONNECTED
;
1925 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1928 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1929 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1930 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1931 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1932 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1933 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1934 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1935 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1936 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1939 // initialize setup packet
1941 CtrlSetup
.bmRequestType
.B
= 0x21;
1942 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1943 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1944 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1945 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1947 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1950 // data direction is device to host
1952 CtrlSetup
.bmRequestType
.B
|= 0x80;
1958 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1961 // assert on failure
1963 if (!NT_SUCCESS(Status
))
1968 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb
->UrbHeader
.Status
);
1977 //-----------------------------------------------------------------------------------------
1979 CHubController::HandleDeviceControl(
1980 IN PDEVICE_OBJECT DeviceObject
,
1983 PIO_STACK_LOCATION IoStack
;
1984 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1986 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1989 // get current stack location
1991 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1994 // get device extension
1996 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1999 // determine which request should be performed
2001 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2003 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2008 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2011 switch (Urb
->UrbHeader
.Function
)
2013 case URB_FUNCTION_SYNC_RESET_PIPE
:
2014 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2015 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2017 case URB_FUNCTION_ABORT_PIPE
:
2018 Status
= HandleAbortPipe(Irp
, Urb
);
2020 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2021 Status
= HandleClearStall(Irp
, Urb
);
2023 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2024 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2026 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2027 Status
= HandleGetDescriptor(Irp
, Urb
);
2029 case URB_FUNCTION_CLASS_DEVICE
:
2030 Status
= HandleClassDevice(Irp
, Urb
);
2032 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2033 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2035 case URB_FUNCTION_SELECT_CONFIGURATION
:
2036 Status
= HandleSelectConfiguration(Irp
, Urb
);
2038 case URB_FUNCTION_SELECT_INTERFACE
:
2039 Status
= HandleSelectInterface(Irp
, Urb
);
2041 case URB_FUNCTION_CLASS_OTHER
:
2042 Status
= HandleClassOther(Irp
, Urb
);
2044 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2045 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2047 case URB_FUNCTION_ISOCH_TRANSFER
:
2048 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2050 case URB_FUNCTION_CLASS_INTERFACE
:
2051 Status
= HandleClassInterface(Irp
, Urb
);
2053 case URB_FUNCTION_CLASS_ENDPOINT
:
2054 Status
= HandleClassEndpoint(Irp
, Urb
);
2057 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
2061 // request completed
2065 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2067 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2069 if (IoStack
->Parameters
.Others
.Argument1
)
2072 // store object as device handle
2074 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2075 Status
= STATUS_SUCCESS
;
2080 // mis-behaving hub driver
2082 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2086 // request completed
2090 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2092 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2095 // this is the first request send, it delivers the PDO to the caller
2097 if (IoStack
->Parameters
.Others
.Argument1
)
2100 // store root hub pdo object
2102 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2105 if (IoStack
->Parameters
.Others
.Argument2
)
2108 // documentation claims to deliver the hcd controller object, although it is wrong
2110 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2114 // request completed
2116 Status
= STATUS_SUCCESS
;
2119 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2121 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2124 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2125 // requests this ioctl to deliver the number of presents.
2127 if (IoStack
->Parameters
.Others
.Argument1
)
2130 // FIXME / verify: there is only one hub
2132 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2136 // request completed
2138 Status
= STATUS_SUCCESS
;
2139 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2142 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2144 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2145 Status
= STATUS_SUCCESS
;
2150 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2151 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2152 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2153 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2157 if (Status
!= STATUS_PENDING
)
2159 Irp
->IoStatus
.Status
= Status
;
2160 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2166 //-----------------------------------------------------------------------------------------
2168 CHubController::GetUsbHardware()
2173 //-----------------------------------------------------------------------------------------
2175 CHubController::AcquireDeviceAddress()
2178 ULONG DeviceAddress
;
2181 // acquire device lock
2183 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2188 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2189 if (DeviceAddress
!= MAXULONG
)
2194 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2197 // device addresses start from 0x1 - 0xFF
2203 // release spin lock
2205 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2208 // return device address
2210 return DeviceAddress
;
2212 //-----------------------------------------------------------------------------------------
2214 CHubController::ReleaseDeviceAddress(
2215 ULONG DeviceAddress
)
2220 // acquire device lock
2222 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2227 PC_ASSERT(DeviceAddress
!= 0);
2230 // convert back to bit number
2237 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2242 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2244 //-----------------------------------------------------------------------------------------
2246 CHubController::RemoveUsbDevice(
2247 PUSBDEVICE UsbDevice
)
2249 PUSBDEVICE_ENTRY DeviceEntry
;
2251 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2257 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2260 // point to first entry
2262 Entry
= m_UsbDeviceList
.Flink
;
2265 // find matching entry
2267 while(Entry
!= &m_UsbDeviceList
)
2272 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2275 // is it current entry
2277 if (DeviceEntry
->Device
== UsbDevice
)
2282 RemoveEntryList(Entry
);
2287 ExFreePoolWithTag(DeviceEntry
, TAG_USBEHCI
);
2292 Status
= STATUS_SUCCESS
;
2299 Entry
= Entry
->Flink
;
2305 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2312 //-----------------------------------------------------------------------------------------
2314 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2316 PUSBDEVICE_ENTRY DeviceEntry
;
2319 BOOLEAN Result
= FALSE
;
2324 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2327 // point to first entry
2329 Entry
= m_UsbDeviceList
.Flink
;
2332 // find matching entry
2334 while(Entry
!= &m_UsbDeviceList
)
2339 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2342 // is it current entry
2344 if (DeviceEntry
->Device
== UsbDevice
)
2356 Entry
= Entry
->Flink
;
2362 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2371 //-----------------------------------------------------------------------------------------
2373 CHubController::AddUsbDevice(
2374 PUSBDEVICE UsbDevice
)
2376 PUSBDEVICE_ENTRY DeviceEntry
;
2380 // allocate device entry
2382 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBEHCI
);
2388 return STATUS_INSUFFICIENT_RESOURCES
;
2394 DeviceEntry
->Device
= UsbDevice
;
2399 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2404 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2407 // release spin lock
2409 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2414 return STATUS_SUCCESS
;
2417 //-----------------------------------------------------------------------------------------
2419 CHubController::SetNotification(
2420 PVOID CallbackContext
,
2421 PRH_INIT_CALLBACK CallbackRoutine
)
2426 // acquire hub controller lock
2428 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2431 // now set the callback routine and context of the hub
2433 m_HubCallbackContext
= CallbackContext
;
2434 m_HubCallbackRoutine
= CallbackRoutine
;
2437 // release hub controller lock
2439 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2442 //=================================================================================================
2444 // Generic Interface functions
2448 USBI_InterfaceReference(
2451 CHubController
* Controller
= (CHubController
*)BusContext
;
2453 DPRINT1("USBH_InterfaceReference\n");
2458 Controller
->AddRef();
2463 USBI_InterfaceDereference(
2466 CHubController
* Controller
= (CHubController
*)BusContext
;
2468 DPRINT1("USBH_InterfaceDereference\n");
2473 Controller
->Release();
2475 //=================================================================================================
2477 // USB Hub Interface functions
2481 USBHI_CreateUsbDevice(
2483 PUSB_DEVICE_HANDLE
*NewDevice
,
2484 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2488 PUSBDEVICE NewUsbDevice
;
2489 CHubController
* Controller
;
2492 DPRINT1("USBHI_CreateUsbDevice\n");
2495 // first get hub controller
2497 Controller
= (CHubController
*)BusContext
;
2502 PC_ASSERT(Controller
);
2503 PC_ASSERT(BusContext
== HubDeviceHandle
);
2506 // now allocate usb device
2508 Status
= CreateUSBDevice(&NewUsbDevice
);
2511 // check for success
2513 if (!NT_SUCCESS(Status
))
2516 // release controller
2518 Controller
->Release();
2519 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2524 // now initialize device
2526 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
2529 // check for success
2531 if (!NT_SUCCESS(Status
))
2534 // release usb device
2536 NewUsbDevice
->Release();
2537 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2544 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2546 // check for success
2548 if (!NT_SUCCESS(Status
))
2551 // release usb device
2553 NewUsbDevice
->Release();
2555 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2562 *NewDevice
= NewUsbDevice
;
2567 return STATUS_SUCCESS
;
2572 USBHI_InitializeUsbDevice(
2574 PUSB_DEVICE_HANDLE DeviceHandle
)
2576 PUSBDEVICE UsbDevice
;
2577 CHubController
* Controller
;
2578 ULONG DeviceAddress
;
2582 DPRINT1("USBHI_InitializeUsbDevice\n");
2585 // first get controller
2587 Controller
= (CHubController
*)BusContext
;
2588 PC_ASSERT(Controller
);
2591 // get device object
2593 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2594 PC_ASSERT(UsbDevice
);
2597 // validate device handle
2599 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2601 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2604 // invalid device handle
2606 return STATUS_DEVICE_NOT_CONNECTED
;
2610 // now reserve an address
2612 DeviceAddress
= Controller
->AcquireDeviceAddress();
2615 // is the device address valid
2617 if (DeviceAddress
== MAXULONG
)
2620 // failed to get an device address from the device address pool
2622 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2623 return STATUS_DEVICE_DATA_ERROR
;
2629 // now set the device address
2631 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2633 if (NT_SUCCESS(Status
))
2636 }while(Index
++ < 3 );
2639 // check for failure
2641 if (!NT_SUCCESS(Status
))
2644 // failed to set device address
2646 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2651 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2656 return STATUS_DEVICE_DATA_ERROR
;
2662 return STATUS_SUCCESS
;
2667 USBHI_GetUsbDescriptors(
2669 PUSB_DEVICE_HANDLE DeviceHandle
,
2670 PUCHAR DeviceDescriptorBuffer
,
2671 PULONG DeviceDescriptorBufferLength
,
2672 PUCHAR ConfigDescriptorBuffer
,
2673 PULONG ConfigDescriptorBufferLength
)
2675 PUSBDEVICE UsbDevice
;
2676 CHubController
* Controller
;
2678 DPRINT1("USBHI_GetUsbDescriptors\n");
2683 PC_ASSERT(DeviceDescriptorBuffer
);
2684 PC_ASSERT(DeviceDescriptorBufferLength
);
2685 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2686 PC_ASSERT(ConfigDescriptorBufferLength
);
2687 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2690 // first get controller
2692 Controller
= (CHubController
*)BusContext
;
2693 PC_ASSERT(Controller
);
2697 // get device object
2699 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2700 PC_ASSERT(UsbDevice
);
2703 // validate device handle
2705 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2707 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2710 // invalid device handle
2712 return STATUS_DEVICE_NOT_CONNECTED
;
2716 // get device descriptor
2718 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2721 // store result length
2723 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2726 // get configuration descriptor
2728 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2731 // complete the request
2733 return STATUS_SUCCESS
;
2738 USBHI_RemoveUsbDevice(
2740 PUSB_DEVICE_HANDLE DeviceHandle
,
2743 PUSBDEVICE UsbDevice
;
2744 CHubController
* Controller
;
2747 DPRINT1("USBHI_RemoveUsbDevice\n");
2750 // first get controller
2752 Controller
= (CHubController
*)BusContext
;
2753 PC_ASSERT(Controller
);
2756 // get device object
2758 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2759 PC_ASSERT(UsbDevice
);
2762 // validate device handle
2764 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2766 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2769 // invalid device handle
2771 return STATUS_DEVICE_NOT_CONNECTED
;
2775 // check if there were flags passed
2777 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2780 // ignore flags for now
2782 return STATUS_SUCCESS
;
2788 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2789 if (!NT_SUCCESS(Status
))
2792 // invalid device handle
2794 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2796 return STATUS_DEVICE_NOT_CONNECTED
;
2800 // release usb device
2802 UsbDevice
->Release();
2807 return STATUS_SUCCESS
;
2812 USBHI_RestoreUsbDevice(
2814 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2815 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2817 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2818 CHubController
* Controller
;
2820 DPRINT1("USBHI_RestoreUsbDevice\n");
2823 // first get controller
2825 Controller
= (CHubController
*)BusContext
;
2826 PC_ASSERT(Controller
);
2829 // get device object
2831 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2832 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2833 PC_ASSERT(OldUsbDevice
);
2834 PC_ASSERT(NewDeviceHandle
);
2837 // validate device handle
2839 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2840 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2842 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2843 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2846 // remove old device handle
2848 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2850 return STATUS_SUCCESS
;
2855 USBHI_QueryDeviceInformation(
2857 PUSB_DEVICE_HANDLE DeviceHandle
,
2858 PVOID DeviceInformationBuffer
,
2859 ULONG DeviceInformationBufferLength
,
2860 PULONG LengthReturned
)
2862 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2863 PUSBDEVICE UsbDevice
;
2864 CHubController
* Controller
;
2866 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2871 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2872 PC_ASSERT(DeviceInformationBuffer
);
2873 PC_ASSERT(LengthReturned
);
2876 // get controller object
2878 Controller
= (CHubController
*)BusContext
;
2879 PC_ASSERT(Controller
);
2882 // get device object
2884 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2885 PC_ASSERT(UsbDevice
);
2887 if (BusContext
!= DeviceHandle
)
2890 // validate device handle
2892 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2894 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2897 // invalid device handle
2899 return STATUS_DEVICE_NOT_CONNECTED
;
2903 // access information buffer
2905 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2908 // initialize with default values
2910 DeviceInfo
->InformationLevel
= 0;
2911 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2912 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2913 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2914 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2915 DeviceInfo
->HubAddress
= 0; //FIXME
2916 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2917 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2918 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2921 // get device descriptor
2923 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2926 // FIXME return pipe information
2930 // store result length
2932 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2934 return STATUS_SUCCESS
;
2938 // access information buffer
2940 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2943 // initialize with default values
2945 DeviceInfo
->InformationLevel
= 0;
2946 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2947 DeviceInfo
->PortNumber
= 0;
2948 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2949 DeviceInfo
->DeviceAddress
= 0;
2950 DeviceInfo
->HubAddress
= 0; //FIXME
2951 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
2952 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
2953 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2956 // get device descriptor
2958 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
2961 // FIXME return pipe information
2965 // store result length
2968 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
2970 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
2975 return STATUS_SUCCESS
;
2980 USBHI_GetControllerInformation(
2982 PVOID ControllerInformationBuffer
,
2983 ULONG ControllerInformationBufferLength
,
2984 PULONG LengthReturned
)
2986 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2988 DPRINT1("USBHI_GetControllerInformation\n");
2993 PC_ASSERT(ControllerInformationBuffer
);
2994 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2997 // get controller info buffer
2999 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3002 // FIXME only version 0 is supported for now
3004 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3007 // fill in information
3009 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3010 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3011 ControllerInfo
->IsHighSpeedController
= TRUE
;
3014 // set length returned
3016 *LengthReturned
= ControllerInfo
->ActualLength
;
3021 return STATUS_SUCCESS
;
3026 USBHI_ControllerSelectiveSuspend(
3031 return STATUS_NOT_IMPLEMENTED
;
3036 USBHI_GetExtendedHubInformation(
3038 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3039 PVOID HubInformationBuffer
,
3040 ULONG HubInformationBufferLength
,
3041 PULONG LengthReturned
)
3043 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3044 CHubController
* Controller
;
3045 PUSBHARDWAREDEVICE Hardware
;
3047 ULONG NumPort
, Dummy2
;
3051 DPRINT1("USBHI_GetExtendedHubInformation\n");
3056 PC_ASSERT(HubInformationBuffer
);
3057 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3058 PC_ASSERT(LengthReturned
);
3061 // get hub controller
3063 Controller
= (CHubController
*)BusContext
;
3064 PC_ASSERT(Controller
);
3067 // get usb hardware device
3069 Hardware
= Controller
->GetUsbHardware();
3072 // retrieve number of ports
3074 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3075 if (!NT_SUCCESS(Status
))
3078 // failed to get hardware details, ouch ;)
3080 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3085 // get hub information buffer
3087 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3090 // initialize hub information
3092 HubInfo
->InformationLevel
= 0;
3097 HubInfo
->NumberOfPorts
= NumPort
;
3100 // initialize port information
3102 for(Index
= 0; Index
< NumPort
; Index
++)
3104 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3105 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3106 HubInfo
->Port
[Index
].VidOverride
= 0;
3107 HubInfo
->Port
[Index
].PidOverride
= 0;
3108 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3112 // store result length
3115 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3117 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3123 return STATUS_SUCCESS
;
3128 USBHI_GetRootHubSymbolicName(
3130 PVOID HubSymNameBuffer
,
3131 ULONG HubSymNameBufferLength
,
3132 PULONG HubSymNameActualLength
)
3135 return STATUS_NOT_IMPLEMENTED
;
3140 USBHI_GetDeviceBusContext(
3141 PVOID HubBusContext
,
3150 USBHI_Initialize20Hub(
3152 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3155 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3156 return STATUS_SUCCESS
;
3161 USBHI_RootHubInitNotification(
3163 PVOID CallbackContext
,
3164 PRH_INIT_CALLBACK CallbackRoutine
)
3166 CHubController
* Controller
;
3168 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3171 // get controller object
3173 Controller
= (CHubController
*)BusContext
;
3174 PC_ASSERT(Controller
);
3177 // set notification routine
3179 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3182 // FIXME: determine when to perform callback
3184 CallbackRoutine(CallbackContext
);
3189 return STATUS_SUCCESS
;
3194 USBHI_FlushTransfers(
3203 USBHI_SetDeviceHandleData(
3206 PDEVICE_OBJECT UsbDevicePdo
)
3208 PUSBDEVICE UsbDevice
;
3209 CHubController
* Controller
;
3214 Controller
= (CHubController
*)BusContext
;
3215 PC_ASSERT(Controller
);
3218 // get device handle
3220 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3223 // validate device handle
3225 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3227 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3237 // usbhub sends this request as a part of the Pnp startup sequence
3238 // looks like we need apply a dragon voodoo to fixup the device stack
3239 // otherwise usbhub will cause a bugcheck
3241 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3246 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3249 // should be usbstor
3250 // fixup device stack voodoo part #2
3252 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3255 // set device handle data
3257 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3261 //=================================================================================================
3263 // USB Device Interface functions
3268 USBDI_GetUSBDIVersion(
3270 PUSBD_VERSION_INFORMATION VersionInformation
,
3271 PULONG HcdCapabilites
)
3273 CHubController
* Controller
;
3274 PUSBHARDWAREDEVICE Device
;
3275 ULONG Speed
, Dummy2
;
3278 DPRINT1("USBDI_GetUSBDIVersion\n");
3283 Controller
= (CHubController
*)BusContext
;
3288 Device
= Controller
->GetUsbHardware();
3291 if (VersionInformation
)
3294 // windows xp supported
3296 VersionInformation
->USBDI_Version
= 0x00000500;
3301 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3304 // store speed details
3306 VersionInformation
->Supported_USB_Version
= Speed
;
3310 // no flags supported
3312 *HcdCapabilites
= 0;
3319 PULONG CurrentFrame
)
3322 return STATUS_NOT_IMPLEMENTED
;
3327 USBDI_SubmitIsoOutUrb(
3332 return STATUS_NOT_IMPLEMENTED
;
3337 USBDI_QueryBusInformation(
3340 PVOID BusInformationBuffer
,
3341 PULONG BusInformationBufferLength
,
3342 PULONG BusInformationActualLength
)
3345 return STATUS_NOT_IMPLEMENTED
;
3350 USBDI_IsDeviceHighSpeed(
3353 CHubController
* Controller
;
3354 PUSBHARDWAREDEVICE Device
;
3355 ULONG Speed
, Dummy2
;
3358 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3363 Controller
= (CHubController
*)BusContext
;
3368 Device
= Controller
->GetUsbHardware();
3374 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3377 // USB 2.0 equals 0x200
3379 return (Speed
== 0x200);
3392 return STATUS_NOT_IMPLEMENTED
;
3396 CHubController::HandleQueryInterface(
3397 PIO_STACK_LOCATION IoStack
)
3399 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3400 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3401 UNICODE_STRING GuidBuffer
;
3404 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3407 // get request parameters
3409 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3410 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3415 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3417 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3420 // version not supported
3422 return STATUS_NOT_SUPPORTED
;
3426 // Interface version 0
3428 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3430 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3431 InterfaceHub
->BusContext
= PVOID(this);
3432 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3433 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3437 // Interface version 1
3439 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3441 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3442 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3443 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3444 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3445 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3446 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3450 // Interface version 2
3452 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3454 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3455 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3456 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3457 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3458 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3459 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3464 // Interface version 3
3466 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3468 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3472 // Interface version 4
3474 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3476 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3480 // Interface version 5
3482 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3484 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3488 // request completed
3490 return STATUS_SUCCESS
;
3492 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3495 // get request parameters
3497 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3498 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3503 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3505 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3508 // version not supported
3510 return STATUS_NOT_SUPPORTED
;
3514 // interface version 0
3516 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3518 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3519 InterfaceDI
->BusContext
= PVOID(this);
3520 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3521 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3522 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3523 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3524 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3525 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3529 // interface version 1
3531 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3533 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3537 // interface version 2
3539 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3541 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3545 // request completed
3547 return STATUS_SUCCESS
;
3552 // convert guid to string
3554 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3555 if (NT_SUCCESS(Status
))
3560 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3565 RtlFreeUnicodeString(&GuidBuffer
);
3568 return STATUS_NOT_SUPPORTED
;
3572 CHubController::SetDeviceInterface(
3575 NTSTATUS Status
= STATUS_SUCCESS
;
3580 // register device interface
3582 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3584 if (NT_SUCCESS(Status
))
3587 // now enable the device interface
3589 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3594 m_InterfaceEnabled
= TRUE
;
3597 else if (m_InterfaceEnabled
)
3600 // disable device interface
3602 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3604 if (NT_SUCCESS(Status
))
3607 // now delete interface string
3609 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3613 // disable interface
3615 m_InterfaceEnabled
= FALSE
;
3621 return STATUS_SUCCESS
;
3625 CHubController::CreatePDO(
3626 PDRIVER_OBJECT DriverObject
,
3627 PDEVICE_OBJECT
* OutDeviceObject
)
3629 WCHAR CharDeviceName
[64];
3631 ULONG UsbDeviceNumber
= 0;
3632 UNICODE_STRING DeviceName
;
3637 // construct device name
3639 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3642 // initialize device name
3644 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3649 Status
= IoCreateDevice(DriverObject
,
3650 sizeof(COMMON_DEVICE_EXTENSION
),
3652 FILE_DEVICE_CONTROLLER
,
3657 /* check for success */
3658 if (NT_SUCCESS(Status
))
3662 // is there a device object with that same name
3664 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3667 // Try the next name
3674 // bail out on other errors
3676 if (!NT_SUCCESS(Status
))
3678 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3683 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3686 // fixup device stack voodoo part #1
3688 (*OutDeviceObject
)->StackSize
++;
3697 CreateHubController(
3698 PHUBCONTROLLER
*OutHcdController
)
3700 PHUBCONTROLLER This
;
3703 // allocate controller
3705 This
= new(NonPagedPool
, TAG_USBEHCI
) CHubController(0);
3709 // failed to allocate
3711 return STATUS_INSUFFICIENT_RESOURCES
;
3715 // add reference count
3722 *OutHcdController
= (PHUBCONTROLLER
)This
;
3727 return STATUS_SUCCESS
;
3730 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3732 CHubController
* This
;
3734 This
= (CHubController
*)Context
;
3738 Irp
= This
->m_PendingSCEIrp
;
3741 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3745 This
->m_PendingSCEIrp
= NULL
;
3746 This
->QueryStatusChageEndpoint(Irp
);
3748 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3749 Irp
->IoStatus
.Information
= 0;
3751 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);