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
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
64 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
65 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
70 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
72 // constructor / destructor
73 CHubController(IUnknown
*OuterUnknown
){}
74 virtual ~CHubController(){}
78 PHCDCONTROLLER m_Controller
;
79 PUSBHARDWAREDEVICE m_Hardware
;
80 BOOLEAN m_IsRootHubDevice
;
81 ULONG m_DeviceAddress
;
83 BOOLEAN m_InterfaceEnabled
;
84 UNICODE_STRING m_HubDeviceInterfaceString
;
86 PDEVICE_OBJECT m_HubControllerDeviceObject
;
87 PDRIVER_OBJECT m_DriverObject
;
89 PVOID m_HubCallbackContext
;
90 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
92 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
95 RTL_BITMAP m_DeviceAddressBitmap
;
96 PULONG m_DeviceAddressBitmapBuffer
;
97 LIST_ENTRY m_UsbDeviceList
;
101 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
108 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
110 /* Lifted from Linux with slight changes */
111 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
114 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
115 0x00, 0x20, /* bcdUSB; v1.1 */
116 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
117 0x01, /* bDeviceSubClass; */
118 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
119 0x08, /* bMaxPacketSize0; 8 Bytes */
120 /* Fill Vendor and Product in when init root hub */
121 0x00, 0x00, /* idVendor; */
122 0x00, 0x00, /* idProduct; */
123 0x00, 0x00, /* bcdDevice */
124 0x00, /* iManufacturer; */
125 0x00, /* iProduct; */
126 0x00, /* iSerialNumber; */
127 0x01 /* bNumConfigurations; */
131 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR
[] =
133 /* one configuration */
135 0x02, /* bDescriptorType; Configuration */
136 0x19, 0x00, /* wTotalLength; */
137 0x01, /* bNumInterfaces; (1) */
138 0x23, /* bConfigurationValue; */
139 0x00, /* iConfiguration; */
140 0x40, /* bmAttributes; */
144 const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR
[] =
147 0x09, /* bLength: Interface; */
148 0x04, /* bDescriptorType; Interface */
149 0x00, /* bInterfaceNumber; */
150 0x00, /* bAlternateSetting; */
151 0x01, /* bNumEndpoints; */
152 0x09, /* bInterfaceClass; HUB_CLASSCODE */
153 0x01, /* bInterfaceSubClass; */
154 0x00, /* bInterfaceProtocol: */
155 0x00 /* iInterface; */
158 const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR
[] =
160 /* one endpoint (status change endpoint) */
162 0x05, /* bDescriptorType; Endpoint */
163 0x81, /* bEndpointAddress; IN Endpoint 1 */
164 0x03, /* bmAttributes; Interrupt */
165 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
166 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
169 //----------------------------------------------------------------------------------------
172 CHubController::QueryInterface(
176 return STATUS_UNSUCCESSFUL
;
178 //----------------------------------------------------------------------------------------
180 CHubController::Initialize(
181 IN PDRIVER_OBJECT DriverObject
,
182 IN PHCDCONTROLLER Controller
,
183 IN PUSBHARDWAREDEVICE Device
,
184 IN BOOLEAN IsRootHubDevice
,
185 IN ULONG DeviceAddress
)
188 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
189 USHORT VendorID
, DeviceID
;
192 DPRINT1("CHubController::Initialize\n");
195 // initialize members
197 m_Controller
= Controller
;
199 m_IsRootHubDevice
= IsRootHubDevice
;
200 m_DeviceAddress
= DeviceAddress
;
201 m_DriverObject
= DriverObject
;
202 KeInitializeSpinLock(&m_Lock
);
203 InitializeListHead(&m_UsbDeviceList
);
206 // allocate device address bitmap buffer
208 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBEHCI
);
209 if (!m_DeviceAddressBitmapBuffer
)
214 return STATUS_INSUFFICIENT_RESOURCES
;
218 // initialize device address bitmap
220 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
221 RtlClearAllBits(&m_DeviceAddressBitmap
);
227 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
228 if (!NT_SUCCESS(Status
))
231 // failed to create hub device object
237 // get device extension
239 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
242 // initialize device extension
244 DeviceExtension
->IsFDO
= FALSE
;
245 DeviceExtension
->IsHub
= TRUE
; //FIXME
246 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
249 // intialize device descriptor
251 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
252 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
254 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
257 // update device descriptor
259 m_DeviceDescriptor
.idVendor
= VendorID
;
260 m_DeviceDescriptor
.idProduct
= DeviceID
;
261 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
265 // Set the SCE Callback that the Hardware Device will call on port status change
267 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
271 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
274 return STATUS_SUCCESS
;
278 // Queries the ports to see if there has been a device connected or removed.
281 CHubController::QueryStatusChageEndpoint(
284 ULONG PortCount
, PortId
;
285 PIO_STACK_LOCATION IoStack
;
286 USHORT PortStatus
, PortChange
;
290 // get current stack location
292 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
298 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
302 // Get the number of ports and check each one for device connected
304 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
305 DPRINT1("SCE Request\n");
306 ((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 0;
307 for (PortId
= 0; PortId
< PortCount
; PortId
++)
309 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
311 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
316 if ((PortStatus
& USB_PORT_STATUS_CONNECT
) && (PortChange
& USB_PORT_STATUS_CONNECT
))
318 DPRINT1("Device is connected on port %d\n", PortId
);
319 // Set the value for the port number
320 ((PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 1 << ((PortId
+ 1) & 7);
325 // If there were changes then return TRUE
327 if (((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] != 0)
333 //-----------------------------------------------------------------------------------------
335 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
338 // store controller object
340 *HubDeviceObject
= m_HubControllerDeviceObject
;
342 return STATUS_SUCCESS
;
344 //-----------------------------------------------------------------------------------------
346 CHubController::GetHubControllerSymbolicLink(
349 PULONG RequiredLength
)
351 if (!m_InterfaceEnabled
)
354 // device interface not yet enabled
356 return STATUS_UNSUCCESSFUL
;
359 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
363 // length is without '\??\'
365 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
370 return STATUS_BUFFER_OVERFLOW
;
374 // copy symbolic link
376 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
379 // store length, length is without '\??\'
381 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
386 return STATUS_SUCCESS
;
389 //-----------------------------------------------------------------------------------------
391 CHubController::HandlePnp(
392 IN PDEVICE_OBJECT DeviceObject
,
395 PIO_STACK_LOCATION IoStack
;
396 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
397 PDEVICE_CAPABILITIES DeviceCapabilities
;
398 PPNP_BUS_INFORMATION BusInformation
;
399 PDEVICE_RELATIONS DeviceRelations
;
401 ULONG Index
= 0, Length
;
402 USHORT VendorID
, DeviceID
;
403 ULONG HiSpeed
, NumPorts
;
408 // get device extension
410 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
415 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
418 // get current stack location
420 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
422 switch(IoStack
->MinorFunction
)
424 case IRP_MN_START_DEVICE
:
426 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
428 // register device interface
430 Status
= SetDeviceInterface(TRUE
);
433 case IRP_MN_QUERY_ID
:
435 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
437 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
444 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
446 if (HiSpeed
== 0x200)
451 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
458 swprintf(Buffer
, L
"USB\\ROOT_HUB");
461 DPRINT1("Name %S\n", Buffer
);
466 Length
= (wcslen(Buffer
) + 1);
471 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBEHCI
);
478 Status
= STATUS_INSUFFICIENT_RESOURCES
;
485 wcscpy(DeviceName
, Buffer
);
490 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
491 Status
= STATUS_SUCCESS
;
494 Status
= STATUS_UNSUCCESSFUL
;
499 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
506 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
515 if (HiSpeed
== 0x200)
520 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
521 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
522 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
529 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
530 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
531 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
534 Buffer
[Index
] = UNICODE_NULL
;
538 DPRINT1("Name %S\n", Buffer
);
543 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBEHCI
);
550 Status
= STATUS_INSUFFICIENT_RESOURCES
;
557 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
562 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
563 Status
= STATUS_SUCCESS
;
567 Status
= STATUS_SUCCESS
;
570 case IRP_MN_QUERY_CAPABILITIES
:
572 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
574 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
576 DeviceCapabilities
->LockSupported
= FALSE
;
577 DeviceCapabilities
->EjectSupported
= FALSE
;
578 DeviceCapabilities
->Removable
= FALSE
;
579 DeviceCapabilities
->DockDevice
= FALSE
;
580 DeviceCapabilities
->UniqueID
= FALSE
;
581 DeviceCapabilities
->SilentInstall
= FALSE
;
582 DeviceCapabilities
->RawDeviceOK
= FALSE
;
583 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
584 DeviceCapabilities
->Address
= 0;
585 DeviceCapabilities
->UINumber
= 0;
586 DeviceCapabilities
->DeviceD2
= 1;
589 DeviceCapabilities
->HardwareDisabled
= FALSE
;
590 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
591 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
592 for (Index
= 0; Index
< PowerSystemMaximum
; Index
++)
593 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
594 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
595 DeviceCapabilities
->D1Latency
= 0;
596 DeviceCapabilities
->D2Latency
= 0;
597 DeviceCapabilities
->D3Latency
= 0;
599 Status
= STATUS_SUCCESS
;
602 case IRP_MN_QUERY_INTERFACE
:
604 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
607 // handle device interface requests
609 Status
= HandleQueryInterface(IoStack
);
612 case IRP_MN_REMOVE_DEVICE
:
614 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
617 // deactivate device interface for BUS PDO
619 SetDeviceInterface(FALSE
);
622 // complete the request first
624 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
625 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
630 IoDeleteDevice(m_HubControllerDeviceObject
);
635 m_HubControllerDeviceObject
= 0;
640 return STATUS_SUCCESS
;
642 case IRP_MN_QUERY_DEVICE_RELATIONS
:
644 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
646 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
649 // allocate device relations
651 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBEHCI
);
652 if (!DeviceRelations
)
657 Status
= STATUS_INSUFFICIENT_RESOURCES
;
662 // initialize device relations
664 DeviceRelations
->Count
= 1;
665 DeviceRelations
->Objects
[0] = DeviceObject
;
666 ObReferenceObject(DeviceObject
);
671 Status
= STATUS_SUCCESS
;
672 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
679 Status
= Irp
->IoStatus
.Status
;
683 case IRP_MN_QUERY_BUS_INFORMATION
:
685 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
688 // allocate buffer for bus information
690 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
696 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
701 BusInformation
->LegacyBusType
= PNPBus
;
702 BusInformation
->BusNumber
= 0;
704 Status
= STATUS_SUCCESS
;
705 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
712 Status
= STATUS_INSUFFICIENT_RESOURCES
;
716 case IRP_MN_STOP_DEVICE
:
718 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
722 Status
= STATUS_SUCCESS
;
728 // ignore request with default status
730 Status
= Irp
->IoStatus
.Status
;
738 Irp
->IoStatus
.Status
= Status
;
739 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
747 //-----------------------------------------------------------------------------------------
749 CHubController::HandlePower(
750 IN PDEVICE_OBJECT DeviceObject
,
754 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
755 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
756 return STATUS_NOT_IMPLEMENTED
;
758 //-----------------------------------------------------------------------------------------
760 CHubController::HandleBulkOrInterruptTransfer(
765 // First check if the request is for the Status Change Endpoint
769 // Is the Request for the root hub
771 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
773 ASSERT(m_PendingSCEIrp
== NULL
);
774 if (QueryStatusChageEndpoint(Irp
))
776 return STATUS_SUCCESS
;
780 // Else pend the IRP, to be completed when a device connects or disconnects.
782 m_PendingSCEIrp
= Irp
;
783 IoMarkIrpPending(Irp
);
784 return STATUS_PENDING
;
788 return STATUS_NOT_IMPLEMENTED
;
791 //-----------------------------------------------------------------------------------------
793 CHubController::HandleClassOther(
797 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
798 USHORT PortStatus
= 0, PortChange
= 0;
803 //DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
806 // get number of ports available
808 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
809 PC_ASSERT(Status
== STATUS_SUCCESS
);
814 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
817 // port range reported start from 1 -n
818 // convert back port id so it matches the hardware
820 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
823 // check request code
825 switch(Urb
->UrbControlVendorClassRequest
.Request
)
827 case USB_REQUEST_GET_STATUS
:
832 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
833 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
838 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
840 if (NT_SUCCESS(Status
))
843 // request contains buffer of 2 ushort which are used from submitting port status and port change status
845 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
848 // store status, then port change
850 *Buffer
= PortStatus
;
852 *Buffer
= PortChange
;
860 case USB_REQUEST_CLEAR_FEATURE
:
862 switch (Urb
->UrbControlVendorClassRequest
.Value
)
864 case C_PORT_CONNECTION
:
865 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
868 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
871 DPRINT("Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
875 Status
= STATUS_SUCCESS
;
878 case USB_REQUEST_SET_FEATURE
:
881 // request set feature
883 switch(Urb
->UrbControlVendorClassRequest
.Value
)
888 // port enable is a no-op for EHCI
890 Status
= STATUS_SUCCESS
;
897 // set suspend port feature
899 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
905 // set power feature on port
907 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
914 // reset port feature
916 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
917 PC_ASSERT(Status
== STATUS_SUCCESS
);
921 DPRINT1("Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
927 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
929 Status
= STATUS_INVALID_DEVICE_REQUEST
;
934 //-----------------------------------------------------------------------------------------
936 CHubController::HandleSelectConfiguration(
940 PUSBDEVICE UsbDevice
;
943 // is the request for the Root Hub
945 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
948 // FIXME: support setting device to unconfigured state
950 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
955 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
958 // TODO: copy interface info
960 return STATUS_SUCCESS
;
965 // check if this is a valid usb device handle
967 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
972 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
975 // select configuration
977 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
981 //-----------------------------------------------------------------------------------------
983 CHubController::HandleSelectInterface(
987 PUSBDEVICE UsbDevice
;
992 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
995 // is the request for the Root Hub
997 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1000 // no op for root hub
1002 return STATUS_SUCCESS
;
1007 // check if this is a valid usb device handle
1009 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1014 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1019 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1023 //-----------------------------------------------------------------------------------------
1025 CHubController::HandleGetStatusFromDevice(
1034 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1035 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1036 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1037 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
1040 // get status buffer
1042 Status
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1045 // FIXME need more flags ?
1047 *Status
= USB_PORT_STATUS_CONNECT
;
1052 return STATUS_SUCCESS
;
1055 //-----------------------------------------------------------------------------------------
1057 CHubController::HandleClassDevice(
1061 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1062 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1063 ULONG PortCount
, Dummy2
;
1067 // check class request type
1069 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1071 case USB_REQUEST_GET_DESCRIPTOR
:
1073 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1075 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1076 case USB_DEVICE_CLASS_HUB
:
1081 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1082 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1085 // get hub descriptor
1087 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1090 // one hub is handled
1092 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1093 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1096 // type should 0x29 according to msdn
1098 UsbHubDescriptor
->bDescriptorType
= 0x29;
1103 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1104 PC_ASSERT(Status
== STATUS_SUCCESS
);
1107 // FIXME: retrieve values
1109 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1110 UsbHubDescriptor
->wHubCharacteristics
= 0x0012;
1111 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1112 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1117 Status
= STATUS_SUCCESS
;
1121 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1127 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1132 //-----------------------------------------------------------------------------------------
1134 CHubController::HandleGetDescriptor(
1138 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1139 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1140 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1142 PUSBDEVICE UsbDevice
;
1146 // check descriptor type
1148 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1150 case USB_DEVICE_DESCRIPTOR_TYPE
:
1155 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1156 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1158 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1161 // copy root hub device descriptor
1163 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1164 Status
= STATUS_SUCCESS
;
1169 // check if this is a valid usb device handle
1171 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1176 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1179 // retrieve device descriptor from device
1181 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1182 Status
= STATUS_SUCCESS
;
1186 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1191 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1192 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1194 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1197 // request is for the root bus controller
1199 C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR
) == sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1200 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1203 // get configuration descriptor, very retarded!
1205 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1208 // check if buffer can hold interface and endpoint descriptor
1210 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1215 Status
= STATUS_SUCCESS
;
1220 // copy interface descriptor template
1222 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1223 C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR
) == sizeof(USB_INTERFACE_DESCRIPTOR
));
1224 RtlCopyMemory(Buffer
, ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1227 // copy end point descriptor template
1229 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1230 C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR
) == sizeof(USB_ENDPOINT_DESCRIPTOR
));
1231 RtlCopyMemory(Buffer
, ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1236 Status
= STATUS_SUCCESS
;
1241 DPRINT1("Length %u\n", Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1244 // check if this is a valid usb device handle
1246 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1251 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1253 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1258 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1263 Status
= STATUS_SUCCESS
;
1268 // perform work in IUSBDevice
1270 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1275 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= Length
);
1278 // store result size
1280 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1281 Status
= STATUS_SUCCESS
;
1285 case USB_STRING_DESCRIPTOR_TYPE
:
1290 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1291 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1295 // check if this is a valid usb device handle
1297 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1302 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1305 // generate setup packet
1307 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1308 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1309 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1310 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1311 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1312 CtrlSetup
.bmRequestType
.B
= 0x80;
1315 // submit setup packet
1317 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1321 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1331 //-----------------------------------------------------------------------------------------
1333 CHubController::HandleDeviceControl(
1334 IN PDEVICE_OBJECT DeviceObject
,
1337 PIO_STACK_LOCATION IoStack
;
1338 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1340 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1343 // get current stack location
1345 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1348 // get device extension
1350 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1353 // determine which request should be performed
1355 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1357 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
1362 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1365 switch (Urb
->UrbHeader
.Function
)
1367 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1368 Status
= HandleGetDescriptor(Irp
, Urb
);
1370 case URB_FUNCTION_CLASS_DEVICE
:
1371 Status
= HandleClassDevice(Irp
, Urb
);
1373 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1374 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
1376 case URB_FUNCTION_SELECT_CONFIGURATION
:
1377 Status
= HandleSelectConfiguration(Irp
, Urb
);
1379 case URB_FUNCTION_SELECT_INTERFACE
:
1380 Status
= HandleSelectInterface(Irp
, Urb
);
1382 case URB_FUNCTION_CLASS_OTHER
:
1383 Status
= HandleClassOther(Irp
, Urb
);
1385 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
1386 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
1389 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
1393 // request completed
1397 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
1399 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
1401 if (IoStack
->Parameters
.Others
.Argument1
)
1404 // store object as device handle
1406 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
1407 Status
= STATUS_SUCCESS
;
1412 // mis-behaving hub driver
1414 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1418 // request completed
1422 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
1424 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1427 // this is the first request send, it delivers the PDO to the caller
1429 if (IoStack
->Parameters
.Others
.Argument1
)
1432 // store root hub pdo object
1434 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
1437 if (IoStack
->Parameters
.Others
.Argument2
)
1440 // documentation claims to deliver the hcd controller object, although it is wrong
1442 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
1446 // request completed
1448 Status
= STATUS_SUCCESS
;
1451 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
1453 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1456 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1457 // requests this ioctl to deliver the number of presents.
1459 if (IoStack
->Parameters
.Others
.Argument1
)
1462 // FIXME / verify: there is only one hub
1464 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
1468 // request completed
1470 Status
= STATUS_SUCCESS
;
1471 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1474 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
1476 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1477 Status
= STATUS_SUCCESS
;
1482 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1483 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1484 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
1485 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
1489 if (Status
!= STATUS_PENDING
)
1491 Irp
->IoStatus
.Status
= Status
;
1492 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1498 //-----------------------------------------------------------------------------------------
1500 CHubController::GetUsbHardware()
1505 //-----------------------------------------------------------------------------------------
1507 CHubController::AcquireDeviceAddress()
1510 ULONG DeviceAddress
;
1513 // acquire device lock
1515 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1520 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
1521 if (DeviceAddress
!= MAXULONG
)
1526 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1529 // device addresses start from 0x1 - 0xFF
1535 // release spin lock
1537 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1540 // return device address
1542 return DeviceAddress
;
1544 //-----------------------------------------------------------------------------------------
1546 CHubController::ReleaseDeviceAddress(
1547 ULONG DeviceAddress
)
1552 // acquire device lock
1554 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1559 PC_ASSERT(DeviceAddress
!= 0);
1562 // convert back to bit number
1569 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1574 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1576 //-----------------------------------------------------------------------------------------
1578 CHubController::RemoveUsbDevice(
1579 PUSBDEVICE UsbDevice
)
1581 PUSBDEVICE_ENTRY DeviceEntry
;
1583 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1589 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1592 // point to first entry
1594 Entry
= m_UsbDeviceList
.Flink
;
1597 // find matching entry
1599 while(Entry
!= &m_UsbDeviceList
)
1604 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1607 // is it current entry
1609 if (DeviceEntry
->Device
== UsbDevice
)
1614 RemoveEntryList(Entry
);
1619 ExFreePoolWithTag(DeviceEntry
, TAG_USBEHCI
);
1624 Status
= STATUS_SUCCESS
;
1631 Entry
= Entry
->Flink
;
1637 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1644 //-----------------------------------------------------------------------------------------
1646 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
1648 PUSBDEVICE_ENTRY DeviceEntry
;
1651 BOOLEAN Result
= FALSE
;
1656 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1659 // point to first entry
1661 Entry
= m_UsbDeviceList
.Flink
;
1664 // find matching entry
1666 while(Entry
!= &m_UsbDeviceList
)
1671 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1674 // is it current entry
1676 if (DeviceEntry
->Device
== UsbDevice
)
1688 Entry
= Entry
->Flink
;
1694 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1703 //-----------------------------------------------------------------------------------------
1705 CHubController::AddUsbDevice(
1706 PUSBDEVICE UsbDevice
)
1708 PUSBDEVICE_ENTRY DeviceEntry
;
1712 // allocate device entry
1714 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBEHCI
);
1720 return STATUS_INSUFFICIENT_RESOURCES
;
1726 DeviceEntry
->Device
= UsbDevice
;
1731 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1736 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
1739 // release spin lock
1741 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1746 return STATUS_SUCCESS
;
1749 //-----------------------------------------------------------------------------------------
1751 CHubController::SetNotification(
1752 PVOID CallbackContext
,
1753 PRH_INIT_CALLBACK CallbackRoutine
)
1758 // acquire hub controller lock
1760 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1763 // now set the callback routine and context of the hub
1765 m_HubCallbackContext
= CallbackContext
;
1766 m_HubCallbackRoutine
= CallbackRoutine
;
1769 // release hub controller lock
1771 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1774 //=================================================================================================
1776 // Generic Interface functions
1780 USBI_InterfaceReference(
1783 CHubController
* Controller
= (CHubController
*)BusContext
;
1785 DPRINT1("USBH_InterfaceReference\n");
1790 Controller
->AddRef();
1795 USBI_InterfaceDereference(
1798 CHubController
* Controller
= (CHubController
*)BusContext
;
1800 DPRINT1("USBH_InterfaceDereference\n");
1805 Controller
->Release();
1807 //=================================================================================================
1809 // USB Hub Interface functions
1813 USBHI_CreateUsbDevice(
1815 PUSB_DEVICE_HANDLE
*NewDevice
,
1816 PUSB_DEVICE_HANDLE HubDeviceHandle
,
1820 PUSBDEVICE NewUsbDevice
;
1821 CHubController
* Controller
;
1824 DPRINT1("USBHI_CreateUsbDevice\n");
1827 // first get hub controller
1829 Controller
= (CHubController
*)BusContext
;
1834 PC_ASSERT(Controller
);
1835 PC_ASSERT(BusContext
== HubDeviceHandle
);
1838 // now allocate usb device
1840 Status
= CreateUSBDevice(&NewUsbDevice
);
1843 // check for success
1845 if (!NT_SUCCESS(Status
))
1848 // release controller
1850 Controller
->Release();
1851 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
1856 // now initialize device
1858 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
1861 // check for success
1863 if (!NT_SUCCESS(Status
))
1866 // release usb device
1868 NewUsbDevice
->Release();
1869 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
1876 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
1878 // check for success
1880 if (!NT_SUCCESS(Status
))
1883 // release usb device
1885 NewUsbDevice
->Release();
1887 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
1894 *NewDevice
= NewUsbDevice
;
1899 return STATUS_SUCCESS
;
1904 USBHI_InitializeUsbDevice(
1906 PUSB_DEVICE_HANDLE DeviceHandle
)
1908 PUSBDEVICE UsbDevice
;
1909 CHubController
* Controller
;
1910 ULONG DeviceAddress
;
1914 DPRINT1("USBHI_InitializeUsbDevice\n");
1917 // first get controller
1919 Controller
= (CHubController
*)BusContext
;
1920 PC_ASSERT(Controller
);
1923 // get device object
1925 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
1926 PC_ASSERT(UsbDevice
);
1929 // validate device handle
1931 if (!Controller
->ValidateUsbDevice(UsbDevice
))
1933 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
1936 // invalid device handle
1938 return STATUS_DEVICE_NOT_CONNECTED
;
1942 // now reserve an address
1944 DeviceAddress
= Controller
->AcquireDeviceAddress();
1947 // is the device address valid
1949 if (DeviceAddress
== MAXULONG
)
1952 // failed to get an device address from the device address pool
1954 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
1955 return STATUS_DEVICE_DATA_ERROR
;
1961 // now set the device address
1963 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
1965 if (NT_SUCCESS(Status
))
1968 }while(Index
++ < 3 );
1971 // check for failure
1973 if (!NT_SUCCESS(Status
))
1976 // failed to set device address
1978 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
1983 Controller
->ReleaseDeviceAddress(DeviceAddress
);
1988 return STATUS_DEVICE_DATA_ERROR
;
1994 return STATUS_SUCCESS
;
1999 USBHI_GetUsbDescriptors(
2001 PUSB_DEVICE_HANDLE DeviceHandle
,
2002 PUCHAR DeviceDescriptorBuffer
,
2003 PULONG DeviceDescriptorBufferLength
,
2004 PUCHAR ConfigDescriptorBuffer
,
2005 PULONG ConfigDescriptorBufferLength
)
2007 PUSBDEVICE UsbDevice
;
2008 CHubController
* Controller
;
2010 DPRINT1("USBHI_GetUsbDescriptors\n");
2015 PC_ASSERT(DeviceDescriptorBuffer
);
2016 PC_ASSERT(DeviceDescriptorBufferLength
);
2017 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2018 PC_ASSERT(ConfigDescriptorBufferLength
);
2019 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2022 // first get controller
2024 Controller
= (CHubController
*)BusContext
;
2025 PC_ASSERT(Controller
);
2029 // get device object
2031 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2032 PC_ASSERT(UsbDevice
);
2035 // validate device handle
2037 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2039 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2042 // invalid device handle
2044 return STATUS_DEVICE_NOT_CONNECTED
;
2048 // get device descriptor
2050 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2053 // store result length
2055 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2058 // get configuration descriptor
2060 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2063 // complete the request
2065 return STATUS_SUCCESS
;
2070 USBHI_RemoveUsbDevice(
2072 PUSB_DEVICE_HANDLE DeviceHandle
,
2075 PUSBDEVICE UsbDevice
;
2076 CHubController
* Controller
;
2079 DPRINT1("USBHI_RemoveUsbDevice\n");
2082 // first get controller
2084 Controller
= (CHubController
*)BusContext
;
2085 PC_ASSERT(Controller
);
2088 // get device object
2090 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2091 PC_ASSERT(UsbDevice
);
2094 // validate device handle
2096 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2098 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2101 // invalid device handle
2103 return STATUS_DEVICE_NOT_CONNECTED
;
2107 // check if there were flags passed
2109 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2112 // ignore flags for now
2114 return STATUS_SUCCESS
;
2120 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2121 if (!NT_SUCCESS(Status
))
2124 // invalid device handle
2126 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2128 return STATUS_DEVICE_NOT_CONNECTED
;
2132 // release usb device
2134 UsbDevice
->Release();
2139 return STATUS_SUCCESS
;
2144 USBHI_RestoreUsbDevice(
2146 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2147 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2149 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2150 CHubController
* Controller
;
2153 DPRINT1("USBHI_RestoreUsbDevice\n");
2156 // first get controller
2158 Controller
= (CHubController
*)BusContext
;
2159 PC_ASSERT(Controller
);
2162 // get device object
2164 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2165 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2166 PC_ASSERT(OldUsbDevice
);
2167 PC_ASSERT(NewDeviceHandle
);
2170 // validate device handle
2172 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2173 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2175 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2178 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2183 // remove old device handle
2185 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2187 return STATUS_SUCCESS
;
2192 USBHI_QueryDeviceInformation(
2194 PUSB_DEVICE_HANDLE DeviceHandle
,
2195 PVOID DeviceInformationBuffer
,
2196 ULONG DeviceInformationBufferLength
,
2197 PULONG LengthReturned
)
2199 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2200 PUSBDEVICE UsbDevice
;
2201 CHubController
* Controller
;
2203 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2208 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2209 PC_ASSERT(DeviceInformationBuffer
);
2210 PC_ASSERT(LengthReturned
);
2213 // get controller object
2215 Controller
= (CHubController
*)BusContext
;
2216 PC_ASSERT(Controller
);
2219 // get device object
2221 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2222 PC_ASSERT(UsbDevice
);
2224 if (BusContext
!= DeviceHandle
)
2227 // validate device handle
2229 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2231 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2234 // invalid device handle
2236 return STATUS_DEVICE_NOT_CONNECTED
;
2240 // access information buffer
2242 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2245 // initialize with default values
2247 DeviceInfo
->InformationLevel
= 0;
2248 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2249 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2250 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2251 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2252 DeviceInfo
->HubAddress
= 0; //FIXME
2253 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2254 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2255 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2258 // get device descriptor
2260 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2263 // FIXME return pipe information
2267 // store result length
2269 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2271 return STATUS_SUCCESS
;
2275 // access information buffer
2277 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2280 // initialize with default values
2282 DeviceInfo
->InformationLevel
= 0;
2283 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2284 DeviceInfo
->PortNumber
= 0;
2285 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2286 DeviceInfo
->DeviceAddress
= 0;
2287 DeviceInfo
->HubAddress
= 0; //FIXME
2288 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
2289 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
2290 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2293 // FIXME get device descriptor
2297 // FIXME return pipe information
2301 // store result length
2303 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2308 return STATUS_SUCCESS
;
2313 USBHI_GetControllerInformation(
2315 PVOID ControllerInformationBuffer
,
2316 ULONG ControllerInformationBufferLength
,
2317 PULONG LengthReturned
)
2319 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2321 DPRINT1("USBHI_GetControllerInformation\n");
2326 PC_ASSERT(ControllerInformationBuffer
);
2327 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2330 // get controller info buffer
2332 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
2335 // FIXME only version 0 is supported for now
2337 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
2340 // fill in information
2342 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
2343 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
2344 ControllerInfo
->IsHighSpeedController
= TRUE
;
2347 // set length returned
2349 *LengthReturned
= ControllerInfo
->ActualLength
;
2354 return STATUS_SUCCESS
;
2359 USBHI_ControllerSelectiveSuspend(
2364 return STATUS_NOT_IMPLEMENTED
;
2369 USBHI_GetExtendedHubInformation(
2371 PDEVICE_OBJECT HubPhysicalDeviceObject
,
2372 PVOID HubInformationBuffer
,
2373 ULONG HubInformationBufferLength
,
2374 PULONG LengthReturned
)
2376 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
2377 CHubController
* Controller
;
2378 PUSBHARDWAREDEVICE Hardware
;
2380 ULONG NumPort
, Dummy2
;
2384 DPRINT1("USBHI_GetExtendedHubInformation\n");
2389 PC_ASSERT(HubInformationBuffer
);
2390 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
2391 PC_ASSERT(LengthReturned
);
2394 // get hub controller
2396 Controller
= (CHubController
*)BusContext
;
2397 PC_ASSERT(Controller
);
2400 // get usb hardware device
2402 Hardware
= Controller
->GetUsbHardware();
2405 // retrieve number of ports
2407 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
2408 if (!NT_SUCCESS(Status
))
2411 // failed to get hardware details, ouch ;)
2413 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
2418 // get hub information buffer
2420 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
2423 // initialize hub information
2425 HubInfo
->InformationLevel
= 0;
2430 HubInfo
->NumberOfPorts
= NumPort
;
2433 // initialize port information
2435 for(Index
= 0; Index
< NumPort
; Index
++)
2437 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
2438 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
2439 HubInfo
->Port
[Index
].VidOverride
= 0;
2440 HubInfo
->Port
[Index
].PidOverride
= 0;
2441 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
2445 // store result length
2448 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
2450 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
2456 return STATUS_SUCCESS
;
2461 USBHI_GetRootHubSymbolicName(
2463 PVOID HubSymNameBuffer
,
2464 ULONG HubSymNameBufferLength
,
2465 PULONG HubSymNameActualLength
)
2468 return STATUS_NOT_IMPLEMENTED
;
2473 USBHI_GetDeviceBusContext(
2474 PVOID HubBusContext
,
2483 USBHI_Initialize20Hub(
2485 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2489 return STATUS_SUCCESS
;
2494 USBHI_RootHubInitNotification(
2496 PVOID CallbackContext
,
2497 PRH_INIT_CALLBACK CallbackRoutine
)
2499 CHubController
* Controller
;
2501 DPRINT1("USBHI_RootHubInitNotification\n");
2504 // get controller object
2506 Controller
= (CHubController
*)BusContext
;
2507 PC_ASSERT(Controller
);
2510 // set notification routine
2512 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
2515 // FIXME: determine when to perform callback
2517 CallbackRoutine(CallbackContext
);
2522 return STATUS_SUCCESS
;
2527 USBHI_FlushTransfers(
2536 USBHI_SetDeviceHandleData(
2539 PDEVICE_OBJECT UsbDevicePdo
)
2541 PUSBDEVICE UsbDevice
;
2542 CHubController
* Controller
;
2547 Controller
= (CHubController
*)BusContext
;
2548 PC_ASSERT(Controller
);
2551 // get device handle
2553 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2556 // validate device handle
2558 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2560 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
2570 // usbhub sends this request as a part of the Pnp startup sequence
2571 // looks like we need apply a dragon voodoo to fixup the device stack
2572 // otherwise usbhub will cause a bugcheck
2574 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
2577 // fixup device stack voodoo part #1
2579 UsbDevicePdo
->StackSize
++;
2584 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
2587 // should be usbstor
2588 // fixup device stack voodoo part #2
2590 UsbDevicePdo
->AttachedDevice
->StackSize
++;
2593 // set device handle data
2595 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
2599 //=================================================================================================
2601 // USB Device Interface functions
2606 USBDI_GetUSBDIVersion(
2608 PUSBD_VERSION_INFORMATION VersionInformation
,
2609 PULONG HcdCapabilites
)
2611 CHubController
* Controller
;
2612 PUSBHARDWAREDEVICE Device
;
2613 ULONG Speed
, Dummy2
;
2616 DPRINT1("USBDI_GetUSBDIVersion\n");
2621 Controller
= (CHubController
*)BusContext
;
2626 Device
= Controller
->GetUsbHardware();
2629 if (VersionInformation
)
2632 // windows xp supported
2634 VersionInformation
->USBDI_Version
= 0x00000500;
2639 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2642 // store speed details
2644 VersionInformation
->Supported_USB_Version
= Speed
;
2648 // no flags supported
2650 *HcdCapabilites
= 0;
2657 PULONG CurrentFrame
)
2660 return STATUS_NOT_IMPLEMENTED
;
2665 USBDI_SubmitIsoOutUrb(
2670 return STATUS_NOT_IMPLEMENTED
;
2675 USBDI_QueryBusInformation(
2678 PVOID BusInformationBuffer
,
2679 PULONG BusInformationBufferLength
,
2680 PULONG BusInformationActualLength
)
2683 return STATUS_NOT_IMPLEMENTED
;
2688 USBDI_IsDeviceHighSpeed(
2691 CHubController
* Controller
;
2692 PUSBHARDWAREDEVICE Device
;
2693 ULONG Speed
, Dummy2
;
2696 DPRINT1("USBDI_IsDeviceHighSpeed\n");
2701 Controller
= (CHubController
*)BusContext
;
2706 Device
= Controller
->GetUsbHardware();
2712 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2715 // USB 2.0 equals 0x200
2717 return (Speed
== 0x200);
2730 return STATUS_NOT_IMPLEMENTED
;
2734 CHubController::HandleQueryInterface(
2735 PIO_STACK_LOCATION IoStack
)
2737 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
2738 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
2739 UNICODE_STRING GuidBuffer
;
2742 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
2745 // get request parameters
2747 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
2748 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2753 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
2755 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2758 // version not supported
2760 return STATUS_NOT_SUPPORTED
;
2764 // Interface version 0
2766 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2768 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2769 InterfaceHub
->BusContext
= PVOID(this);
2770 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
2771 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
2775 // Interface version 1
2777 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2779 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
2780 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
2781 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
2782 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
2783 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
2784 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
2788 // Interface version 2
2790 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2792 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
2793 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
2794 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
2795 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
2796 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
2797 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
2802 // Interface version 3
2804 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2806 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
2810 // Interface version 4
2812 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
2814 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
2818 // Interface version 5
2820 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
2822 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
2826 // request completed
2828 return STATUS_SUCCESS
;
2830 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
2833 // get request parameters
2835 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
2836 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2841 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2843 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2846 // version not supported
2848 return STATUS_NOT_SUPPORTED
;
2852 // interface version 0
2854 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2856 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2857 InterfaceDI
->BusContext
= PVOID(this);
2858 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
2859 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
2860 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
2861 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
2862 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
2863 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
2867 // interface version 1
2869 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2871 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
2875 // interface version 2
2877 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2879 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
2883 // request completed
2885 return STATUS_SUCCESS
;
2890 // convert guid to string
2892 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
2893 if (NT_SUCCESS(Status
))
2898 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
2903 RtlFreeUnicodeString(&GuidBuffer
);
2906 return STATUS_NOT_SUPPORTED
;
2910 CHubController::SetDeviceInterface(
2913 NTSTATUS Status
= STATUS_SUCCESS
;
2918 // register device interface
2920 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
2922 if (NT_SUCCESS(Status
))
2925 // now enable the device interface
2927 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
2932 m_InterfaceEnabled
= TRUE
;
2935 else if (m_InterfaceEnabled
)
2938 // disable device interface
2940 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
2942 if (NT_SUCCESS(Status
))
2945 // now delete interface string
2947 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
2951 // disable interface
2953 m_InterfaceEnabled
= FALSE
;
2963 CHubController::CreatePDO(
2964 PDRIVER_OBJECT DriverObject
,
2965 PDEVICE_OBJECT
* OutDeviceObject
)
2967 WCHAR CharDeviceName
[64];
2969 ULONG UsbDeviceNumber
= 0;
2970 UNICODE_STRING DeviceName
;
2975 // construct device name
2977 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
2980 // initialize device name
2982 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
2987 Status
= IoCreateDevice(DriverObject
,
2988 sizeof(COMMON_DEVICE_EXTENSION
),
2990 FILE_DEVICE_CONTROLLER
,
2995 /* check for success */
2996 if (NT_SUCCESS(Status
))
3000 // is there a device object with that same name
3002 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3005 // Try the next name
3012 // bail out on other errors
3014 if (!NT_SUCCESS(Status
))
3016 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3021 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3030 CreateHubController(
3031 PHUBCONTROLLER
*OutHcdController
)
3033 PHUBCONTROLLER This
;
3036 // allocate controller
3038 This
= new(NonPagedPool
, TAG_USBEHCI
) CHubController(0);
3042 // failed to allocate
3044 return STATUS_INSUFFICIENT_RESOURCES
;
3048 // add reference count
3055 *OutHcdController
= (PHUBCONTROLLER
)This
;
3060 return STATUS_SUCCESS
;
3063 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3065 CHubController
* This
;
3067 This
= (CHubController
*)Context
;
3071 DPRINT1("SCE Notification!\n");
3072 Irp
= This
->m_PendingSCEIrp
;
3073 This
->m_PendingSCEIrp
= NULL
;
3075 This
->QueryStatusChageEndpoint(Irp
);
3077 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3078 Irp
->IoStatus
.Information
= 0;
3079 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);