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
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
71 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
73 // constructor / destructor
74 CHubController(IUnknown
*OuterUnknown
){}
75 virtual ~CHubController(){}
79 PHCDCONTROLLER m_Controller
;
80 PUSBHARDWAREDEVICE m_Hardware
;
81 BOOLEAN m_IsRootHubDevice
;
82 ULONG m_DeviceAddress
;
84 BOOLEAN m_InterfaceEnabled
;
85 UNICODE_STRING m_HubDeviceInterfaceString
;
87 PDEVICE_OBJECT m_HubControllerDeviceObject
;
88 PDRIVER_OBJECT m_DriverObject
;
90 PVOID m_HubCallbackContext
;
91 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
93 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
96 RTL_BITMAP m_DeviceAddressBitmap
;
97 PULONG m_DeviceAddressBitmapBuffer
;
98 LIST_ENTRY m_UsbDeviceList
;
102 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
109 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
111 /* Lifted from Linux with slight changes */
112 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
115 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
116 0x00, 0x20, /* bcdUSB; v1.1 */
117 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
118 0x01, /* bDeviceSubClass; */
119 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
120 0x08, /* bMaxPacketSize0; 8 Bytes */
121 /* Fill Vendor and Product in when init root hub */
122 0x00, 0x00, /* idVendor; */
123 0x00, 0x00, /* idProduct; */
124 0x00, 0x00, /* bcdDevice */
125 0x00, /* iManufacturer; */
126 0x00, /* iProduct; */
127 0x00, /* iSerialNumber; */
128 0x01 /* bNumConfigurations; */
132 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR
[] =
134 /* one configuration */
136 0x02, /* bDescriptorType; Configuration */
137 0x19, 0x00, /* wTotalLength; */
138 0x01, /* bNumInterfaces; (1) */
139 0x23, /* bConfigurationValue; */
140 0x00, /* iConfiguration; */
141 0x40, /* bmAttributes; */
145 const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR
[] =
148 0x09, /* bLength: Interface; */
149 0x04, /* bDescriptorType; Interface */
150 0x00, /* bInterfaceNumber; */
151 0x00, /* bAlternateSetting; */
152 0x01, /* bNumEndpoints; */
153 0x09, /* bInterfaceClass; HUB_CLASSCODE */
154 0x01, /* bInterfaceSubClass; */
155 0x00, /* bInterfaceProtocol: */
156 0x00 /* iInterface; */
159 const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR
[] =
161 /* one endpoint (status change endpoint) */
163 0x05, /* bDescriptorType; Endpoint */
164 0x81, /* bEndpointAddress; IN Endpoint 1 */
165 0x03, /* bmAttributes; Interrupt */
166 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
167 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
170 //----------------------------------------------------------------------------------------
173 CHubController::QueryInterface(
177 return STATUS_UNSUCCESSFUL
;
179 //----------------------------------------------------------------------------------------
181 CHubController::Initialize(
182 IN PDRIVER_OBJECT DriverObject
,
183 IN PHCDCONTROLLER Controller
,
184 IN PUSBHARDWAREDEVICE Device
,
185 IN BOOLEAN IsRootHubDevice
,
186 IN ULONG DeviceAddress
)
189 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
190 USHORT VendorID
, DeviceID
;
193 DPRINT1("CHubController::Initialize\n");
196 // initialize members
198 m_Controller
= Controller
;
200 m_IsRootHubDevice
= IsRootHubDevice
;
201 m_DeviceAddress
= DeviceAddress
;
202 m_DriverObject
= DriverObject
;
203 KeInitializeSpinLock(&m_Lock
);
204 InitializeListHead(&m_UsbDeviceList
);
207 // allocate device address bitmap buffer
209 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBEHCI
);
210 if (!m_DeviceAddressBitmapBuffer
)
215 return STATUS_INSUFFICIENT_RESOURCES
;
219 // initialize device address bitmap
221 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
222 RtlClearAllBits(&m_DeviceAddressBitmap
);
228 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
229 if (!NT_SUCCESS(Status
))
232 // failed to create hub device object
238 // get device extension
240 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
243 // initialize device extension
245 DeviceExtension
->IsFDO
= FALSE
;
246 DeviceExtension
->IsHub
= TRUE
; //FIXME
247 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
250 // intialize device descriptor
252 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
253 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
255 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
258 // update device descriptor
260 m_DeviceDescriptor
.idVendor
= VendorID
;
261 m_DeviceDescriptor
.idProduct
= DeviceID
;
262 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
266 // Set the SCE Callback that the Hardware Device will call on port status change
268 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
272 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
275 return STATUS_SUCCESS
;
279 // Queries the ports to see if there has been a device connected or removed.
282 CHubController::QueryStatusChageEndpoint(
285 ULONG PortCount
, PortId
;
286 PIO_STACK_LOCATION IoStack
;
287 USHORT PortStatus
, PortChange
;
291 // get current stack location
293 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
299 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
303 // Get the number of ports and check each one for device connected
305 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
306 DPRINT1("SCE Request\n");
307 ((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 0;
308 for (PortId
= 0; PortId
< PortCount
; PortId
++)
310 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
312 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
317 if ((PortStatus
& USB_PORT_STATUS_CONNECT
) && (PortChange
& USB_PORT_STATUS_CONNECT
))
319 DPRINT1("Device is connected on port %d\n", PortId
);
320 // Set the value for the port number
321 ((PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 1 << ((PortId
+ 1) & 7);
326 // If there were changes then return TRUE
328 if (((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] != 0)
334 //-----------------------------------------------------------------------------------------
336 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
339 // store controller object
341 *HubDeviceObject
= m_HubControllerDeviceObject
;
343 return STATUS_SUCCESS
;
345 //-----------------------------------------------------------------------------------------
347 CHubController::GetHubControllerSymbolicLink(
350 PULONG RequiredLength
)
352 if (!m_InterfaceEnabled
)
355 // device interface not yet enabled
357 return STATUS_UNSUCCESSFUL
;
360 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
364 // length is without '\??\'
366 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
371 return STATUS_BUFFER_OVERFLOW
;
375 // copy symbolic link
377 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
380 // store length, length is without '\??\'
382 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
387 return STATUS_SUCCESS
;
390 //-----------------------------------------------------------------------------------------
392 CHubController::HandlePnp(
393 IN PDEVICE_OBJECT DeviceObject
,
396 PIO_STACK_LOCATION IoStack
;
397 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
398 PDEVICE_CAPABILITIES DeviceCapabilities
;
399 PPNP_BUS_INFORMATION BusInformation
;
400 PDEVICE_RELATIONS DeviceRelations
;
402 ULONG Index
= 0, Length
;
403 USHORT VendorID
, DeviceID
;
404 ULONG HiSpeed
, NumPorts
;
409 // get device extension
411 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
416 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
419 // get current stack location
421 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
423 switch(IoStack
->MinorFunction
)
425 case IRP_MN_START_DEVICE
:
427 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
429 // register device interface
431 Status
= SetDeviceInterface(TRUE
);
434 case IRP_MN_QUERY_ID
:
436 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
438 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
445 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
447 if (HiSpeed
== 0x200)
452 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
459 swprintf(Buffer
, L
"USB\\ROOT_HUB");
462 DPRINT1("Name %S\n", Buffer
);
467 Length
= (wcslen(Buffer
) + 1);
472 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBEHCI
);
479 Status
= STATUS_INSUFFICIENT_RESOURCES
;
486 wcscpy(DeviceName
, Buffer
);
491 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
492 Status
= STATUS_SUCCESS
;
495 Status
= STATUS_UNSUCCESSFUL
;
500 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
507 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
509 if (!NT_SUCCESS(Status
))
511 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
516 if (HiSpeed
== 0x200)
521 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
522 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
523 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
530 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
531 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
532 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
535 Buffer
[Index
] = UNICODE_NULL
;
539 DPRINT1("Name %S\n", Buffer
);
544 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBEHCI
);
551 Status
= STATUS_INSUFFICIENT_RESOURCES
;
558 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
563 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
564 Status
= STATUS_SUCCESS
;
568 Status
= STATUS_SUCCESS
;
571 case IRP_MN_QUERY_CAPABILITIES
:
573 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
575 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
577 DeviceCapabilities
->LockSupported
= FALSE
;
578 DeviceCapabilities
->EjectSupported
= FALSE
;
579 DeviceCapabilities
->Removable
= FALSE
;
580 DeviceCapabilities
->DockDevice
= FALSE
;
581 DeviceCapabilities
->UniqueID
= FALSE
;
582 DeviceCapabilities
->SilentInstall
= FALSE
;
583 DeviceCapabilities
->RawDeviceOK
= FALSE
;
584 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
585 DeviceCapabilities
->Address
= 0;
586 DeviceCapabilities
->UINumber
= 0;
587 DeviceCapabilities
->DeviceD2
= 1;
590 DeviceCapabilities
->HardwareDisabled
= FALSE
;
591 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
592 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
593 for (Index
= 0; Index
< PowerSystemMaximum
; Index
++)
594 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
595 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
596 DeviceCapabilities
->D1Latency
= 0;
597 DeviceCapabilities
->D2Latency
= 0;
598 DeviceCapabilities
->D3Latency
= 0;
600 Status
= STATUS_SUCCESS
;
603 case IRP_MN_QUERY_INTERFACE
:
605 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
608 // handle device interface requests
610 Status
= HandleQueryInterface(IoStack
);
613 case IRP_MN_REMOVE_DEVICE
:
615 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
618 // deactivate device interface for BUS PDO
620 SetDeviceInterface(FALSE
);
623 // complete the request first
625 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
626 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
631 IoDeleteDevice(m_HubControllerDeviceObject
);
636 m_HubControllerDeviceObject
= 0;
641 return STATUS_SUCCESS
;
643 case IRP_MN_QUERY_DEVICE_RELATIONS
:
645 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
647 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
650 // allocate device relations
652 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBEHCI
);
653 if (!DeviceRelations
)
658 Status
= STATUS_INSUFFICIENT_RESOURCES
;
663 // initialize device relations
665 DeviceRelations
->Count
= 1;
666 DeviceRelations
->Objects
[0] = DeviceObject
;
667 ObReferenceObject(DeviceObject
);
672 Status
= STATUS_SUCCESS
;
673 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
680 Status
= Irp
->IoStatus
.Status
;
684 case IRP_MN_QUERY_BUS_INFORMATION
:
686 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
689 // allocate buffer for bus information
691 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
697 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
702 BusInformation
->LegacyBusType
= PNPBus
;
703 BusInformation
->BusNumber
= 0;
705 Status
= STATUS_SUCCESS
;
706 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
713 Status
= STATUS_INSUFFICIENT_RESOURCES
;
717 case IRP_MN_STOP_DEVICE
:
719 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
723 Status
= STATUS_SUCCESS
;
729 // ignore request with default status
731 Status
= Irp
->IoStatus
.Status
;
739 Irp
->IoStatus
.Status
= Status
;
740 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
748 //-----------------------------------------------------------------------------------------
750 CHubController::HandlePower(
751 IN PDEVICE_OBJECT DeviceObject
,
755 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
756 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
757 return STATUS_NOT_IMPLEMENTED
;
759 //-----------------------------------------------------------------------------------------
761 CHubController::HandleBulkOrInterruptTransfer(
765 PUSBDEVICE UsbDevice
;
766 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
768 // First check if the request is for the Status Change Endpoint
772 // Is the Request for the root hub
774 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
776 ASSERT(m_PendingSCEIrp
== NULL
);
777 if (QueryStatusChageEndpoint(Irp
))
779 return STATUS_SUCCESS
;
783 // Else pend the IRP, to be completed when a device connects or disconnects.
785 DPRINT1("Pending SCE Irp\n");;
786 m_PendingSCEIrp
= Irp
;
787 IoMarkIrpPending(Irp
);
788 return STATUS_PENDING
;
792 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
794 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
796 switch(EndPointDesc
->bmAttributes
& 0x0F)
798 case USB_ENDPOINT_TYPE_CONTROL
:
799 DPRINT1("Control Transfer is not expected!!!\n");
800 return STATUS_INVALID_DEVICE_REQUEST
;
801 case USB_ENDPOINT_TYPE_BULK
:
802 DPRINT("Initiating Bulk Transfer\n");
804 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
805 case USB_ENDPOINT_TYPE_INTERRUPT
:
806 DPRINT1("Not Supported\n");
809 DPRINT1("Unknown EndPoint Type!\n");
814 // check if this is a valid usb device handle
816 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
821 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
823 return UsbDevice
->SubmitIrp(Irp
);
826 //-----------------------------------------------------------------------------------------
828 CHubController::HandleClassOther(
832 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
833 USHORT PortStatus
= 0, PortChange
= 0;
838 //DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
841 // get number of ports available
843 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
844 PC_ASSERT(Status
== STATUS_SUCCESS
);
849 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
852 // port range reported start from 1 -n
853 // convert back port id so it matches the hardware
855 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
858 // check request code
860 switch(Urb
->UrbControlVendorClassRequest
.Request
)
862 case USB_REQUEST_GET_STATUS
:
867 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
868 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
873 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
875 if (NT_SUCCESS(Status
))
878 // request contains buffer of 2 ushort which are used from submitting port status and port change status
880 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
883 // store status, then port change
885 *Buffer
= PortStatus
;
887 *Buffer
= PortChange
;
895 case USB_REQUEST_CLEAR_FEATURE
:
897 switch (Urb
->UrbControlVendorClassRequest
.Value
)
899 case C_PORT_CONNECTION
:
900 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
903 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
906 DPRINT("Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
910 Status
= STATUS_SUCCESS
;
913 case USB_REQUEST_SET_FEATURE
:
916 // request set feature
918 switch(Urb
->UrbControlVendorClassRequest
.Value
)
923 // port enable is a no-op for EHCI
925 Status
= STATUS_SUCCESS
;
932 // set suspend port feature
934 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
940 // set power feature on port
942 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
949 // reset port feature
951 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
952 PC_ASSERT(Status
== STATUS_SUCCESS
);
956 DPRINT1("Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
962 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
964 Status
= STATUS_INVALID_DEVICE_REQUEST
;
969 //-----------------------------------------------------------------------------------------
971 CHubController::HandleSelectConfiguration(
975 PUSBDEVICE UsbDevice
;
978 // is the request for the Root Hub
980 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
983 // FIXME: support setting device to unconfigured state
985 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
990 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
993 // TODO: copy interface info
995 return STATUS_SUCCESS
;
1000 // check if this is a valid usb device handle
1002 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1007 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1010 // select configuration
1012 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1016 //-----------------------------------------------------------------------------------------
1018 CHubController::HandleSelectInterface(
1022 PUSBDEVICE UsbDevice
;
1027 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1030 // is the request for the Root Hub
1032 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1035 // no op for root hub
1037 return STATUS_SUCCESS
;
1042 // check if this is a valid usb device handle
1044 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1049 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1054 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1058 //-----------------------------------------------------------------------------------------
1060 CHubController::HandleGetStatusFromDevice(
1069 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1070 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1071 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1072 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
1075 // get status buffer
1077 Status
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1080 // FIXME need more flags ?
1082 *Status
= USB_PORT_STATUS_CONNECT
;
1087 return STATUS_SUCCESS
;
1090 //-----------------------------------------------------------------------------------------
1092 CHubController::HandleClassDevice(
1096 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1097 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1098 ULONG PortCount
, Dummy2
;
1102 // check class request type
1104 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1106 case USB_REQUEST_GET_DESCRIPTOR
:
1108 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1110 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1111 case USB_DEVICE_CLASS_HUB
:
1116 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1117 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1120 // get hub descriptor
1122 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1125 // one hub is handled
1127 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1128 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1131 // type should 0x29 according to msdn
1133 UsbHubDescriptor
->bDescriptorType
= 0x29;
1138 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1139 PC_ASSERT(Status
== STATUS_SUCCESS
);
1142 // FIXME: retrieve values
1144 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1145 UsbHubDescriptor
->wHubCharacteristics
= 0x0012;
1146 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1147 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1152 Status
= STATUS_SUCCESS
;
1156 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1162 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1167 //-----------------------------------------------------------------------------------------
1169 CHubController::HandleGetDescriptor(
1173 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1174 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1175 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1177 PUSBDEVICE UsbDevice
;
1181 // check descriptor type
1183 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1185 case USB_DEVICE_DESCRIPTOR_TYPE
:
1190 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1191 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1193 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1196 // copy root hub device descriptor
1198 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1199 Status
= STATUS_SUCCESS
;
1204 // check if this is a valid usb device handle
1206 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1211 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1214 // retrieve device descriptor from device
1216 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1217 Status
= STATUS_SUCCESS
;
1221 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1226 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1227 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1229 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1232 // request is for the root bus controller
1234 C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR
) == sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1235 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1238 // get configuration descriptor, very retarded!
1240 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1243 // check if buffer can hold interface and endpoint descriptor
1245 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1250 Status
= STATUS_SUCCESS
;
1255 // copy interface descriptor template
1257 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1258 C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR
) == sizeof(USB_INTERFACE_DESCRIPTOR
));
1259 RtlCopyMemory(Buffer
, ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1262 // copy end point descriptor template
1264 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1265 C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR
) == sizeof(USB_ENDPOINT_DESCRIPTOR
));
1266 RtlCopyMemory(Buffer
, ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1271 Status
= STATUS_SUCCESS
;
1276 DPRINT1("Length %u\n", Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1279 // check if this is a valid usb device handle
1281 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1286 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1288 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1293 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1298 Status
= STATUS_SUCCESS
;
1303 // perform work in IUSBDevice
1305 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1310 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= Length
);
1313 // store result size
1315 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1316 Status
= STATUS_SUCCESS
;
1320 case USB_STRING_DESCRIPTOR_TYPE
:
1325 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1326 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1330 // check if this is a valid usb device handle
1332 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1337 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1340 // generate setup packet
1342 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1343 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1344 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1345 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1346 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1347 CtrlSetup
.bmRequestType
.B
= 0x80;
1350 // submit setup packet
1352 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1356 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1366 //-----------------------------------------------------------------------------------------
1368 CHubController::HandleClassInterface(
1372 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1374 PUSBDEVICE UsbDevice
;
1379 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1380 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1381 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1384 // check if this is a valid usb device handle
1386 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1391 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1394 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1395 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1396 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1397 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1398 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1399 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1400 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1401 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1402 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1405 // initialize setup packet
1407 CtrlSetup
.bmRequestType
.B
= 0xa1; //FIXME: Const.
1408 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1409 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1410 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1411 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1416 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1419 // assert on failure
1421 PC_ASSERT(NT_SUCCESS(Status
));
1430 //-----------------------------------------------------------------------------------------
1432 CHubController::HandleDeviceControl(
1433 IN PDEVICE_OBJECT DeviceObject
,
1436 PIO_STACK_LOCATION IoStack
;
1437 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1439 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1442 // get current stack location
1444 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1447 // get device extension
1449 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1452 // determine which request should be performed
1454 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1456 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
1461 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1464 switch (Urb
->UrbHeader
.Function
)
1466 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1467 Status
= HandleGetDescriptor(Irp
, Urb
);
1469 case URB_FUNCTION_CLASS_DEVICE
:
1470 Status
= HandleClassDevice(Irp
, Urb
);
1472 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1473 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
1475 case URB_FUNCTION_SELECT_CONFIGURATION
:
1476 Status
= HandleSelectConfiguration(Irp
, Urb
);
1478 case URB_FUNCTION_SELECT_INTERFACE
:
1479 Status
= HandleSelectInterface(Irp
, Urb
);
1481 case URB_FUNCTION_CLASS_OTHER
:
1482 Status
= HandleClassOther(Irp
, Urb
);
1484 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
1485 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
1487 case URB_FUNCTION_CLASS_INTERFACE
:
1488 Status
= HandleClassInterface(Irp
, Urb
);
1491 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
1495 // request completed
1499 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
1501 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
1503 if (IoStack
->Parameters
.Others
.Argument1
)
1506 // store object as device handle
1508 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
1509 Status
= STATUS_SUCCESS
;
1514 // mis-behaving hub driver
1516 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1520 // request completed
1524 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
1526 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1529 // this is the first request send, it delivers the PDO to the caller
1531 if (IoStack
->Parameters
.Others
.Argument1
)
1534 // store root hub pdo object
1536 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
1539 if (IoStack
->Parameters
.Others
.Argument2
)
1542 // documentation claims to deliver the hcd controller object, although it is wrong
1544 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
1548 // request completed
1550 Status
= STATUS_SUCCESS
;
1553 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
1555 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1558 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1559 // requests this ioctl to deliver the number of presents.
1561 if (IoStack
->Parameters
.Others
.Argument1
)
1564 // FIXME / verify: there is only one hub
1566 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
1570 // request completed
1572 Status
= STATUS_SUCCESS
;
1573 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1576 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
1578 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1579 Status
= STATUS_SUCCESS
;
1584 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1585 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1586 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
1587 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
1591 if (Status
!= STATUS_PENDING
)
1593 Irp
->IoStatus
.Status
= Status
;
1594 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1600 //-----------------------------------------------------------------------------------------
1602 CHubController::GetUsbHardware()
1607 //-----------------------------------------------------------------------------------------
1609 CHubController::AcquireDeviceAddress()
1612 ULONG DeviceAddress
;
1615 // acquire device lock
1617 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1622 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
1623 if (DeviceAddress
!= MAXULONG
)
1628 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1631 // device addresses start from 0x1 - 0xFF
1637 // release spin lock
1639 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1642 // return device address
1644 return DeviceAddress
;
1646 //-----------------------------------------------------------------------------------------
1648 CHubController::ReleaseDeviceAddress(
1649 ULONG DeviceAddress
)
1654 // acquire device lock
1656 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1661 PC_ASSERT(DeviceAddress
!= 0);
1664 // convert back to bit number
1671 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1676 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1678 //-----------------------------------------------------------------------------------------
1680 CHubController::RemoveUsbDevice(
1681 PUSBDEVICE UsbDevice
)
1683 PUSBDEVICE_ENTRY DeviceEntry
;
1685 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1691 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1694 // point to first entry
1696 Entry
= m_UsbDeviceList
.Flink
;
1699 // find matching entry
1701 while(Entry
!= &m_UsbDeviceList
)
1706 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1709 // is it current entry
1711 if (DeviceEntry
->Device
== UsbDevice
)
1716 RemoveEntryList(Entry
);
1721 ExFreePoolWithTag(DeviceEntry
, TAG_USBEHCI
);
1726 Status
= STATUS_SUCCESS
;
1733 Entry
= Entry
->Flink
;
1739 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1746 //-----------------------------------------------------------------------------------------
1748 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
1750 PUSBDEVICE_ENTRY DeviceEntry
;
1753 BOOLEAN Result
= FALSE
;
1758 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1761 // point to first entry
1763 Entry
= m_UsbDeviceList
.Flink
;
1766 // find matching entry
1768 while(Entry
!= &m_UsbDeviceList
)
1773 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1776 // is it current entry
1778 if (DeviceEntry
->Device
== UsbDevice
)
1790 Entry
= Entry
->Flink
;
1796 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1805 //-----------------------------------------------------------------------------------------
1807 CHubController::AddUsbDevice(
1808 PUSBDEVICE UsbDevice
)
1810 PUSBDEVICE_ENTRY DeviceEntry
;
1814 // allocate device entry
1816 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBEHCI
);
1822 return STATUS_INSUFFICIENT_RESOURCES
;
1828 DeviceEntry
->Device
= UsbDevice
;
1833 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1838 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
1841 // release spin lock
1843 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1848 return STATUS_SUCCESS
;
1851 //-----------------------------------------------------------------------------------------
1853 CHubController::SetNotification(
1854 PVOID CallbackContext
,
1855 PRH_INIT_CALLBACK CallbackRoutine
)
1860 // acquire hub controller lock
1862 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1865 // now set the callback routine and context of the hub
1867 m_HubCallbackContext
= CallbackContext
;
1868 m_HubCallbackRoutine
= CallbackRoutine
;
1871 // release hub controller lock
1873 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1876 //=================================================================================================
1878 // Generic Interface functions
1882 USBI_InterfaceReference(
1885 CHubController
* Controller
= (CHubController
*)BusContext
;
1887 DPRINT1("USBH_InterfaceReference\n");
1892 Controller
->AddRef();
1897 USBI_InterfaceDereference(
1900 CHubController
* Controller
= (CHubController
*)BusContext
;
1902 DPRINT1("USBH_InterfaceDereference\n");
1907 Controller
->Release();
1909 //=================================================================================================
1911 // USB Hub Interface functions
1915 USBHI_CreateUsbDevice(
1917 PUSB_DEVICE_HANDLE
*NewDevice
,
1918 PUSB_DEVICE_HANDLE HubDeviceHandle
,
1922 PUSBDEVICE NewUsbDevice
;
1923 CHubController
* Controller
;
1926 DPRINT1("USBHI_CreateUsbDevice\n");
1929 // first get hub controller
1931 Controller
= (CHubController
*)BusContext
;
1936 PC_ASSERT(Controller
);
1937 PC_ASSERT(BusContext
== HubDeviceHandle
);
1940 // now allocate usb device
1942 Status
= CreateUSBDevice(&NewUsbDevice
);
1945 // check for success
1947 if (!NT_SUCCESS(Status
))
1950 // release controller
1952 Controller
->Release();
1953 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
1958 // now initialize device
1960 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
1963 // check for success
1965 if (!NT_SUCCESS(Status
))
1968 // release usb device
1970 NewUsbDevice
->Release();
1971 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
1978 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
1980 // check for success
1982 if (!NT_SUCCESS(Status
))
1985 // release usb device
1987 NewUsbDevice
->Release();
1989 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
1996 *NewDevice
= NewUsbDevice
;
2001 return STATUS_SUCCESS
;
2006 USBHI_InitializeUsbDevice(
2008 PUSB_DEVICE_HANDLE DeviceHandle
)
2010 PUSBDEVICE UsbDevice
;
2011 CHubController
* Controller
;
2012 ULONG DeviceAddress
;
2016 DPRINT1("USBHI_InitializeUsbDevice\n");
2019 // first get controller
2021 Controller
= (CHubController
*)BusContext
;
2022 PC_ASSERT(Controller
);
2025 // get device object
2027 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2028 PC_ASSERT(UsbDevice
);
2031 // validate device handle
2033 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2035 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2038 // invalid device handle
2040 return STATUS_DEVICE_NOT_CONNECTED
;
2044 // now reserve an address
2046 DeviceAddress
= Controller
->AcquireDeviceAddress();
2049 // is the device address valid
2051 if (DeviceAddress
== MAXULONG
)
2054 // failed to get an device address from the device address pool
2056 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2057 return STATUS_DEVICE_DATA_ERROR
;
2063 // now set the device address
2065 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2067 if (NT_SUCCESS(Status
))
2070 }while(Index
++ < 3 );
2073 // check for failure
2075 if (!NT_SUCCESS(Status
))
2078 // failed to set device address
2080 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2085 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2090 return STATUS_DEVICE_DATA_ERROR
;
2096 return STATUS_SUCCESS
;
2101 USBHI_GetUsbDescriptors(
2103 PUSB_DEVICE_HANDLE DeviceHandle
,
2104 PUCHAR DeviceDescriptorBuffer
,
2105 PULONG DeviceDescriptorBufferLength
,
2106 PUCHAR ConfigDescriptorBuffer
,
2107 PULONG ConfigDescriptorBufferLength
)
2109 PUSBDEVICE UsbDevice
;
2110 CHubController
* Controller
;
2112 DPRINT1("USBHI_GetUsbDescriptors\n");
2117 PC_ASSERT(DeviceDescriptorBuffer
);
2118 PC_ASSERT(DeviceDescriptorBufferLength
);
2119 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2120 PC_ASSERT(ConfigDescriptorBufferLength
);
2121 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2124 // first get controller
2126 Controller
= (CHubController
*)BusContext
;
2127 PC_ASSERT(Controller
);
2131 // get device object
2133 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2134 PC_ASSERT(UsbDevice
);
2137 // validate device handle
2139 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2141 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2144 // invalid device handle
2146 return STATUS_DEVICE_NOT_CONNECTED
;
2150 // get device descriptor
2152 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2155 // store result length
2157 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2160 // get configuration descriptor
2162 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2165 // complete the request
2167 return STATUS_SUCCESS
;
2172 USBHI_RemoveUsbDevice(
2174 PUSB_DEVICE_HANDLE DeviceHandle
,
2177 PUSBDEVICE UsbDevice
;
2178 CHubController
* Controller
;
2181 DPRINT1("USBHI_RemoveUsbDevice\n");
2184 // first get controller
2186 Controller
= (CHubController
*)BusContext
;
2187 PC_ASSERT(Controller
);
2190 // get device object
2192 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2193 PC_ASSERT(UsbDevice
);
2196 // validate device handle
2198 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2200 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2203 // invalid device handle
2205 return STATUS_DEVICE_NOT_CONNECTED
;
2209 // check if there were flags passed
2211 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2214 // ignore flags for now
2216 return STATUS_SUCCESS
;
2222 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2223 if (!NT_SUCCESS(Status
))
2226 // invalid device handle
2228 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2230 return STATUS_DEVICE_NOT_CONNECTED
;
2234 // release usb device
2236 UsbDevice
->Release();
2241 return STATUS_SUCCESS
;
2246 USBHI_RestoreUsbDevice(
2248 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2249 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2251 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2252 CHubController
* Controller
;
2255 DPRINT1("USBHI_RestoreUsbDevice\n");
2258 // first get controller
2260 Controller
= (CHubController
*)BusContext
;
2261 PC_ASSERT(Controller
);
2264 // get device object
2266 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2267 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2268 PC_ASSERT(OldUsbDevice
);
2269 PC_ASSERT(NewDeviceHandle
);
2272 // validate device handle
2274 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2275 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2277 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2280 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2285 // remove old device handle
2287 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2289 return STATUS_SUCCESS
;
2294 USBHI_QueryDeviceInformation(
2296 PUSB_DEVICE_HANDLE DeviceHandle
,
2297 PVOID DeviceInformationBuffer
,
2298 ULONG DeviceInformationBufferLength
,
2299 PULONG LengthReturned
)
2301 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2302 PUSBDEVICE UsbDevice
;
2303 CHubController
* Controller
;
2305 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2310 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2311 PC_ASSERT(DeviceInformationBuffer
);
2312 PC_ASSERT(LengthReturned
);
2315 // get controller object
2317 Controller
= (CHubController
*)BusContext
;
2318 PC_ASSERT(Controller
);
2321 // get device object
2323 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2324 PC_ASSERT(UsbDevice
);
2326 if (BusContext
!= DeviceHandle
)
2329 // validate device handle
2331 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2333 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2336 // invalid device handle
2338 return STATUS_DEVICE_NOT_CONNECTED
;
2342 // access information buffer
2344 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2347 // initialize with default values
2349 DeviceInfo
->InformationLevel
= 0;
2350 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2351 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2352 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2353 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2354 DeviceInfo
->HubAddress
= 0; //FIXME
2355 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2356 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2357 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2360 // get device descriptor
2362 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2365 // FIXME return pipe information
2369 // store result length
2371 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2373 return STATUS_SUCCESS
;
2377 // access information buffer
2379 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2382 // initialize with default values
2384 DeviceInfo
->InformationLevel
= 0;
2385 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2386 DeviceInfo
->PortNumber
= 0;
2387 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2388 DeviceInfo
->DeviceAddress
= 0;
2389 DeviceInfo
->HubAddress
= 0; //FIXME
2390 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
2391 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
2392 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2395 // FIXME get device descriptor
2399 // FIXME return pipe information
2403 // store result length
2405 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2410 return STATUS_SUCCESS
;
2415 USBHI_GetControllerInformation(
2417 PVOID ControllerInformationBuffer
,
2418 ULONG ControllerInformationBufferLength
,
2419 PULONG LengthReturned
)
2421 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2423 DPRINT1("USBHI_GetControllerInformation\n");
2428 PC_ASSERT(ControllerInformationBuffer
);
2429 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2432 // get controller info buffer
2434 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
2437 // FIXME only version 0 is supported for now
2439 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
2442 // fill in information
2444 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
2445 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
2446 ControllerInfo
->IsHighSpeedController
= TRUE
;
2449 // set length returned
2451 *LengthReturned
= ControllerInfo
->ActualLength
;
2456 return STATUS_SUCCESS
;
2461 USBHI_ControllerSelectiveSuspend(
2466 return STATUS_NOT_IMPLEMENTED
;
2471 USBHI_GetExtendedHubInformation(
2473 PDEVICE_OBJECT HubPhysicalDeviceObject
,
2474 PVOID HubInformationBuffer
,
2475 ULONG HubInformationBufferLength
,
2476 PULONG LengthReturned
)
2478 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
2479 CHubController
* Controller
;
2480 PUSBHARDWAREDEVICE Hardware
;
2482 ULONG NumPort
, Dummy2
;
2486 DPRINT1("USBHI_GetExtendedHubInformation\n");
2491 PC_ASSERT(HubInformationBuffer
);
2492 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
2493 PC_ASSERT(LengthReturned
);
2496 // get hub controller
2498 Controller
= (CHubController
*)BusContext
;
2499 PC_ASSERT(Controller
);
2502 // get usb hardware device
2504 Hardware
= Controller
->GetUsbHardware();
2507 // retrieve number of ports
2509 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
2510 if (!NT_SUCCESS(Status
))
2513 // failed to get hardware details, ouch ;)
2515 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
2520 // get hub information buffer
2522 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
2525 // initialize hub information
2527 HubInfo
->InformationLevel
= 0;
2532 HubInfo
->NumberOfPorts
= NumPort
;
2535 // initialize port information
2537 for(Index
= 0; Index
< NumPort
; Index
++)
2539 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
2540 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
2541 HubInfo
->Port
[Index
].VidOverride
= 0;
2542 HubInfo
->Port
[Index
].PidOverride
= 0;
2543 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
2547 // store result length
2550 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
2552 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
2558 return STATUS_SUCCESS
;
2563 USBHI_GetRootHubSymbolicName(
2565 PVOID HubSymNameBuffer
,
2566 ULONG HubSymNameBufferLength
,
2567 PULONG HubSymNameActualLength
)
2570 return STATUS_NOT_IMPLEMENTED
;
2575 USBHI_GetDeviceBusContext(
2576 PVOID HubBusContext
,
2585 USBHI_Initialize20Hub(
2587 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2591 return STATUS_SUCCESS
;
2596 USBHI_RootHubInitNotification(
2598 PVOID CallbackContext
,
2599 PRH_INIT_CALLBACK CallbackRoutine
)
2601 CHubController
* Controller
;
2603 DPRINT1("USBHI_RootHubInitNotification\n");
2606 // get controller object
2608 Controller
= (CHubController
*)BusContext
;
2609 PC_ASSERT(Controller
);
2612 // set notification routine
2614 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
2617 // FIXME: determine when to perform callback
2619 CallbackRoutine(CallbackContext
);
2624 return STATUS_SUCCESS
;
2629 USBHI_FlushTransfers(
2638 USBHI_SetDeviceHandleData(
2641 PDEVICE_OBJECT UsbDevicePdo
)
2643 PUSBDEVICE UsbDevice
;
2644 CHubController
* Controller
;
2649 Controller
= (CHubController
*)BusContext
;
2650 PC_ASSERT(Controller
);
2653 // get device handle
2655 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2658 // validate device handle
2660 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2662 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
2672 // usbhub sends this request as a part of the Pnp startup sequence
2673 // looks like we need apply a dragon voodoo to fixup the device stack
2674 // otherwise usbhub will cause a bugcheck
2676 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
2679 // fixup device stack voodoo part #1
2681 UsbDevicePdo
->StackSize
++;
2686 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
2689 // should be usbstor
2690 // fixup device stack voodoo part #2
2692 UsbDevicePdo
->AttachedDevice
->StackSize
++;
2695 // set device handle data
2697 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
2701 //=================================================================================================
2703 // USB Device Interface functions
2708 USBDI_GetUSBDIVersion(
2710 PUSBD_VERSION_INFORMATION VersionInformation
,
2711 PULONG HcdCapabilites
)
2713 CHubController
* Controller
;
2714 PUSBHARDWAREDEVICE Device
;
2715 ULONG Speed
, Dummy2
;
2718 DPRINT1("USBDI_GetUSBDIVersion\n");
2723 Controller
= (CHubController
*)BusContext
;
2728 Device
= Controller
->GetUsbHardware();
2731 if (VersionInformation
)
2734 // windows xp supported
2736 VersionInformation
->USBDI_Version
= 0x00000500;
2741 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2744 // store speed details
2746 VersionInformation
->Supported_USB_Version
= Speed
;
2750 // no flags supported
2752 *HcdCapabilites
= 0;
2759 PULONG CurrentFrame
)
2762 return STATUS_NOT_IMPLEMENTED
;
2767 USBDI_SubmitIsoOutUrb(
2772 return STATUS_NOT_IMPLEMENTED
;
2777 USBDI_QueryBusInformation(
2780 PVOID BusInformationBuffer
,
2781 PULONG BusInformationBufferLength
,
2782 PULONG BusInformationActualLength
)
2785 return STATUS_NOT_IMPLEMENTED
;
2790 USBDI_IsDeviceHighSpeed(
2793 CHubController
* Controller
;
2794 PUSBHARDWAREDEVICE Device
;
2795 ULONG Speed
, Dummy2
;
2798 DPRINT1("USBDI_IsDeviceHighSpeed\n");
2803 Controller
= (CHubController
*)BusContext
;
2808 Device
= Controller
->GetUsbHardware();
2814 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2817 // USB 2.0 equals 0x200
2819 return (Speed
== 0x200);
2832 return STATUS_NOT_IMPLEMENTED
;
2836 CHubController::HandleQueryInterface(
2837 PIO_STACK_LOCATION IoStack
)
2839 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
2840 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
2841 UNICODE_STRING GuidBuffer
;
2844 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
2847 // get request parameters
2849 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
2850 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2855 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
2857 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2860 // version not supported
2862 return STATUS_NOT_SUPPORTED
;
2866 // Interface version 0
2868 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2870 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2871 InterfaceHub
->BusContext
= PVOID(this);
2872 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
2873 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
2877 // Interface version 1
2879 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2881 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
2882 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
2883 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
2884 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
2885 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
2886 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
2890 // Interface version 2
2892 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2894 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
2895 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
2896 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
2897 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
2898 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
2899 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
2904 // Interface version 3
2906 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2908 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
2912 // Interface version 4
2914 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
2916 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
2920 // Interface version 5
2922 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
2924 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
2928 // request completed
2930 return STATUS_SUCCESS
;
2932 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
2935 // get request parameters
2937 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
2938 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2943 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2945 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2948 // version not supported
2950 return STATUS_NOT_SUPPORTED
;
2954 // interface version 0
2956 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2958 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2959 InterfaceDI
->BusContext
= PVOID(this);
2960 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
2961 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
2962 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
2963 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
2964 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
2965 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
2969 // interface version 1
2971 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2973 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
2977 // interface version 2
2979 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2981 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
2985 // request completed
2987 return STATUS_SUCCESS
;
2992 // convert guid to string
2994 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
2995 if (NT_SUCCESS(Status
))
3000 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3005 RtlFreeUnicodeString(&GuidBuffer
);
3008 return STATUS_NOT_SUPPORTED
;
3012 CHubController::SetDeviceInterface(
3015 NTSTATUS Status
= STATUS_SUCCESS
;
3020 // register device interface
3022 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3024 if (NT_SUCCESS(Status
))
3027 // now enable the device interface
3029 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3034 m_InterfaceEnabled
= TRUE
;
3037 else if (m_InterfaceEnabled
)
3040 // disable device interface
3042 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3044 if (NT_SUCCESS(Status
))
3047 // now delete interface string
3049 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3053 // disable interface
3055 m_InterfaceEnabled
= FALSE
;
3065 CHubController::CreatePDO(
3066 PDRIVER_OBJECT DriverObject
,
3067 PDEVICE_OBJECT
* OutDeviceObject
)
3069 WCHAR CharDeviceName
[64];
3071 ULONG UsbDeviceNumber
= 0;
3072 UNICODE_STRING DeviceName
;
3077 // construct device name
3079 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3082 // initialize device name
3084 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3089 Status
= IoCreateDevice(DriverObject
,
3090 sizeof(COMMON_DEVICE_EXTENSION
),
3092 FILE_DEVICE_CONTROLLER
,
3097 /* check for success */
3098 if (NT_SUCCESS(Status
))
3102 // is there a device object with that same name
3104 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3107 // Try the next name
3114 // bail out on other errors
3116 if (!NT_SUCCESS(Status
))
3118 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3123 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3132 CreateHubController(
3133 PHUBCONTROLLER
*OutHcdController
)
3135 PHUBCONTROLLER This
;
3138 // allocate controller
3140 This
= new(NonPagedPool
, TAG_USBEHCI
) CHubController(0);
3144 // failed to allocate
3146 return STATUS_INSUFFICIENT_RESOURCES
;
3150 // add reference count
3157 *OutHcdController
= (PHUBCONTROLLER
)This
;
3162 return STATUS_SUCCESS
;
3165 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3167 CHubController
* This
;
3169 This
= (CHubController
*)Context
;
3173 Irp
= This
->m_PendingSCEIrp
;
3176 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3180 This
->m_PendingSCEIrp
= NULL
;
3181 This
->QueryStatusChageEndpoint(Irp
);
3183 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3184 Irp
->IoStatus
.Information
= 0;
3186 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);