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
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
69 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
71 // constructor / destructor
72 CHubController(IUnknown
*OuterUnknown
){}
73 virtual ~CHubController(){}
77 PHCDCONTROLLER m_Controller
;
78 PUSBHARDWAREDEVICE m_Hardware
;
79 BOOLEAN m_IsRootHubDevice
;
80 ULONG m_DeviceAddress
;
82 BOOLEAN m_InterfaceEnabled
;
83 UNICODE_STRING m_HubDeviceInterfaceString
;
85 PDEVICE_OBJECT m_HubControllerDeviceObject
;
86 PDRIVER_OBJECT m_DriverObject
;
88 PVOID m_HubCallbackContext
;
89 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
91 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
94 RTL_BITMAP m_DeviceAddressBitmap
;
95 PULONG m_DeviceAddressBitmapBuffer
;
96 LIST_ENTRY m_UsbDeviceList
;
100 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
107 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
109 /* Lifted from Linux with slight changes */
110 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
113 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
114 0x00, 0x20, /* bcdUSB; v1.1 */
115 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
116 0x01, /* bDeviceSubClass; */
117 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
118 0x08, /* bMaxPacketSize0; 8 Bytes */
119 /* Fill Vendor and Product in when init root hub */
120 0x00, 0x00, /* idVendor; */
121 0x00, 0x00, /* idProduct; */
122 0x00, 0x00, /* bcdDevice */
123 0x00, /* iManufacturer; */
124 0x00, /* iProduct; */
125 0x00, /* iSerialNumber; */
126 0x01 /* bNumConfigurations; */
130 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR
[] =
132 /* one configuration */
134 0x02, /* bDescriptorType; Configuration */
135 0x19, 0x00, /* wTotalLength; */
136 0x01, /* bNumInterfaces; (1) */
137 0x23, /* bConfigurationValue; */
138 0x00, /* iConfiguration; */
139 0x40, /* bmAttributes; */
143 const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR
[] =
146 0x09, /* bLength: Interface; */
147 0x04, /* bDescriptorType; Interface */
148 0x00, /* bInterfaceNumber; */
149 0x00, /* bAlternateSetting; */
150 0x01, /* bNumEndpoints; */
151 0x09, /* bInterfaceClass; HUB_CLASSCODE */
152 0x01, /* bInterfaceSubClass; */
153 0x00, /* bInterfaceProtocol: */
154 0x00 /* iInterface; */
157 const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR
[] =
159 /* one endpoint (status change endpoint) */
161 0x05, /* bDescriptorType; Endpoint */
162 0x81, /* bEndpointAddress; IN Endpoint 1 */
163 0x03, /* bmAttributes; Interrupt */
164 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
165 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
168 //----------------------------------------------------------------------------------------
171 CHubController::QueryInterface(
175 return STATUS_UNSUCCESSFUL
;
177 //----------------------------------------------------------------------------------------
179 CHubController::Initialize(
180 IN PDRIVER_OBJECT DriverObject
,
181 IN PHCDCONTROLLER Controller
,
182 IN PUSBHARDWAREDEVICE Device
,
183 IN BOOLEAN IsRootHubDevice
,
184 IN ULONG DeviceAddress
)
187 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
188 USHORT VendorID
, DeviceID
;
191 DPRINT1("CHubController::Initialize\n");
194 // initialize members
196 m_Controller
= Controller
;
198 m_IsRootHubDevice
= IsRootHubDevice
;
199 m_DeviceAddress
= DeviceAddress
;
200 m_DriverObject
= DriverObject
;
201 KeInitializeSpinLock(&m_Lock
);
202 InitializeListHead(&m_UsbDeviceList
);
205 // allocate device address bitmap buffer
207 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBEHCI
);
208 if (!m_DeviceAddressBitmapBuffer
)
213 return STATUS_INSUFFICIENT_RESOURCES
;
217 // initialize device address bitmap
219 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
220 RtlClearAllBits(&m_DeviceAddressBitmap
);
226 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
227 if (!NT_SUCCESS(Status
))
230 // failed to create hub device object
236 // get device extension
238 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
241 // initialize device extension
243 DeviceExtension
->IsFDO
= FALSE
;
244 DeviceExtension
->IsHub
= TRUE
; //FIXME
245 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
248 // intialize device descriptor
250 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
251 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
253 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
256 // update device descriptor
258 m_DeviceDescriptor
.idVendor
= VendorID
;
259 m_DeviceDescriptor
.idProduct
= DeviceID
;
260 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
264 // Set the SCE Callback that the Hardware Device will call on port status change
266 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
270 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
273 return STATUS_SUCCESS
;
277 // Queries the ports to see if there has been a device connected or removed.
280 CHubController::QueryStatusChageEndpoint(
283 ULONG PortCount
, PortId
;
284 PIO_STACK_LOCATION IoStack
;
285 USHORT PortStatus
, PortChange
;
289 // get current stack location
291 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
297 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
301 // Get the number of ports and check each one for device connected
303 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
304 DPRINT1("SCE Request\n");
305 ((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 0;
306 for (PortId
= 0; PortId
< PortCount
; PortId
++)
308 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
310 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
315 if ((PortStatus
& USB_PORT_STATUS_CONNECT
) && (PortChange
& USB_PORT_STATUS_CONNECT
))
317 DPRINT1("Device is connected on port %d\n", PortId
);
318 // Set the value for the port number
319 ((PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] = 1 << ((PortId
+ 1) & 7);
324 // If there were changes then return TRUE
326 if (((PULONG
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
)[0] != 0)
332 //-----------------------------------------------------------------------------------------
334 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
337 // store controller object
339 *HubDeviceObject
= m_HubControllerDeviceObject
;
341 return STATUS_SUCCESS
;
343 //-----------------------------------------------------------------------------------------
345 CHubController::GetHubControllerSymbolicLink(
348 PULONG RequiredLength
)
350 if (!m_InterfaceEnabled
)
353 // device interface not yet enabled
355 return STATUS_UNSUCCESSFUL
;
358 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
362 // length is without '\??\'
364 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
369 return STATUS_BUFFER_OVERFLOW
;
373 // copy symbolic link
375 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
378 // store length, length is without '\??\'
380 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
385 return STATUS_SUCCESS
;
388 //-----------------------------------------------------------------------------------------
390 CHubController::HandlePnp(
391 IN PDEVICE_OBJECT DeviceObject
,
394 PIO_STACK_LOCATION IoStack
;
395 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
396 PDEVICE_CAPABILITIES DeviceCapabilities
;
397 PPNP_BUS_INFORMATION BusInformation
;
398 PDEVICE_RELATIONS DeviceRelations
;
400 ULONG Index
= 0, Length
;
401 USHORT VendorID
, DeviceID
;
402 ULONG HiSpeed
, NumPorts
;
407 // get device extension
409 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
414 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
417 // get current stack location
419 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
421 switch(IoStack
->MinorFunction
)
423 case IRP_MN_START_DEVICE
:
425 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
427 // register device interface
429 Status
= SetDeviceInterface(TRUE
);
432 case IRP_MN_QUERY_ID
:
434 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
436 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
443 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
445 if (HiSpeed
== 0x200)
450 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
457 swprintf(Buffer
, L
"USB\\ROOT_HUB");
460 DPRINT1("Name %S\n", Buffer
);
465 Length
= (wcslen(Buffer
) + 1);
470 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBEHCI
);
477 Status
= STATUS_INSUFFICIENT_RESOURCES
;
484 wcscpy(DeviceName
, Buffer
);
489 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
490 Status
= STATUS_SUCCESS
;
493 Status
= STATUS_UNSUCCESSFUL
;
498 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
505 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
514 if (HiSpeed
== 0x200)
519 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
520 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
521 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
528 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
529 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
530 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
533 Buffer
[Index
] = UNICODE_NULL
;
537 DPRINT1("Name %S\n", Buffer
);
542 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBEHCI
);
549 Status
= STATUS_INSUFFICIENT_RESOURCES
;
556 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
561 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
562 Status
= STATUS_SUCCESS
;
566 Status
= STATUS_SUCCESS
;
569 case IRP_MN_QUERY_CAPABILITIES
:
571 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
573 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
575 DeviceCapabilities
->LockSupported
= FALSE
;
576 DeviceCapabilities
->EjectSupported
= FALSE
;
577 DeviceCapabilities
->Removable
= FALSE
;
578 DeviceCapabilities
->DockDevice
= FALSE
;
579 DeviceCapabilities
->UniqueID
= FALSE
;
580 DeviceCapabilities
->SilentInstall
= FALSE
;
581 DeviceCapabilities
->RawDeviceOK
= FALSE
;
582 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
583 DeviceCapabilities
->Address
= 0;
584 DeviceCapabilities
->UINumber
= 0;
585 DeviceCapabilities
->DeviceD2
= 1;
588 DeviceCapabilities
->HardwareDisabled
= FALSE
;
589 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
590 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
591 for (Index
= 0; Index
< PowerSystemMaximum
; Index
++)
592 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
593 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
594 DeviceCapabilities
->D1Latency
= 0;
595 DeviceCapabilities
->D2Latency
= 0;
596 DeviceCapabilities
->D3Latency
= 0;
598 Status
= STATUS_SUCCESS
;
601 case IRP_MN_QUERY_INTERFACE
:
603 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
606 // handle device interface requests
608 Status
= HandleQueryInterface(IoStack
);
611 case IRP_MN_REMOVE_DEVICE
:
613 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
616 // deactivate device interface for BUS PDO
618 SetDeviceInterface(FALSE
);
621 // complete the request first
623 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
624 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
629 IoDeleteDevice(m_HubControllerDeviceObject
);
634 m_HubControllerDeviceObject
= 0;
639 return STATUS_SUCCESS
;
641 case IRP_MN_QUERY_DEVICE_RELATIONS
:
643 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
645 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
648 // allocate device relations
650 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBEHCI
);
651 if (!DeviceRelations
)
656 Status
= STATUS_INSUFFICIENT_RESOURCES
;
661 // initialize device relations
663 DeviceRelations
->Count
= 1;
664 DeviceRelations
->Objects
[0] = DeviceObject
;
665 ObReferenceObject(DeviceObject
);
670 Status
= STATUS_SUCCESS
;
671 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
678 Status
= Irp
->IoStatus
.Status
;
682 case IRP_MN_QUERY_BUS_INFORMATION
:
684 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
687 // allocate buffer for bus information
689 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
695 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
700 BusInformation
->LegacyBusType
= PNPBus
;
701 BusInformation
->BusNumber
= 0;
703 Status
= STATUS_SUCCESS
;
704 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
711 Status
= STATUS_INSUFFICIENT_RESOURCES
;
715 case IRP_MN_STOP_DEVICE
:
717 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
721 Status
= STATUS_SUCCESS
;
727 // ignore request with default status
729 Status
= Irp
->IoStatus
.Status
;
737 Irp
->IoStatus
.Status
= Status
;
738 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
746 //-----------------------------------------------------------------------------------------
748 CHubController::HandlePower(
749 IN PDEVICE_OBJECT DeviceObject
,
753 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
754 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
755 return STATUS_NOT_IMPLEMENTED
;
757 //-----------------------------------------------------------------------------------------
759 CHubController::HandleBulkOrInterruptTransfer(
764 // First check if the request is for the Status Change Endpoint
768 // Is the Request for the root hub
770 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
772 ASSERT(m_PendingSCEIrp
== NULL
);
773 if (QueryStatusChageEndpoint(Irp
))
775 return STATUS_SUCCESS
;
779 // Else pend the IRP, to be completed when a device connects or disconnects.
781 m_PendingSCEIrp
= Irp
;
782 IoMarkIrpPending(Irp
);
783 return STATUS_PENDING
;
787 return STATUS_NOT_IMPLEMENTED
;
790 //-----------------------------------------------------------------------------------------
792 CHubController::HandleClassOther(
796 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
797 USHORT PortStatus
= 0, PortChange
= 0;
802 //DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
805 // get number of ports available
807 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
808 PC_ASSERT(Status
== STATUS_SUCCESS
);
813 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
816 // port range reported start from 1 -n
817 // convert back port id so it matches the hardware
819 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
822 // check request code
824 switch(Urb
->UrbControlVendorClassRequest
.Request
)
826 case USB_REQUEST_GET_STATUS
:
831 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
832 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
837 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
839 if (NT_SUCCESS(Status
))
842 // request contains buffer of 2 ushort which are used from submitting port status and port change status
844 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
847 // store status, then port change
849 *Buffer
= PortStatus
;
851 *Buffer
= PortChange
;
859 case USB_REQUEST_CLEAR_FEATURE
:
861 switch (Urb
->UrbControlVendorClassRequest
.Value
)
863 case C_PORT_CONNECTION
:
864 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
867 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
870 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
->ResetPort(PortId
);
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
;
933 return STATUS_SUCCESS
;
936 //-----------------------------------------------------------------------------------------
938 CHubController::HandleSelectConfiguration(
947 // FIXME: support devices
949 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
952 // FIXME: support setting device to unconfigured state
954 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
959 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
962 // TODO: copy interface info
964 return STATUS_SUCCESS
;
967 //-----------------------------------------------------------------------------------------
969 CHubController::HandleGetStatusFromDevice(
978 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
979 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
980 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
981 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
986 Status
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
989 // FIXME need more flags ?
991 *Status
= USB_PORT_STATUS_CONNECT
;
996 return STATUS_SUCCESS
;
999 //-----------------------------------------------------------------------------------------
1001 CHubController::HandleClassDevice(
1005 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1006 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1007 ULONG PortCount
, Dummy2
;
1011 // check class request type
1013 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1015 case USB_REQUEST_GET_DESCRIPTOR
:
1017 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1019 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1020 case USB_DEVICE_CLASS_HUB
:
1025 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1026 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1029 // get hub descriptor
1031 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1034 // one hub is handled
1036 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1037 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1040 // type should 0x29 according to msdn
1042 UsbHubDescriptor
->bDescriptorType
= 0x29;
1047 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1048 PC_ASSERT(Status
== STATUS_SUCCESS
);
1051 // FIXME: retrieve values
1053 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1054 UsbHubDescriptor
->wHubCharacteristics
= 0x0012;
1055 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1056 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1061 Status
= STATUS_SUCCESS
;
1065 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1071 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1076 //-----------------------------------------------------------------------------------------
1078 CHubController::HandleGetDescriptor(
1082 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1083 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1087 // check descriptor type
1089 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1091 case USB_DEVICE_DESCRIPTOR_TYPE
:
1096 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1098 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1101 // copy root hub device descriptor
1103 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1104 Status
= STATUS_SUCCESS
;
1109 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1114 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1115 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1118 // FIXME: support devices
1120 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
1123 // copy configuration descriptor template
1125 C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR
) == sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1126 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1129 // get configuration descriptor, very retarded!
1131 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1134 // check if buffer can hold interface and endpoint descriptor
1136 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1141 Status
= STATUS_SUCCESS
;
1146 // copy interface descriptor template
1148 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1149 C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR
) == sizeof(USB_INTERFACE_DESCRIPTOR
));
1150 RtlCopyMemory(Buffer
, ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1153 // copy end point descriptor template
1155 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1156 C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR
) == sizeof(USB_ENDPOINT_DESCRIPTOR
));
1157 RtlCopyMemory(Buffer
, ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1162 Status
= STATUS_SUCCESS
;
1166 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1176 //-----------------------------------------------------------------------------------------
1178 CHubController::HandleDeviceControl(
1179 IN PDEVICE_OBJECT DeviceObject
,
1182 PIO_STACK_LOCATION IoStack
;
1183 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1185 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1188 // get current stack location
1190 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1193 // get device extension
1195 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1198 // determine which request should be performed
1200 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1202 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
1207 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1210 switch (Urb
->UrbHeader
.Function
)
1212 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1213 Status
= HandleGetDescriptor(Irp
, Urb
);
1215 case URB_FUNCTION_CLASS_DEVICE
:
1216 Status
= HandleClassDevice(Irp
, Urb
);
1218 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1219 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
1221 case URB_FUNCTION_SELECT_CONFIGURATION
:
1222 Status
= HandleSelectConfiguration(Irp
, Urb
);
1224 case URB_FUNCTION_CLASS_OTHER
:
1225 Status
= HandleClassOther(Irp
, Urb
);
1227 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
1228 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
1231 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
1235 // request completed
1239 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
1241 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
1243 if (IoStack
->Parameters
.Others
.Argument1
)
1246 // store object as device handle
1248 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
1249 Status
= STATUS_SUCCESS
;
1254 // mis-behaving hub driver
1256 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1260 // request completed
1264 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
1266 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1269 // this is the first request send, it delivers the PDO to the caller
1271 if (IoStack
->Parameters
.Others
.Argument1
)
1274 // store root hub pdo object
1276 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
1279 if (IoStack
->Parameters
.Others
.Argument2
)
1282 // documentation claims to deliver the hcd controller object, although it is wrong
1284 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
1288 // request completed
1290 Status
= STATUS_SUCCESS
;
1293 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
1295 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1298 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1299 // requests this ioctl to deliver the number of presents.
1301 if (IoStack
->Parameters
.Others
.Argument1
)
1304 // FIXME / verify: there is only one hub
1306 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
1310 // request completed
1312 Status
= STATUS_SUCCESS
;
1313 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1318 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1319 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1320 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
1321 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
1325 if (Status
!= STATUS_PENDING
)
1327 Irp
->IoStatus
.Status
= Status
;
1328 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1334 //-----------------------------------------------------------------------------------------
1336 CHubController::GetUsbHardware()
1341 //-----------------------------------------------------------------------------------------
1343 CHubController::AcquireDeviceAddress()
1346 ULONG DeviceAddress
;
1349 // acquire device lock
1351 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1356 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
1357 if (DeviceAddress
!= MAXULONG
)
1362 RtlSetBit(&m_DeviceAddressBitmap
, DeviceAddress
);
1365 // device addresses start from 0x1 - 0xFF
1371 // release spin lock
1373 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1376 // return device address
1378 return DeviceAddress
;
1380 //-----------------------------------------------------------------------------------------
1382 CHubController::ReleaseDeviceAddress(
1383 ULONG DeviceAddress
)
1388 // acquire device lock
1390 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1395 PC_ASSERT(DeviceAddress
!= 0);
1398 // convert back to bit number
1405 RtlClearBit(&m_DeviceAddressBitmap
, DeviceAddress
);
1410 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1412 //-----------------------------------------------------------------------------------------
1414 CHubController::RemoveUsbDevice(
1415 PUSBDEVICE UsbDevice
)
1417 PUSBDEVICE_ENTRY DeviceEntry
;
1419 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1425 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1428 // point to first entry
1430 Entry
= m_UsbDeviceList
.Flink
;
1433 // find matching entry
1435 while(Entry
!= &m_UsbDeviceList
)
1440 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1443 // is it current entry
1445 if (DeviceEntry
->Device
== UsbDevice
)
1450 RemoveEntryList(Entry
);
1455 ExFreePoolWithTag(DeviceEntry
, TAG_USBEHCI
);
1460 Status
= STATUS_SUCCESS
;
1467 Entry
= Entry
->Flink
;
1473 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1480 //-----------------------------------------------------------------------------------------
1482 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
1484 PUSBDEVICE_ENTRY DeviceEntry
;
1487 BOOLEAN Result
= FALSE
;
1492 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1495 // point to first entry
1497 Entry
= m_UsbDeviceList
.Flink
;
1500 // find matching entry
1502 while(Entry
!= &m_UsbDeviceList
)
1507 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1510 // is it current entry
1512 if (DeviceEntry
->Device
== UsbDevice
)
1524 Entry
= Entry
->Flink
;
1530 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1539 //-----------------------------------------------------------------------------------------
1541 CHubController::AddUsbDevice(
1542 PUSBDEVICE UsbDevice
)
1544 PUSBDEVICE_ENTRY DeviceEntry
;
1548 // allocate device entry
1550 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBEHCI
);
1556 return STATUS_INSUFFICIENT_RESOURCES
;
1562 DeviceEntry
->Device
= UsbDevice
;
1567 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1572 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
1575 // release spin lock
1577 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1582 return STATUS_SUCCESS
;
1585 //-----------------------------------------------------------------------------------------
1587 CHubController::SetNotification(
1588 PVOID CallbackContext
,
1589 PRH_INIT_CALLBACK CallbackRoutine
)
1594 // acquire hub controller lock
1596 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1599 // now set the callback routine and context of the hub
1601 m_HubCallbackContext
= CallbackContext
;
1602 m_HubCallbackRoutine
= CallbackRoutine
;
1605 // release hub controller lock
1607 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1610 //=================================================================================================
1612 // Generic Interface functions
1616 USBI_InterfaceReference(
1619 CHubController
* Controller
= (CHubController
*)BusContext
;
1621 DPRINT1("USBH_InterfaceReference\n");
1626 Controller
->AddRef();
1631 USBI_InterfaceDereference(
1634 CHubController
* Controller
= (CHubController
*)BusContext
;
1636 DPRINT1("USBH_InterfaceDereference\n");
1641 Controller
->Release();
1643 //=================================================================================================
1645 // USB Hub Interface functions
1649 USBHI_CreateUsbDevice(
1651 PUSB_DEVICE_HANDLE
*NewDevice
,
1652 PUSB_DEVICE_HANDLE HubDeviceHandle
,
1656 PUSBDEVICE NewUsbDevice
;
1657 CHubController
* Controller
;
1660 DPRINT1("USBHI_CreateUsbDevice\n");
1663 // first get hub controller
1665 Controller
= (CHubController
*)BusContext
;
1670 PC_ASSERT(Controller
);
1671 PC_ASSERT(BusContext
== HubDeviceHandle
);
1674 // now allocate usb device
1676 Status
= CreateUSBDevice(&NewUsbDevice
);
1679 // check for success
1681 if (!NT_SUCCESS(Status
))
1684 // release controller
1686 Controller
->Release();
1687 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
1692 // now initialize device
1694 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
1697 // check for success
1699 if (!NT_SUCCESS(Status
))
1702 // release usb device
1704 NewUsbDevice
->Release();
1705 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
1712 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
1714 // check for success
1716 if (!NT_SUCCESS(Status
))
1719 // release usb device
1721 NewUsbDevice
->Release();
1723 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
1730 *NewDevice
= NewUsbDevice
;
1735 return STATUS_SUCCESS
;
1740 USBHI_InitializeUsbDevice(
1742 PUSB_DEVICE_HANDLE DeviceHandle
)
1744 PUSBDEVICE UsbDevice
;
1745 CHubController
* Controller
;
1746 ULONG DeviceAddress
;
1750 DPRINT1("USBHI_InitializeUsbDevice\n");
1753 // first get controller
1755 Controller
= (CHubController
*)BusContext
;
1756 PC_ASSERT(Controller
);
1759 // get device object
1761 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
1762 PC_ASSERT(UsbDevice
);
1765 // validate device handle
1767 if (!Controller
->ValidateUsbDevice(UsbDevice
))
1769 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
1772 // invalid device handle
1774 return STATUS_DEVICE_NOT_CONNECTED
;
1778 // now reserve an address
1780 DeviceAddress
= Controller
->AcquireDeviceAddress();
1783 // is the device address valid
1785 if (DeviceAddress
== MAXULONG
)
1788 // failed to get an device address from the device address pool
1790 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
1791 return STATUS_DEVICE_DATA_ERROR
;
1797 // now set the device address
1799 Status
= UsbDevice
->SetDeviceAddress(DeviceAddress
);
1801 if (NT_SUCCESS(Status
))
1804 }while(Index
++ < 3 );
1807 // check for failure
1809 if (!NT_SUCCESS(Status
))
1812 // failed to set device address
1814 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
1819 Controller
->ReleaseDeviceAddress(DeviceAddress
);
1824 return STATUS_DEVICE_DATA_ERROR
;
1830 return STATUS_SUCCESS
;
1835 USBHI_GetUsbDescriptors(
1837 PUSB_DEVICE_HANDLE DeviceHandle
,
1838 PUCHAR DeviceDescriptorBuffer
,
1839 PULONG DeviceDescriptorBufferLength
,
1840 PUCHAR ConfigDescriptorBuffer
,
1841 PULONG ConfigDescriptorBufferLength
)
1843 PUSBDEVICE UsbDevice
;
1844 CHubController
* Controller
;
1846 DPRINT1("USBHI_GetUsbDescriptors\n");
1851 PC_ASSERT(DeviceDescriptorBuffer
);
1852 PC_ASSERT(DeviceDescriptorBufferLength
);
1853 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1854 PC_ASSERT(ConfigDescriptorBufferLength
);
1855 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1858 // first get controller
1860 Controller
= (CHubController
*)BusContext
;
1861 PC_ASSERT(Controller
);
1865 // get device object
1867 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
1868 PC_ASSERT(UsbDevice
);
1871 // validate device handle
1873 if (!Controller
->ValidateUsbDevice(UsbDevice
))
1875 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
1878 // invalid device handle
1880 return STATUS_DEVICE_NOT_CONNECTED
;
1884 // get device descriptor
1886 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
1889 // store result length
1891 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
1894 // get configuration descriptor
1896 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
1899 // complete the request
1901 return STATUS_SUCCESS
;
1906 USBHI_RemoveUsbDevice(
1908 PUSB_DEVICE_HANDLE DeviceHandle
,
1911 PUSBDEVICE UsbDevice
;
1912 CHubController
* Controller
;
1915 DPRINT1("USBHI_RemoveUsbDevice\n");
1918 // first get controller
1920 Controller
= (CHubController
*)BusContext
;
1921 PC_ASSERT(Controller
);
1924 // get device object
1926 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
1927 PC_ASSERT(UsbDevice
);
1930 // validate device handle
1932 if (!Controller
->ValidateUsbDevice(UsbDevice
))
1934 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
1937 // invalid device handle
1939 return STATUS_DEVICE_NOT_CONNECTED
;
1943 // check if there were flags passed
1945 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
1948 // ignore flags for now
1950 return STATUS_SUCCESS
;
1956 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
1957 if (!NT_SUCCESS(Status
))
1960 // invalid device handle
1962 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
1964 return STATUS_DEVICE_NOT_CONNECTED
;
1968 // release usb device
1970 UsbDevice
->Release();
1975 return STATUS_SUCCESS
;
1980 USBHI_RestoreUsbDevice(
1982 PUSB_DEVICE_HANDLE OldDeviceHandle
,
1983 PUSB_DEVICE_HANDLE NewDeviceHandle
)
1986 return STATUS_NOT_IMPLEMENTED
;
1991 USBHI_QueryDeviceInformation(
1993 PUSB_DEVICE_HANDLE DeviceHandle
,
1994 PVOID DeviceInformationBuffer
,
1995 ULONG DeviceInformationBufferLength
,
1996 PULONG LengthReturned
)
1998 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
1999 PUSBDEVICE UsbDevice
;
2000 CHubController
* Controller
;
2002 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2007 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2008 PC_ASSERT(DeviceInformationBuffer
);
2009 PC_ASSERT(LengthReturned
);
2012 // get controller object
2014 Controller
= (CHubController
*)BusContext
;
2015 PC_ASSERT(Controller
);
2018 // get device object
2020 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2021 PC_ASSERT(UsbDevice
);
2023 if (BusContext
!= DeviceHandle
)
2026 // validate device handle
2028 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2030 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2033 // invalid device handle
2035 return STATUS_DEVICE_NOT_CONNECTED
;
2039 // access information buffer
2041 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2044 // initialize with default values
2046 DeviceInfo
->InformationLevel
= 0;
2047 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2048 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2049 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2050 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2051 DeviceInfo
->HubAddress
= 0; //FIXME
2052 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2053 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2054 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2057 // get device descriptor
2059 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2062 // FIXME return pipe information
2066 // store result length
2068 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2070 return STATUS_SUCCESS
;
2074 // access information buffer
2076 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2079 // initialize with default values
2081 DeviceInfo
->InformationLevel
= 0;
2082 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2083 DeviceInfo
->PortNumber
= 0;
2084 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2085 DeviceInfo
->DeviceAddress
= 0;
2086 DeviceInfo
->HubAddress
= 0; //FIXME
2087 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
2088 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
2089 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2092 // FIXME get device descriptor
2096 // FIXME return pipe information
2100 // store result length
2102 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2107 return STATUS_SUCCESS
;
2112 USBHI_GetControllerInformation(
2114 PVOID ControllerInformationBuffer
,
2115 ULONG ControllerInformationBufferLength
,
2116 PULONG LengthReturned
)
2118 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2120 DPRINT1("USBHI_GetControllerInformation\n");
2125 PC_ASSERT(ControllerInformationBuffer
);
2126 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2129 // get controller info buffer
2131 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
2134 // FIXME only version 0 is supported for now
2136 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
2139 // fill in information
2141 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
2142 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
2143 ControllerInfo
->IsHighSpeedController
= TRUE
;
2146 // set length returned
2148 *LengthReturned
= ControllerInfo
->ActualLength
;
2153 return STATUS_SUCCESS
;
2158 USBHI_ControllerSelectiveSuspend(
2163 return STATUS_NOT_IMPLEMENTED
;
2168 USBHI_GetExtendedHubInformation(
2170 PDEVICE_OBJECT HubPhysicalDeviceObject
,
2171 PVOID HubInformationBuffer
,
2172 ULONG HubInformationBufferLength
,
2173 PULONG LengthReturned
)
2175 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
2176 CHubController
* Controller
;
2177 PUSBHARDWAREDEVICE Hardware
;
2179 ULONG NumPort
, Dummy2
;
2183 DPRINT1("USBHI_GetExtendedHubInformation\n");
2188 PC_ASSERT(HubInformationBuffer
);
2189 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
2190 PC_ASSERT(LengthReturned
);
2193 // get hub controller
2195 Controller
= (CHubController
*)BusContext
;
2196 PC_ASSERT(Controller
);
2199 // get usb hardware device
2201 Hardware
= Controller
->GetUsbHardware();
2204 // retrieve number of ports
2206 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
2207 if (!NT_SUCCESS(Status
))
2210 // failed to get hardware details, ouch ;)
2212 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
2217 // get hub information buffer
2219 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
2222 // initialize hub information
2224 HubInfo
->InformationLevel
= 0;
2229 HubInfo
->NumberOfPorts
= NumPort
;
2232 // initialize port information
2234 for(Index
= 0; Index
< NumPort
; Index
++)
2236 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
2237 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
2238 HubInfo
->Port
[Index
].VidOverride
= 0;
2239 HubInfo
->Port
[Index
].PidOverride
= 0;
2240 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
2244 // store result length
2247 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
2249 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
2255 return STATUS_SUCCESS
;
2260 USBHI_GetRootHubSymbolicName(
2262 PVOID HubSymNameBuffer
,
2263 ULONG HubSymNameBufferLength
,
2264 PULONG HubSymNameActualLength
)
2267 return STATUS_NOT_IMPLEMENTED
;
2272 USBHI_GetDeviceBusContext(
2273 PVOID HubBusContext
,
2282 USBHI_Initialize20Hub(
2284 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2288 return STATUS_SUCCESS
;
2293 USBHI_RootHubInitNotification(
2295 PVOID CallbackContext
,
2296 PRH_INIT_CALLBACK CallbackRoutine
)
2298 CHubController
* Controller
;
2300 DPRINT1("USBHI_RootHubInitNotification\n");
2303 // get controller object
2305 Controller
= (CHubController
*)BusContext
;
2306 PC_ASSERT(Controller
);
2309 // set notification routine
2311 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
2314 // FIXME: determine when to perform callback
2316 CallbackRoutine(CallbackContext
);
2321 return STATUS_SUCCESS
;
2326 USBHI_FlushTransfers(
2335 USBHI_SetDeviceHandleData(
2338 PDEVICE_OBJECT UsbDevicePdo
)
2340 PUSBDEVICE UsbDevice
;
2341 CHubController
* Controller
;
2346 Controller
= (CHubController
*)BusContext
;
2347 PC_ASSERT(Controller
);
2350 // get device handle
2352 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2355 // validate device handle
2357 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2359 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
2368 // set device handle data
2370 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
2373 //=================================================================================================
2375 // USB Device Interface functions
2380 USBDI_GetUSBDIVersion(
2382 PUSBD_VERSION_INFORMATION VersionInformation
,
2383 PULONG HcdCapabilites
)
2385 CHubController
* Controller
;
2386 PUSBHARDWAREDEVICE Device
;
2387 ULONG Speed
, Dummy2
;
2390 DPRINT1("USBDI_GetUSBDIVersion\n");
2395 Controller
= (CHubController
*)BusContext
;
2400 Device
= Controller
->GetUsbHardware();
2403 if (VersionInformation
)
2406 // windows xp supported
2408 VersionInformation
->USBDI_Version
= 0x00000500;
2413 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2416 // store speed details
2418 VersionInformation
->Supported_USB_Version
= Speed
;
2422 // no flags supported
2424 *HcdCapabilites
= 0;
2431 PULONG CurrentFrame
)
2434 return STATUS_NOT_IMPLEMENTED
;
2439 USBDI_SubmitIsoOutUrb(
2444 return STATUS_NOT_IMPLEMENTED
;
2449 USBDI_QueryBusInformation(
2452 PVOID BusInformationBuffer
,
2453 PULONG BusInformationBufferLength
,
2454 PULONG BusInformationActualLength
)
2457 return STATUS_NOT_IMPLEMENTED
;
2462 USBDI_IsDeviceHighSpeed(
2465 CHubController
* Controller
;
2466 PUSBHARDWAREDEVICE Device
;
2467 ULONG Speed
, Dummy2
;
2470 DPRINT1("USBDI_IsDeviceHighSpeed\n");
2475 Controller
= (CHubController
*)BusContext
;
2480 Device
= Controller
->GetUsbHardware();
2486 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2489 // USB 2.0 equals 0x200
2491 return (Speed
== 0x200);
2504 return STATUS_NOT_IMPLEMENTED
;
2508 CHubController::HandleQueryInterface(
2509 PIO_STACK_LOCATION IoStack
)
2511 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
2512 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
2513 UNICODE_STRING GuidBuffer
;
2516 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
2519 // get request parameters
2521 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
2522 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2527 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
2529 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2532 // version not supported
2534 return STATUS_NOT_SUPPORTED
;
2538 // Interface version 0
2540 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2542 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2543 InterfaceHub
->BusContext
= PVOID(this);
2544 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
2545 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
2549 // Interface version 1
2551 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2553 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
2554 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
2555 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
2556 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
2557 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
2558 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
2562 // Interface version 2
2564 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2566 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
2567 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
2568 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
2569 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
2570 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
2571 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
2576 // Interface version 3
2578 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2580 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
2584 // Interface version 4
2586 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
2588 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
2592 // Interface version 5
2594 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
2596 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
2600 // request completed
2602 return STATUS_SUCCESS
;
2604 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
2607 // get request parameters
2609 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
2610 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2615 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
2617 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2620 // version not supported
2622 return STATUS_NOT_SUPPORTED
;
2626 // interface version 0
2628 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2630 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2631 InterfaceDI
->BusContext
= PVOID(this);
2632 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
2633 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
2634 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
2635 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
2636 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
2637 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
2641 // interface version 1
2643 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2645 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
2649 // interface version 2
2651 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2653 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
2657 // request completed
2659 return STATUS_SUCCESS
;
2664 // convert guid to string
2666 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
2667 if (NT_SUCCESS(Status
))
2672 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
2677 RtlFreeUnicodeString(&GuidBuffer
);
2680 return STATUS_NOT_SUPPORTED
;
2684 CHubController::SetDeviceInterface(
2687 NTSTATUS Status
= STATUS_SUCCESS
;
2692 // register device interface
2694 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
2696 if (NT_SUCCESS(Status
))
2699 // now enable the device interface
2701 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
2706 m_InterfaceEnabled
= TRUE
;
2709 else if (m_InterfaceEnabled
)
2712 // disable device interface
2714 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
2716 if (NT_SUCCESS(Status
))
2719 // now delete interface string
2721 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
2725 // disable interface
2727 m_InterfaceEnabled
= FALSE
;
2737 CHubController::CreatePDO(
2738 PDRIVER_OBJECT DriverObject
,
2739 PDEVICE_OBJECT
* OutDeviceObject
)
2741 WCHAR CharDeviceName
[64];
2743 ULONG UsbDeviceNumber
= 0;
2744 UNICODE_STRING DeviceName
;
2749 // construct device name
2751 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
2754 // initialize device name
2756 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
2761 Status
= IoCreateDevice(DriverObject
,
2762 sizeof(COMMON_DEVICE_EXTENSION
),
2764 FILE_DEVICE_CONTROLLER
,
2769 /* check for success */
2770 if (NT_SUCCESS(Status
))
2774 // is there a device object with that same name
2776 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
2779 // Try the next name
2786 // bail out on other errors
2788 if (!NT_SUCCESS(Status
))
2790 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
2795 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
2804 CreateHubController(
2805 PHUBCONTROLLER
*OutHcdController
)
2807 PHUBCONTROLLER This
;
2810 // allocate controller
2812 This
= new(NonPagedPool
, TAG_USBEHCI
) CHubController(0);
2816 // failed to allocate
2818 return STATUS_INSUFFICIENT_RESOURCES
;
2822 // add reference count
2829 *OutHcdController
= (PHUBCONTROLLER
)This
;
2834 return STATUS_SUCCESS
;
2837 VOID
StatusChangeEndpointCallBack(PVOID Context
)
2839 CHubController
* This
;
2841 This
= (CHubController
*)Context
;
2845 DPRINT1("SCE Notification!\n");
2846 Irp
= This
->m_PendingSCEIrp
;
2847 This
->m_PendingSCEIrp
= NULL
;
2849 This
->QueryStatusChageEndpoint(Irp
);
2851 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2852 Irp
->IoStatus
.Information
= 0;
2853 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);