2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbohci/hub_controller.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 VOID
StatusChangeEndpointCallBack(
17 class CHubController
: public IHubController
,
21 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
23 STDMETHODIMP_(ULONG
) AddRef()
25 InterlockedIncrement(&m_Ref
);
28 STDMETHODIMP_(ULONG
) Release()
30 InterlockedDecrement(&m_Ref
);
40 // IHubController interface functions
41 virtual NTSTATUS
Initialize(IN PDRIVER_OBJECT DriverObject
, IN PHCDCONTROLLER Controller
, IN PUSBHARDWAREDEVICE Device
, IN BOOLEAN IsRootHubDevice
, IN ULONG DeviceAddress
);
42 virtual NTSTATUS
GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
);
43 virtual NTSTATUS
GetHubControllerSymbolicLink(ULONG BufferLength
, PVOID Buffer
, PULONG RequiredLength
);
45 // IDispatchIrp interface functions
46 virtual NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
47 virtual NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
48 virtual NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
51 NTSTATUS
HandleQueryInterface(PIO_STACK_LOCATION IoStack
);
52 NTSTATUS
SetDeviceInterface(BOOLEAN bEnable
);
53 NTSTATUS
CreatePDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
54 PUSBHARDWAREDEVICE
GetUsbHardware();
55 ULONG
AcquireDeviceAddress();
56 VOID
ReleaseDeviceAddress(ULONG DeviceAddress
);
57 BOOLEAN
ValidateUsbDevice(PUSBDEVICE UsbDevice
);
58 NTSTATUS
AddUsbDevice(PUSBDEVICE UsbDevice
);
59 NTSTATUS
RemoveUsbDevice(PUSBDEVICE UsbDevice
);
60 VOID
SetNotification(PVOID CallbackContext
, PRH_INIT_CALLBACK CallbackRoutine
);
61 // internal ioctl routines
62 NTSTATUS
HandleGetDescriptor(IN OUT PIRP Irp
, PURB Urb
);
63 NTSTATUS
HandleGetDescriptorFromInterface(IN OUT PIRP Irp
, PURB Urb
);
64 NTSTATUS
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
65 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
70 NTSTATUS
HandleClassEndpoint(IN OUT PIRP Irp
, PURB Urb
);
71 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
72 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
73 NTSTATUS
HandleClearStall(IN OUT PIRP Irp
, PURB Urb
);
74 NTSTATUS
HandleSyncResetAndClearStall(IN OUT PIRP Irp
, PURB Urb
);
75 NTSTATUS
HandleAbortPipe(IN OUT PIRP Irp
, PURB Urb
);
77 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
79 // constructor / destructor
80 CHubController(IUnknown
*OuterUnknown
){}
81 virtual ~CHubController(){}
85 PHCDCONTROLLER m_Controller
;
86 PUSBHARDWAREDEVICE m_Hardware
;
87 BOOLEAN m_IsRootHubDevice
;
88 ULONG m_DeviceAddress
;
90 BOOLEAN m_InterfaceEnabled
;
91 UNICODE_STRING m_HubDeviceInterfaceString
;
93 PDEVICE_OBJECT m_HubControllerDeviceObject
;
94 PDRIVER_OBJECT m_DriverObject
;
96 PVOID m_HubCallbackContext
;
97 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
99 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
102 RTL_BITMAP m_DeviceAddressBitmap
;
103 PULONG m_DeviceAddressBitmapBuffer
;
104 LIST_ENTRY m_UsbDeviceList
;
105 PIRP m_PendingSCEIrp
;
108 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
115 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
117 /* Lifted from Linux with slight changes */
118 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
121 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
122 0x00, 0x20, /* bcdUSB; v1.1 */
123 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
124 0x01, /* bDeviceSubClass; */
125 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
126 0x08, /* bMaxPacketSize0; 8 Bytes */
127 /* Fill Vendor and Product in when init root hub */
128 0x00, 0x00, /* idVendor; */
129 0x00, 0x00, /* idProduct; */
130 0x00, 0x00, /* bcdDevice */
131 0x00, /* iManufacturer; */
132 0x00, /* iProduct; */
133 0x00, /* iSerialNumber; */
134 0x01 /* bNumConfigurations; */
138 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
140 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
141 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
142 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
146 0x40, /* self powered */
150 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
152 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
153 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
154 0, /* bInterfaceNumber; */
155 0, /* bAlternateSetting; */
156 0x1, /* bNumEndpoints; */
157 0x09, /* bInterfaceClass; HUB_CLASSCODE */
158 0x01, /* bInterfaceSubClass; */
159 0x00, /* bInterfaceProtocol: */
160 0x00, /* iInterface; */
163 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
165 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
166 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
167 0x81, /* bEndPointAddress */
168 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
169 0x01, /* wMaxPacketSize */
173 //----------------------------------------------------------------------------------------
176 CHubController::QueryInterface(
180 return STATUS_UNSUCCESSFUL
;
182 //----------------------------------------------------------------------------------------
184 CHubController::Initialize(
185 IN PDRIVER_OBJECT DriverObject
,
186 IN PHCDCONTROLLER Controller
,
187 IN PUSBHARDWAREDEVICE Device
,
188 IN BOOLEAN IsRootHubDevice
,
189 IN ULONG DeviceAddress
)
192 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
193 USHORT VendorID
, DeviceID
;
196 DPRINT1("CHubController::Initialize\n");
199 // initialize members
201 m_Controller
= Controller
;
203 m_IsRootHubDevice
= IsRootHubDevice
;
204 m_DeviceAddress
= DeviceAddress
;
205 m_DriverObject
= DriverObject
;
206 KeInitializeSpinLock(&m_Lock
);
207 InitializeListHead(&m_UsbDeviceList
);
210 // allocate device address bitmap buffer
212 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBOHCI
);
213 if (!m_DeviceAddressBitmapBuffer
)
218 return STATUS_INSUFFICIENT_RESOURCES
;
222 // initialize device address bitmap
224 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
225 RtlClearAllBits(&m_DeviceAddressBitmap
);
231 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
232 if (!NT_SUCCESS(Status
))
235 // failed to create hub device object
241 // get device extension
243 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
246 // initialize device extension
248 DeviceExtension
->IsFDO
= FALSE
;
249 DeviceExtension
->IsHub
= TRUE
; //FIXME
250 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
253 // intialize device descriptor
255 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
256 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
258 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
261 // update device descriptor
263 m_DeviceDescriptor
.idVendor
= VendorID
;
264 m_DeviceDescriptor
.idProduct
= DeviceID
;
265 m_DeviceDescriptor
.bcdUSB
= 0x110; //FIXME
269 // Set the SCE Callback that the Hardware Device will call on port status change
271 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
276 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
278 return STATUS_SUCCESS
;
282 // Queries the ports to see if there has been a device connected or removed.
285 CHubController::QueryStatusChageEndpoint(
288 ULONG PortCount
, PortId
;
289 PIO_STACK_LOCATION IoStack
;
290 USHORT PortStatus
, PortChange
;
292 PUCHAR TransferBuffer
;
293 UCHAR Changed
= FALSE
;
296 // get current stack location
298 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
304 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
308 // Get the number of ports and check each one for device connected
310 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
311 DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
, Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
313 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
318 for (PortId
= 0; PortId
< PortCount
; PortId
++)
320 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
322 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
326 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
330 DPRINT1("Change state on port %d\n", PortId
);
331 // Set the value for the port number
332 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
340 //-----------------------------------------------------------------------------------------
342 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
345 // store controller object
347 *HubDeviceObject
= m_HubControllerDeviceObject
;
349 return STATUS_SUCCESS
;
351 //-----------------------------------------------------------------------------------------
353 CHubController::GetHubControllerSymbolicLink(
356 PULONG RequiredLength
)
358 if (!m_InterfaceEnabled
)
361 // device interface not yet enabled
363 return STATUS_UNSUCCESSFUL
;
366 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
370 // length is without '\??\'
372 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
377 return STATUS_BUFFER_OVERFLOW
;
381 // copy symbolic link
383 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
386 // store length, length is without '\??\'
388 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
393 return STATUS_SUCCESS
;
396 //-----------------------------------------------------------------------------------------
398 CHubController::HandlePnp(
399 IN PDEVICE_OBJECT DeviceObject
,
402 PIO_STACK_LOCATION IoStack
;
403 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
404 PDEVICE_CAPABILITIES DeviceCapabilities
;
405 PPNP_BUS_INFORMATION BusInformation
;
406 PDEVICE_RELATIONS DeviceRelations
;
408 ULONG Index
= 0, Length
;
409 USHORT VendorID
, DeviceID
;
410 ULONG HiSpeed
, NumPorts
;
415 // get device extension
417 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
422 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
425 // get current stack location
427 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
429 switch(IoStack
->MinorFunction
)
431 case IRP_MN_START_DEVICE
:
433 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
435 // register device interface
437 Status
= SetDeviceInterface(TRUE
);
440 case IRP_MN_QUERY_ID
:
442 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
444 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
451 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
453 if (HiSpeed
== 0x200)
458 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
465 swprintf(Buffer
, L
"USB\\ROOT_HUB");
468 DPRINT1("Name %S\n", Buffer
);
473 Length
= (wcslen(Buffer
) + 1);
478 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBOHCI
);
485 Status
= STATUS_INSUFFICIENT_RESOURCES
;
492 wcscpy(DeviceName
, Buffer
);
497 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
498 Status
= STATUS_SUCCESS
;
501 Status
= STATUS_UNSUCCESSFUL
;
506 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
513 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
515 if (!NT_SUCCESS(Status
))
517 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
522 if (HiSpeed
== 0x200)
527 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
528 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
529 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
536 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
537 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
538 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
541 Buffer
[Index
] = UNICODE_NULL
;
545 DPRINT1("Name %S\n", Buffer
);
550 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBOHCI
);
557 Status
= STATUS_INSUFFICIENT_RESOURCES
;
564 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
569 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
570 Status
= STATUS_SUCCESS
;
574 Status
= STATUS_SUCCESS
;
577 case IRP_MN_QUERY_CAPABILITIES
:
579 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
581 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
583 DeviceCapabilities
->LockSupported
= FALSE
;
584 DeviceCapabilities
->EjectSupported
= FALSE
;
585 DeviceCapabilities
->Removable
= FALSE
;
586 DeviceCapabilities
->DockDevice
= FALSE
;
587 DeviceCapabilities
->UniqueID
= FALSE
;
588 DeviceCapabilities
->SilentInstall
= FALSE
;
589 DeviceCapabilities
->RawDeviceOK
= FALSE
;
590 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
591 DeviceCapabilities
->Address
= 0;
592 DeviceCapabilities
->UINumber
= 0;
593 DeviceCapabilities
->DeviceD2
= 1;
596 DeviceCapabilities
->HardwareDisabled
= FALSE
;
597 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
598 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
599 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
600 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
601 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
602 DeviceCapabilities
->D1Latency
= 0;
603 DeviceCapabilities
->D2Latency
= 0;
604 DeviceCapabilities
->D3Latency
= 0;
606 Status
= STATUS_SUCCESS
;
609 case IRP_MN_QUERY_INTERFACE
:
611 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
614 // handle device interface requests
616 Status
= HandleQueryInterface(IoStack
);
619 case IRP_MN_REMOVE_DEVICE
:
621 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
624 // deactivate device interface for BUS PDO
626 SetDeviceInterface(FALSE
);
629 // complete the request first
631 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
632 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
637 IoDeleteDevice(m_HubControllerDeviceObject
);
642 m_HubControllerDeviceObject
= 0;
647 return STATUS_SUCCESS
;
649 case IRP_MN_QUERY_DEVICE_RELATIONS
:
651 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
653 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
656 // allocate device relations
658 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBOHCI
);
659 if (!DeviceRelations
)
664 Status
= STATUS_INSUFFICIENT_RESOURCES
;
669 // initialize device relations
671 DeviceRelations
->Count
= 1;
672 DeviceRelations
->Objects
[0] = DeviceObject
;
673 ObReferenceObject(DeviceObject
);
678 Status
= STATUS_SUCCESS
;
679 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
686 Status
= Irp
->IoStatus
.Status
;
690 case IRP_MN_QUERY_BUS_INFORMATION
:
692 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
695 // allocate buffer for bus information
697 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
703 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
708 BusInformation
->LegacyBusType
= PNPBus
;
709 BusInformation
->BusNumber
= 0;
711 Status
= STATUS_SUCCESS
;
712 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
719 Status
= STATUS_INSUFFICIENT_RESOURCES
;
723 case IRP_MN_STOP_DEVICE
:
725 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
729 Status
= STATUS_SUCCESS
;
735 // ignore request with default status
737 Status
= Irp
->IoStatus
.Status
;
745 Irp
->IoStatus
.Status
= Status
;
746 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
754 //-----------------------------------------------------------------------------------------
756 CHubController::HandlePower(
757 IN PDEVICE_OBJECT DeviceObject
,
761 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
762 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
763 return STATUS_NOT_IMPLEMENTED
;
766 //-----------------------------------------------------------------------------------------
768 CHubController::HandleIsochronousTransfer(
772 PUSBDEVICE UsbDevice
;
773 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
776 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
778 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
782 DPRINT1("No EndpointDesc\n");
783 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
784 return STATUS_INVALID_PARAMETER
;
790 ASSERT(EndPointDesc
);
791 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
794 // check if this is a valid usb device handle
796 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
798 DPRINT1("HandleIsochronousTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
801 // invalid device handle
803 return STATUS_DEVICE_NOT_CONNECTED
;
809 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
811 return UsbDevice
->SubmitIrp(Irp
);
814 //-----------------------------------------------------------------------------------------
816 CHubController::HandleBulkOrInterruptTransfer(
820 PUSBDEVICE UsbDevice
;
821 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
823 // First check if the request is for the Status Change Endpoint
827 // Is the Request for the root hub
829 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
831 ASSERT(m_PendingSCEIrp
== NULL
);
832 if (QueryStatusChageEndpoint(Irp
))
834 StatusChangeEndpointCallBack(this);
835 return STATUS_SUCCESS
;
839 // Else pend the IRP, to be completed when a device connects or disconnects.
841 DPRINT1("Pending SCE Irp\n");;
842 m_PendingSCEIrp
= Irp
;
843 IoMarkIrpPending(Irp
);
844 return STATUS_PENDING
;
848 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
850 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
855 ASSERT(EndPointDesc
);
856 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
859 // check if this is a valid usb device handle
861 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
863 DPRINT1("HandleBuldOrInterruptTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
866 // invalid device handle
868 return STATUS_DEVICE_NOT_CONNECTED
;
874 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
876 return UsbDevice
->SubmitIrp(Irp
);
879 //-----------------------------------------------------------------------------------------
881 CHubController::HandleClassOther(
885 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
886 USHORT PortStatus
= 0, PortChange
= 0;
891 DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
894 // get number of ports available
896 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
897 PC_ASSERT(Status
== STATUS_SUCCESS
);
902 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
905 // port range reported start from 1 -n
906 // convert back port id so it matches the hardware
908 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
911 // check request code
913 switch(Urb
->UrbControlVendorClassRequest
.Request
)
915 case USB_REQUEST_GET_STATUS
:
920 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
921 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
926 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
928 if (NT_SUCCESS(Status
))
931 // request contains buffer of 2 ushort which are used from submitting port status and port change status
933 DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId
, PortStatus
, PortChange
);
934 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
937 // store status, then port change
939 *Buffer
= PortStatus
;
941 *Buffer
= PortChange
;
949 case USB_REQUEST_CLEAR_FEATURE
:
951 switch (Urb
->UrbControlVendorClassRequest
.Value
)
953 case C_PORT_CONNECTION
:
954 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
957 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
960 DPRINT("Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
964 Status
= STATUS_SUCCESS
;
967 case USB_REQUEST_SET_FEATURE
:
970 // request set feature
972 switch(Urb
->UrbControlVendorClassRequest
.Value
)
979 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_ENABLE
);
986 // set suspend port feature
988 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
994 // set power feature on port
996 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1003 // reset port feature
1005 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1006 PC_ASSERT(Status
== STATUS_SUCCESS
);
1010 DPRINT1("Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1016 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1018 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1023 //-----------------------------------------------------------------------------------------
1025 CHubController::HandleSelectConfiguration(
1029 PUSBDEVICE UsbDevice
;
1030 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1033 // is the request for the Root Hub
1035 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1038 // FIXME: support setting device to unconfigured state
1040 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1043 // set device handle
1045 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1048 // copy interface info
1050 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1052 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1053 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1054 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1055 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1056 InterfaceInfo
->Reserved
= 0;
1061 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1066 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1067 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1068 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1069 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1070 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1072 return STATUS_SUCCESS
;
1077 // check if this is a valid usb device handle
1079 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1081 DPRINT1("HandleSelectConfiguration invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1084 // invalid device handle
1086 return STATUS_DEVICE_NOT_CONNECTED
;
1092 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1095 // select configuration
1097 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1101 //-----------------------------------------------------------------------------------------
1103 CHubController::HandleSelectInterface(
1107 PUSBDEVICE UsbDevice
;
1112 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1115 // is the request for the Root Hub
1117 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1120 // no op for root hub
1122 return STATUS_SUCCESS
;
1127 // check if this is a valid usb device handle
1129 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1131 DPRINT1("HandleSelectInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1134 // invalid device handle
1136 return STATUS_DEVICE_NOT_CONNECTED
;
1142 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1147 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1151 //-----------------------------------------------------------------------------------------
1153 CHubController::HandleGetStatusFromDevice(
1157 PUSHORT DeviceStatus
;
1158 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1160 PUSBDEVICE UsbDevice
;
1165 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1166 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1167 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1170 // get status buffer
1172 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1175 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1178 // FIXME need more flags ?
1180 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1181 return STATUS_SUCCESS
;
1185 // check if this is a valid usb device handle
1187 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1189 DPRINT1("HandleGetStatusFromDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1192 // invalid device handle
1194 return STATUS_DEVICE_NOT_CONNECTED
;
1200 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1204 // generate setup packet
1206 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1207 CtrlSetup
.wValue
.LowByte
= 0;
1208 CtrlSetup
.wValue
.HiByte
= 0;
1209 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1210 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1211 CtrlSetup
.bmRequestType
.B
= 0x80;
1214 // submit setup packet
1216 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1217 ASSERT(Status
== STATUS_SUCCESS
);
1218 DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1226 //-----------------------------------------------------------------------------------------
1228 CHubController::HandleClassDevice(
1232 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1233 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1234 ULONG PortCount
, Dummy2
;
1236 PUSBDEVICE UsbDevice
;
1237 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1239 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1242 // check class request type
1244 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1246 case USB_REQUEST_GET_STATUS
:
1249 // check if this is a valid usb device handle
1251 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1253 DPRINT1("USB_REQUEST_GET_STATUS invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1256 // invalid device handle
1258 return STATUS_DEVICE_NOT_CONNECTED
;
1264 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1268 // generate setup packet
1270 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1271 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlVendorClassRequest
.Index
;
1272 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1273 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1274 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1275 CtrlSetup
.bmRequestType
.B
= 0xA0;
1278 // submit setup packet
1280 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1281 ASSERT(Status
== STATUS_SUCCESS
);
1284 case USB_REQUEST_GET_DESCRIPTOR
:
1286 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1288 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1289 case USB_DEVICE_CLASS_HUB
:
1294 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1295 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1298 // get hub descriptor
1300 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1303 // one hub is handled
1305 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1306 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1309 // type should 0x29 according to msdn
1311 UsbHubDescriptor
->bDescriptorType
= 0x29;
1316 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1317 PC_ASSERT(Status
== STATUS_SUCCESS
);
1320 // FIXME: retrieve values
1322 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1323 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1324 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1325 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1330 Status
= STATUS_SUCCESS
;
1334 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1340 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1346 //-----------------------------------------------------------------------------------------
1348 CHubController::HandleGetDescriptorFromInterface(
1352 PUSBDEVICE UsbDevice
;
1353 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1359 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1360 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1363 // check if this is a valid usb device handle
1365 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1367 DPRINT1("HandleGetDescriptorFromInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1370 // invalid device handle
1372 return STATUS_DEVICE_NOT_CONNECTED
;
1378 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1381 // generate setup packet
1383 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1384 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1385 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1386 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1387 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1388 CtrlSetup
.bmRequestType
.B
= 0x81;
1391 // submit setup packet
1393 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1394 ASSERT(Status
== STATUS_SUCCESS
);
1402 //-----------------------------------------------------------------------------------------
1404 CHubController::HandleGetDescriptor(
1408 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1409 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1410 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1412 PUSBDEVICE UsbDevice
;
1415 DPRINT("CHubController::HandleGetDescriptor\n");
1418 // check descriptor type
1420 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1422 case USB_DEVICE_DESCRIPTOR_TYPE
:
1427 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1428 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1430 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1433 // copy root hub device descriptor
1435 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1436 Status
= STATUS_SUCCESS
;
1441 // check if this is a valid usb device handle
1443 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1445 DPRINT1("HandleGetDescriptor invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1448 // invalid device handle
1450 return STATUS_DEVICE_NOT_CONNECTED
;
1456 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1459 // retrieve device descriptor from device
1461 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1462 Status
= STATUS_SUCCESS
;
1466 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1471 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1472 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1474 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1477 // request is for the root bus controller
1479 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1482 // get configuration descriptor, very retarded!
1484 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1487 // check if buffer can hold interface and endpoint descriptor
1489 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1494 Status
= STATUS_SUCCESS
;
1500 // copy interface descriptor template
1502 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1503 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1506 // copy end point descriptor template
1508 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1509 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1514 Status
= STATUS_SUCCESS
;
1520 // check if this is a valid usb device handle
1522 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1524 DPRINT1("USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1527 // invalid device handle
1529 return STATUS_DEVICE_NOT_CONNECTED
;
1535 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1537 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1542 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1547 Status
= STATUS_SUCCESS
;
1552 // perform work in IUSBDevice
1554 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1557 // store result size
1559 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1560 Status
= STATUS_SUCCESS
;
1564 case USB_STRING_DESCRIPTOR_TYPE
:
1569 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1570 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1573 // check if this is a valid usb device handle
1575 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1577 DPRINT1("USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1580 // invalid device handle
1582 return STATUS_DEVICE_NOT_CONNECTED
;
1588 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1591 // generate setup packet
1593 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1594 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1595 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1596 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1597 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1598 CtrlSetup
.bmRequestType
.B
= 0x80;
1601 // submit setup packet
1603 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1607 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1617 //-----------------------------------------------------------------------------------------
1619 CHubController::HandleClassEndpoint(
1623 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1625 PUSBDEVICE UsbDevice
;
1630 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1631 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1632 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1635 // check if this is a valid usb device handle
1637 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1639 DPRINT1("HandleClassEndpoint invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1642 // invalid device handle
1644 return STATUS_DEVICE_NOT_CONNECTED
;
1650 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1653 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1654 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1655 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1656 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1657 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1658 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1659 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1660 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1661 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1664 // initialize setup packet
1666 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1667 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1668 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1669 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1670 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1672 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1675 // data direction is device to host
1677 CtrlSetup
.bmRequestType
.B
|= 0x80;
1684 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1687 // assert on failure
1689 PC_ASSERT(NT_SUCCESS(Status
));
1699 CHubController::HandleSyncResetAndClearStall(
1703 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1704 NTSTATUS Status
= STATUS_SUCCESS
;
1705 PUSBDEVICE UsbDevice
;
1706 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1712 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1713 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1714 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1717 // check if this is a valid usb device handle
1719 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1721 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1724 // invalid device handle
1726 return STATUS_DEVICE_NOT_CONNECTED
;
1730 // get endpoint descriptor
1732 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1737 Type
= (EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1738 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1743 Status
= HandleClearStall(Irp
, Urb
);
1745 DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status
);
1748 // FIXME reset data toggle
1758 CHubController::HandleAbortPipe(
1762 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1764 PUSBDEVICE UsbDevice
;
1765 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1771 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1772 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1773 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1776 // check if this is a valid usb device handle
1778 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1780 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1783 // invalid device handle
1785 return STATUS_DEVICE_NOT_CONNECTED
;
1789 // get endpoint descriptor
1791 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1796 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1802 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
1803 DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status
);
1812 //-----------------------------------------------------------------------------------------
1814 CHubController::HandleClearStall(
1818 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1820 PUSBDEVICE UsbDevice
;
1821 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1827 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1828 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1829 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1832 // check if this is a valid usb device handle
1834 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1836 DPRINT1("HandleClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1839 // invalid device handle
1841 return STATUS_DEVICE_NOT_CONNECTED
;
1845 // get endpoint descriptor
1847 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1852 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1853 DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
1856 // initialize setup packet
1858 CtrlSetup
.bmRequestType
.B
= 0x02;
1859 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
1860 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
1861 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
1862 CtrlSetup
.wLength
= 0;
1863 CtrlSetup
.wValue
.W
= 0;
1868 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
1870 DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status
);
1879 //-----------------------------------------------------------------------------------------
1881 CHubController::HandleClassInterface(
1885 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1887 PUSBDEVICE UsbDevice
;
1892 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1893 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1894 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1897 // check if this is a valid usb device handle
1899 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1901 DPRINT1("HandleClassInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1904 // invalid device handle
1906 return STATUS_DEVICE_NOT_CONNECTED
;
1912 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1915 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1916 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1917 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1918 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1919 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1920 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1921 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1922 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1923 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1926 // initialize setup packet
1928 CtrlSetup
.bmRequestType
.B
= 0x21;
1929 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1930 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1931 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1932 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1934 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1937 // data direction is device to host
1939 CtrlSetup
.bmRequestType
.B
|= 0x80;
1945 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1948 // assert on failure
1950 if (!NT_SUCCESS(Status
))
1955 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb
->UrbHeader
.Status
);
1964 //-----------------------------------------------------------------------------------------
1966 CHubController::HandleDeviceControl(
1967 IN PDEVICE_OBJECT DeviceObject
,
1970 PIO_STACK_LOCATION IoStack
;
1971 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1973 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1976 // get current stack location
1978 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1981 // get device extension
1983 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1986 // determine which request should be performed
1988 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1990 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
1995 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1998 switch (Urb
->UrbHeader
.Function
)
2000 case URB_FUNCTION_SYNC_RESET_PIPE
:
2001 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2002 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2004 case URB_FUNCTION_ABORT_PIPE
:
2005 Status
= HandleAbortPipe(Irp
, Urb
);
2007 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2008 Status
= HandleClearStall(Irp
, Urb
);
2010 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2011 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2013 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2014 Status
= HandleGetDescriptor(Irp
, Urb
);
2016 case URB_FUNCTION_CLASS_DEVICE
:
2017 Status
= HandleClassDevice(Irp
, Urb
);
2019 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2020 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2022 case URB_FUNCTION_SELECT_CONFIGURATION
:
2023 Status
= HandleSelectConfiguration(Irp
, Urb
);
2025 case URB_FUNCTION_SELECT_INTERFACE
:
2026 Status
= HandleSelectInterface(Irp
, Urb
);
2028 case URB_FUNCTION_CLASS_OTHER
:
2029 Status
= HandleClassOther(Irp
, Urb
);
2031 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2032 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2034 case URB_FUNCTION_ISOCH_TRANSFER
:
2035 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2037 case URB_FUNCTION_CLASS_INTERFACE
:
2038 Status
= HandleClassInterface(Irp
, Urb
);
2040 case URB_FUNCTION_CLASS_ENDPOINT
:
2041 Status
= HandleClassEndpoint(Irp
, Urb
);
2044 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
2048 // request completed
2052 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2054 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2056 if (IoStack
->Parameters
.Others
.Argument1
)
2059 // store object as device handle
2061 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2062 Status
= STATUS_SUCCESS
;
2067 // mis-behaving hub driver
2069 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2073 // request completed
2077 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2079 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2082 // this is the first request send, it delivers the PDO to the caller
2084 if (IoStack
->Parameters
.Others
.Argument1
)
2087 // store root hub pdo object
2089 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2092 if (IoStack
->Parameters
.Others
.Argument2
)
2095 // documentation claims to deliver the hcd controller object, although it is wrong
2097 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2101 // request completed
2103 Status
= STATUS_SUCCESS
;
2106 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2108 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2111 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2112 // requests this ioctl to deliver the number of presents.
2114 if (IoStack
->Parameters
.Others
.Argument1
)
2117 // FIXME / verify: there is only one hub
2119 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2123 // request completed
2125 Status
= STATUS_SUCCESS
;
2126 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2129 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2131 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2132 Status
= STATUS_SUCCESS
;
2137 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2138 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2139 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2140 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2144 if (Status
!= STATUS_PENDING
)
2146 Irp
->IoStatus
.Status
= Status
;
2147 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2153 //-----------------------------------------------------------------------------------------
2155 CHubController::GetUsbHardware()
2160 //-----------------------------------------------------------------------------------------
2162 CHubController::AcquireDeviceAddress()
2165 ULONG DeviceAddress
;
2168 // acquire device lock
2170 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2175 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2176 if (DeviceAddress
!= MAXULONG
)
2181 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2184 // device addresses start from 0x1 - 0xFF
2190 // release spin lock
2192 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2195 // return device address
2197 return DeviceAddress
;
2199 //-----------------------------------------------------------------------------------------
2201 CHubController::ReleaseDeviceAddress(
2202 ULONG DeviceAddress
)
2207 // acquire device lock
2209 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2214 PC_ASSERT(DeviceAddress
!= 0);
2217 // convert back to bit number
2224 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2229 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2231 //-----------------------------------------------------------------------------------------
2233 CHubController::RemoveUsbDevice(
2234 PUSBDEVICE UsbDevice
)
2236 PUSBDEVICE_ENTRY DeviceEntry
;
2238 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2244 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2247 // point to first entry
2249 Entry
= m_UsbDeviceList
.Flink
;
2252 // find matching entry
2254 while(Entry
!= &m_UsbDeviceList
)
2259 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2262 // is it current entry
2264 if (DeviceEntry
->Device
== UsbDevice
)
2269 RemoveEntryList(Entry
);
2274 ExFreePoolWithTag(DeviceEntry
, TAG_USBOHCI
);
2279 Status
= STATUS_SUCCESS
;
2286 Entry
= Entry
->Flink
;
2292 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2299 //-----------------------------------------------------------------------------------------
2301 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2303 PUSBDEVICE_ENTRY DeviceEntry
;
2306 BOOLEAN Result
= FALSE
;
2311 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2314 // point to first entry
2316 Entry
= m_UsbDeviceList
.Flink
;
2319 // find matching entry
2321 while(Entry
!= &m_UsbDeviceList
)
2326 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2329 // is it current entry
2331 if (DeviceEntry
->Device
== UsbDevice
)
2343 Entry
= Entry
->Flink
;
2349 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2358 //-----------------------------------------------------------------------------------------
2360 CHubController::AddUsbDevice(
2361 PUSBDEVICE UsbDevice
)
2363 PUSBDEVICE_ENTRY DeviceEntry
;
2367 // allocate device entry
2369 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBOHCI
);
2375 return STATUS_INSUFFICIENT_RESOURCES
;
2381 DeviceEntry
->Device
= UsbDevice
;
2386 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2391 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2394 // release spin lock
2396 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2401 return STATUS_SUCCESS
;
2404 //-----------------------------------------------------------------------------------------
2406 CHubController::SetNotification(
2407 PVOID CallbackContext
,
2408 PRH_INIT_CALLBACK CallbackRoutine
)
2413 // acquire hub controller lock
2415 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2418 // now set the callback routine and context of the hub
2420 m_HubCallbackContext
= CallbackContext
;
2421 m_HubCallbackRoutine
= CallbackRoutine
;
2424 // release hub controller lock
2426 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2429 //=================================================================================================
2431 // Generic Interface functions
2435 USBI_InterfaceReference(
2438 CHubController
* Controller
= (CHubController
*)BusContext
;
2440 DPRINT1("USBH_InterfaceReference\n");
2445 Controller
->AddRef();
2450 USBI_InterfaceDereference(
2453 CHubController
* Controller
= (CHubController
*)BusContext
;
2455 DPRINT1("USBH_InterfaceDereference\n");
2460 Controller
->Release();
2462 //=================================================================================================
2464 // USB Hub Interface functions
2468 USBHI_CreateUsbDevice(
2470 PUSB_DEVICE_HANDLE
*NewDevice
,
2471 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2475 PUSBDEVICE NewUsbDevice
;
2476 CHubController
* Controller
;
2479 DPRINT1("USBHI_CreateUsbDevice PortStatus %x\n", PortStatus
);
2482 // first get hub controller
2484 Controller
= (CHubController
*)BusContext
;
2489 PC_ASSERT(Controller
);
2490 PC_ASSERT(BusContext
== HubDeviceHandle
);
2493 // now allocate usb device
2495 Status
= CreateUSBDevice(&NewUsbDevice
);
2498 // check for success
2500 if (!NT_SUCCESS(Status
))
2503 // release controller
2505 Controller
->Release();
2506 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2511 // now initialize device
2513 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
2516 // check for success
2518 if (!NT_SUCCESS(Status
))
2521 // release usb device
2523 NewUsbDevice
->Release();
2524 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2531 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2533 // check for success
2535 if (!NT_SUCCESS(Status
))
2538 // release usb device
2540 NewUsbDevice
->Release();
2542 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2549 *NewDevice
= NewUsbDevice
;
2554 return STATUS_SUCCESS
;
2559 USBHI_InitializeUsbDevice(
2561 PUSB_DEVICE_HANDLE DeviceHandle
)
2563 PUSBDEVICE UsbDevice
;
2564 CHubController
* Controller
;
2565 ULONG DeviceAddress
;
2569 DPRINT1("USBHI_InitializeUsbDevice\n");
2572 // first get controller
2574 Controller
= (CHubController
*)BusContext
;
2575 PC_ASSERT(Controller
);
2578 // get device object
2580 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2581 PC_ASSERT(UsbDevice
);
2584 // validate device handle
2586 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2588 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2591 // invalid device handle
2593 return STATUS_DEVICE_NOT_CONNECTED
;
2597 // now reserve an address
2599 DeviceAddress
= Controller
->AcquireDeviceAddress();
2602 // is the device address valid
2604 if (DeviceAddress
== MAXULONG
)
2607 // failed to get an device address from the device address pool
2609 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2610 return STATUS_DEVICE_DATA_ERROR
;
2616 // now set the device address
2618 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2620 if (NT_SUCCESS(Status
))
2623 }while(Index
++ < 3 );
2626 // check for failure
2628 if (!NT_SUCCESS(Status
))
2631 // failed to set device address
2633 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2638 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2643 return STATUS_DEVICE_DATA_ERROR
;
2649 return STATUS_SUCCESS
;
2654 USBHI_GetUsbDescriptors(
2656 PUSB_DEVICE_HANDLE DeviceHandle
,
2657 PUCHAR DeviceDescriptorBuffer
,
2658 PULONG DeviceDescriptorBufferLength
,
2659 PUCHAR ConfigDescriptorBuffer
,
2660 PULONG ConfigDescriptorBufferLength
)
2662 PUSBDEVICE UsbDevice
;
2663 CHubController
* Controller
;
2665 DPRINT1("USBHI_GetUsbDescriptors\n");
2670 PC_ASSERT(DeviceDescriptorBuffer
);
2671 PC_ASSERT(DeviceDescriptorBufferLength
);
2672 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2673 PC_ASSERT(ConfigDescriptorBufferLength
);
2674 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2677 // first get controller
2679 Controller
= (CHubController
*)BusContext
;
2680 PC_ASSERT(Controller
);
2684 // get device object
2686 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2687 PC_ASSERT(UsbDevice
);
2690 // validate device handle
2692 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2694 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2697 // invalid device handle
2699 return STATUS_DEVICE_NOT_CONNECTED
;
2703 // get device descriptor
2705 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2708 // store result length
2710 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2713 // get configuration descriptor
2715 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2718 // complete the request
2720 return STATUS_SUCCESS
;
2725 USBHI_RemoveUsbDevice(
2727 PUSB_DEVICE_HANDLE DeviceHandle
,
2730 PUSBDEVICE UsbDevice
;
2731 CHubController
* Controller
;
2734 DPRINT1("USBHI_RemoveUsbDevice\n");
2737 // first get controller
2739 Controller
= (CHubController
*)BusContext
;
2740 PC_ASSERT(Controller
);
2743 // get device object
2745 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2746 PC_ASSERT(UsbDevice
);
2749 // validate device handle
2751 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2753 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2756 // invalid device handle
2758 return STATUS_DEVICE_NOT_CONNECTED
;
2762 // check if there were flags passed
2764 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2767 // ignore flags for now
2769 return STATUS_SUCCESS
;
2775 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2776 if (!NT_SUCCESS(Status
))
2779 // invalid device handle
2781 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2783 return STATUS_DEVICE_NOT_CONNECTED
;
2787 // release usb device
2789 UsbDevice
->Release();
2794 return STATUS_SUCCESS
;
2799 USBHI_RestoreUsbDevice(
2801 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2802 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2804 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2805 CHubController
* Controller
;
2807 DPRINT1("USBHI_RestoreUsbDevice\n");
2810 // first get controller
2812 Controller
= (CHubController
*)BusContext
;
2813 PC_ASSERT(Controller
);
2816 // get device object
2818 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2819 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2820 PC_ASSERT(OldUsbDevice
);
2821 PC_ASSERT(NewDeviceHandle
);
2824 // validate device handle
2826 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2827 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2829 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2830 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2833 // remove old device handle
2835 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2837 return STATUS_SUCCESS
;
2842 USBHI_QueryDeviceInformation(
2844 PUSB_DEVICE_HANDLE DeviceHandle
,
2845 PVOID DeviceInformationBuffer
,
2846 ULONG DeviceInformationBufferLength
,
2847 PULONG LengthReturned
)
2849 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2850 PUSBDEVICE UsbDevice
;
2851 CHubController
* Controller
;
2853 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2858 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2859 PC_ASSERT(DeviceInformationBuffer
);
2860 PC_ASSERT(LengthReturned
);
2863 // get controller object
2865 Controller
= (CHubController
*)BusContext
;
2866 PC_ASSERT(Controller
);
2869 // get device object
2871 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2872 PC_ASSERT(UsbDevice
);
2874 if (BusContext
!= DeviceHandle
)
2877 // validate device handle
2879 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2881 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2884 // invalid device handle
2886 return STATUS_DEVICE_NOT_CONNECTED
;
2890 // access information buffer
2892 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2895 // initialize with default values
2897 DeviceInfo
->InformationLevel
= 0;
2898 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2899 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2900 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2901 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2902 DeviceInfo
->HubAddress
= 0; //FIXME
2903 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2904 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2905 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2908 // get device descriptor
2910 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2913 // FIXME return pipe information
2917 // store result length
2919 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2921 return STATUS_SUCCESS
;
2925 // access information buffer
2927 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2930 // initialize with default values
2932 DeviceInfo
->InformationLevel
= 0;
2933 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2934 DeviceInfo
->PortNumber
= 0;
2935 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2936 DeviceInfo
->DeviceAddress
= 0;
2937 DeviceInfo
->HubAddress
= 0; //FIXME
2938 DeviceInfo
->DeviceSpeed
= UsbFullSpeed
; //FIXME
2939 DeviceInfo
->DeviceType
= Usb11Device
; //FIXME
2940 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2943 // get device descriptor
2945 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
2948 // FIXME return pipe information
2952 // store result length
2955 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
2957 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
2962 return STATUS_SUCCESS
;
2967 USBHI_GetControllerInformation(
2969 PVOID ControllerInformationBuffer
,
2970 ULONG ControllerInformationBufferLength
,
2971 PULONG LengthReturned
)
2973 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2975 DPRINT1("USBHI_GetControllerInformation\n");
2980 PC_ASSERT(ControllerInformationBuffer
);
2981 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2984 // get controller info buffer
2986 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
2989 // FIXME only version 0 is supported for now
2991 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
2994 // fill in information
2996 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
2997 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
2998 ControllerInfo
->IsHighSpeedController
= FALSE
;
3001 // set length returned
3003 *LengthReturned
= ControllerInfo
->ActualLength
;
3008 return STATUS_SUCCESS
;
3013 USBHI_ControllerSelectiveSuspend(
3018 return STATUS_NOT_IMPLEMENTED
;
3023 USBHI_GetExtendedHubInformation(
3025 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3026 PVOID HubInformationBuffer
,
3027 ULONG HubInformationBufferLength
,
3028 PULONG LengthReturned
)
3030 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3031 CHubController
* Controller
;
3032 PUSBHARDWAREDEVICE Hardware
;
3034 ULONG NumPort
, Dummy2
;
3038 DPRINT1("USBHI_GetExtendedHubInformation\n");
3043 PC_ASSERT(HubInformationBuffer
);
3044 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3045 PC_ASSERT(LengthReturned
);
3048 // get hub controller
3050 Controller
= (CHubController
*)BusContext
;
3051 PC_ASSERT(Controller
);
3054 // get usb hardware device
3056 Hardware
= Controller
->GetUsbHardware();
3059 // retrieve number of ports
3061 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3062 if (!NT_SUCCESS(Status
))
3065 // failed to get hardware details, ouch ;)
3067 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3072 // get hub information buffer
3074 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3077 // initialize hub information
3079 HubInfo
->InformationLevel
= 0;
3084 HubInfo
->NumberOfPorts
= NumPort
;
3087 // initialize port information
3089 for(Index
= 0; Index
< NumPort
; Index
++)
3091 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3092 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3093 HubInfo
->Port
[Index
].VidOverride
= 0;
3094 HubInfo
->Port
[Index
].PidOverride
= 0;
3095 HubInfo
->Port
[Index
].PortAttributes
= 0; //FIXME
3099 // store result length
3102 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3104 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3110 return STATUS_SUCCESS
;
3115 USBHI_GetRootHubSymbolicName(
3117 PVOID HubSymNameBuffer
,
3118 ULONG HubSymNameBufferLength
,
3119 PULONG HubSymNameActualLength
)
3122 return STATUS_NOT_IMPLEMENTED
;
3127 USBHI_GetDeviceBusContext(
3128 PVOID HubBusContext
,
3137 USBHI_RootHubInitNotification(
3139 PVOID CallbackContext
,
3140 PRH_INIT_CALLBACK CallbackRoutine
)
3142 CHubController
* Controller
;
3144 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3147 // get controller object
3149 Controller
= (CHubController
*)BusContext
;
3150 PC_ASSERT(Controller
);
3153 // set notification routine
3155 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3158 // FIXME: determine when to perform callback
3160 CallbackRoutine(CallbackContext
);
3165 return STATUS_SUCCESS
;
3170 USBHI_FlushTransfers(
3179 USBHI_SetDeviceHandleData(
3182 PDEVICE_OBJECT UsbDevicePdo
)
3184 PUSBDEVICE UsbDevice
;
3185 CHubController
* Controller
;
3190 Controller
= (CHubController
*)BusContext
;
3191 PC_ASSERT(Controller
);
3194 // get device handle
3196 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3199 // validate device handle
3201 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3203 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3213 // usbhub sends this request as a part of the Pnp startup sequence
3214 // looks like we need apply a dragon voodoo to fixup the device stack
3215 // otherwise usbhub will cause a bugcheck
3217 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3222 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3225 // should be usbstor
3226 // fixup device stack voodoo part #2
3228 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3231 // set device handle data
3233 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3237 //=================================================================================================
3239 // USB Device Interface functions
3244 USBDI_GetUSBDIVersion(
3246 PUSBD_VERSION_INFORMATION VersionInformation
,
3247 PULONG HcdCapabilites
)
3249 CHubController
* Controller
;
3250 PUSBHARDWAREDEVICE Device
;
3251 ULONG Speed
, Dummy2
;
3254 DPRINT1("USBDI_GetUSBDIVersion\n");
3259 Controller
= (CHubController
*)BusContext
;
3264 Device
= Controller
->GetUsbHardware();
3267 if (VersionInformation
)
3270 // windows xp supported
3272 VersionInformation
->USBDI_Version
= 0x00000500;
3277 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3280 // store speed details
3282 VersionInformation
->Supported_USB_Version
= Speed
;
3286 // no flags supported
3288 *HcdCapabilites
= 0;
3295 PULONG CurrentFrame
)
3298 return STATUS_NOT_IMPLEMENTED
;
3303 USBDI_SubmitIsoOutUrb(
3308 return STATUS_NOT_IMPLEMENTED
;
3313 USBDI_QueryBusInformation(
3316 PVOID BusInformationBuffer
,
3317 PULONG BusInformationBufferLength
,
3318 PULONG BusInformationActualLength
)
3321 return STATUS_NOT_IMPLEMENTED
;
3326 USBDI_IsDeviceHighSpeed(
3329 CHubController
* Controller
;
3330 PUSBHARDWAREDEVICE Device
;
3331 ULONG Speed
, Dummy2
;
3334 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3339 Controller
= (CHubController
*)BusContext
;
3344 Device
= Controller
->GetUsbHardware();
3350 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3353 // USB 2.0 equals 0x200
3355 return (Speed
== 0x200);
3368 return STATUS_NOT_IMPLEMENTED
;
3372 CHubController::HandleQueryInterface(
3373 PIO_STACK_LOCATION IoStack
)
3375 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3376 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3377 UNICODE_STRING GuidBuffer
;
3380 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3383 // get request parameters
3385 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3386 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3391 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3393 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3396 // version not supported
3398 return STATUS_NOT_SUPPORTED
;
3402 // Interface version 0
3404 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3406 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3407 InterfaceHub
->BusContext
= PVOID(this);
3408 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3409 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3413 // Interface version 1
3415 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3417 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3418 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3419 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3420 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3421 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3422 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3426 // Interface version 2
3428 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3430 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3431 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3432 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3433 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3434 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3438 // Interface version 3
3440 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3442 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3446 // Interface version 4
3448 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3450 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3454 // Interface version 5
3456 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3458 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3462 // request completed
3464 return STATUS_SUCCESS
;
3466 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3469 // get request parameters
3471 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3472 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3477 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3479 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3482 // version not supported
3484 return STATUS_NOT_SUPPORTED
;
3488 // interface version 0
3490 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3492 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3493 InterfaceDI
->BusContext
= PVOID(this);
3494 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3495 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3496 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3497 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3498 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3499 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3503 // interface version 1
3505 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3507 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3511 // interface version 2
3513 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3515 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3519 // request completed
3521 return STATUS_SUCCESS
;
3526 // convert guid to string
3528 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3529 if (NT_SUCCESS(Status
))
3534 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3539 RtlFreeUnicodeString(&GuidBuffer
);
3542 return STATUS_NOT_SUPPORTED
;
3546 CHubController::SetDeviceInterface(
3549 NTSTATUS Status
= STATUS_SUCCESS
;
3554 // register device interface
3556 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3558 if (NT_SUCCESS(Status
))
3561 // now enable the device interface
3563 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3568 m_InterfaceEnabled
= TRUE
;
3571 else if (m_InterfaceEnabled
)
3574 // disable device interface
3576 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3578 if (NT_SUCCESS(Status
))
3581 // now delete interface string
3583 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3587 // disable interface
3589 m_InterfaceEnabled
= FALSE
;
3595 return STATUS_SUCCESS
;
3599 CHubController::CreatePDO(
3600 PDRIVER_OBJECT DriverObject
,
3601 PDEVICE_OBJECT
* OutDeviceObject
)
3603 WCHAR CharDeviceName
[64];
3605 ULONG UsbDeviceNumber
= 0;
3606 UNICODE_STRING DeviceName
;
3611 // construct device name
3613 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3616 // initialize device name
3618 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3623 Status
= IoCreateDevice(DriverObject
,
3624 sizeof(COMMON_DEVICE_EXTENSION
),
3626 FILE_DEVICE_CONTROLLER
,
3631 /* check for success */
3632 if (NT_SUCCESS(Status
))
3636 // is there a device object with that same name
3638 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3641 // Try the next name
3648 // bail out on other errors
3650 if (!NT_SUCCESS(Status
))
3652 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3657 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3660 // fixup device stack voodoo part #1
3662 (*OutDeviceObject
)->StackSize
++;
3671 CreateHubController(
3672 PHUBCONTROLLER
*OutHcdController
)
3674 PHUBCONTROLLER This
;
3677 // allocate controller
3679 This
= new(NonPagedPool
, TAG_USBOHCI
) CHubController(0);
3683 // failed to allocate
3685 return STATUS_INSUFFICIENT_RESOURCES
;
3689 // add reference count
3696 *OutHcdController
= (PHUBCONTROLLER
)This
;
3701 return STATUS_SUCCESS
;
3704 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3706 CHubController
* This
;
3708 This
= (CHubController
*)Context
;
3712 Irp
= This
->m_PendingSCEIrp
;
3715 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3719 This
->m_PendingSCEIrp
= NULL
;
3720 This
->QueryStatusChageEndpoint(Irp
);
3722 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3723 Irp
->IoStatus
.Information
= 0;
3725 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);