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)
16 VOID
StatusChangeEndpointCallBack(
19 class CHubController
: public IHubController
,
23 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
25 STDMETHODIMP_(ULONG
) AddRef()
27 InterlockedIncrement(&m_Ref
);
30 STDMETHODIMP_(ULONG
) Release()
32 InterlockedDecrement(&m_Ref
);
42 // IHubController interface functions
43 virtual NTSTATUS
Initialize(IN PDRIVER_OBJECT DriverObject
, IN PHCDCONTROLLER Controller
, IN PUSBHARDWAREDEVICE Device
, IN BOOLEAN IsRootHubDevice
, IN ULONG DeviceAddress
);
44 virtual NTSTATUS
GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
);
45 virtual NTSTATUS
GetHubControllerSymbolicLink(ULONG BufferLength
, PVOID Buffer
, PULONG RequiredLength
);
47 // IDispatchIrp interface functions
48 virtual NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
49 virtual NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
50 virtual NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
51 virtual NTSTATUS
HandleSystemControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
54 NTSTATUS
HandleQueryInterface(PIO_STACK_LOCATION IoStack
);
55 NTSTATUS
SetDeviceInterface(BOOLEAN bEnable
);
56 NTSTATUS
CreatePDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
57 PUSBHARDWAREDEVICE
GetUsbHardware();
58 ULONG
AcquireDeviceAddress();
59 VOID
ReleaseDeviceAddress(ULONG DeviceAddress
);
60 BOOLEAN
ValidateUsbDevice(PUSBDEVICE UsbDevice
);
61 NTSTATUS
AddUsbDevice(PUSBDEVICE UsbDevice
);
62 NTSTATUS
RemoveUsbDevice(PUSBDEVICE UsbDevice
);
63 VOID
SetNotification(PVOID CallbackContext
, PRH_INIT_CALLBACK CallbackRoutine
);
64 // internal ioctl routines
65 NTSTATUS
HandleGetDescriptor(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleGetDescriptorFromInterface(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
70 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
71 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
72 NTSTATUS
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
73 NTSTATUS
HandleClassEndpoint(IN OUT PIRP Irp
, PURB Urb
);
74 NTSTATUS
HandleVendorDevice(IN OUT PIRP Irp
, PURB Urb
);
75 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
76 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
77 NTSTATUS
HandleClearStall(IN OUT PIRP Irp
, PURB Urb
);
78 NTSTATUS
HandleSyncResetAndClearStall(IN OUT PIRP Irp
, PURB Urb
);
79 NTSTATUS
HandleAbortPipe(IN OUT PIRP Irp
, PURB Urb
);
81 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
83 // constructor / destructor
84 CHubController(IUnknown
*OuterUnknown
){}
85 virtual ~CHubController(){}
89 PHCDCONTROLLER m_Controller
;
90 PUSBHARDWAREDEVICE m_Hardware
;
91 BOOLEAN m_IsRootHubDevice
;
92 ULONG m_DeviceAddress
;
94 BOOLEAN m_InterfaceEnabled
;
95 UNICODE_STRING m_HubDeviceInterfaceString
;
97 PDEVICE_OBJECT m_HubControllerDeviceObject
;
98 PDRIVER_OBJECT m_DriverObject
;
100 PVOID m_HubCallbackContext
;
101 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
103 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
106 RTL_BITMAP m_DeviceAddressBitmap
;
107 PULONG m_DeviceAddressBitmapBuffer
;
108 LIST_ENTRY m_UsbDeviceList
;
109 PIRP m_PendingSCEIrp
;
114 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
121 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
123 /* Lifted from Linux with slight changes */
124 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
127 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
128 0x00, 0x20, /* bcdUSB; v1.1 */
129 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
130 0x01, /* bDeviceSubClass; */
131 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
132 0x08, /* bMaxPacketSize0; 8 Bytes */
133 /* Fill Vendor and Product in when init root hub */
134 0x00, 0x00, /* idVendor; */
135 0x00, 0x00, /* idProduct; */
136 0x00, 0x00, /* bcdDevice */
137 0x00, /* iManufacturer; */
138 0x00, /* iProduct; */
139 0x00, /* iSerialNumber; */
140 0x01 /* bNumConfigurations; */
144 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
146 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
147 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
148 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
152 0x40, /* self powered */
156 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
158 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
159 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
160 0, /* bInterfaceNumber; */
161 0, /* bAlternateSetting; */
162 0x1, /* bNumEndpoints; */
163 0x09, /* bInterfaceClass; HUB_CLASSCODE */
164 0x01, /* bInterfaceSubClass; */
165 0x00, /* bInterfaceProtocol: */
166 0x00, /* iInterface; */
169 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
171 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
172 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
173 0x81, /* bEndPointAddress */
174 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
175 0x01, /* wMaxPacketSize */
179 //----------------------------------------------------------------------------------------
182 CHubController::QueryInterface(
186 return STATUS_UNSUCCESSFUL
;
188 //----------------------------------------------------------------------------------------
190 CHubController::Initialize(
191 IN PDRIVER_OBJECT DriverObject
,
192 IN PHCDCONTROLLER Controller
,
193 IN PUSBHARDWAREDEVICE Device
,
194 IN BOOLEAN IsRootHubDevice
,
195 IN ULONG DeviceAddress
)
198 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
199 USHORT VendorID
, DeviceID
;
203 // initialize members
205 m_Controller
= Controller
;
207 m_IsRootHubDevice
= IsRootHubDevice
;
208 m_DeviceAddress
= DeviceAddress
;
209 m_DriverObject
= DriverObject
;
210 m_USBType
= m_Hardware
->GetUSBType();
211 KeInitializeSpinLock(&m_Lock
);
212 InitializeListHead(&m_UsbDeviceList
);
215 // allocate device address bitmap buffer
217 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBLIB
);
218 if (!m_DeviceAddressBitmapBuffer
)
223 return STATUS_INSUFFICIENT_RESOURCES
;
227 // initialize device address bitmap
229 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
230 RtlClearAllBits(&m_DeviceAddressBitmap
);
235 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
236 if (!NT_SUCCESS(Status
))
239 // failed to create hub device object
245 // get device extension
247 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
250 // initialize device extension
252 DeviceExtension
->IsFDO
= FALSE
;
253 DeviceExtension
->IsHub
= TRUE
; //FIXME
254 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
257 // intialize device descriptor
259 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
260 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
262 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
265 // update device descriptor
267 m_DeviceDescriptor
.idVendor
= VendorID
;
268 m_DeviceDescriptor
.idProduct
= DeviceID
;
269 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
273 // Set the SCE Callback that the Hardware Device will call on port status change
275 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
280 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
282 return STATUS_SUCCESS
;
286 // Queries the ports to see if there has been a device connected or removed.
289 CHubController::QueryStatusChageEndpoint(
292 ULONG PortCount
, PortId
;
293 PIO_STACK_LOCATION IoStack
;
294 USHORT PortStatus
, PortChange
;
296 PUCHAR TransferBuffer
;
297 UCHAR Changed
= FALSE
;
300 // get current stack location
302 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
308 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
312 // Get the number of ports and check each one for device connected
314 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
315 DPRINT1("[%s] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", m_USBType
, Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
, Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
317 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
322 for (PortId
= 0; PortId
< PortCount
; PortId
++)
324 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
326 DPRINT1("[%s] Port %d: Status %x, Change %x\n", m_USBType
, PortId
, PortStatus
, PortChange
);
330 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
334 DPRINT1("[%s] Change state on port %d\n", m_USBType
, PortId
);
335 // Set the value for the port number
336 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
344 //-----------------------------------------------------------------------------------------
346 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
349 // store controller object
351 *HubDeviceObject
= m_HubControllerDeviceObject
;
353 return STATUS_SUCCESS
;
355 //-----------------------------------------------------------------------------------------
357 CHubController::GetHubControllerSymbolicLink(
360 PULONG RequiredLength
)
362 if (!m_InterfaceEnabled
)
365 // device interface not yet enabled
367 return STATUS_UNSUCCESSFUL
;
370 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
374 // length is without '\??\'
376 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
381 return STATUS_BUFFER_OVERFLOW
;
385 // copy symbolic link
387 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
390 // store length, length is without '\??\'
392 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
397 return STATUS_SUCCESS
;
400 //-----------------------------------------------------------------------------------------
402 CHubController::HandlePnp(
403 IN PDEVICE_OBJECT DeviceObject
,
406 PIO_STACK_LOCATION IoStack
;
407 PDEVICE_CAPABILITIES DeviceCapabilities
;
408 PPNP_BUS_INFORMATION BusInformation
;
409 PDEVICE_RELATIONS DeviceRelations
;
411 ULONG Index
= 0, Length
;
412 USHORT VendorID
, DeviceID
;
413 ULONG HiSpeed
, NumPorts
;
418 // get current stack location
420 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
422 switch(IoStack
->MinorFunction
)
424 case IRP_MN_START_DEVICE
:
426 DPRINT("[%s] HandlePnp IRP_MN_START_DEVICE\n", m_USBType
);
428 // register device interface
430 Status
= SetDeviceInterface(TRUE
);
433 case IRP_MN_QUERY_STOP_DEVICE
:
434 case IRP_MN_QUERY_REMOVE_DEVICE
:
439 Status
= STATUS_SUCCESS
;
442 case IRP_MN_QUERY_ID
:
444 DPRINT("[%s] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType
, IoStack
->Parameters
.QueryId
.IdType
);
446 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
453 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
455 if (HiSpeed
== 0x200)
460 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
467 swprintf(Buffer
, L
"USB\\ROOT_HUB");
473 Length
= (wcslen(Buffer
) + 1);
478 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBLIB
);
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("[%s] HandlePnp> failed to get hardware id %x\n", m_USBType
, 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
;
547 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBLIB
);
554 Status
= STATUS_INSUFFICIENT_RESOURCES
;
561 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
566 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
567 Status
= STATUS_SUCCESS
;
571 Status
= STATUS_SUCCESS
;
574 case IRP_MN_QUERY_CAPABILITIES
:
576 DPRINT("[%s] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType
);
578 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
580 DeviceCapabilities
->LockSupported
= FALSE
;
581 DeviceCapabilities
->EjectSupported
= FALSE
;
582 DeviceCapabilities
->Removable
= FALSE
;
583 DeviceCapabilities
->DockDevice
= FALSE
;
584 DeviceCapabilities
->UniqueID
= FALSE
;
585 DeviceCapabilities
->SilentInstall
= FALSE
;
586 DeviceCapabilities
->RawDeviceOK
= FALSE
;
587 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
588 DeviceCapabilities
->Address
= 0;
589 DeviceCapabilities
->UINumber
= 0;
590 DeviceCapabilities
->DeviceD2
= 1;
593 DeviceCapabilities
->HardwareDisabled
= FALSE
;
594 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
595 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
596 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
597 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
598 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
599 DeviceCapabilities
->D1Latency
= 0;
600 DeviceCapabilities
->D2Latency
= 0;
601 DeviceCapabilities
->D3Latency
= 0;
603 Status
= STATUS_SUCCESS
;
606 case IRP_MN_QUERY_INTERFACE
:
608 DPRINT("[%s] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType
);
611 // handle device interface requests
613 Status
= HandleQueryInterface(IoStack
);
616 case IRP_MN_REMOVE_DEVICE
:
618 DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType
);
621 // deactivate device interface for BUS PDO
623 SetDeviceInterface(FALSE
);
626 // complete the request first
628 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
629 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
634 IoDeleteDevice(m_HubControllerDeviceObject
);
639 m_HubControllerDeviceObject
= 0;
644 return STATUS_SUCCESS
;
646 case IRP_MN_QUERY_DEVICE_RELATIONS
:
648 DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
650 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
653 // allocate device relations
655 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBLIB
);
656 if (!DeviceRelations
)
661 Status
= STATUS_INSUFFICIENT_RESOURCES
;
666 // initialize device relations
668 DeviceRelations
->Count
= 1;
669 DeviceRelations
->Objects
[0] = DeviceObject
;
670 ObReferenceObject(DeviceObject
);
675 Status
= STATUS_SUCCESS
;
676 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
683 Status
= Irp
->IoStatus
.Status
;
687 case IRP_MN_QUERY_BUS_INFORMATION
:
689 DPRINT("[%s] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType
);
692 // allocate buffer for bus information
694 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
700 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
705 BusInformation
->LegacyBusType
= PNPBus
;
706 BusInformation
->BusNumber
= 0;
708 Status
= STATUS_SUCCESS
;
709 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
716 Status
= STATUS_INSUFFICIENT_RESOURCES
;
720 case IRP_MN_STOP_DEVICE
:
722 DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType
);
726 Status
= STATUS_SUCCESS
;
729 case IRP_MN_SURPRISE_REMOVAL
:
731 DPRINT("[%s] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType
);
732 Status
= STATUS_SUCCESS
;
738 // ignore request with default status
740 Status
= Irp
->IoStatus
.Status
;
748 Irp
->IoStatus
.Status
= Status
;
749 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
757 //-----------------------------------------------------------------------------------------
759 CHubController::HandlePower(
760 IN PDEVICE_OBJECT DeviceObject
,
764 Status
= Irp
->IoStatus
.Status
;
765 PoStartNextPowerIrp(Irp
);
766 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
770 //-----------------------------------------------------------------------------------------
772 CHubController::HandleSystemControl(
773 IN PDEVICE_OBJECT DeviceObject
,
777 Status
= Irp
->IoStatus
.Status
;
778 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
782 //-----------------------------------------------------------------------------------------
784 CHubController::HandleIsochronousTransfer(
788 PUSBDEVICE UsbDevice
;
789 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
792 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
794 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
798 DPRINT1("[%s] Error No EndpointDesc\n", m_USBType
);
799 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
800 return STATUS_INVALID_PARAMETER
;
806 ASSERT(EndPointDesc
);
807 DPRINT("[%s] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType
, EndPointDesc
, EndPointDesc
->bEndpointAddress
, EndPointDesc
->bmAttributes
);
808 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
811 // check if this is a valid usb device handle
813 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
815 DPRINT1("[%s] HandleIsochronousTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
818 // invalid device handle
820 return STATUS_DEVICE_NOT_CONNECTED
;
826 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
828 return UsbDevice
->SubmitIrp(Irp
);
831 //-----------------------------------------------------------------------------------------
833 CHubController::HandleBulkOrInterruptTransfer(
837 PUSBDEVICE UsbDevice
;
838 PUSB_ENDPOINT EndPointDesc
= NULL
;
840 // First check if the request is for the Status Change Endpoint
844 // Is the Request for the root hub
846 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
848 ASSERT(m_PendingSCEIrp
== NULL
);
849 if (QueryStatusChageEndpoint(Irp
))
851 StatusChangeEndpointCallBack(this);
852 return STATUS_SUCCESS
;
856 // Else pend the IRP, to be completed when a device connects or disconnects.
858 DPRINT("[%s] Pending SCE Irp\n", m_USBType
);
859 m_PendingSCEIrp
= Irp
;
860 IoMarkIrpPending(Irp
);
861 return STATUS_PENDING
;
865 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
867 EndPointDesc
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
872 ASSERT(EndPointDesc
);
873 ASSERT((EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
876 // check if this is a valid usb device handle
878 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
880 DPRINT1("[%s] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
883 // invalid device handle
885 return STATUS_DEVICE_NOT_CONNECTED
;
891 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
892 return UsbDevice
->SubmitIrp(Irp
);
895 //-----------------------------------------------------------------------------------------
897 CHubController::HandleClassOther(
901 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
902 USHORT PortStatus
= 0, PortChange
= 0;
907 DPRINT("[%s] HandleClassOther> Request %x Value %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
910 // get number of ports available
912 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
913 PC_ASSERT(Status
== STATUS_SUCCESS
);
918 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
921 // port range reported start from 1 -n
922 // convert back port id so it matches the hardware
924 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
927 // check request code
929 switch(Urb
->UrbControlVendorClassRequest
.Request
)
931 case USB_REQUEST_GET_STATUS
:
936 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
937 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
942 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
944 if (NT_SUCCESS(Status
))
947 // request contains buffer of 2 ushort which are used from submitting port status and port change status
949 DPRINT("[%s] PortId %x PortStatus %x PortChange %x\n", m_USBType
, PortId
, PortStatus
, PortChange
);
950 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
953 // store status, then port change
955 *Buffer
= PortStatus
;
957 *Buffer
= PortChange
;
965 case USB_REQUEST_CLEAR_FEATURE
:
967 switch (Urb
->UrbControlVendorClassRequest
.Value
)
969 case C_PORT_CONNECTION
:
970 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
973 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
976 DPRINT("[%s] Unknown Value for Clear Feature %x \n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
982 case USB_REQUEST_SET_FEATURE
:
985 // request set feature
987 switch(Urb
->UrbControlVendorClassRequest
.Value
)
992 // port enable is a no-op for EHCI
994 Status
= STATUS_SUCCESS
;
1001 // set suspend port feature
1003 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
1009 // set power feature on port
1011 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1018 // reset port feature
1020 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1021 PC_ASSERT(Status
== STATUS_SUCCESS
);
1025 DPRINT1("[%s] Unsupported request id %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
1031 DPRINT1("[%s] HandleClassOther Unknown request code %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
);
1033 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1038 //-----------------------------------------------------------------------------------------
1040 CHubController::HandleSelectConfiguration(
1044 PUSBDEVICE UsbDevice
;
1045 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1049 // is the request for the Root Hub
1051 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1054 // FIXME: support setting device to unconfigured state
1056 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1059 // set device handle
1061 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1064 // copy interface info
1066 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1068 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1069 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1070 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1071 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1072 InterfaceInfo
->Reserved
= 0;
1077 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1082 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1083 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1084 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1085 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1086 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1088 return STATUS_SUCCESS
;
1093 // check if this is a valid usb device handle
1095 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1097 DPRINT1("[%s] HandleSelectConfiguration invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1100 // invalid device handle
1102 return STATUS_DEVICE_NOT_CONNECTED
;
1108 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1111 // select configuration
1113 Status
= UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1114 if (NT_SUCCESS(Status
))
1116 // successfully configured device
1117 Urb
->UrbSelectConfiguration
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1123 //-----------------------------------------------------------------------------------------
1125 CHubController::HandleSelectInterface(
1129 PUSBDEVICE UsbDevice
;
1134 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1137 // is the request for the Root Hub
1139 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1142 // no op for root hub
1144 return STATUS_SUCCESS
;
1149 // check if this is a valid usb device handle
1151 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1153 DPRINT1("[%s] HandleSelectInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1156 // invalid device handle
1158 return STATUS_DEVICE_NOT_CONNECTED
;
1164 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1169 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1173 //-----------------------------------------------------------------------------------------
1175 CHubController::HandleGetStatusFromDevice(
1179 PUSHORT DeviceStatus
;
1180 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1182 PUSBDEVICE UsbDevice
;
1187 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1188 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1191 // get status buffer
1193 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1196 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1199 // FIXME need more flags ?
1201 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1202 return STATUS_SUCCESS
;
1206 // check if this is a valid usb device handle
1208 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1210 DPRINT1("[%s] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1213 // invalid device handle
1215 return STATUS_DEVICE_NOT_CONNECTED
;
1221 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1225 // generate setup packet
1227 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1228 CtrlSetup
.wValue
.LowByte
= 0;
1229 CtrlSetup
.wValue
.HiByte
= 0;
1230 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1231 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1232 CtrlSetup
.bmRequestType
.B
= 0x80;
1234 if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_INTERFACE
)
1237 // add interface type
1239 CtrlSetup
.bmRequestType
.B
|= 0x01;
1241 else if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
)
1244 // add interface type
1246 CtrlSetup
.bmRequestType
.B
|= 0x02;
1250 // submit setup packet
1252 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1253 ASSERT(Status
== STATUS_SUCCESS
);
1254 DPRINT1("[%s] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType
, Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1262 //-----------------------------------------------------------------------------------------
1264 CHubController::HandleClassDevice(
1268 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1269 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1270 ULONG PortCount
, Dummy2
;
1272 PUSBDEVICE UsbDevice
;
1273 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1275 DPRINT("[%s] HandleClassDevice Request %x Class %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1278 // check class request type
1280 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1282 case USB_REQUEST_GET_STATUS
:
1285 // check if this is a valid usb device handle
1287 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1289 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1292 // invalid device handle
1294 return STATUS_DEVICE_NOT_CONNECTED
;
1300 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1304 // generate setup packet
1306 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1307 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1308 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1309 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1310 CtrlSetup
.bmRequestType
.B
= 0xA0;
1313 // submit setup packet
1315 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1316 ASSERT(Status
== STATUS_SUCCESS
);
1319 case USB_REQUEST_GET_DESCRIPTOR
:
1321 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1323 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1324 case USB_DEVICE_CLASS_HUB
:
1326 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1331 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1332 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1335 // get hub descriptor
1337 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1340 // one hub is handled
1342 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1343 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1346 // type should 0x29 according to msdn
1348 UsbHubDescriptor
->bDescriptorType
= 0x29;
1353 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1354 PC_ASSERT(Status
== STATUS_SUCCESS
);
1357 // FIXME: retrieve values
1359 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1360 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1361 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1362 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1367 Status
= STATUS_SUCCESS
;
1371 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1373 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1375 // invalid device handle
1377 return STATUS_DEVICE_NOT_CONNECTED
;
1381 // FIXME: implement support for real hubs
1384 Status
= STATUS_NOT_IMPLEMENTED
;
1389 DPRINT1("[%s] HandleClassDevice Class %x not implemented\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1397 // check if this is a valid usb device handle
1399 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1401 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1404 // invalid device handle
1406 return STATUS_DEVICE_NOT_CONNECTED
;
1412 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1415 // generate setup packet
1417 CtrlSetup
.bmRequestType
.B
= 0;
1418 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1419 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_CLASS
;
1420 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1421 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1422 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1423 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1425 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1428 // data direction is device to host
1430 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1434 // submit setup packet
1436 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1437 ASSERT(Status
== STATUS_SUCCESS
);
1446 //-----------------------------------------------------------------------------------------
1448 CHubController::HandleGetDescriptorFromInterface(
1452 PUSBDEVICE UsbDevice
;
1453 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1459 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1460 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1463 // check if this is a valid usb device handle
1465 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1467 DPRINT1("[%s] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1470 // invalid device handle
1472 return STATUS_DEVICE_NOT_CONNECTED
;
1478 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1481 // generate setup packet
1483 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1484 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1485 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1486 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1487 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1488 CtrlSetup
.bmRequestType
.B
= 0x81;
1491 // submit setup packet
1493 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1494 if (!NT_SUCCESS(Status
))
1496 DPRINT1("[%s] HandleGetDescriptorFromInterface failed with %x\n", m_USBType
, Status
);
1505 //-----------------------------------------------------------------------------------------
1507 CHubController::HandleGetDescriptor(
1511 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1512 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1514 PUSBDEVICE UsbDevice
;
1515 ULONG Length
, BufferLength
;
1517 DPRINT("[%s] HandleGetDescriptor Type %x\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1520 // check descriptor type
1522 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1524 case USB_DEVICE_DESCRIPTOR_TYPE
:
1529 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1530 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1532 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1535 // copy root hub device descriptor
1537 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1538 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1539 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1540 Status
= STATUS_SUCCESS
;
1545 // check if this is a valid usb device handle
1547 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1549 DPRINT1("[%s] HandleGetDescriptor invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1552 // invalid device handle
1554 return STATUS_DEVICE_NOT_CONNECTED
;
1560 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1563 // retrieve device descriptor from device
1565 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1566 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1567 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1568 Status
= STATUS_SUCCESS
;
1572 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1577 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1580 // The caller must allocate a buffer large enough to hold all of this information or the data is truncated without error.
1582 BufferLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1583 Buffer
= (PUCHAR
) Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1585 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1588 // request is for the root bus controller
1590 Length
= BufferLength
> sizeof(USB_CONFIGURATION_DESCRIPTOR
) ?
1591 sizeof(USB_CONFIGURATION_DESCRIPTOR
) : BufferLength
;
1592 RtlCopyMemory(Buffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, Length
);
1595 // Check if we still have some space left
1597 if(Length
== BufferLength
)
1600 // We copied all we could
1602 Status
= STATUS_SUCCESS
;
1609 BufferLength
-= Length
;
1612 // copy interface descriptor template
1614 Length
= BufferLength
> sizeof(USB_INTERFACE_DESCRIPTOR
) ?
1615 sizeof(USB_INTERFACE_DESCRIPTOR
) : BufferLength
;
1616 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, Length
);
1619 // Check if we still have some space left
1621 if(Length
== BufferLength
)
1624 // We copied all we could
1626 Status
= STATUS_SUCCESS
;
1633 BufferLength
-= Length
;
1637 // copy end point descriptor template
1639 Length
= BufferLength
> sizeof(USB_ENDPOINT_DESCRIPTOR
) ?
1640 sizeof(USB_ENDPOINT_DESCRIPTOR
) : BufferLength
;
1641 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, Length
);
1646 Status
= STATUS_SUCCESS
;
1652 // check if this is a valid usb device handle
1654 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1656 DPRINT1("[%s] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1659 // invalid device handle
1661 return STATUS_DEVICE_NOT_CONNECTED
;
1667 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1670 // Allocate temporary buffer
1672 BufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1673 Buffer
= (PUCHAR
)ExAllocatePoolWithTag(NonPagedPool
, BufferLength
, TAG_USBLIB
);
1676 Status
= STATUS_NO_MEMORY
;
1681 // perform work in IUSBDevice
1683 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
, BufferLength
, &Length
);
1688 Length
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
> Length
?
1689 Length
: Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1690 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Buffer
, Length
);
1693 // Free temporary buffer
1695 ExFreePoolWithTag(Buffer
, TAG_USBLIB
);
1698 // store result size
1700 Irp
->IoStatus
.Information
= Length
;
1701 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1702 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1703 Status
= STATUS_SUCCESS
;
1707 case USB_STRING_DESCRIPTOR_TYPE
:
1712 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1713 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1717 // check if this is a valid usb device handle
1719 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1721 DPRINT1("[%s] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1724 // invalid device handle
1726 return STATUS_DEVICE_NOT_CONNECTED
;
1732 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1735 // generate setup packet
1737 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1738 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1739 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1740 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1741 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1742 CtrlSetup
.bmRequestType
.B
= 0x80;
1745 // submit setup packet
1747 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1751 DPRINT1("[%s] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1761 //-----------------------------------------------------------------------------------------
1763 CHubController::HandleClassEndpoint(
1767 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1769 PUSBDEVICE UsbDevice
;
1774 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1775 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1776 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1779 // check if this is a valid usb device handle
1781 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1783 DPRINT1("[%s] HandleClassEndpoint invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1786 // invalid device handle
1788 return STATUS_DEVICE_NOT_CONNECTED
;
1794 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1797 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1798 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1799 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1800 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1801 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1802 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1803 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1804 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1805 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1808 // initialize setup packet
1810 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1811 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1812 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1813 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1814 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1816 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1819 // data direction is device to host
1821 CtrlSetup
.bmRequestType
.B
|= 0x80;
1828 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1831 // assert on failure
1833 PC_ASSERT(NT_SUCCESS(Status
));
1842 //-----------------------------------------------------------------------------------------
1844 CHubController::HandleVendorDevice(
1848 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1849 PUSBDEVICE UsbDevice
;
1850 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1852 //DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1857 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1860 // check if this is a valid usb device handle
1862 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1864 DPRINT1("[%s] HandleVendorDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1867 // invalid device handle
1869 return STATUS_DEVICE_NOT_CONNECTED
;
1875 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1878 // initialize setup packet
1880 CtrlSetup
.bmRequestType
.B
= 0;
1881 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1882 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_VENDOR
;
1883 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1884 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1885 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1886 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1888 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1891 // data direction is device to host
1893 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1899 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1900 if (NT_SUCCESS(Status
))
1903 Urb
->UrbControlVendorClassRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1904 Irp
->IoStatus
.Information
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1910 //-----------------------------------------------------------------------------------------
1912 CHubController::HandleSyncResetAndClearStall(
1916 NTSTATUS Status
= STATUS_SUCCESS
;
1917 PUSB_ENDPOINT EndpointDescriptor
;
1923 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1924 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1925 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1928 // check if this is a valid usb device handle
1930 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1932 DPRINT1("[%s] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1935 // invalid device handle
1937 return STATUS_DEVICE_NOT_CONNECTED
;
1943 Status
= HandleAbortPipe(Irp
, Urb
);
1944 if (!NT_SUCCESS(Status
))
1949 DPRINT1("[%s] failed to reset pipe %x\n", m_USBType
, Status
);
1954 // get endpoint descriptor
1956 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1961 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1962 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1967 Status
= HandleClearStall(Irp
, Urb
);
1969 DPRINT1("[%s] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType
, Status
);
1972 // reset data toggle
1974 if (NT_SUCCESS(Status
))
1975 EndpointDescriptor
->DataToggle
= 0x0;
1983 //-----------------------------------------------------------------------------------------
1985 CHubController::HandleAbortPipe(
1990 PUSBDEVICE UsbDevice
;
1991 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1996 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1997 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1998 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
2001 // check if this is a valid usb device handle
2003 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2005 DPRINT1("[%s] HandleAbortPipe invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2008 // invalid device handle
2010 return STATUS_DEVICE_NOT_CONNECTED
;
2014 // get endpoint descriptor
2016 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2021 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2027 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
2028 DPRINT1("[%s] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType
, Status
);
2037 //-----------------------------------------------------------------------------------------
2039 CHubController::HandleClearStall(
2043 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2045 PUSBDEVICE UsbDevice
;
2046 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
2052 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2053 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
2054 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
2057 // check if this is a valid usb device handle
2059 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2061 DPRINT1("[%s] HandleClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2064 // invalid device handle
2066 return STATUS_DEVICE_NOT_CONNECTED
;
2070 // get endpoint descriptor
2072 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2077 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2078 DPRINT1("[%s] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType
);
2081 // initialize setup packet
2083 CtrlSetup
.bmRequestType
.B
= 0x02;
2084 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
2085 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
2086 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
2087 CtrlSetup
.wLength
= 0;
2088 CtrlSetup
.wValue
.W
= 0;
2093 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
2095 DPRINT1("[%s] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType
, Status
);
2104 //-----------------------------------------------------------------------------------------
2106 CHubController::HandleClassInterface(
2110 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2112 PUSBDEVICE UsbDevice
;
2117 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2118 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2119 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2122 // check if this is a valid usb device handle
2124 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2126 DPRINT1("[%s] HandleClassInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2129 // invalid device handle
2131 return STATUS_DEVICE_NOT_CONNECTED
;
2137 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2140 DPRINT("URB_FUNCTION_CLASS_INTERFACE\n");
2141 DPRINT("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
2142 DPRINT("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
2143 DPRINT("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2144 DPRINT("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
2145 DPRINT("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
2146 DPRINT("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
2147 DPRINT("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
2148 DPRINT("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
2151 // initialize setup packet
2153 CtrlSetup
.bmRequestType
.B
= 0x21;
2154 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
2155 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
2156 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
2157 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
2159 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2162 // data direction is device to host
2164 CtrlSetup
.bmRequestType
.B
|= 0x80;
2170 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2173 // assert on failure
2175 if (!NT_SUCCESS(Status
))
2180 DPRINT1("[%s] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType
, Urb
->UrbHeader
.Status
);
2189 //-----------------------------------------------------------------------------------------
2191 CHubController::HandleDeviceControl(
2192 IN PDEVICE_OBJECT DeviceObject
,
2195 PIO_STACK_LOCATION IoStack
;
2197 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2200 // get current stack location
2202 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2205 // determine which request should be performed
2207 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2209 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2214 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2217 switch (Urb
->UrbHeader
.Function
)
2219 case URB_FUNCTION_SYNC_RESET_PIPE
:
2220 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2221 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2223 case URB_FUNCTION_ABORT_PIPE
:
2224 Status
= HandleAbortPipe(Irp
, Urb
);
2226 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2227 Status
= HandleClearStall(Irp
, Urb
);
2229 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2230 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2232 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2233 Status
= HandleGetDescriptor(Irp
, Urb
);
2235 case URB_FUNCTION_CLASS_DEVICE
:
2236 Status
= HandleClassDevice(Irp
, Urb
);
2238 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2239 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
2240 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
2241 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2243 case URB_FUNCTION_SELECT_CONFIGURATION
:
2244 Status
= HandleSelectConfiguration(Irp
, Urb
);
2246 case URB_FUNCTION_SELECT_INTERFACE
:
2247 Status
= HandleSelectInterface(Irp
, Urb
);
2249 case URB_FUNCTION_CLASS_OTHER
:
2250 Status
= HandleClassOther(Irp
, Urb
);
2252 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2253 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2255 case URB_FUNCTION_ISOCH_TRANSFER
:
2256 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2258 case URB_FUNCTION_CLASS_INTERFACE
:
2259 Status
= HandleClassInterface(Irp
, Urb
);
2261 case URB_FUNCTION_CLASS_ENDPOINT
:
2262 Status
= HandleClassEndpoint(Irp
, Urb
);
2264 case URB_FUNCTION_VENDOR_DEVICE
:
2265 Status
= HandleVendorDevice(Irp
, Urb
);
2268 DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType
, Urb
->UrbHeader
.Function
);
2272 // request completed
2276 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2278 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType
, this);
2280 if (IoStack
->Parameters
.Others
.Argument1
)
2283 // store object as device handle
2285 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2286 Status
= STATUS_SUCCESS
;
2291 // mis-behaving hub driver
2293 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2297 // request completed
2301 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2303 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType
);
2306 // this is the first request send, it delivers the PDO to the caller
2308 if (IoStack
->Parameters
.Others
.Argument1
)
2311 // store root hub pdo object
2313 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2316 if (IoStack
->Parameters
.Others
.Argument2
)
2319 // documentation claims to deliver the hcd controller object, although it is wrong
2321 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2325 // request completed
2327 Status
= STATUS_SUCCESS
;
2330 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2332 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType
);
2335 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2336 // requests this ioctl to deliver the number of presents.
2338 if (IoStack
->Parameters
.Others
.Argument1
)
2341 // FIXME / verify: there is only one hub
2343 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2347 // request completed
2349 Status
= STATUS_SUCCESS
;
2350 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2353 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2355 DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType
);
2356 Status
= STATUS_SUCCESS
;
2361 DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType
,
2362 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2363 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2364 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2368 if (Status
!= STATUS_PENDING
)
2370 Irp
->IoStatus
.Status
= Status
;
2371 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2377 //-----------------------------------------------------------------------------------------
2379 CHubController::GetUsbHardware()
2384 //-----------------------------------------------------------------------------------------
2386 CHubController::AcquireDeviceAddress()
2389 ULONG DeviceAddress
;
2392 // acquire device lock
2394 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2399 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2400 if (DeviceAddress
!= MAXULONG
)
2405 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2408 // device addresses start from 0x1 - 0xFF
2414 // release spin lock
2416 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2419 // return device address
2421 return DeviceAddress
;
2423 //-----------------------------------------------------------------------------------------
2425 CHubController::ReleaseDeviceAddress(
2426 ULONG DeviceAddress
)
2431 // acquire device lock
2433 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2438 PC_ASSERT(DeviceAddress
!= 0);
2441 // convert back to bit number
2448 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2453 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2455 //-----------------------------------------------------------------------------------------
2457 CHubController::RemoveUsbDevice(
2458 PUSBDEVICE UsbDevice
)
2460 PUSBDEVICE_ENTRY DeviceEntry
;
2462 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2468 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2471 // point to first entry
2473 Entry
= m_UsbDeviceList
.Flink
;
2476 // find matching entry
2478 while(Entry
!= &m_UsbDeviceList
)
2483 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2486 // is it current entry
2488 if (DeviceEntry
->Device
== UsbDevice
)
2493 RemoveEntryList(Entry
);
2498 ExFreePoolWithTag(DeviceEntry
, TAG_USBLIB
);
2503 Status
= STATUS_SUCCESS
;
2510 Entry
= Entry
->Flink
;
2516 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2523 //-----------------------------------------------------------------------------------------
2525 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2527 PUSBDEVICE_ENTRY DeviceEntry
;
2530 BOOLEAN Result
= FALSE
;
2535 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2538 // point to first entry
2540 Entry
= m_UsbDeviceList
.Flink
;
2543 // find matching entry
2545 while(Entry
!= &m_UsbDeviceList
)
2550 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2553 // is it current entry
2555 if (DeviceEntry
->Device
== UsbDevice
)
2567 Entry
= Entry
->Flink
;
2573 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2582 //-----------------------------------------------------------------------------------------
2584 CHubController::AddUsbDevice(
2585 PUSBDEVICE UsbDevice
)
2587 PUSBDEVICE_ENTRY DeviceEntry
;
2591 // allocate device entry
2593 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBLIB
);
2599 return STATUS_INSUFFICIENT_RESOURCES
;
2605 DeviceEntry
->Device
= UsbDevice
;
2610 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2615 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2618 // release spin lock
2620 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2625 return STATUS_SUCCESS
;
2628 //-----------------------------------------------------------------------------------------
2630 CHubController::SetNotification(
2631 PVOID CallbackContext
,
2632 PRH_INIT_CALLBACK CallbackRoutine
)
2637 // acquire hub controller lock
2639 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2642 // now set the callback routine and context of the hub
2644 m_HubCallbackContext
= CallbackContext
;
2645 m_HubCallbackRoutine
= CallbackRoutine
;
2648 // release hub controller lock
2650 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2653 //=================================================================================================
2655 // Generic Interface functions
2659 USBI_InterfaceReference(
2662 CHubController
* Controller
= (CHubController
*)BusContext
;
2664 DPRINT1("USBH_InterfaceReference\n");
2669 Controller
->AddRef();
2674 USBI_InterfaceDereference(
2677 CHubController
* Controller
= (CHubController
*)BusContext
;
2679 DPRINT1("USBH_InterfaceDereference\n");
2684 Controller
->Release();
2686 //=================================================================================================
2688 // USB Hub Interface functions
2692 USBHI_CreateUsbDevice(
2694 PUSB_DEVICE_HANDLE
*NewDevice
,
2695 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2699 PUSBDEVICE NewUsbDevice
;
2700 CHubController
* Controller
;
2703 DPRINT1("USBHI_CreateUsbDevice\n");
2706 // first get hub controller
2708 Controller
= (CHubController
*)BusContext
;
2713 PC_ASSERT(Controller
);
2714 PC_ASSERT(BusContext
== HubDeviceHandle
);
2717 // now allocate usb device
2719 Status
= CreateUSBDevice(&NewUsbDevice
);
2722 // check for success
2724 if (!NT_SUCCESS(Status
))
2727 // release controller
2729 Controller
->Release();
2730 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2735 // now initialize device
2737 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(), HubDeviceHandle
, PortNumber
, PortStatus
);
2740 // check for success
2742 if (!NT_SUCCESS(Status
))
2745 // release usb device
2747 NewUsbDevice
->Release();
2748 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2755 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2757 // check for success
2759 if (!NT_SUCCESS(Status
))
2762 // release usb device
2764 NewUsbDevice
->Release();
2766 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2773 *NewDevice
= NewUsbDevice
;
2778 return STATUS_SUCCESS
;
2783 USBHI_InitializeUsbDevice(
2785 PUSB_DEVICE_HANDLE DeviceHandle
)
2787 PUSBDEVICE UsbDevice
;
2788 CHubController
* Controller
;
2789 ULONG DeviceAddress
;
2793 DPRINT("USBHI_InitializeUsbDevice\n");
2796 // first get controller
2798 Controller
= (CHubController
*)BusContext
;
2799 PC_ASSERT(Controller
);
2802 // get device object
2804 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2805 PC_ASSERT(UsbDevice
);
2808 // validate device handle
2810 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2812 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2815 // invalid device handle
2817 return STATUS_DEVICE_NOT_CONNECTED
;
2821 // now reserve an address
2823 DeviceAddress
= Controller
->AcquireDeviceAddress();
2826 // is the device address valid
2828 if (DeviceAddress
== MAXULONG
)
2831 // failed to get an device address from the device address pool
2833 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2834 return STATUS_DEVICE_DATA_ERROR
;
2840 // now set the device address
2842 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2844 if (NT_SUCCESS(Status
))
2847 }while(Index
++ < 3 );
2850 // check for failure
2852 if (!NT_SUCCESS(Status
))
2855 // failed to set device address
2857 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2862 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2867 return STATUS_DEVICE_DATA_ERROR
;
2873 return STATUS_SUCCESS
;
2878 USBHI_GetUsbDescriptors(
2880 PUSB_DEVICE_HANDLE DeviceHandle
,
2881 PUCHAR DeviceDescriptorBuffer
,
2882 PULONG DeviceDescriptorBufferLength
,
2883 PUCHAR ConfigDescriptorBuffer
,
2884 PULONG ConfigDescriptorBufferLength
)
2886 PUSBDEVICE UsbDevice
;
2887 CHubController
* Controller
;
2889 DPRINT("USBHI_GetUsbDescriptors\n");
2894 PC_ASSERT(DeviceDescriptorBuffer
);
2895 PC_ASSERT(DeviceDescriptorBufferLength
);
2896 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2897 PC_ASSERT(ConfigDescriptorBufferLength
);
2898 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2901 // first get controller
2903 Controller
= (CHubController
*)BusContext
;
2904 PC_ASSERT(Controller
);
2908 // get device object
2910 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2911 PC_ASSERT(UsbDevice
);
2914 // validate device handle
2916 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2918 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2921 // invalid device handle
2923 return STATUS_DEVICE_NOT_CONNECTED
;
2927 // get device descriptor
2929 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2932 // store result length
2934 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2937 // get configuration descriptor
2939 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2942 // complete the request
2944 return STATUS_SUCCESS
;
2949 USBHI_RemoveUsbDevice(
2951 PUSB_DEVICE_HANDLE DeviceHandle
,
2954 PUSBDEVICE UsbDevice
;
2955 CHubController
* Controller
;
2958 DPRINT("USBHI_RemoveUsbDevice\n");
2961 // first get controller
2963 Controller
= (CHubController
*)BusContext
;
2964 PC_ASSERT(Controller
);
2967 // get device object
2969 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2970 PC_ASSERT(UsbDevice
);
2973 // validate device handle
2975 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2977 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2980 // invalid device handle
2982 return STATUS_DEVICE_NOT_CONNECTED
;
2986 // check if there were flags passed
2988 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2991 // ignore flags for now
2993 return STATUS_SUCCESS
;
2999 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
3000 if (!NT_SUCCESS(Status
))
3003 // invalid device handle
3005 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
3006 return STATUS_DEVICE_NOT_CONNECTED
;
3010 // release usb device
3012 UsbDevice
->Release();
3017 return STATUS_SUCCESS
;
3022 USBHI_RestoreUsbDevice(
3024 PUSB_DEVICE_HANDLE OldDeviceHandle
,
3025 PUSB_DEVICE_HANDLE NewDeviceHandle
)
3027 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
3028 CHubController
* Controller
;
3030 DPRINT("USBHI_RestoreUsbDevice\n");
3033 // first get controller
3035 Controller
= (CHubController
*)BusContext
;
3036 PC_ASSERT(Controller
);
3039 // get device object
3041 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
3042 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
3043 PC_ASSERT(OldUsbDevice
);
3044 PC_ASSERT(NewDeviceHandle
);
3047 // validate device handle
3049 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
3050 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
3052 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
3053 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
3056 // remove old device handle
3058 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
3060 return STATUS_SUCCESS
;
3065 USBHI_QueryDeviceInformation(
3067 PUSB_DEVICE_HANDLE DeviceHandle
,
3068 PVOID DeviceInformationBuffer
,
3069 ULONG DeviceInformationBufferLength
,
3070 PULONG LengthReturned
)
3072 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
3073 PUSBDEVICE UsbDevice
;
3074 CHubController
* Controller
;
3076 DPRINT("USBHI_QueryDeviceInformation %p\n", BusContext
);
3081 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
3082 PC_ASSERT(DeviceInformationBuffer
);
3083 PC_ASSERT(LengthReturned
);
3086 // get controller object
3088 Controller
= (CHubController
*)BusContext
;
3089 PC_ASSERT(Controller
);
3092 // get device object
3094 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3095 PC_ASSERT(UsbDevice
);
3097 if (BusContext
!= DeviceHandle
)
3100 // validate device handle
3102 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3104 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
3107 // invalid device handle
3109 return STATUS_DEVICE_NOT_CONNECTED
;
3113 // access information buffer
3115 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3118 // initialize with default values
3120 DeviceInfo
->InformationLevel
= 0;
3121 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3122 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
3123 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
3124 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
3125 DeviceInfo
->HubAddress
= 0; //FIXME
3126 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
3127 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
3128 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3131 // get device descriptor
3133 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
3136 // FIXME return pipe information
3140 // store result length
3142 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
3144 return STATUS_SUCCESS
;
3148 // access information buffer
3150 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3153 // initialize with default values
3155 DeviceInfo
->InformationLevel
= 0;
3156 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3157 DeviceInfo
->PortNumber
= 0;
3158 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
3159 DeviceInfo
->DeviceAddress
= 0;
3160 DeviceInfo
->HubAddress
= 0; //FIXME
3161 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
3162 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
3163 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3166 // get device descriptor
3168 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
3171 // FIXME return pipe information
3175 // store result length
3178 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
3180 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
3185 return STATUS_SUCCESS
;
3190 USBHI_GetControllerInformation(
3192 PVOID ControllerInformationBuffer
,
3193 ULONG ControllerInformationBufferLength
,
3194 PULONG LengthReturned
)
3196 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
3198 DPRINT("USBHI_GetControllerInformation\n");
3203 PC_ASSERT(ControllerInformationBuffer
);
3204 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
3207 // get controller info buffer
3209 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3212 // FIXME only version 0 is supported for now
3214 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3217 // fill in information
3219 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3220 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3221 ControllerInfo
->IsHighSpeedController
= TRUE
;
3224 // set length returned
3226 *LengthReturned
= ControllerInfo
->ActualLength
;
3231 return STATUS_SUCCESS
;
3236 USBHI_ControllerSelectiveSuspend(
3241 return STATUS_NOT_IMPLEMENTED
;
3246 USBHI_GetExtendedHubInformation(
3248 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3249 PVOID HubInformationBuffer
,
3250 ULONG HubInformationBufferLength
,
3251 PULONG LengthReturned
)
3253 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3254 CHubController
* Controller
;
3255 PUSBHARDWAREDEVICE Hardware
;
3257 ULONG NumPort
, Dummy2
;
3261 DPRINT("USBHI_GetExtendedHubInformation\n");
3266 PC_ASSERT(HubInformationBuffer
);
3267 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3268 PC_ASSERT(LengthReturned
);
3271 // get hub controller
3273 Controller
= (CHubController
*)BusContext
;
3274 PC_ASSERT(Controller
);
3277 // get usb hardware device
3279 Hardware
= Controller
->GetUsbHardware();
3282 // retrieve number of ports
3284 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3285 if (!NT_SUCCESS(Status
))
3288 // failed to get hardware details, ouch ;)
3290 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3295 // get hub information buffer
3297 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3300 // initialize hub information
3302 HubInfo
->InformationLevel
= 0;
3307 HubInfo
->NumberOfPorts
= NumPort
;
3310 // initialize port information
3312 for(Index
= 0; Index
< NumPort
; Index
++)
3314 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3315 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3316 HubInfo
->Port
[Index
].VidOverride
= 0;
3317 HubInfo
->Port
[Index
].PidOverride
= 0;
3318 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3322 // store result length
3325 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3327 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3333 return STATUS_SUCCESS
;
3338 USBHI_GetRootHubSymbolicName(
3340 PVOID HubSymNameBuffer
,
3341 ULONG HubSymNameBufferLength
,
3342 PULONG HubSymNameActualLength
)
3345 return STATUS_NOT_IMPLEMENTED
;
3350 USBHI_GetDeviceBusContext(
3351 PVOID HubBusContext
,
3360 USBHI_Initialize20Hub(
3362 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3365 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3366 return STATUS_SUCCESS
;
3370 WORKER_THREAD_ROUTINE InitRootHub
;
3374 InitRootHub(IN PVOID Context
)
3376 PINIT_ROOT_HUB_CONTEXT WorkItem
;
3381 WorkItem
= (PINIT_ROOT_HUB_CONTEXT
)Context
;
3386 WorkItem
->CallbackRoutine(WorkItem
->CallbackContext
);
3391 ExFreePoolWithTag(Context
, TAG_USBLIB
);
3396 USBHI_RootHubInitNotification(
3398 PVOID CallbackContext
,
3399 PRH_INIT_CALLBACK CallbackRoutine
)
3401 CHubController
* Controller
;
3402 PINIT_ROOT_HUB_CONTEXT WorkItem
;
3404 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3407 // get controller object
3409 Controller
= (CHubController
*)BusContext
;
3410 PC_ASSERT(Controller
);
3413 // set notification routine
3415 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3418 // Create and initialize work item data
3420 WorkItem
= (PINIT_ROOT_HUB_CONTEXT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(INIT_ROOT_HUB_CONTEXT
), TAG_USBLIB
);
3423 DPRINT1("Failed to allocate memory!n");
3424 return STATUS_INSUFFICIENT_RESOURCES
;
3430 WorkItem
->CallbackRoutine
= CallbackRoutine
;
3431 WorkItem
->CallbackContext
= CallbackContext
;
3434 // Queue the work item to handle initializing the device
3436 ExInitializeWorkItem(&WorkItem
->WorkItem
, InitRootHub
, (PVOID
)WorkItem
);
3437 ExQueueWorkItem(&WorkItem
->WorkItem
, DelayedWorkQueue
);
3442 return STATUS_SUCCESS
;
3447 USBHI_FlushTransfers(
3456 USBHI_SetDeviceHandleData(
3459 PDEVICE_OBJECT UsbDevicePdo
)
3461 PUSBDEVICE UsbDevice
;
3462 CHubController
* Controller
;
3467 Controller
= (CHubController
*)BusContext
;
3468 PC_ASSERT(Controller
);
3471 // get device handle
3473 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3476 // validate device handle
3478 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3480 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3490 // usbhub sends this request as a part of the Pnp startup sequence
3491 // looks like we need apply a dragon voodoo to fixup the device stack
3492 // otherwise usbhub will cause a bugcheck
3494 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3499 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3502 // should be usbstor
3503 // fixup device stack voodoo part #2
3505 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3508 // set device handle data
3510 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3514 //=================================================================================================
3516 // USB Device Interface functions
3521 USBDI_GetUSBDIVersion(
3523 PUSBD_VERSION_INFORMATION VersionInformation
,
3524 PULONG HcdCapabilites
)
3526 CHubController
* Controller
;
3527 PUSBHARDWAREDEVICE Device
;
3528 ULONG Speed
, Dummy2
;
3531 DPRINT("USBDI_GetUSBDIVersion\n");
3536 Controller
= (CHubController
*)BusContext
;
3541 Device
= Controller
->GetUsbHardware();
3544 if (VersionInformation
)
3547 // windows xp supported
3549 VersionInformation
->USBDI_Version
= 0x00000500;
3554 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3557 // store speed details
3559 VersionInformation
->Supported_USB_Version
= Speed
;
3563 // no flags supported
3565 *HcdCapabilites
= 0;
3572 PULONG CurrentFrame
)
3575 return STATUS_NOT_IMPLEMENTED
;
3580 USBDI_SubmitIsoOutUrb(
3585 return STATUS_NOT_IMPLEMENTED
;
3590 USBDI_QueryBusInformation(
3593 PVOID BusInformationBuffer
,
3594 PULONG BusInformationBufferLength
,
3595 PULONG BusInformationActualLength
)
3598 return STATUS_NOT_IMPLEMENTED
;
3603 USBDI_IsDeviceHighSpeed(
3606 CHubController
* Controller
;
3607 PUSBHARDWAREDEVICE Device
;
3608 ULONG Speed
, Dummy2
;
3611 DPRINT("USBDI_IsDeviceHighSpeed\n");
3616 Controller
= (CHubController
*)BusContext
;
3621 Device
= Controller
->GetUsbHardware();
3627 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3630 // USB 2.0 equals 0x200
3632 return (Speed
== 0x200);
3645 return STATUS_NOT_IMPLEMENTED
;
3649 CHubController::HandleQueryInterface(
3650 PIO_STACK_LOCATION IoStack
)
3652 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3653 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3654 UNICODE_STRING GuidBuffer
;
3657 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3660 // get request parameters
3662 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3663 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3668 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3670 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3673 // version not supported
3675 return STATUS_NOT_SUPPORTED
;
3679 // Interface version 0
3681 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3683 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3684 InterfaceHub
->BusContext
= PVOID(this);
3685 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3686 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3690 // Interface version 1
3692 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3694 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3695 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3696 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3697 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3698 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3699 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3703 // Interface version 2
3705 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3707 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3708 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3709 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3710 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3711 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3712 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3717 // Interface version 3
3719 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3721 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3725 // Interface version 4
3727 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3729 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3733 // Interface version 5
3735 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3737 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3741 // request completed
3743 return STATUS_SUCCESS
;
3745 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3748 // get request parameters
3750 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3751 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3756 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3758 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3761 // version not supported
3763 return STATUS_NOT_SUPPORTED
;
3767 // interface version 0
3769 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3771 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3772 InterfaceDI
->BusContext
= PVOID(this);
3773 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3774 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3775 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3776 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3777 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3778 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3782 // interface version 1
3784 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3786 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3790 // interface version 2
3792 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3794 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3798 // request completed
3800 return STATUS_SUCCESS
;
3805 // convert guid to string
3807 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3808 if (NT_SUCCESS(Status
))
3813 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3818 RtlFreeUnicodeString(&GuidBuffer
);
3821 return STATUS_NOT_SUPPORTED
;
3825 CHubController::SetDeviceInterface(
3828 NTSTATUS Status
= STATUS_SUCCESS
;
3833 // register device interface
3835 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3837 if (NT_SUCCESS(Status
))
3840 // now enable the device interface
3842 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3847 m_InterfaceEnabled
= TRUE
;
3850 else if (m_InterfaceEnabled
)
3853 // disable device interface
3855 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3857 if (NT_SUCCESS(Status
))
3860 // now delete interface string
3862 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3866 // disable interface
3868 m_InterfaceEnabled
= FALSE
;
3874 return STATUS_SUCCESS
;
3878 CHubController::CreatePDO(
3879 PDRIVER_OBJECT DriverObject
,
3880 PDEVICE_OBJECT
* OutDeviceObject
)
3882 WCHAR CharDeviceName
[64];
3884 ULONG UsbDeviceNumber
= 0;
3885 UNICODE_STRING DeviceName
;
3890 // construct device name
3892 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3895 // initialize device name
3897 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3902 Status
= IoCreateDevice(DriverObject
,
3903 sizeof(COMMON_DEVICE_EXTENSION
),
3905 FILE_DEVICE_CONTROLLER
,
3910 /* check for success */
3911 if (NT_SUCCESS(Status
))
3915 // is there a device object with that same name
3917 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3920 // Try the next name
3927 // bail out on other errors
3929 if (!NT_SUCCESS(Status
))
3931 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3936 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3939 // fixup device stack voodoo part #1
3941 (*OutDeviceObject
)->StackSize
++;
3951 CreateHubController(
3952 PHUBCONTROLLER
*OutHcdController
)
3954 PHUBCONTROLLER This
;
3957 // allocate controller
3959 This
= new(NonPagedPool
, TAG_USBLIB
) CHubController(0);
3963 // failed to allocate
3965 return STATUS_INSUFFICIENT_RESOURCES
;
3969 // add reference count
3976 *OutHcdController
= (PHUBCONTROLLER
)This
;
3981 return STATUS_SUCCESS
;
3984 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3986 CHubController
* This
;
3988 This
= (CHubController
*)Context
;
3992 Irp
= This
->m_PendingSCEIrp
;
3995 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3999 This
->m_PendingSCEIrp
= NULL
;
4000 This
->QueryStatusChageEndpoint(Irp
);
4002 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
4003 Irp
->IoStatus
.Information
= 0;
4005 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);