2 * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/libusb/hub_controller.cpp
5 * PURPOSE: USB Common Driver Library.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 VOID
StatusChangeEndpointCallBack(
18 class CHubController
: public IHubController
,
22 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
24 STDMETHODIMP_(ULONG
) AddRef()
26 InterlockedIncrement(&m_Ref
);
29 STDMETHODIMP_(ULONG
) Release()
31 InterlockedDecrement(&m_Ref
);
41 // IHubController interface functions
42 virtual NTSTATUS
Initialize(IN PDRIVER_OBJECT DriverObject
, IN PHCDCONTROLLER Controller
, IN PUSBHARDWAREDEVICE Device
, IN BOOLEAN IsRootHubDevice
, IN ULONG DeviceAddress
);
43 virtual NTSTATUS
GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
);
44 virtual NTSTATUS
GetHubControllerSymbolicLink(ULONG BufferLength
, PVOID Buffer
, PULONG RequiredLength
);
46 // IDispatchIrp interface functions
47 virtual NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
48 virtual NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
49 virtual NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
52 NTSTATUS
HandleQueryInterface(PIO_STACK_LOCATION IoStack
);
53 NTSTATUS
SetDeviceInterface(BOOLEAN bEnable
);
54 NTSTATUS
CreatePDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
55 PUSBHARDWAREDEVICE
GetUsbHardware();
56 ULONG
AcquireDeviceAddress();
57 VOID
ReleaseDeviceAddress(ULONG DeviceAddress
);
58 BOOLEAN
ValidateUsbDevice(PUSBDEVICE UsbDevice
);
59 NTSTATUS
AddUsbDevice(PUSBDEVICE UsbDevice
);
60 NTSTATUS
RemoveUsbDevice(PUSBDEVICE UsbDevice
);
61 VOID
SetNotification(PVOID CallbackContext
, PRH_INIT_CALLBACK CallbackRoutine
);
62 // internal ioctl routines
63 NTSTATUS
HandleGetDescriptor(IN OUT PIRP Irp
, PURB Urb
);
64 NTSTATUS
HandleGetDescriptorFromInterface(IN OUT PIRP Irp
, PURB Urb
);
65 NTSTATUS
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
70 NTSTATUS
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
71 NTSTATUS
HandleClassEndpoint(IN OUT PIRP Irp
, PURB Urb
);
72 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
73 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
74 NTSTATUS
HandleClearStall(IN OUT PIRP Irp
, PURB Urb
);
75 NTSTATUS
HandleSyncResetAndClearStall(IN OUT PIRP Irp
, PURB Urb
);
76 NTSTATUS
HandleAbortPipe(IN OUT PIRP Irp
, PURB Urb
);
78 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
80 // constructor / destructor
81 CHubController(IUnknown
*OuterUnknown
){}
82 virtual ~CHubController(){}
86 PHCDCONTROLLER m_Controller
;
87 PUSBHARDWAREDEVICE m_Hardware
;
88 BOOLEAN m_IsRootHubDevice
;
89 ULONG m_DeviceAddress
;
91 BOOLEAN m_InterfaceEnabled
;
92 UNICODE_STRING m_HubDeviceInterfaceString
;
94 PDEVICE_OBJECT m_HubControllerDeviceObject
;
95 PDRIVER_OBJECT m_DriverObject
;
97 PVOID m_HubCallbackContext
;
98 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
100 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
103 RTL_BITMAP m_DeviceAddressBitmap
;
104 PULONG m_DeviceAddressBitmapBuffer
;
105 LIST_ENTRY m_UsbDeviceList
;
106 PIRP m_PendingSCEIrp
;
109 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
116 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
118 /* Lifted from Linux with slight changes */
119 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
122 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
123 0x00, 0x20, /* bcdUSB; v1.1 */
124 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
125 0x01, /* bDeviceSubClass; */
126 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
127 0x08, /* bMaxPacketSize0; 8 Bytes */
128 /* Fill Vendor and Product in when init root hub */
129 0x00, 0x00, /* idVendor; */
130 0x00, 0x00, /* idProduct; */
131 0x00, 0x00, /* bcdDevice */
132 0x00, /* iManufacturer; */
133 0x00, /* iProduct; */
134 0x00, /* iSerialNumber; */
135 0x01 /* bNumConfigurations; */
139 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
141 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
142 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
143 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
147 0x40, /* self powered */
151 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
153 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
154 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
155 0, /* bInterfaceNumber; */
156 0, /* bAlternateSetting; */
157 0x1, /* bNumEndpoints; */
158 0x09, /* bInterfaceClass; HUB_CLASSCODE */
159 0x01, /* bInterfaceSubClass; */
160 0x00, /* bInterfaceProtocol: */
161 0x00, /* iInterface; */
164 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
166 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
167 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
168 0x81, /* bEndPointAddress */
169 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
170 0x01, /* wMaxPacketSize */
174 //----------------------------------------------------------------------------------------
177 CHubController::QueryInterface(
181 return STATUS_UNSUCCESSFUL
;
183 //----------------------------------------------------------------------------------------
185 CHubController::Initialize(
186 IN PDRIVER_OBJECT DriverObject
,
187 IN PHCDCONTROLLER Controller
,
188 IN PUSBHARDWAREDEVICE Device
,
189 IN BOOLEAN IsRootHubDevice
,
190 IN ULONG DeviceAddress
)
193 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
194 USHORT VendorID
, DeviceID
;
197 DPRINT1("CHubController::Initialize\n");
200 // initialize members
202 m_Controller
= Controller
;
204 m_IsRootHubDevice
= IsRootHubDevice
;
205 m_DeviceAddress
= DeviceAddress
;
206 m_DriverObject
= DriverObject
;
207 KeInitializeSpinLock(&m_Lock
);
208 InitializeListHead(&m_UsbDeviceList
);
211 // allocate device address bitmap buffer
213 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBLIB
);
214 if (!m_DeviceAddressBitmapBuffer
)
219 return STATUS_INSUFFICIENT_RESOURCES
;
223 // initialize device address bitmap
225 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
226 RtlClearAllBits(&m_DeviceAddressBitmap
);
232 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
233 if (!NT_SUCCESS(Status
))
236 // failed to create hub device object
242 // get device extension
244 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
247 // initialize device extension
249 DeviceExtension
->IsFDO
= FALSE
;
250 DeviceExtension
->IsHub
= TRUE
; //FIXME
251 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
254 // intialize device descriptor
256 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
257 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
259 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
262 // update device descriptor
264 m_DeviceDescriptor
.idVendor
= VendorID
;
265 m_DeviceDescriptor
.idProduct
= DeviceID
;
266 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
270 // Set the SCE Callback that the Hardware Device will call on port status change
272 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
277 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
279 return STATUS_SUCCESS
;
283 // Queries the ports to see if there has been a device connected or removed.
286 CHubController::QueryStatusChageEndpoint(
289 ULONG PortCount
, PortId
;
290 PIO_STACK_LOCATION IoStack
;
291 USHORT PortStatus
, PortChange
;
293 PUCHAR TransferBuffer
;
294 UCHAR Changed
= FALSE
;
297 // get current stack location
299 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
305 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
309 // Get the number of ports and check each one for device connected
311 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
312 DPRINT1("[USBLIB] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
, Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
314 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
319 for (PortId
= 0; PortId
< PortCount
; PortId
++)
321 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
323 DPRINT1("[USBLIB] Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
327 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
331 DPRINT1("[USBLIB] Change state on port %d\n", PortId
);
332 // Set the value for the port number
333 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
341 //-----------------------------------------------------------------------------------------
343 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
346 // store controller object
348 *HubDeviceObject
= m_HubControllerDeviceObject
;
350 return STATUS_SUCCESS
;
352 //-----------------------------------------------------------------------------------------
354 CHubController::GetHubControllerSymbolicLink(
357 PULONG RequiredLength
)
359 if (!m_InterfaceEnabled
)
362 // device interface not yet enabled
364 return STATUS_UNSUCCESSFUL
;
367 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
371 // length is without '\??\'
373 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
378 return STATUS_BUFFER_OVERFLOW
;
382 // copy symbolic link
384 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
387 // store length, length is without '\??\'
389 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
394 return STATUS_SUCCESS
;
397 //-----------------------------------------------------------------------------------------
399 CHubController::HandlePnp(
400 IN PDEVICE_OBJECT DeviceObject
,
403 PIO_STACK_LOCATION IoStack
;
404 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
405 PDEVICE_CAPABILITIES DeviceCapabilities
;
406 PPNP_BUS_INFORMATION BusInformation
;
407 PDEVICE_RELATIONS DeviceRelations
;
409 ULONG Index
= 0, Length
;
410 USHORT VendorID
, DeviceID
;
411 ULONG HiSpeed
, NumPorts
;
416 // get device extension
418 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
423 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
426 // get current stack location
428 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
430 switch(IoStack
->MinorFunction
)
432 case IRP_MN_START_DEVICE
:
434 DPRINT("[USBLIB] HandlePnp IRP_MN_START_DEVICE\n");
436 // register device interface
438 Status
= SetDeviceInterface(TRUE
);
441 case IRP_MN_QUERY_STOP_DEVICE
:
442 case IRP_MN_QUERY_REMOVE_DEVICE
:
447 Status
= STATUS_SUCCESS
;
450 case IRP_MN_QUERY_ID
:
452 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
454 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
461 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
463 if (HiSpeed
== 0x200)
468 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
475 swprintf(Buffer
, L
"USB\\ROOT_HUB");
478 DPRINT("Name %S\n", Buffer
);
483 Length
= (wcslen(Buffer
) + 1);
488 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBLIB
);
495 Status
= STATUS_INSUFFICIENT_RESOURCES
;
502 wcscpy(DeviceName
, Buffer
);
507 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
508 Status
= STATUS_SUCCESS
;
511 Status
= STATUS_UNSUCCESSFUL
;
516 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
523 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
525 if (!NT_SUCCESS(Status
))
527 DPRINT1("[USBLIB] HandlePnp> failed to get hardware id %x\n", Status
);
532 if (HiSpeed
== 0x200)
537 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
538 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
539 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
546 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
547 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
548 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
551 Buffer
[Index
] = UNICODE_NULL
;
555 DPRINT1("[USBLIB] Name %S\n", Buffer
);
560 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBLIB
);
567 Status
= STATUS_INSUFFICIENT_RESOURCES
;
574 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
579 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
580 Status
= STATUS_SUCCESS
;
584 Status
= STATUS_SUCCESS
;
587 case IRP_MN_QUERY_CAPABILITIES
:
589 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
591 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
593 DeviceCapabilities
->LockSupported
= FALSE
;
594 DeviceCapabilities
->EjectSupported
= FALSE
;
595 DeviceCapabilities
->Removable
= FALSE
;
596 DeviceCapabilities
->DockDevice
= FALSE
;
597 DeviceCapabilities
->UniqueID
= FALSE
;
598 DeviceCapabilities
->SilentInstall
= FALSE
;
599 DeviceCapabilities
->RawDeviceOK
= FALSE
;
600 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
601 DeviceCapabilities
->Address
= 0;
602 DeviceCapabilities
->UINumber
= 0;
603 DeviceCapabilities
->DeviceD2
= 1;
606 DeviceCapabilities
->HardwareDisabled
= FALSE
;
607 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
608 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
609 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
610 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
611 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
612 DeviceCapabilities
->D1Latency
= 0;
613 DeviceCapabilities
->D2Latency
= 0;
614 DeviceCapabilities
->D3Latency
= 0;
616 Status
= STATUS_SUCCESS
;
619 case IRP_MN_QUERY_INTERFACE
:
621 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_INTERFACE\n");
624 // handle device interface requests
626 Status
= HandleQueryInterface(IoStack
);
629 case IRP_MN_REMOVE_DEVICE
:
631 DPRINT("[USBLIB] HandlePnp IRP_MN_REMOVE_DEVICE\n");
634 // deactivate device interface for BUS PDO
636 SetDeviceInterface(FALSE
);
639 // complete the request first
641 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
642 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
647 IoDeleteDevice(m_HubControllerDeviceObject
);
652 m_HubControllerDeviceObject
= 0;
657 return STATUS_SUCCESS
;
659 case IRP_MN_QUERY_DEVICE_RELATIONS
:
661 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
663 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
666 // allocate device relations
668 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBLIB
);
669 if (!DeviceRelations
)
674 Status
= STATUS_INSUFFICIENT_RESOURCES
;
679 // initialize device relations
681 DeviceRelations
->Count
= 1;
682 DeviceRelations
->Objects
[0] = DeviceObject
;
683 ObReferenceObject(DeviceObject
);
688 Status
= STATUS_SUCCESS
;
689 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
696 Status
= Irp
->IoStatus
.Status
;
700 case IRP_MN_QUERY_BUS_INFORMATION
:
702 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
705 // allocate buffer for bus information
707 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
713 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
718 BusInformation
->LegacyBusType
= PNPBus
;
719 BusInformation
->BusNumber
= 0;
721 Status
= STATUS_SUCCESS
;
722 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
729 Status
= STATUS_INSUFFICIENT_RESOURCES
;
733 case IRP_MN_STOP_DEVICE
:
735 DPRINT("[USBLIB] HandlePnp IRP_MN_STOP_DEVICE\n");
739 Status
= STATUS_SUCCESS
;
745 // ignore request with default status
747 Status
= Irp
->IoStatus
.Status
;
755 Irp
->IoStatus
.Status
= Status
;
756 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
764 //-----------------------------------------------------------------------------------------
766 CHubController::HandlePower(
767 IN PDEVICE_OBJECT DeviceObject
,
771 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
772 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
773 return STATUS_NOT_IMPLEMENTED
;
776 //-----------------------------------------------------------------------------------------
778 CHubController::HandleIsochronousTransfer(
782 PUSBDEVICE UsbDevice
;
783 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
786 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
788 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
792 DPRINT1("[USBLIB] Error No EndpointDesc\n");
793 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
794 return STATUS_INVALID_PARAMETER
;
800 ASSERT(EndPointDesc
);
801 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
804 // check if this is a valid usb device handle
806 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
808 DPRINT1("[USBLIB] HandleIsochronousTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
811 // invalid device handle
813 return STATUS_DEVICE_NOT_CONNECTED
;
819 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
821 return UsbDevice
->SubmitIrp(Irp
);
824 //-----------------------------------------------------------------------------------------
826 CHubController::HandleBulkOrInterruptTransfer(
830 PUSBDEVICE UsbDevice
;
831 PUSB_ENDPOINT EndPointDesc
= NULL
;
833 // First check if the request is for the Status Change Endpoint
837 // Is the Request for the root hub
839 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
841 ASSERT(m_PendingSCEIrp
== NULL
);
842 if (QueryStatusChageEndpoint(Irp
))
844 StatusChangeEndpointCallBack(this);
845 return STATUS_SUCCESS
;
849 // Else pend the IRP, to be completed when a device connects or disconnects.
851 DPRINT("[USBLIB] Pending SCE Irp\n");
852 m_PendingSCEIrp
= Irp
;
853 IoMarkIrpPending(Irp
);
854 return STATUS_PENDING
;
858 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
860 EndPointDesc
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
865 ASSERT(EndPointDesc
);
866 ASSERT((EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
869 // check if this is a valid usb device handle
871 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
873 DPRINT1("[USBLIB] HandleBulkOrInterruptTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
876 // invalid device handle
878 return STATUS_DEVICE_NOT_CONNECTED
;
884 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
885 return UsbDevice
->SubmitIrp(Irp
);
888 //-----------------------------------------------------------------------------------------
890 CHubController::HandleClassOther(
894 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
895 USHORT PortStatus
= 0, PortChange
= 0;
900 DPRINT("[USBLIB] HandleClassOther> Request %x Value %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
903 // get number of ports available
905 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
906 PC_ASSERT(Status
== STATUS_SUCCESS
);
911 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
914 // port range reported start from 1 -n
915 // convert back port id so it matches the hardware
917 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
920 // check request code
922 switch(Urb
->UrbControlVendorClassRequest
.Request
)
924 case USB_REQUEST_GET_STATUS
:
929 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
930 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
935 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
937 if (NT_SUCCESS(Status
))
940 // request contains buffer of 2 ushort which are used from submitting port status and port change status
942 DPRINT("[USBLIB] PortId %x PortStatus %x PortChange %x\n", PortId
, PortStatus
, PortChange
);
943 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
946 // store status, then port change
948 *Buffer
= PortStatus
;
950 *Buffer
= PortChange
;
958 case USB_REQUEST_CLEAR_FEATURE
:
960 switch (Urb
->UrbControlVendorClassRequest
.Value
)
962 case C_PORT_CONNECTION
:
963 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
966 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
969 DPRINT("[USBLIB] Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
975 case USB_REQUEST_SET_FEATURE
:
978 // request set feature
980 switch(Urb
->UrbControlVendorClassRequest
.Value
)
985 // port enable is a no-op for EHCI
987 Status
= STATUS_SUCCESS
;
994 // set suspend port feature
996 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
1002 // set power feature on port
1004 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1011 // reset port feature
1013 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1014 PC_ASSERT(Status
== STATUS_SUCCESS
);
1018 DPRINT1("[USBLIB] Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1024 DPRINT1("[USBLIB] HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1026 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1031 //-----------------------------------------------------------------------------------------
1033 CHubController::HandleSelectConfiguration(
1037 PUSBDEVICE UsbDevice
;
1038 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1041 // is the request for the Root Hub
1043 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1046 // FIXME: support setting device to unconfigured state
1048 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1051 // set device handle
1053 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1056 // copy interface info
1058 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1060 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1061 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1062 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1063 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1064 InterfaceInfo
->Reserved
= 0;
1069 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1074 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1075 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1076 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1077 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1078 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1080 return STATUS_SUCCESS
;
1085 // check if this is a valid usb device handle
1087 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1089 DPRINT1("[USBLIB] HandleSelectConfiguration invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1092 // invalid device handle
1094 return STATUS_DEVICE_NOT_CONNECTED
;
1100 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1103 // select configuration
1105 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1109 //-----------------------------------------------------------------------------------------
1111 CHubController::HandleSelectInterface(
1115 PUSBDEVICE UsbDevice
;
1120 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1123 // is the request for the Root Hub
1125 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1128 // no op for root hub
1130 return STATUS_SUCCESS
;
1135 // check if this is a valid usb device handle
1137 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1139 DPRINT1("[USBLIB] HandleSelectInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1142 // invalid device handle
1144 return STATUS_DEVICE_NOT_CONNECTED
;
1150 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1155 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1159 //-----------------------------------------------------------------------------------------
1161 CHubController::HandleGetStatusFromDevice(
1165 PUSHORT DeviceStatus
;
1166 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1168 PUSBDEVICE UsbDevice
;
1173 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1174 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1177 // get status buffer
1179 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1182 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1185 // FIXME need more flags ?
1187 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1188 return STATUS_SUCCESS
;
1192 // check if this is a valid usb device handle
1194 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1196 DPRINT1("[USBLIB] HandleGetStatusFromDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1199 // invalid device handle
1201 return STATUS_DEVICE_NOT_CONNECTED
;
1207 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1211 // generate setup packet
1213 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1214 CtrlSetup
.wValue
.LowByte
= 0;
1215 CtrlSetup
.wValue
.HiByte
= 0;
1216 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1217 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1218 CtrlSetup
.bmRequestType
.B
= 0x80;
1221 if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_INTERFACE
)
1224 // add interface type
1226 CtrlSetup
.bmRequestType
.B
|= 0x01;
1228 else if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
)
1231 // add interface type
1233 CtrlSetup
.bmRequestType
.B
|= 0x02;
1237 // submit setup packet
1239 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1240 ASSERT(Status
== STATUS_SUCCESS
);
1241 DPRINT1("[USBLIB] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1249 //-----------------------------------------------------------------------------------------
1251 CHubController::HandleClassDevice(
1255 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1256 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1257 ULONG PortCount
, Dummy2
;
1259 PUSBDEVICE UsbDevice
;
1260 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1262 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1265 // check class request type
1267 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1269 case USB_REQUEST_GET_STATUS
:
1272 // check if this is a valid usb device handle
1274 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1276 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1279 // invalid device handle
1281 return STATUS_DEVICE_NOT_CONNECTED
;
1287 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1291 // generate setup packet
1293 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1294 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlVendorClassRequest
.Index
;
1295 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1296 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1297 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1298 CtrlSetup
.bmRequestType
.B
= 0xA0;
1301 // submit setup packet
1303 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1304 ASSERT(Status
== STATUS_SUCCESS
);
1307 case USB_REQUEST_GET_DESCRIPTOR
:
1309 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1311 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1312 case USB_DEVICE_CLASS_HUB
:
1317 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1318 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1321 // get hub descriptor
1323 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1326 // one hub is handled
1328 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1329 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1332 // type should 0x29 according to msdn
1334 UsbHubDescriptor
->bDescriptorType
= 0x29;
1339 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1340 PC_ASSERT(Status
== STATUS_SUCCESS
);
1343 // FIXME: retrieve values
1345 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1346 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1347 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1348 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1353 Status
= STATUS_SUCCESS
;
1357 DPRINT1("[USBLIB] HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1363 DPRINT1("[USBLIB] HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1369 //-----------------------------------------------------------------------------------------
1371 CHubController::HandleGetDescriptorFromInterface(
1375 PUSBDEVICE UsbDevice
;
1376 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1382 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1383 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1386 // check if this is a valid usb device handle
1388 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1390 DPRINT1("[USBLIB] HandleGetDescriptorFromInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1393 // invalid device handle
1395 return STATUS_DEVICE_NOT_CONNECTED
;
1401 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1404 // generate setup packet
1406 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1407 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1408 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1409 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1410 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1411 CtrlSetup
.bmRequestType
.B
= 0x81;
1414 // submit setup packet
1416 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1417 ASSERT(Status
== STATUS_SUCCESS
);
1425 //-----------------------------------------------------------------------------------------
1427 CHubController::HandleGetDescriptor(
1431 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1432 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1433 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1435 PUSBDEVICE UsbDevice
;
1438 DPRINT("[USBLIB] HandleGetDescriptor\n");
1441 // check descriptor type
1443 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1445 case USB_DEVICE_DESCRIPTOR_TYPE
:
1450 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1451 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1453 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1456 // copy root hub device descriptor
1458 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1459 Status
= STATUS_SUCCESS
;
1464 // check if this is a valid usb device handle
1466 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1468 DPRINT1("[USBLIB] HandleGetDescriptor invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1471 // invalid device handle
1473 return STATUS_DEVICE_NOT_CONNECTED
;
1479 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1482 // retrieve device descriptor from device
1484 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1485 Status
= STATUS_SUCCESS
;
1489 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1494 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1495 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1497 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1500 // request is for the root bus controller
1502 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1505 // get configuration descriptor, very retarded!
1507 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1510 // check if buffer can hold interface and endpoint descriptor
1512 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1517 Status
= STATUS_SUCCESS
;
1523 // copy interface descriptor template
1525 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1526 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1529 // copy end point descriptor template
1531 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1532 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1537 Status
= STATUS_SUCCESS
;
1543 // check if this is a valid usb device handle
1545 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1547 DPRINT1("[USBLIB] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1550 // invalid device handle
1552 return STATUS_DEVICE_NOT_CONNECTED
;
1558 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1560 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1565 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1570 Status
= STATUS_SUCCESS
;
1575 // perform work in IUSBDevice
1577 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1580 // store result size
1582 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1583 Status
= STATUS_SUCCESS
;
1587 case USB_STRING_DESCRIPTOR_TYPE
:
1592 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1593 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1597 // check if this is a valid usb device handle
1599 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1601 DPRINT1("[USBLIB] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1604 // invalid device handle
1606 return STATUS_DEVICE_NOT_CONNECTED
;
1612 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1615 // generate setup packet
1617 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1618 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1619 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1620 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1621 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1622 CtrlSetup
.bmRequestType
.B
= 0x80;
1625 // submit setup packet
1627 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1631 DPRINT1("[USBLIB] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1641 //-----------------------------------------------------------------------------------------
1643 CHubController::HandleClassEndpoint(
1647 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1649 PUSBDEVICE UsbDevice
;
1654 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1655 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1656 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1659 // check if this is a valid usb device handle
1661 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1663 DPRINT1("[USBLIB] HandleClassEndpoint invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1666 // invalid device handle
1668 return STATUS_DEVICE_NOT_CONNECTED
;
1674 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1677 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1678 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1679 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1680 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1681 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1682 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1683 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1684 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1685 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1688 // initialize setup packet
1690 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1691 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1692 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1693 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1694 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1696 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1699 // data direction is device to host
1701 CtrlSetup
.bmRequestType
.B
|= 0x80;
1708 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1711 // assert on failure
1713 PC_ASSERT(NT_SUCCESS(Status
));
1723 CHubController::HandleSyncResetAndClearStall(
1727 NTSTATUS Status
= STATUS_SUCCESS
;
1728 PUSB_ENDPOINT EndpointDescriptor
;
1734 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1735 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1736 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1739 // check if this is a valid usb device handle
1741 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1743 DPRINT1("[USBLIB] HandleSyncResetAndClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1746 // invalid device handle
1748 return STATUS_DEVICE_NOT_CONNECTED
;
1754 Status
= HandleAbortPipe(Irp
, Urb
);
1755 if (!NT_SUCCESS(Status
))
1760 DPRINT1("[USBLIB] failed to reset pipe %x\n", Status
);
1765 // get endpoint descriptor
1767 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1772 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1773 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1778 Status
= HandleClearStall(Irp
, Urb
);
1780 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status
);
1783 // reset data toggle
1785 ASSERT(NT_SUCCESS(Status
));
1786 EndpointDescriptor
->DataToggle
= 0x0;
1795 CHubController::HandleAbortPipe(
1800 PUSBDEVICE UsbDevice
;
1801 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1806 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1807 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1808 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1811 // check if this is a valid usb device handle
1813 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1815 DPRINT1("[USBLIB] HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1818 // invalid device handle
1820 return STATUS_DEVICE_NOT_CONNECTED
;
1824 // get endpoint descriptor
1826 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1831 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1837 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
1838 DPRINT1("[USBLIB] URB_FUNCTION_ABORT_PIPE Status %x\n", Status
);
1847 //-----------------------------------------------------------------------------------------
1849 CHubController::HandleClearStall(
1853 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1855 PUSBDEVICE UsbDevice
;
1856 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1862 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1863 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1864 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1867 // check if this is a valid usb device handle
1869 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1871 DPRINT1("[USBLIB] HandleClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1874 // invalid device handle
1876 return STATUS_DEVICE_NOT_CONNECTED
;
1880 // get endpoint descriptor
1882 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1887 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1888 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_CLEAR_STALL\n");
1891 // initialize setup packet
1893 CtrlSetup
.bmRequestType
.B
= 0x02;
1894 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
1895 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
1896 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
1897 CtrlSetup
.wLength
= 0;
1898 CtrlSetup
.wValue
.W
= 0;
1903 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
1905 DPRINT1("[USBLIB] URB_FUNCTION_CLEAR_STALL Status %x\n", Status
);
1914 //-----------------------------------------------------------------------------------------
1916 CHubController::HandleClassInterface(
1920 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1922 PUSBDEVICE UsbDevice
;
1927 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1928 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1929 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1932 // check if this is a valid usb device handle
1934 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1936 DPRINT1("[USBLIB] HandleClassInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1939 // invalid device handle
1941 return STATUS_DEVICE_NOT_CONNECTED
;
1947 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1950 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1951 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1952 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1953 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1954 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1955 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1956 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1957 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1958 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1961 // initialize setup packet
1963 CtrlSetup
.bmRequestType
.B
= 0x21;
1964 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1965 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1966 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1967 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1969 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1972 // data direction is device to host
1974 CtrlSetup
.bmRequestType
.B
|= 0x80;
1980 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1983 // assert on failure
1985 if (!NT_SUCCESS(Status
))
1990 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb
->UrbHeader
.Status
);
1999 //-----------------------------------------------------------------------------------------
2001 CHubController::HandleDeviceControl(
2002 IN PDEVICE_OBJECT DeviceObject
,
2005 PIO_STACK_LOCATION IoStack
;
2006 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
2008 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2011 // get current stack location
2013 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2016 // get device extension
2018 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
2021 // determine which request should be performed
2023 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2025 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2030 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2033 switch (Urb
->UrbHeader
.Function
)
2035 case URB_FUNCTION_SYNC_RESET_PIPE
:
2036 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2037 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2039 case URB_FUNCTION_ABORT_PIPE
:
2040 Status
= HandleAbortPipe(Irp
, Urb
);
2042 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2043 Status
= HandleClearStall(Irp
, Urb
);
2045 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2046 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2048 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2049 Status
= HandleGetDescriptor(Irp
, Urb
);
2051 case URB_FUNCTION_CLASS_DEVICE
:
2052 Status
= HandleClassDevice(Irp
, Urb
);
2054 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2055 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
2056 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
2057 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2059 case URB_FUNCTION_SELECT_CONFIGURATION
:
2060 Status
= HandleSelectConfiguration(Irp
, Urb
);
2062 case URB_FUNCTION_SELECT_INTERFACE
:
2063 Status
= HandleSelectInterface(Irp
, Urb
);
2065 case URB_FUNCTION_CLASS_OTHER
:
2066 Status
= HandleClassOther(Irp
, Urb
);
2068 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2069 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2071 case URB_FUNCTION_ISOCH_TRANSFER
:
2072 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2074 case URB_FUNCTION_CLASS_INTERFACE
:
2075 Status
= HandleClassInterface(Irp
, Urb
);
2077 case URB_FUNCTION_CLASS_ENDPOINT
:
2078 Status
= HandleClassEndpoint(Irp
, Urb
);
2081 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
2085 // request completed
2089 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2091 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2093 if (IoStack
->Parameters
.Others
.Argument1
)
2096 // store object as device handle
2098 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2099 Status
= STATUS_SUCCESS
;
2104 // mis-behaving hub driver
2106 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2110 // request completed
2114 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2116 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2119 // this is the first request send, it delivers the PDO to the caller
2121 if (IoStack
->Parameters
.Others
.Argument1
)
2124 // store root hub pdo object
2126 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2129 if (IoStack
->Parameters
.Others
.Argument2
)
2132 // documentation claims to deliver the hcd controller object, although it is wrong
2134 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2138 // request completed
2140 Status
= STATUS_SUCCESS
;
2143 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2145 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2148 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2149 // requests this ioctl to deliver the number of presents.
2151 if (IoStack
->Parameters
.Others
.Argument1
)
2154 // FIXME / verify: there is only one hub
2156 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2160 // request completed
2162 Status
= STATUS_SUCCESS
;
2163 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2166 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2168 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2169 Status
= STATUS_SUCCESS
;
2174 DPRINT1("[USBLIB] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2175 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2176 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2177 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2181 if (Status
!= STATUS_PENDING
)
2183 Irp
->IoStatus
.Status
= Status
;
2184 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2190 //-----------------------------------------------------------------------------------------
2192 CHubController::GetUsbHardware()
2197 //-----------------------------------------------------------------------------------------
2199 CHubController::AcquireDeviceAddress()
2202 ULONG DeviceAddress
;
2205 // acquire device lock
2207 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2212 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2213 if (DeviceAddress
!= MAXULONG
)
2218 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2221 // device addresses start from 0x1 - 0xFF
2227 // release spin lock
2229 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2232 // return device address
2234 return DeviceAddress
;
2236 //-----------------------------------------------------------------------------------------
2238 CHubController::ReleaseDeviceAddress(
2239 ULONG DeviceAddress
)
2244 // acquire device lock
2246 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2251 PC_ASSERT(DeviceAddress
!= 0);
2254 // convert back to bit number
2261 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2266 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2268 //-----------------------------------------------------------------------------------------
2270 CHubController::RemoveUsbDevice(
2271 PUSBDEVICE UsbDevice
)
2273 PUSBDEVICE_ENTRY DeviceEntry
;
2275 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2281 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2284 // point to first entry
2286 Entry
= m_UsbDeviceList
.Flink
;
2289 // find matching entry
2291 while(Entry
!= &m_UsbDeviceList
)
2296 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2299 // is it current entry
2301 if (DeviceEntry
->Device
== UsbDevice
)
2306 RemoveEntryList(Entry
);
2311 ExFreePoolWithTag(DeviceEntry
, TAG_USBLIB
);
2316 Status
= STATUS_SUCCESS
;
2323 Entry
= Entry
->Flink
;
2329 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2336 //-----------------------------------------------------------------------------------------
2338 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2340 PUSBDEVICE_ENTRY DeviceEntry
;
2343 BOOLEAN Result
= FALSE
;
2348 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2351 // point to first entry
2353 Entry
= m_UsbDeviceList
.Flink
;
2356 // find matching entry
2358 while(Entry
!= &m_UsbDeviceList
)
2363 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2366 // is it current entry
2368 if (DeviceEntry
->Device
== UsbDevice
)
2380 Entry
= Entry
->Flink
;
2386 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2395 //-----------------------------------------------------------------------------------------
2397 CHubController::AddUsbDevice(
2398 PUSBDEVICE UsbDevice
)
2400 PUSBDEVICE_ENTRY DeviceEntry
;
2404 // allocate device entry
2406 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBLIB
);
2412 return STATUS_INSUFFICIENT_RESOURCES
;
2418 DeviceEntry
->Device
= UsbDevice
;
2423 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2428 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2431 // release spin lock
2433 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2438 return STATUS_SUCCESS
;
2441 //-----------------------------------------------------------------------------------------
2443 CHubController::SetNotification(
2444 PVOID CallbackContext
,
2445 PRH_INIT_CALLBACK CallbackRoutine
)
2450 // acquire hub controller lock
2452 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2455 // now set the callback routine and context of the hub
2457 m_HubCallbackContext
= CallbackContext
;
2458 m_HubCallbackRoutine
= CallbackRoutine
;
2461 // release hub controller lock
2463 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2466 //=================================================================================================
2468 // Generic Interface functions
2472 USBI_InterfaceReference(
2475 CHubController
* Controller
= (CHubController
*)BusContext
;
2477 DPRINT1("USBH_InterfaceReference\n");
2482 Controller
->AddRef();
2487 USBI_InterfaceDereference(
2490 CHubController
* Controller
= (CHubController
*)BusContext
;
2492 DPRINT1("USBH_InterfaceDereference\n");
2497 Controller
->Release();
2499 //=================================================================================================
2501 // USB Hub Interface functions
2505 USBHI_CreateUsbDevice(
2507 PUSB_DEVICE_HANDLE
*NewDevice
,
2508 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2512 PUSBDEVICE NewUsbDevice
;
2513 CHubController
* Controller
;
2516 DPRINT1("USBHI_CreateUsbDevice\n");
2519 // first get hub controller
2521 Controller
= (CHubController
*)BusContext
;
2526 PC_ASSERT(Controller
);
2527 PC_ASSERT(BusContext
== HubDeviceHandle
);
2530 // now allocate usb device
2532 Status
= CreateUSBDevice(&NewUsbDevice
);
2535 // check for success
2537 if (!NT_SUCCESS(Status
))
2540 // release controller
2542 Controller
->Release();
2543 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2548 // now initialize device
2550 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(), HubDeviceHandle
, PortNumber
, PortStatus
);
2553 // check for success
2555 if (!NT_SUCCESS(Status
))
2558 // release usb device
2560 NewUsbDevice
->Release();
2561 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2568 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2570 // check for success
2572 if (!NT_SUCCESS(Status
))
2575 // release usb device
2577 NewUsbDevice
->Release();
2579 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2586 *NewDevice
= NewUsbDevice
;
2591 return STATUS_SUCCESS
;
2596 USBHI_InitializeUsbDevice(
2598 PUSB_DEVICE_HANDLE DeviceHandle
)
2600 PUSBDEVICE UsbDevice
;
2601 CHubController
* Controller
;
2602 ULONG DeviceAddress
;
2606 DPRINT1("USBHI_InitializeUsbDevice\n");
2609 // first get controller
2611 Controller
= (CHubController
*)BusContext
;
2612 PC_ASSERT(Controller
);
2615 // get device object
2617 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2618 PC_ASSERT(UsbDevice
);
2621 // validate device handle
2623 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2625 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2628 // invalid device handle
2630 return STATUS_DEVICE_NOT_CONNECTED
;
2634 // now reserve an address
2636 DeviceAddress
= Controller
->AcquireDeviceAddress();
2639 // is the device address valid
2641 if (DeviceAddress
== MAXULONG
)
2644 // failed to get an device address from the device address pool
2646 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2647 return STATUS_DEVICE_DATA_ERROR
;
2653 // now set the device address
2655 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2657 if (NT_SUCCESS(Status
))
2660 }while(Index
++ < 3 );
2663 // check for failure
2665 if (!NT_SUCCESS(Status
))
2668 // failed to set device address
2670 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2675 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2680 return STATUS_DEVICE_DATA_ERROR
;
2686 return STATUS_SUCCESS
;
2691 USBHI_GetUsbDescriptors(
2693 PUSB_DEVICE_HANDLE DeviceHandle
,
2694 PUCHAR DeviceDescriptorBuffer
,
2695 PULONG DeviceDescriptorBufferLength
,
2696 PUCHAR ConfigDescriptorBuffer
,
2697 PULONG ConfigDescriptorBufferLength
)
2699 PUSBDEVICE UsbDevice
;
2700 CHubController
* Controller
;
2702 DPRINT1("USBHI_GetUsbDescriptors\n");
2707 PC_ASSERT(DeviceDescriptorBuffer
);
2708 PC_ASSERT(DeviceDescriptorBufferLength
);
2709 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2710 PC_ASSERT(ConfigDescriptorBufferLength
);
2711 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2714 // first get controller
2716 Controller
= (CHubController
*)BusContext
;
2717 PC_ASSERT(Controller
);
2721 // get device object
2723 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2724 PC_ASSERT(UsbDevice
);
2727 // validate device handle
2729 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2731 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2734 // invalid device handle
2736 return STATUS_DEVICE_NOT_CONNECTED
;
2740 // get device descriptor
2742 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2745 // store result length
2747 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2750 // get configuration descriptor
2752 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2755 // complete the request
2757 return STATUS_SUCCESS
;
2762 USBHI_RemoveUsbDevice(
2764 PUSB_DEVICE_HANDLE DeviceHandle
,
2767 PUSBDEVICE UsbDevice
;
2768 CHubController
* Controller
;
2771 DPRINT1("USBHI_RemoveUsbDevice\n");
2774 // first get controller
2776 Controller
= (CHubController
*)BusContext
;
2777 PC_ASSERT(Controller
);
2780 // get device object
2782 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2783 PC_ASSERT(UsbDevice
);
2786 // validate device handle
2788 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2790 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2793 // invalid device handle
2795 return STATUS_DEVICE_NOT_CONNECTED
;
2799 // check if there were flags passed
2801 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2804 // ignore flags for now
2806 return STATUS_SUCCESS
;
2812 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2813 if (!NT_SUCCESS(Status
))
2816 // invalid device handle
2818 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2820 return STATUS_DEVICE_NOT_CONNECTED
;
2824 // release usb device
2826 UsbDevice
->Release();
2831 return STATUS_SUCCESS
;
2836 USBHI_RestoreUsbDevice(
2838 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2839 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2841 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2842 CHubController
* Controller
;
2844 DPRINT1("USBHI_RestoreUsbDevice\n");
2847 // first get controller
2849 Controller
= (CHubController
*)BusContext
;
2850 PC_ASSERT(Controller
);
2853 // get device object
2855 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2856 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2857 PC_ASSERT(OldUsbDevice
);
2858 PC_ASSERT(NewDeviceHandle
);
2861 // validate device handle
2863 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2864 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2866 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2867 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2870 // remove old device handle
2872 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2874 return STATUS_SUCCESS
;
2879 USBHI_QueryDeviceInformation(
2881 PUSB_DEVICE_HANDLE DeviceHandle
,
2882 PVOID DeviceInformationBuffer
,
2883 ULONG DeviceInformationBufferLength
,
2884 PULONG LengthReturned
)
2886 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2887 PUSBDEVICE UsbDevice
;
2888 CHubController
* Controller
;
2890 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2895 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2896 PC_ASSERT(DeviceInformationBuffer
);
2897 PC_ASSERT(LengthReturned
);
2900 // get controller object
2902 Controller
= (CHubController
*)BusContext
;
2903 PC_ASSERT(Controller
);
2906 // get device object
2908 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2909 PC_ASSERT(UsbDevice
);
2911 if (BusContext
!= DeviceHandle
)
2914 // validate device handle
2916 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2918 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2921 // invalid device handle
2923 return STATUS_DEVICE_NOT_CONNECTED
;
2927 // access information buffer
2929 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2932 // initialize with default values
2934 DeviceInfo
->InformationLevel
= 0;
2935 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2936 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2937 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2938 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2939 DeviceInfo
->HubAddress
= 0; //FIXME
2940 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2941 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2942 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2945 // get device descriptor
2947 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2950 // FIXME return pipe information
2954 // store result length
2956 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2958 return STATUS_SUCCESS
;
2962 // access information buffer
2964 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2967 // initialize with default values
2969 DeviceInfo
->InformationLevel
= 0;
2970 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2971 DeviceInfo
->PortNumber
= 0;
2972 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2973 DeviceInfo
->DeviceAddress
= 0;
2974 DeviceInfo
->HubAddress
= 0; //FIXME
2975 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
2976 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
2977 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2980 // get device descriptor
2982 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
2985 // FIXME return pipe information
2989 // store result length
2992 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
2994 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
2999 return STATUS_SUCCESS
;
3004 USBHI_GetControllerInformation(
3006 PVOID ControllerInformationBuffer
,
3007 ULONG ControllerInformationBufferLength
,
3008 PULONG LengthReturned
)
3010 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
3012 DPRINT1("USBHI_GetControllerInformation\n");
3017 PC_ASSERT(ControllerInformationBuffer
);
3018 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
3021 // get controller info buffer
3023 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3026 // FIXME only version 0 is supported for now
3028 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3031 // fill in information
3033 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3034 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3035 ControllerInfo
->IsHighSpeedController
= TRUE
;
3038 // set length returned
3040 *LengthReturned
= ControllerInfo
->ActualLength
;
3045 return STATUS_SUCCESS
;
3050 USBHI_ControllerSelectiveSuspend(
3055 return STATUS_NOT_IMPLEMENTED
;
3060 USBHI_GetExtendedHubInformation(
3062 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3063 PVOID HubInformationBuffer
,
3064 ULONG HubInformationBufferLength
,
3065 PULONG LengthReturned
)
3067 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3068 CHubController
* Controller
;
3069 PUSBHARDWAREDEVICE Hardware
;
3071 ULONG NumPort
, Dummy2
;
3075 DPRINT1("USBHI_GetExtendedHubInformation\n");
3080 PC_ASSERT(HubInformationBuffer
);
3081 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3082 PC_ASSERT(LengthReturned
);
3085 // get hub controller
3087 Controller
= (CHubController
*)BusContext
;
3088 PC_ASSERT(Controller
);
3091 // get usb hardware device
3093 Hardware
= Controller
->GetUsbHardware();
3096 // retrieve number of ports
3098 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3099 if (!NT_SUCCESS(Status
))
3102 // failed to get hardware details, ouch ;)
3104 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3109 // get hub information buffer
3111 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3114 // initialize hub information
3116 HubInfo
->InformationLevel
= 0;
3121 HubInfo
->NumberOfPorts
= NumPort
;
3124 // initialize port information
3126 for(Index
= 0; Index
< NumPort
; Index
++)
3128 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3129 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3130 HubInfo
->Port
[Index
].VidOverride
= 0;
3131 HubInfo
->Port
[Index
].PidOverride
= 0;
3132 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3136 // store result length
3139 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3141 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3147 return STATUS_SUCCESS
;
3152 USBHI_GetRootHubSymbolicName(
3154 PVOID HubSymNameBuffer
,
3155 ULONG HubSymNameBufferLength
,
3156 PULONG HubSymNameActualLength
)
3159 return STATUS_NOT_IMPLEMENTED
;
3164 USBHI_GetDeviceBusContext(
3165 PVOID HubBusContext
,
3174 USBHI_Initialize20Hub(
3176 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3179 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3180 return STATUS_SUCCESS
;
3185 USBHI_RootHubInitNotification(
3187 PVOID CallbackContext
,
3188 PRH_INIT_CALLBACK CallbackRoutine
)
3190 CHubController
* Controller
;
3192 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3195 // get controller object
3197 Controller
= (CHubController
*)BusContext
;
3198 PC_ASSERT(Controller
);
3201 // set notification routine
3203 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3206 // FIXME: determine when to perform callback
3208 CallbackRoutine(CallbackContext
);
3213 return STATUS_SUCCESS
;
3218 USBHI_FlushTransfers(
3227 USBHI_SetDeviceHandleData(
3230 PDEVICE_OBJECT UsbDevicePdo
)
3232 PUSBDEVICE UsbDevice
;
3233 CHubController
* Controller
;
3238 Controller
= (CHubController
*)BusContext
;
3239 PC_ASSERT(Controller
);
3242 // get device handle
3244 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3247 // validate device handle
3249 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3251 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3261 // usbhub sends this request as a part of the Pnp startup sequence
3262 // looks like we need apply a dragon voodoo to fixup the device stack
3263 // otherwise usbhub will cause a bugcheck
3265 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3270 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3273 // should be usbstor
3274 // fixup device stack voodoo part #2
3276 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3279 // set device handle data
3281 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3285 //=================================================================================================
3287 // USB Device Interface functions
3292 USBDI_GetUSBDIVersion(
3294 PUSBD_VERSION_INFORMATION VersionInformation
,
3295 PULONG HcdCapabilites
)
3297 CHubController
* Controller
;
3298 PUSBHARDWAREDEVICE Device
;
3299 ULONG Speed
, Dummy2
;
3302 DPRINT1("USBDI_GetUSBDIVersion\n");
3307 Controller
= (CHubController
*)BusContext
;
3312 Device
= Controller
->GetUsbHardware();
3315 if (VersionInformation
)
3318 // windows xp supported
3320 VersionInformation
->USBDI_Version
= 0x00000500;
3325 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3328 // store speed details
3330 VersionInformation
->Supported_USB_Version
= Speed
;
3334 // no flags supported
3336 *HcdCapabilites
= 0;
3343 PULONG CurrentFrame
)
3346 return STATUS_NOT_IMPLEMENTED
;
3351 USBDI_SubmitIsoOutUrb(
3356 return STATUS_NOT_IMPLEMENTED
;
3361 USBDI_QueryBusInformation(
3364 PVOID BusInformationBuffer
,
3365 PULONG BusInformationBufferLength
,
3366 PULONG BusInformationActualLength
)
3369 return STATUS_NOT_IMPLEMENTED
;
3374 USBDI_IsDeviceHighSpeed(
3377 CHubController
* Controller
;
3378 PUSBHARDWAREDEVICE Device
;
3379 ULONG Speed
, Dummy2
;
3382 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3387 Controller
= (CHubController
*)BusContext
;
3392 Device
= Controller
->GetUsbHardware();
3398 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3401 // USB 2.0 equals 0x200
3403 return (Speed
== 0x200);
3416 return STATUS_NOT_IMPLEMENTED
;
3420 CHubController::HandleQueryInterface(
3421 PIO_STACK_LOCATION IoStack
)
3423 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3424 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3425 UNICODE_STRING GuidBuffer
;
3428 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3431 // get request parameters
3433 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3434 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3439 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3441 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3444 // version not supported
3446 return STATUS_NOT_SUPPORTED
;
3450 // Interface version 0
3452 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3454 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3455 InterfaceHub
->BusContext
= PVOID(this);
3456 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3457 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3461 // Interface version 1
3463 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3465 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3466 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3467 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3468 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3469 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3470 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3474 // Interface version 2
3476 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3478 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3479 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3480 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3481 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3482 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3483 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3488 // Interface version 3
3490 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3492 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3496 // Interface version 4
3498 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3500 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3504 // Interface version 5
3506 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3508 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3512 // request completed
3514 return STATUS_SUCCESS
;
3516 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3519 // get request parameters
3521 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3522 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3527 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3529 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3532 // version not supported
3534 return STATUS_NOT_SUPPORTED
;
3538 // interface version 0
3540 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3542 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3543 InterfaceDI
->BusContext
= PVOID(this);
3544 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3545 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3546 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3547 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3548 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3549 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3553 // interface version 1
3555 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3557 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3561 // interface version 2
3563 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3565 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3569 // request completed
3571 return STATUS_SUCCESS
;
3576 // convert guid to string
3578 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3579 if (NT_SUCCESS(Status
))
3584 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3589 RtlFreeUnicodeString(&GuidBuffer
);
3592 return STATUS_NOT_SUPPORTED
;
3596 CHubController::SetDeviceInterface(
3599 NTSTATUS Status
= STATUS_SUCCESS
;
3604 // register device interface
3606 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3608 if (NT_SUCCESS(Status
))
3611 // now enable the device interface
3613 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3618 m_InterfaceEnabled
= TRUE
;
3621 else if (m_InterfaceEnabled
)
3624 // disable device interface
3626 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3628 if (NT_SUCCESS(Status
))
3631 // now delete interface string
3633 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3637 // disable interface
3639 m_InterfaceEnabled
= FALSE
;
3645 return STATUS_SUCCESS
;
3649 CHubController::CreatePDO(
3650 PDRIVER_OBJECT DriverObject
,
3651 PDEVICE_OBJECT
* OutDeviceObject
)
3653 WCHAR CharDeviceName
[64];
3655 ULONG UsbDeviceNumber
= 0;
3656 UNICODE_STRING DeviceName
;
3661 // construct device name
3663 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3666 // initialize device name
3668 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3673 Status
= IoCreateDevice(DriverObject
,
3674 sizeof(COMMON_DEVICE_EXTENSION
),
3676 FILE_DEVICE_CONTROLLER
,
3681 /* check for success */
3682 if (NT_SUCCESS(Status
))
3686 // is there a device object with that same name
3688 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3691 // Try the next name
3698 // bail out on other errors
3700 if (!NT_SUCCESS(Status
))
3702 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3707 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3710 // fixup device stack voodoo part #1
3712 (*OutDeviceObject
)->StackSize
++;
3721 CreateHubController(
3722 PHUBCONTROLLER
*OutHcdController
)
3724 PHUBCONTROLLER This
;
3727 // allocate controller
3729 This
= new(NonPagedPool
, TAG_USBLIB
) CHubController(0);
3733 // failed to allocate
3735 return STATUS_INSUFFICIENT_RESOURCES
;
3739 // add reference count
3746 *OutHcdController
= (PHUBCONTROLLER
)This
;
3751 return STATUS_SUCCESS
;
3754 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3756 CHubController
* This
;
3758 This
= (CHubController
*)Context
;
3762 Irp
= This
->m_PendingSCEIrp
;
3765 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3769 This
->m_PendingSCEIrp
= NULL
;
3770 This
->QueryStatusChageEndpoint(Irp
);
3772 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3773 Irp
->IoStatus
.Information
= 0;
3775 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);