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
HandleVendorDevice(IN OUT PIRP Irp
, PURB Urb
);
73 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
74 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
75 NTSTATUS
HandleClearStall(IN OUT PIRP Irp
, PURB Urb
);
76 NTSTATUS
HandleSyncResetAndClearStall(IN OUT PIRP Irp
, PURB Urb
);
77 NTSTATUS
HandleAbortPipe(IN OUT PIRP Irp
, PURB Urb
);
79 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
81 // constructor / destructor
82 CHubController(IUnknown
*OuterUnknown
){}
83 virtual ~CHubController(){}
87 PHCDCONTROLLER m_Controller
;
88 PUSBHARDWAREDEVICE m_Hardware
;
89 BOOLEAN m_IsRootHubDevice
;
90 ULONG m_DeviceAddress
;
92 BOOLEAN m_InterfaceEnabled
;
93 UNICODE_STRING m_HubDeviceInterfaceString
;
95 PDEVICE_OBJECT m_HubControllerDeviceObject
;
96 PDRIVER_OBJECT m_DriverObject
;
98 PVOID m_HubCallbackContext
;
99 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
101 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
104 RTL_BITMAP m_DeviceAddressBitmap
;
105 PULONG m_DeviceAddressBitmapBuffer
;
106 LIST_ENTRY m_UsbDeviceList
;
107 PIRP m_PendingSCEIrp
;
112 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
119 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
121 /* Lifted from Linux with slight changes */
122 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
125 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
126 0x00, 0x20, /* bcdUSB; v1.1 */
127 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
128 0x01, /* bDeviceSubClass; */
129 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
130 0x08, /* bMaxPacketSize0; 8 Bytes */
131 /* Fill Vendor and Product in when init root hub */
132 0x00, 0x00, /* idVendor; */
133 0x00, 0x00, /* idProduct; */
134 0x00, 0x00, /* bcdDevice */
135 0x00, /* iManufacturer; */
136 0x00, /* iProduct; */
137 0x00, /* iSerialNumber; */
138 0x01 /* bNumConfigurations; */
142 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
144 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
145 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
146 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
150 0x40, /* self powered */
154 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
156 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
157 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
158 0, /* bInterfaceNumber; */
159 0, /* bAlternateSetting; */
160 0x1, /* bNumEndpoints; */
161 0x09, /* bInterfaceClass; HUB_CLASSCODE */
162 0x01, /* bInterfaceSubClass; */
163 0x00, /* bInterfaceProtocol: */
164 0x00, /* iInterface; */
167 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
169 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
170 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
171 0x81, /* bEndPointAddress */
172 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
173 0x01, /* wMaxPacketSize */
177 //----------------------------------------------------------------------------------------
180 CHubController::QueryInterface(
184 return STATUS_UNSUCCESSFUL
;
186 //----------------------------------------------------------------------------------------
188 CHubController::Initialize(
189 IN PDRIVER_OBJECT DriverObject
,
190 IN PHCDCONTROLLER Controller
,
191 IN PUSBHARDWAREDEVICE Device
,
192 IN BOOLEAN IsRootHubDevice
,
193 IN ULONG DeviceAddress
)
196 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
197 USHORT VendorID
, DeviceID
;
201 // initialize members
203 m_Controller
= Controller
;
205 m_IsRootHubDevice
= IsRootHubDevice
;
206 m_DeviceAddress
= DeviceAddress
;
207 m_DriverObject
= DriverObject
;
208 m_USBType
= m_Hardware
->GetUSBType();
209 KeInitializeSpinLock(&m_Lock
);
210 InitializeListHead(&m_UsbDeviceList
);
213 // allocate device address bitmap buffer
215 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBLIB
);
216 if (!m_DeviceAddressBitmapBuffer
)
221 return STATUS_INSUFFICIENT_RESOURCES
;
225 // initialize device address bitmap
227 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
228 RtlClearAllBits(&m_DeviceAddressBitmap
);
233 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
234 if (!NT_SUCCESS(Status
))
237 // failed to create hub device object
243 // get device extension
245 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
248 // initialize device extension
250 DeviceExtension
->IsFDO
= FALSE
;
251 DeviceExtension
->IsHub
= TRUE
; //FIXME
252 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
255 // intialize device descriptor
257 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
258 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
260 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
263 // update device descriptor
265 m_DeviceDescriptor
.idVendor
= VendorID
;
266 m_DeviceDescriptor
.idProduct
= DeviceID
;
267 m_DeviceDescriptor
.bcdUSB
= 0x200; //FIXME
271 // Set the SCE Callback that the Hardware Device will call on port status change
273 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
278 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
280 return STATUS_SUCCESS
;
284 // Queries the ports to see if there has been a device connected or removed.
287 CHubController::QueryStatusChageEndpoint(
290 ULONG PortCount
, PortId
;
291 PIO_STACK_LOCATION IoStack
;
292 USHORT PortStatus
, PortChange
;
294 PUCHAR TransferBuffer
;
295 UCHAR Changed
= FALSE
;
298 // get current stack location
300 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
306 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
310 // Get the number of ports and check each one for device connected
312 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
313 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
);
315 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
320 for (PortId
= 0; PortId
< PortCount
; PortId
++)
322 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
324 DPRINT1("[%s] Port %d: Status %x, Change %x\n", m_USBType
, PortId
, PortStatus
, PortChange
);
328 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
332 DPRINT1("[%s] Change state on port %d\n", m_USBType
, PortId
);
333 // Set the value for the port number
334 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
342 //-----------------------------------------------------------------------------------------
344 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
347 // store controller object
349 *HubDeviceObject
= m_HubControllerDeviceObject
;
351 return STATUS_SUCCESS
;
353 //-----------------------------------------------------------------------------------------
355 CHubController::GetHubControllerSymbolicLink(
358 PULONG RequiredLength
)
360 if (!m_InterfaceEnabled
)
363 // device interface not yet enabled
365 return STATUS_UNSUCCESSFUL
;
368 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
372 // length is without '\??\'
374 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
379 return STATUS_BUFFER_OVERFLOW
;
383 // copy symbolic link
385 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
388 // store length, length is without '\??\'
390 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
395 return STATUS_SUCCESS
;
398 //-----------------------------------------------------------------------------------------
400 CHubController::HandlePnp(
401 IN PDEVICE_OBJECT DeviceObject
,
404 PIO_STACK_LOCATION IoStack
;
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 current stack location
418 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
420 switch(IoStack
->MinorFunction
)
422 case IRP_MN_START_DEVICE
:
424 DPRINT("[%s] HandlePnp IRP_MN_START_DEVICE\n", m_USBType
);
426 // register device interface
428 Status
= SetDeviceInterface(TRUE
);
431 case IRP_MN_QUERY_STOP_DEVICE
:
432 case IRP_MN_QUERY_REMOVE_DEVICE
:
437 Status
= STATUS_SUCCESS
;
440 case IRP_MN_QUERY_ID
:
442 DPRINT("[%s] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType
, IoStack
->Parameters
.QueryId
.IdType
);
444 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
451 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
453 if (HiSpeed
== 0x200)
458 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
465 swprintf(Buffer
, L
"USB\\ROOT_HUB");
471 Length
= (wcslen(Buffer
) + 1);
476 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBLIB
);
483 Status
= STATUS_INSUFFICIENT_RESOURCES
;
490 wcscpy(DeviceName
, Buffer
);
495 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
496 Status
= STATUS_SUCCESS
;
499 Status
= STATUS_UNSUCCESSFUL
;
504 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
511 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
513 if (!NT_SUCCESS(Status
))
515 DPRINT1("[%s] HandlePnp> failed to get hardware id %x\n", m_USBType
, Status
);
520 if (HiSpeed
== 0x200)
525 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
526 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
527 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
534 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
535 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
536 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
539 Buffer
[Index
] = UNICODE_NULL
;
545 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBLIB
);
552 Status
= STATUS_INSUFFICIENT_RESOURCES
;
559 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
564 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
565 Status
= STATUS_SUCCESS
;
569 Status
= STATUS_SUCCESS
;
572 case IRP_MN_QUERY_CAPABILITIES
:
574 DPRINT("[%s] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType
);
576 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
578 DeviceCapabilities
->LockSupported
= FALSE
;
579 DeviceCapabilities
->EjectSupported
= FALSE
;
580 DeviceCapabilities
->Removable
= FALSE
;
581 DeviceCapabilities
->DockDevice
= FALSE
;
582 DeviceCapabilities
->UniqueID
= FALSE
;
583 DeviceCapabilities
->SilentInstall
= FALSE
;
584 DeviceCapabilities
->RawDeviceOK
= FALSE
;
585 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
586 DeviceCapabilities
->Address
= 0;
587 DeviceCapabilities
->UINumber
= 0;
588 DeviceCapabilities
->DeviceD2
= 1;
591 DeviceCapabilities
->HardwareDisabled
= FALSE
;
592 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
593 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
594 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
595 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
596 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
597 DeviceCapabilities
->D1Latency
= 0;
598 DeviceCapabilities
->D2Latency
= 0;
599 DeviceCapabilities
->D3Latency
= 0;
601 Status
= STATUS_SUCCESS
;
604 case IRP_MN_QUERY_INTERFACE
:
606 DPRINT("[%s] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType
);
609 // handle device interface requests
611 Status
= HandleQueryInterface(IoStack
);
614 case IRP_MN_REMOVE_DEVICE
:
616 DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType
);
619 // deactivate device interface for BUS PDO
621 SetDeviceInterface(FALSE
);
624 // complete the request first
626 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
627 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
632 IoDeleteDevice(m_HubControllerDeviceObject
);
637 m_HubControllerDeviceObject
= 0;
642 return STATUS_SUCCESS
;
644 case IRP_MN_QUERY_DEVICE_RELATIONS
:
646 DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
648 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
651 // allocate device relations
653 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBLIB
);
654 if (!DeviceRelations
)
659 Status
= STATUS_INSUFFICIENT_RESOURCES
;
664 // initialize device relations
666 DeviceRelations
->Count
= 1;
667 DeviceRelations
->Objects
[0] = DeviceObject
;
668 ObReferenceObject(DeviceObject
);
673 Status
= STATUS_SUCCESS
;
674 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
681 Status
= Irp
->IoStatus
.Status
;
685 case IRP_MN_QUERY_BUS_INFORMATION
:
687 DPRINT("[%s] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType
);
690 // allocate buffer for bus information
692 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
698 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
703 BusInformation
->LegacyBusType
= PNPBus
;
704 BusInformation
->BusNumber
= 0;
706 Status
= STATUS_SUCCESS
;
707 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
714 Status
= STATUS_INSUFFICIENT_RESOURCES
;
718 case IRP_MN_STOP_DEVICE
:
720 DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType
);
724 Status
= STATUS_SUCCESS
;
727 case IRP_MN_SURPRISE_REMOVAL
:
729 DPRINT("[%s] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType
);
730 Status
= STATUS_SUCCESS
;
736 // ignore request with default status
738 Status
= Irp
->IoStatus
.Status
;
746 Irp
->IoStatus
.Status
= Status
;
747 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
755 //-----------------------------------------------------------------------------------------
757 CHubController::HandlePower(
758 IN PDEVICE_OBJECT DeviceObject
,
762 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
764 return STATUS_NOT_IMPLEMENTED
;
767 //-----------------------------------------------------------------------------------------
769 CHubController::HandleIsochronousTransfer(
773 PUSBDEVICE UsbDevice
;
774 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
777 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
779 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
783 DPRINT1("[%s] Error No EndpointDesc\n", m_USBType
);
784 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
785 return STATUS_INVALID_PARAMETER
;
791 ASSERT(EndPointDesc
);
792 DPRINT("[%s] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType
, EndPointDesc
, EndPointDesc
->bEndpointAddress
, EndPointDesc
->bmAttributes
);
793 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
796 // check if this is a valid usb device handle
798 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
800 DPRINT1("[%s] HandleIsochronousTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
803 // invalid device handle
805 return STATUS_DEVICE_NOT_CONNECTED
;
811 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
813 return UsbDevice
->SubmitIrp(Irp
);
816 //-----------------------------------------------------------------------------------------
818 CHubController::HandleBulkOrInterruptTransfer(
822 PUSBDEVICE UsbDevice
;
823 PUSB_ENDPOINT EndPointDesc
= NULL
;
825 // First check if the request is for the Status Change Endpoint
829 // Is the Request for the root hub
831 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
833 ASSERT(m_PendingSCEIrp
== NULL
);
834 if (QueryStatusChageEndpoint(Irp
))
836 StatusChangeEndpointCallBack(this);
837 return STATUS_SUCCESS
;
841 // Else pend the IRP, to be completed when a device connects or disconnects.
843 DPRINT("[%s] Pending SCE Irp\n", m_USBType
);
844 m_PendingSCEIrp
= Irp
;
845 IoMarkIrpPending(Irp
);
846 return STATUS_PENDING
;
850 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
852 EndPointDesc
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
857 ASSERT(EndPointDesc
);
858 ASSERT((EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
861 // check if this is a valid usb device handle
863 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
865 DPRINT1("[%s] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
868 // invalid device handle
870 return STATUS_DEVICE_NOT_CONNECTED
;
876 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
877 return UsbDevice
->SubmitIrp(Irp
);
880 //-----------------------------------------------------------------------------------------
882 CHubController::HandleClassOther(
886 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
887 USHORT PortStatus
= 0, PortChange
= 0;
892 DPRINT("[%s] HandleClassOther> Request %x Value %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
895 // get number of ports available
897 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
898 PC_ASSERT(Status
== STATUS_SUCCESS
);
903 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
906 // port range reported start from 1 -n
907 // convert back port id so it matches the hardware
909 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
912 // check request code
914 switch(Urb
->UrbControlVendorClassRequest
.Request
)
916 case USB_REQUEST_GET_STATUS
:
921 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
922 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
927 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
929 if (NT_SUCCESS(Status
))
932 // request contains buffer of 2 ushort which are used from submitting port status and port change status
934 DPRINT("[%s] PortId %x PortStatus %x PortChange %x\n", m_USBType
, PortId
, PortStatus
, PortChange
);
935 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
938 // store status, then port change
940 *Buffer
= PortStatus
;
942 *Buffer
= PortChange
;
950 case USB_REQUEST_CLEAR_FEATURE
:
952 switch (Urb
->UrbControlVendorClassRequest
.Value
)
954 case C_PORT_CONNECTION
:
955 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
958 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
961 DPRINT("[%s] Unknown Value for Clear Feature %x \n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
967 case USB_REQUEST_SET_FEATURE
:
970 // request set feature
972 switch(Urb
->UrbControlVendorClassRequest
.Value
)
977 // port enable is a no-op for EHCI
979 Status
= STATUS_SUCCESS
;
986 // set suspend port feature
988 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
994 // set power feature on port
996 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1003 // reset port feature
1005 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1006 PC_ASSERT(Status
== STATUS_SUCCESS
);
1010 DPRINT1("[%s] Unsupported request id %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
1016 DPRINT1("[%s] HandleClassOther Unknown request code %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
);
1018 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1023 //-----------------------------------------------------------------------------------------
1025 CHubController::HandleSelectConfiguration(
1029 PUSBDEVICE UsbDevice
;
1030 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1034 // is the request for the Root Hub
1036 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1039 // FIXME: support setting device to unconfigured state
1041 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1044 // set device handle
1046 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1049 // copy interface info
1051 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1053 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1054 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1055 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1056 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1057 InterfaceInfo
->Reserved
= 0;
1062 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1067 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1068 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1069 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1070 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1071 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1073 return STATUS_SUCCESS
;
1078 // check if this is a valid usb device handle
1080 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1082 DPRINT1("[%s] HandleSelectConfiguration invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1085 // invalid device handle
1087 return STATUS_DEVICE_NOT_CONNECTED
;
1093 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1096 // select configuration
1098 Status
= UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1099 if (NT_SUCCESS(Status
))
1101 // successfully configured device
1102 Urb
->UrbSelectConfiguration
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1108 //-----------------------------------------------------------------------------------------
1110 CHubController::HandleSelectInterface(
1114 PUSBDEVICE UsbDevice
;
1119 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1122 // is the request for the Root Hub
1124 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1127 // no op for root hub
1129 return STATUS_SUCCESS
;
1134 // check if this is a valid usb device handle
1136 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1138 DPRINT1("[%s] HandleSelectInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1141 // invalid device handle
1143 return STATUS_DEVICE_NOT_CONNECTED
;
1149 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1154 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1158 //-----------------------------------------------------------------------------------------
1160 CHubController::HandleGetStatusFromDevice(
1164 PUSHORT DeviceStatus
;
1165 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1167 PUSBDEVICE UsbDevice
;
1172 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1173 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1176 // get status buffer
1178 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1181 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1184 // FIXME need more flags ?
1186 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1187 return STATUS_SUCCESS
;
1191 // check if this is a valid usb device handle
1193 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1195 DPRINT1("[%s] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1198 // invalid device handle
1200 return STATUS_DEVICE_NOT_CONNECTED
;
1206 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1210 // generate setup packet
1212 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1213 CtrlSetup
.wValue
.LowByte
= 0;
1214 CtrlSetup
.wValue
.HiByte
= 0;
1215 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1216 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1217 CtrlSetup
.bmRequestType
.B
= 0x80;
1219 if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_INTERFACE
)
1222 // add interface type
1224 CtrlSetup
.bmRequestType
.B
|= 0x01;
1226 else if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
)
1229 // add interface type
1231 CtrlSetup
.bmRequestType
.B
|= 0x02;
1235 // submit setup packet
1237 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1238 ASSERT(Status
== STATUS_SUCCESS
);
1239 DPRINT1("[%s] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType
, Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1247 //-----------------------------------------------------------------------------------------
1249 CHubController::HandleClassDevice(
1253 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1254 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1255 ULONG PortCount
, Dummy2
;
1257 PUSBDEVICE UsbDevice
;
1258 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1260 DPRINT("[%s] HandleClassDevice Request %x Class %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1263 // check class request type
1265 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1267 case USB_REQUEST_GET_STATUS
:
1270 // check if this is a valid usb device handle
1272 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1274 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1277 // invalid device handle
1279 return STATUS_DEVICE_NOT_CONNECTED
;
1285 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1289 // generate setup packet
1291 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1292 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1293 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1294 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1295 CtrlSetup
.bmRequestType
.B
= 0xA0;
1298 // submit setup packet
1300 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1301 ASSERT(Status
== STATUS_SUCCESS
);
1304 case USB_REQUEST_GET_DESCRIPTOR
:
1306 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1308 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1309 case USB_DEVICE_CLASS_HUB
:
1311 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1316 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1317 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1320 // get hub descriptor
1322 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1325 // one hub is handled
1327 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1328 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1331 // type should 0x29 according to msdn
1333 UsbHubDescriptor
->bDescriptorType
= 0x29;
1338 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1339 PC_ASSERT(Status
== STATUS_SUCCESS
);
1342 // FIXME: retrieve values
1344 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1345 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1346 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1347 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1352 Status
= STATUS_SUCCESS
;
1356 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1358 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1360 // invalid device handle
1362 return STATUS_DEVICE_NOT_CONNECTED
;
1366 // FIXME: implement support for real hubs
1369 Status
= STATUS_NOT_IMPLEMENTED
;
1374 DPRINT1("[%s] HandleClassDevice Class %x not implemented\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1382 // check if this is a valid usb device handle
1384 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1386 DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1389 // invalid device handle
1391 return STATUS_DEVICE_NOT_CONNECTED
;
1397 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1400 // generate setup packet
1402 CtrlSetup
.bmRequestType
.B
= 0;
1403 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1404 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_CLASS
;
1405 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1406 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1407 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1408 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1410 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1413 // data direction is device to host
1415 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1419 // submit setup packet
1421 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1422 ASSERT(Status
== STATUS_SUCCESS
);
1431 //-----------------------------------------------------------------------------------------
1433 CHubController::HandleGetDescriptorFromInterface(
1437 PUSBDEVICE UsbDevice
;
1438 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1444 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1445 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1448 // check if this is a valid usb device handle
1450 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1452 DPRINT1("[%s] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1455 // invalid device handle
1457 return STATUS_DEVICE_NOT_CONNECTED
;
1463 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1466 // generate setup packet
1468 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1469 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1470 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1471 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1472 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1473 CtrlSetup
.bmRequestType
.B
= 0x81;
1476 // submit setup packet
1478 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1479 if (!NT_SUCCESS(Status
))
1481 DPRINT1("[%s] HandleGetDescriptorFromInterface failed with %x\n", m_USBType
, Status
);
1490 //-----------------------------------------------------------------------------------------
1492 CHubController::HandleGetDescriptor(
1496 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1497 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1499 PUSBDEVICE UsbDevice
;
1500 ULONG Length
, BufferLength
;
1502 DPRINT("[%s] HandleGetDescriptor Type %x\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1505 // check descriptor type
1507 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1509 case USB_DEVICE_DESCRIPTOR_TYPE
:
1514 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1515 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1517 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1520 // copy root hub device descriptor
1522 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1523 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1524 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1525 Status
= STATUS_SUCCESS
;
1530 // check if this is a valid usb device handle
1532 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1534 DPRINT1("[%s] HandleGetDescriptor invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1537 // invalid device handle
1539 return STATUS_DEVICE_NOT_CONNECTED
;
1545 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1548 // retrieve device descriptor from device
1550 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1551 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1552 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1553 Status
= STATUS_SUCCESS
;
1557 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1562 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1565 // The caller must allocate a buffer large enough to hold all of this information or the data is truncated without error.
1567 BufferLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1568 Buffer
= (PUCHAR
) Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1570 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this) || Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1573 // request is for the root bus controller
1575 Length
= BufferLength
> sizeof(USB_CONFIGURATION_DESCRIPTOR
) ?
1576 sizeof(USB_CONFIGURATION_DESCRIPTOR
) : BufferLength
;
1577 RtlCopyMemory(Buffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, Length
);
1580 // Check if we still have some space left
1582 if(Length
== BufferLength
)
1585 // We copied all we could
1587 Status
= STATUS_SUCCESS
;
1594 BufferLength
-= Length
;
1597 // copy interface descriptor template
1599 Length
= BufferLength
> sizeof(USB_INTERFACE_DESCRIPTOR
) ?
1600 sizeof(USB_INTERFACE_DESCRIPTOR
) : BufferLength
;
1601 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, Length
);
1604 // Check if we still have some space left
1606 if(Length
== BufferLength
)
1609 // We copied all we could
1611 Status
= STATUS_SUCCESS
;
1618 BufferLength
-= Length
;
1622 // copy end point descriptor template
1624 Length
= BufferLength
> sizeof(USB_ENDPOINT_DESCRIPTOR
) ?
1625 sizeof(USB_ENDPOINT_DESCRIPTOR
) : BufferLength
;
1626 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, Length
);
1631 Status
= STATUS_SUCCESS
;
1637 // check if this is a valid usb device handle
1639 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1641 DPRINT1("[%s] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1644 // invalid device handle
1646 return STATUS_DEVICE_NOT_CONNECTED
;
1652 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1655 // Allocate temporary buffer
1657 BufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1658 Buffer
= (PUCHAR
)ExAllocatePoolWithTag(NonPagedPool
, BufferLength
, TAG_USBLIB
);
1661 Status
= STATUS_NO_MEMORY
;
1666 // perform work in IUSBDevice
1668 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
, BufferLength
, &Length
);
1673 Length
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
> Length
?
1674 Length
: Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1675 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Buffer
, Length
);
1678 // Free temporary buffer
1680 ExFreePoolWithTag(Buffer
, TAG_USBLIB
);
1683 // store result size
1685 Irp
->IoStatus
.Information
= Length
;
1686 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1687 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1688 Status
= STATUS_SUCCESS
;
1692 case USB_STRING_DESCRIPTOR_TYPE
:
1697 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1698 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1702 // check if this is a valid usb device handle
1704 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1706 DPRINT1("[%s] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1709 // invalid device handle
1711 return STATUS_DEVICE_NOT_CONNECTED
;
1717 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1720 // generate setup packet
1722 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1723 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1724 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1725 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1726 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1727 CtrlSetup
.bmRequestType
.B
= 0x80;
1730 // submit setup packet
1732 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1736 DPRINT1("[%s] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1746 //-----------------------------------------------------------------------------------------
1748 CHubController::HandleClassEndpoint(
1752 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1754 PUSBDEVICE UsbDevice
;
1759 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1760 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1761 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1764 // check if this is a valid usb device handle
1766 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1768 DPRINT1("[%s] HandleClassEndpoint invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1771 // invalid device handle
1773 return STATUS_DEVICE_NOT_CONNECTED
;
1779 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1782 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1783 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1784 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1785 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1786 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1787 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1788 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1789 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1790 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1793 // initialize setup packet
1795 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1796 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1797 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1798 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1799 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1801 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1804 // data direction is device to host
1806 CtrlSetup
.bmRequestType
.B
|= 0x80;
1813 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1816 // assert on failure
1818 PC_ASSERT(NT_SUCCESS(Status
));
1827 //-----------------------------------------------------------------------------------------
1829 CHubController::HandleVendorDevice(
1833 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1834 PUSBDEVICE UsbDevice
;
1835 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1837 //DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1842 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1845 // check if this is a valid usb device handle
1847 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1849 DPRINT1("[%s] HandleVendorDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1852 // invalid device handle
1854 return STATUS_DEVICE_NOT_CONNECTED
;
1860 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1863 // initialize setup packet
1865 CtrlSetup
.bmRequestType
.B
= 0;
1866 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1867 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_VENDOR
;
1868 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1869 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1870 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1871 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1873 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1876 // data direction is device to host
1878 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1884 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1885 if (NT_SUCCESS(Status
))
1888 Urb
->UrbControlVendorClassRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1889 Irp
->IoStatus
.Information
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1895 //-----------------------------------------------------------------------------------------
1897 CHubController::HandleSyncResetAndClearStall(
1901 NTSTATUS Status
= STATUS_SUCCESS
;
1902 PUSB_ENDPOINT EndpointDescriptor
;
1908 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1909 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1910 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1913 // check if this is a valid usb device handle
1915 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1917 DPRINT1("[%s] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1920 // invalid device handle
1922 return STATUS_DEVICE_NOT_CONNECTED
;
1928 Status
= HandleAbortPipe(Irp
, Urb
);
1929 if (!NT_SUCCESS(Status
))
1934 DPRINT1("[%s] failed to reset pipe %x\n", m_USBType
, Status
);
1939 // get endpoint descriptor
1941 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1946 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1947 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1952 Status
= HandleClearStall(Irp
, Urb
);
1954 DPRINT1("[%s] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType
, Status
);
1957 // reset data toggle
1959 if (NT_SUCCESS(Status
))
1960 EndpointDescriptor
->DataToggle
= 0x0;
1968 //-----------------------------------------------------------------------------------------
1970 CHubController::HandleAbortPipe(
1975 PUSBDEVICE UsbDevice
;
1976 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1981 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1982 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1983 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1986 // check if this is a valid usb device handle
1988 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1990 DPRINT1("[%s] HandleAbortPipe invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1993 // invalid device handle
1995 return STATUS_DEVICE_NOT_CONNECTED
;
1999 // get endpoint descriptor
2001 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2006 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2012 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
2013 DPRINT1("[%s] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType
, Status
);
2022 //-----------------------------------------------------------------------------------------
2024 CHubController::HandleClearStall(
2028 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2030 PUSBDEVICE UsbDevice
;
2031 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
2037 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2038 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
2039 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
2042 // check if this is a valid usb device handle
2044 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2046 DPRINT1("[%s] HandleClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2049 // invalid device handle
2051 return STATUS_DEVICE_NOT_CONNECTED
;
2055 // get endpoint descriptor
2057 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2062 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2063 DPRINT1("[%s] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType
);
2066 // initialize setup packet
2068 CtrlSetup
.bmRequestType
.B
= 0x02;
2069 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
2070 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
2071 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
2072 CtrlSetup
.wLength
= 0;
2073 CtrlSetup
.wValue
.W
= 0;
2078 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
2080 DPRINT1("[%s] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType
, Status
);
2089 //-----------------------------------------------------------------------------------------
2091 CHubController::HandleClassInterface(
2095 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2097 PUSBDEVICE UsbDevice
;
2102 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2103 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2104 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2107 // check if this is a valid usb device handle
2109 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2111 DPRINT1("[%s] HandleClassInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2114 // invalid device handle
2116 return STATUS_DEVICE_NOT_CONNECTED
;
2122 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2125 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
2126 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
2127 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
2128 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2129 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
2130 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
2131 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
2132 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
2133 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
2136 // initialize setup packet
2138 CtrlSetup
.bmRequestType
.B
= 0x21;
2139 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
2140 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
2141 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
2142 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
2144 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2147 // data direction is device to host
2149 CtrlSetup
.bmRequestType
.B
|= 0x80;
2155 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2158 // assert on failure
2160 if (!NT_SUCCESS(Status
))
2165 DPRINT1("[%s] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType
, Urb
->UrbHeader
.Status
);
2174 //-----------------------------------------------------------------------------------------
2176 CHubController::HandleDeviceControl(
2177 IN PDEVICE_OBJECT DeviceObject
,
2180 PIO_STACK_LOCATION IoStack
;
2182 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2185 // get current stack location
2187 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2190 // determine which request should be performed
2192 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2194 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2199 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2202 switch (Urb
->UrbHeader
.Function
)
2204 case URB_FUNCTION_SYNC_RESET_PIPE
:
2205 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2206 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2208 case URB_FUNCTION_ABORT_PIPE
:
2209 Status
= HandleAbortPipe(Irp
, Urb
);
2211 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2212 Status
= HandleClearStall(Irp
, Urb
);
2214 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2215 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2217 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2218 Status
= HandleGetDescriptor(Irp
, Urb
);
2220 case URB_FUNCTION_CLASS_DEVICE
:
2221 Status
= HandleClassDevice(Irp
, Urb
);
2223 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2224 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
2225 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
2226 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2228 case URB_FUNCTION_SELECT_CONFIGURATION
:
2229 Status
= HandleSelectConfiguration(Irp
, Urb
);
2231 case URB_FUNCTION_SELECT_INTERFACE
:
2232 Status
= HandleSelectInterface(Irp
, Urb
);
2234 case URB_FUNCTION_CLASS_OTHER
:
2235 Status
= HandleClassOther(Irp
, Urb
);
2237 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2238 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2240 case URB_FUNCTION_ISOCH_TRANSFER
:
2241 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2243 case URB_FUNCTION_CLASS_INTERFACE
:
2244 Status
= HandleClassInterface(Irp
, Urb
);
2246 case URB_FUNCTION_CLASS_ENDPOINT
:
2247 Status
= HandleClassEndpoint(Irp
, Urb
);
2249 case URB_FUNCTION_VENDOR_DEVICE
:
2250 Status
= HandleVendorDevice(Irp
, Urb
);
2253 DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType
, Urb
->UrbHeader
.Function
);
2257 // request completed
2261 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2263 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType
, this);
2265 if (IoStack
->Parameters
.Others
.Argument1
)
2268 // store object as device handle
2270 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2271 Status
= STATUS_SUCCESS
;
2276 // mis-behaving hub driver
2278 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2282 // request completed
2286 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2288 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType
);
2291 // this is the first request send, it delivers the PDO to the caller
2293 if (IoStack
->Parameters
.Others
.Argument1
)
2296 // store root hub pdo object
2298 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2301 if (IoStack
->Parameters
.Others
.Argument2
)
2304 // documentation claims to deliver the hcd controller object, although it is wrong
2306 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2310 // request completed
2312 Status
= STATUS_SUCCESS
;
2315 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2317 DPRINT("[%s] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType
);
2320 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2321 // requests this ioctl to deliver the number of presents.
2323 if (IoStack
->Parameters
.Others
.Argument1
)
2326 // FIXME / verify: there is only one hub
2328 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2332 // request completed
2334 Status
= STATUS_SUCCESS
;
2335 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2338 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2340 DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType
);
2341 Status
= STATUS_SUCCESS
;
2346 DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType
,
2347 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2348 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2349 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2353 if (Status
!= STATUS_PENDING
)
2355 Irp
->IoStatus
.Status
= Status
;
2356 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2362 //-----------------------------------------------------------------------------------------
2364 CHubController::GetUsbHardware()
2369 //-----------------------------------------------------------------------------------------
2371 CHubController::AcquireDeviceAddress()
2374 ULONG DeviceAddress
;
2377 // acquire device lock
2379 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2384 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2385 if (DeviceAddress
!= MAXULONG
)
2390 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2393 // device addresses start from 0x1 - 0xFF
2399 // release spin lock
2401 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2404 // return device address
2406 return DeviceAddress
;
2408 //-----------------------------------------------------------------------------------------
2410 CHubController::ReleaseDeviceAddress(
2411 ULONG DeviceAddress
)
2416 // acquire device lock
2418 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2423 PC_ASSERT(DeviceAddress
!= 0);
2426 // convert back to bit number
2433 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2438 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2440 //-----------------------------------------------------------------------------------------
2442 CHubController::RemoveUsbDevice(
2443 PUSBDEVICE UsbDevice
)
2445 PUSBDEVICE_ENTRY DeviceEntry
;
2447 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2453 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2456 // point to first entry
2458 Entry
= m_UsbDeviceList
.Flink
;
2461 // find matching entry
2463 while(Entry
!= &m_UsbDeviceList
)
2468 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2471 // is it current entry
2473 if (DeviceEntry
->Device
== UsbDevice
)
2478 RemoveEntryList(Entry
);
2483 ExFreePoolWithTag(DeviceEntry
, TAG_USBLIB
);
2488 Status
= STATUS_SUCCESS
;
2495 Entry
= Entry
->Flink
;
2501 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2508 //-----------------------------------------------------------------------------------------
2510 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2512 PUSBDEVICE_ENTRY DeviceEntry
;
2515 BOOLEAN Result
= FALSE
;
2520 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2523 // point to first entry
2525 Entry
= m_UsbDeviceList
.Flink
;
2528 // find matching entry
2530 while(Entry
!= &m_UsbDeviceList
)
2535 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2538 // is it current entry
2540 if (DeviceEntry
->Device
== UsbDevice
)
2552 Entry
= Entry
->Flink
;
2558 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2567 //-----------------------------------------------------------------------------------------
2569 CHubController::AddUsbDevice(
2570 PUSBDEVICE UsbDevice
)
2572 PUSBDEVICE_ENTRY DeviceEntry
;
2576 // allocate device entry
2578 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBLIB
);
2584 return STATUS_INSUFFICIENT_RESOURCES
;
2590 DeviceEntry
->Device
= UsbDevice
;
2595 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2600 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2603 // release spin lock
2605 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2610 return STATUS_SUCCESS
;
2613 //-----------------------------------------------------------------------------------------
2615 CHubController::SetNotification(
2616 PVOID CallbackContext
,
2617 PRH_INIT_CALLBACK CallbackRoutine
)
2622 // acquire hub controller lock
2624 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2627 // now set the callback routine and context of the hub
2629 m_HubCallbackContext
= CallbackContext
;
2630 m_HubCallbackRoutine
= CallbackRoutine
;
2633 // release hub controller lock
2635 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2638 //=================================================================================================
2640 // Generic Interface functions
2644 USBI_InterfaceReference(
2647 CHubController
* Controller
= (CHubController
*)BusContext
;
2649 DPRINT1("USBH_InterfaceReference\n");
2654 Controller
->AddRef();
2659 USBI_InterfaceDereference(
2662 CHubController
* Controller
= (CHubController
*)BusContext
;
2664 DPRINT1("USBH_InterfaceDereference\n");
2669 Controller
->Release();
2671 //=================================================================================================
2673 // USB Hub Interface functions
2677 USBHI_CreateUsbDevice(
2679 PUSB_DEVICE_HANDLE
*NewDevice
,
2680 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2684 PUSBDEVICE NewUsbDevice
;
2685 CHubController
* Controller
;
2688 DPRINT1("USBHI_CreateUsbDevice\n");
2691 // first get hub controller
2693 Controller
= (CHubController
*)BusContext
;
2698 PC_ASSERT(Controller
);
2699 PC_ASSERT(BusContext
== HubDeviceHandle
);
2702 // now allocate usb device
2704 Status
= CreateUSBDevice(&NewUsbDevice
);
2707 // check for success
2709 if (!NT_SUCCESS(Status
))
2712 // release controller
2714 Controller
->Release();
2715 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2720 // now initialize device
2722 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(), HubDeviceHandle
, PortNumber
, PortStatus
);
2725 // check for success
2727 if (!NT_SUCCESS(Status
))
2730 // release usb device
2732 NewUsbDevice
->Release();
2733 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2740 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2742 // check for success
2744 if (!NT_SUCCESS(Status
))
2747 // release usb device
2749 NewUsbDevice
->Release();
2751 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2758 *NewDevice
= NewUsbDevice
;
2763 return STATUS_SUCCESS
;
2768 USBHI_InitializeUsbDevice(
2770 PUSB_DEVICE_HANDLE DeviceHandle
)
2772 PUSBDEVICE UsbDevice
;
2773 CHubController
* Controller
;
2774 ULONG DeviceAddress
;
2778 DPRINT("USBHI_InitializeUsbDevice\n");
2781 // first get controller
2783 Controller
= (CHubController
*)BusContext
;
2784 PC_ASSERT(Controller
);
2787 // get device object
2789 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2790 PC_ASSERT(UsbDevice
);
2793 // validate device handle
2795 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2797 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2800 // invalid device handle
2802 return STATUS_DEVICE_NOT_CONNECTED
;
2806 // now reserve an address
2808 DeviceAddress
= Controller
->AcquireDeviceAddress();
2811 // is the device address valid
2813 if (DeviceAddress
== MAXULONG
)
2816 // failed to get an device address from the device address pool
2818 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2819 return STATUS_DEVICE_DATA_ERROR
;
2825 // now set the device address
2827 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2829 if (NT_SUCCESS(Status
))
2832 }while(Index
++ < 3 );
2835 // check for failure
2837 if (!NT_SUCCESS(Status
))
2840 // failed to set device address
2842 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2847 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2852 return STATUS_DEVICE_DATA_ERROR
;
2858 return STATUS_SUCCESS
;
2863 USBHI_GetUsbDescriptors(
2865 PUSB_DEVICE_HANDLE DeviceHandle
,
2866 PUCHAR DeviceDescriptorBuffer
,
2867 PULONG DeviceDescriptorBufferLength
,
2868 PUCHAR ConfigDescriptorBuffer
,
2869 PULONG ConfigDescriptorBufferLength
)
2871 PUSBDEVICE UsbDevice
;
2872 CHubController
* Controller
;
2874 DPRINT("USBHI_GetUsbDescriptors\n");
2879 PC_ASSERT(DeviceDescriptorBuffer
);
2880 PC_ASSERT(DeviceDescriptorBufferLength
);
2881 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2882 PC_ASSERT(ConfigDescriptorBufferLength
);
2883 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2886 // first get controller
2888 Controller
= (CHubController
*)BusContext
;
2889 PC_ASSERT(Controller
);
2893 // get device object
2895 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2896 PC_ASSERT(UsbDevice
);
2899 // validate device handle
2901 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2903 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2906 // invalid device handle
2908 return STATUS_DEVICE_NOT_CONNECTED
;
2912 // get device descriptor
2914 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2917 // store result length
2919 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2922 // get configuration descriptor
2924 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2927 // complete the request
2929 return STATUS_SUCCESS
;
2934 USBHI_RemoveUsbDevice(
2936 PUSB_DEVICE_HANDLE DeviceHandle
,
2939 PUSBDEVICE UsbDevice
;
2940 CHubController
* Controller
;
2943 DPRINT("USBHI_RemoveUsbDevice\n");
2946 // first get controller
2948 Controller
= (CHubController
*)BusContext
;
2949 PC_ASSERT(Controller
);
2952 // get device object
2954 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2955 PC_ASSERT(UsbDevice
);
2958 // validate device handle
2960 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2962 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2965 // invalid device handle
2967 return STATUS_DEVICE_NOT_CONNECTED
;
2971 // check if there were flags passed
2973 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2976 // ignore flags for now
2978 return STATUS_SUCCESS
;
2984 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2985 if (!NT_SUCCESS(Status
))
2988 // invalid device handle
2990 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2991 return STATUS_DEVICE_NOT_CONNECTED
;
2995 // release usb device
2997 UsbDevice
->Release();
3002 return STATUS_SUCCESS
;
3007 USBHI_RestoreUsbDevice(
3009 PUSB_DEVICE_HANDLE OldDeviceHandle
,
3010 PUSB_DEVICE_HANDLE NewDeviceHandle
)
3012 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
3013 CHubController
* Controller
;
3015 DPRINT("USBHI_RestoreUsbDevice\n");
3018 // first get controller
3020 Controller
= (CHubController
*)BusContext
;
3021 PC_ASSERT(Controller
);
3024 // get device object
3026 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
3027 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
3028 PC_ASSERT(OldUsbDevice
);
3029 PC_ASSERT(NewDeviceHandle
);
3032 // validate device handle
3034 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
3035 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
3037 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
3038 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
3041 // remove old device handle
3043 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
3045 return STATUS_SUCCESS
;
3050 USBHI_QueryDeviceInformation(
3052 PUSB_DEVICE_HANDLE DeviceHandle
,
3053 PVOID DeviceInformationBuffer
,
3054 ULONG DeviceInformationBufferLength
,
3055 PULONG LengthReturned
)
3057 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
3058 PUSBDEVICE UsbDevice
;
3059 CHubController
* Controller
;
3061 DPRINT("USBHI_QueryDeviceInformation %p\n", BusContext
);
3066 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
3067 PC_ASSERT(DeviceInformationBuffer
);
3068 PC_ASSERT(LengthReturned
);
3071 // get controller object
3073 Controller
= (CHubController
*)BusContext
;
3074 PC_ASSERT(Controller
);
3077 // get device object
3079 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3080 PC_ASSERT(UsbDevice
);
3082 if (BusContext
!= DeviceHandle
)
3085 // validate device handle
3087 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3089 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
3092 // invalid device handle
3094 return STATUS_DEVICE_NOT_CONNECTED
;
3098 // access information buffer
3100 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3103 // initialize with default values
3105 DeviceInfo
->InformationLevel
= 0;
3106 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3107 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
3108 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
3109 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
3110 DeviceInfo
->HubAddress
= 0; //FIXME
3111 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
3112 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
3113 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3116 // get device descriptor
3118 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
3121 // FIXME return pipe information
3125 // store result length
3127 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
3129 return STATUS_SUCCESS
;
3133 // access information buffer
3135 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3138 // initialize with default values
3140 DeviceInfo
->InformationLevel
= 0;
3141 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3142 DeviceInfo
->PortNumber
= 0;
3143 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
3144 DeviceInfo
->DeviceAddress
= 0;
3145 DeviceInfo
->HubAddress
= 0; //FIXME
3146 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
3147 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
3148 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3151 // get device descriptor
3153 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
3156 // FIXME return pipe information
3160 // store result length
3163 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
3165 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
3170 return STATUS_SUCCESS
;
3175 USBHI_GetControllerInformation(
3177 PVOID ControllerInformationBuffer
,
3178 ULONG ControllerInformationBufferLength
,
3179 PULONG LengthReturned
)
3181 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
3183 DPRINT("USBHI_GetControllerInformation\n");
3188 PC_ASSERT(ControllerInformationBuffer
);
3189 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
3192 // get controller info buffer
3194 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3197 // FIXME only version 0 is supported for now
3199 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3202 // fill in information
3204 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3205 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3206 ControllerInfo
->IsHighSpeedController
= TRUE
;
3209 // set length returned
3211 *LengthReturned
= ControllerInfo
->ActualLength
;
3216 return STATUS_SUCCESS
;
3221 USBHI_ControllerSelectiveSuspend(
3226 return STATUS_NOT_IMPLEMENTED
;
3231 USBHI_GetExtendedHubInformation(
3233 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3234 PVOID HubInformationBuffer
,
3235 ULONG HubInformationBufferLength
,
3236 PULONG LengthReturned
)
3238 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3239 CHubController
* Controller
;
3240 PUSBHARDWAREDEVICE Hardware
;
3242 ULONG NumPort
, Dummy2
;
3246 DPRINT("USBHI_GetExtendedHubInformation\n");
3251 PC_ASSERT(HubInformationBuffer
);
3252 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3253 PC_ASSERT(LengthReturned
);
3256 // get hub controller
3258 Controller
= (CHubController
*)BusContext
;
3259 PC_ASSERT(Controller
);
3262 // get usb hardware device
3264 Hardware
= Controller
->GetUsbHardware();
3267 // retrieve number of ports
3269 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3270 if (!NT_SUCCESS(Status
))
3273 // failed to get hardware details, ouch ;)
3275 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3280 // get hub information buffer
3282 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3285 // initialize hub information
3287 HubInfo
->InformationLevel
= 0;
3292 HubInfo
->NumberOfPorts
= NumPort
;
3295 // initialize port information
3297 for(Index
= 0; Index
< NumPort
; Index
++)
3299 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3300 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3301 HubInfo
->Port
[Index
].VidOverride
= 0;
3302 HubInfo
->Port
[Index
].PidOverride
= 0;
3303 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3307 // store result length
3310 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3312 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3318 return STATUS_SUCCESS
;
3323 USBHI_GetRootHubSymbolicName(
3325 PVOID HubSymNameBuffer
,
3326 ULONG HubSymNameBufferLength
,
3327 PULONG HubSymNameActualLength
)
3330 return STATUS_NOT_IMPLEMENTED
;
3335 USBHI_GetDeviceBusContext(
3336 PVOID HubBusContext
,
3345 USBHI_Initialize20Hub(
3347 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3350 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3351 return STATUS_SUCCESS
;
3355 WORKER_THREAD_ROUTINE InitRootHub
;
3359 InitRootHub(IN PVOID Context
)
3361 PINIT_ROOT_HUB_CONTEXT WorkItem
;
3366 WorkItem
= (PINIT_ROOT_HUB_CONTEXT
)Context
;
3371 WorkItem
->CallbackRoutine(WorkItem
->CallbackContext
);
3376 ExFreePoolWithTag(Context
, TAG_USBLIB
);
3381 USBHI_RootHubInitNotification(
3383 PVOID CallbackContext
,
3384 PRH_INIT_CALLBACK CallbackRoutine
)
3386 CHubController
* Controller
;
3387 PINIT_ROOT_HUB_CONTEXT WorkItem
;
3389 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3392 // get controller object
3394 Controller
= (CHubController
*)BusContext
;
3395 PC_ASSERT(Controller
);
3398 // set notification routine
3400 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3403 // Create and initialize work item data
3405 WorkItem
= (PINIT_ROOT_HUB_CONTEXT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(INIT_ROOT_HUB_CONTEXT
), TAG_USBLIB
);
3408 DPRINT1("Failed to allocate memory!n");
3409 return STATUS_INSUFFICIENT_RESOURCES
;
3415 WorkItem
->CallbackRoutine
= CallbackRoutine
;
3416 WorkItem
->CallbackContext
= CallbackContext
;
3419 // Queue the work item to handle initializing the device
3421 ExInitializeWorkItem(&WorkItem
->WorkItem
, InitRootHub
, (PVOID
)WorkItem
);
3422 ExQueueWorkItem(&WorkItem
->WorkItem
, DelayedWorkQueue
);
3427 return STATUS_SUCCESS
;
3432 USBHI_FlushTransfers(
3441 USBHI_SetDeviceHandleData(
3444 PDEVICE_OBJECT UsbDevicePdo
)
3446 PUSBDEVICE UsbDevice
;
3447 CHubController
* Controller
;
3452 Controller
= (CHubController
*)BusContext
;
3453 PC_ASSERT(Controller
);
3456 // get device handle
3458 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3461 // validate device handle
3463 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3465 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3475 // usbhub sends this request as a part of the Pnp startup sequence
3476 // looks like we need apply a dragon voodoo to fixup the device stack
3477 // otherwise usbhub will cause a bugcheck
3479 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3484 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3487 // should be usbstor
3488 // fixup device stack voodoo part #2
3490 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3493 // set device handle data
3495 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3499 //=================================================================================================
3501 // USB Device Interface functions
3506 USBDI_GetUSBDIVersion(
3508 PUSBD_VERSION_INFORMATION VersionInformation
,
3509 PULONG HcdCapabilites
)
3511 CHubController
* Controller
;
3512 PUSBHARDWAREDEVICE Device
;
3513 ULONG Speed
, Dummy2
;
3516 DPRINT("USBDI_GetUSBDIVersion\n");
3521 Controller
= (CHubController
*)BusContext
;
3526 Device
= Controller
->GetUsbHardware();
3529 if (VersionInformation
)
3532 // windows xp supported
3534 VersionInformation
->USBDI_Version
= 0x00000500;
3539 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3542 // store speed details
3544 VersionInformation
->Supported_USB_Version
= Speed
;
3548 // no flags supported
3550 *HcdCapabilites
= 0;
3557 PULONG CurrentFrame
)
3560 return STATUS_NOT_IMPLEMENTED
;
3565 USBDI_SubmitIsoOutUrb(
3570 return STATUS_NOT_IMPLEMENTED
;
3575 USBDI_QueryBusInformation(
3578 PVOID BusInformationBuffer
,
3579 PULONG BusInformationBufferLength
,
3580 PULONG BusInformationActualLength
)
3583 return STATUS_NOT_IMPLEMENTED
;
3588 USBDI_IsDeviceHighSpeed(
3591 CHubController
* Controller
;
3592 PUSBHARDWAREDEVICE Device
;
3593 ULONG Speed
, Dummy2
;
3596 DPRINT("USBDI_IsDeviceHighSpeed\n");
3601 Controller
= (CHubController
*)BusContext
;
3606 Device
= Controller
->GetUsbHardware();
3612 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3615 // USB 2.0 equals 0x200
3617 return (Speed
== 0x200);
3630 return STATUS_NOT_IMPLEMENTED
;
3634 CHubController::HandleQueryInterface(
3635 PIO_STACK_LOCATION IoStack
)
3637 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3638 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3639 UNICODE_STRING GuidBuffer
;
3642 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3645 // get request parameters
3647 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3648 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3653 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3655 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3658 // version not supported
3660 return STATUS_NOT_SUPPORTED
;
3664 // Interface version 0
3666 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3668 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3669 InterfaceHub
->BusContext
= PVOID(this);
3670 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3671 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3675 // Interface version 1
3677 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3679 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3680 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3681 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3682 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3683 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3684 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3688 // Interface version 2
3690 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3692 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3693 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3694 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3695 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3696 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3697 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3702 // Interface version 3
3704 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3706 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3710 // Interface version 4
3712 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3714 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3718 // Interface version 5
3720 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3722 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3726 // request completed
3728 return STATUS_SUCCESS
;
3730 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3733 // get request parameters
3735 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3736 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3741 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3743 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3746 // version not supported
3748 return STATUS_NOT_SUPPORTED
;
3752 // interface version 0
3754 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3756 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3757 InterfaceDI
->BusContext
= PVOID(this);
3758 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3759 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3760 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3761 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3762 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3763 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3767 // interface version 1
3769 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3771 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3775 // interface version 2
3777 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3779 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3783 // request completed
3785 return STATUS_SUCCESS
;
3790 // convert guid to string
3792 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3793 if (NT_SUCCESS(Status
))
3798 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3803 RtlFreeUnicodeString(&GuidBuffer
);
3806 return STATUS_NOT_SUPPORTED
;
3810 CHubController::SetDeviceInterface(
3813 NTSTATUS Status
= STATUS_SUCCESS
;
3818 // register device interface
3820 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3822 if (NT_SUCCESS(Status
))
3825 // now enable the device interface
3827 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3832 m_InterfaceEnabled
= TRUE
;
3835 else if (m_InterfaceEnabled
)
3838 // disable device interface
3840 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3842 if (NT_SUCCESS(Status
))
3845 // now delete interface string
3847 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3851 // disable interface
3853 m_InterfaceEnabled
= FALSE
;
3859 return STATUS_SUCCESS
;
3863 CHubController::CreatePDO(
3864 PDRIVER_OBJECT DriverObject
,
3865 PDEVICE_OBJECT
* OutDeviceObject
)
3867 WCHAR CharDeviceName
[64];
3869 ULONG UsbDeviceNumber
= 0;
3870 UNICODE_STRING DeviceName
;
3875 // construct device name
3877 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3880 // initialize device name
3882 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3887 Status
= IoCreateDevice(DriverObject
,
3888 sizeof(COMMON_DEVICE_EXTENSION
),
3890 FILE_DEVICE_CONTROLLER
,
3895 /* check for success */
3896 if (NT_SUCCESS(Status
))
3900 // is there a device object with that same name
3902 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3905 // Try the next name
3912 // bail out on other errors
3914 if (!NT_SUCCESS(Status
))
3916 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3921 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3924 // fixup device stack voodoo part #1
3926 (*OutDeviceObject
)->StackSize
++;
3936 CreateHubController(
3937 PHUBCONTROLLER
*OutHcdController
)
3939 PHUBCONTROLLER This
;
3942 // allocate controller
3944 This
= new(NonPagedPool
, TAG_USBLIB
) CHubController(0);
3948 // failed to allocate
3950 return STATUS_INSUFFICIENT_RESOURCES
;
3954 // add reference count
3961 *OutHcdController
= (PHUBCONTROLLER
)This
;
3966 return STATUS_SUCCESS
;
3969 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3971 CHubController
* This
;
3973 This
= (CHubController
*)Context
;
3977 Irp
= This
->m_PendingSCEIrp
;
3980 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3984 This
->m_PendingSCEIrp
= NULL
;
3985 This
->QueryStatusChageEndpoint(Irp
);
3987 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3988 Irp
->IoStatus
.Information
= 0;
3990 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);