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 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
406 PDEVICE_CAPABILITIES DeviceCapabilities
;
407 PPNP_BUS_INFORMATION BusInformation
;
408 PDEVICE_RELATIONS DeviceRelations
;
410 ULONG Index
= 0, Length
;
411 USHORT VendorID
, DeviceID
;
412 ULONG HiSpeed
, NumPorts
;
417 // get device extension
419 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
424 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
427 // get current stack location
429 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
431 switch(IoStack
->MinorFunction
)
433 case IRP_MN_START_DEVICE
:
435 DPRINT("[%S] HandlePnp IRP_MN_START_DEVICE\n", m_USBType
);
437 // register device interface
439 Status
= SetDeviceInterface(TRUE
);
442 case IRP_MN_QUERY_STOP_DEVICE
:
443 case IRP_MN_QUERY_REMOVE_DEVICE
:
448 Status
= STATUS_SUCCESS
;
451 case IRP_MN_QUERY_ID
:
453 DPRINT("[%S] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType
, IoStack
->Parameters
.QueryId
.IdType
);
455 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
462 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
464 if (HiSpeed
== 0x200)
469 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
476 swprintf(Buffer
, L
"USB\\ROOT_HUB");
479 DPRINT("Name %S\n", Buffer
);
484 Length
= (wcslen(Buffer
) + 1);
489 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBLIB
);
496 Status
= STATUS_INSUFFICIENT_RESOURCES
;
503 wcscpy(DeviceName
, Buffer
);
508 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
509 Status
= STATUS_SUCCESS
;
512 Status
= STATUS_UNSUCCESSFUL
;
517 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
524 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
526 if (!NT_SUCCESS(Status
))
528 DPRINT1("[%S] HandlePnp> failed to get hardware id %x\n", m_USBType
, Status
);
533 if (HiSpeed
== 0x200)
538 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
539 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
540 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
547 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
548 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
549 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
552 Buffer
[Index
] = UNICODE_NULL
;
556 DPRINT1("[%S] Name %S\n", m_USBType
, Buffer
);
561 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBLIB
);
568 Status
= STATUS_INSUFFICIENT_RESOURCES
;
575 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
580 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
581 Status
= STATUS_SUCCESS
;
585 Status
= STATUS_SUCCESS
;
588 case IRP_MN_QUERY_CAPABILITIES
:
590 DPRINT("[%S] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType
);
592 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
594 DeviceCapabilities
->LockSupported
= FALSE
;
595 DeviceCapabilities
->EjectSupported
= FALSE
;
596 DeviceCapabilities
->Removable
= FALSE
;
597 DeviceCapabilities
->DockDevice
= FALSE
;
598 DeviceCapabilities
->UniqueID
= FALSE
;
599 DeviceCapabilities
->SilentInstall
= FALSE
;
600 DeviceCapabilities
->RawDeviceOK
= FALSE
;
601 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
602 DeviceCapabilities
->Address
= 0;
603 DeviceCapabilities
->UINumber
= 0;
604 DeviceCapabilities
->DeviceD2
= 1;
607 DeviceCapabilities
->HardwareDisabled
= FALSE
;
608 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
609 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
610 for (Index
= 1; Index
< PowerSystemMaximum
; Index
++)
611 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
612 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
613 DeviceCapabilities
->D1Latency
= 0;
614 DeviceCapabilities
->D2Latency
= 0;
615 DeviceCapabilities
->D3Latency
= 0;
617 Status
= STATUS_SUCCESS
;
620 case IRP_MN_QUERY_INTERFACE
:
622 DPRINT("[%S] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType
);
625 // handle device interface requests
627 Status
= HandleQueryInterface(IoStack
);
630 case IRP_MN_REMOVE_DEVICE
:
632 DPRINT("[%S] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType
);
635 // deactivate device interface for BUS PDO
637 SetDeviceInterface(FALSE
);
640 // complete the request first
642 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
643 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
648 IoDeleteDevice(m_HubControllerDeviceObject
);
653 m_HubControllerDeviceObject
= 0;
658 return STATUS_SUCCESS
;
660 case IRP_MN_QUERY_DEVICE_RELATIONS
:
662 DPRINT("[%S] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
664 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
667 // allocate device relations
669 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBLIB
);
670 if (!DeviceRelations
)
675 Status
= STATUS_INSUFFICIENT_RESOURCES
;
680 // initialize device relations
682 DeviceRelations
->Count
= 1;
683 DeviceRelations
->Objects
[0] = DeviceObject
;
684 ObReferenceObject(DeviceObject
);
689 Status
= STATUS_SUCCESS
;
690 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
697 Status
= Irp
->IoStatus
.Status
;
701 case IRP_MN_QUERY_BUS_INFORMATION
:
703 DPRINT("[%S] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType
);
706 // allocate buffer for bus information
708 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
714 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
719 BusInformation
->LegacyBusType
= PNPBus
;
720 BusInformation
->BusNumber
= 0;
722 Status
= STATUS_SUCCESS
;
723 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
730 Status
= STATUS_INSUFFICIENT_RESOURCES
;
734 case IRP_MN_STOP_DEVICE
:
736 DPRINT("[%S] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType
);
740 Status
= STATUS_SUCCESS
;
743 case IRP_MN_SURPRISE_REMOVAL
:
745 DPRINT("[%S] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType
);
746 Status
= STATUS_SUCCESS
;
752 // ignore request with default status
754 Status
= Irp
->IoStatus
.Status
;
762 Irp
->IoStatus
.Status
= Status
;
763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
771 //-----------------------------------------------------------------------------------------
773 CHubController::HandlePower(
774 IN PDEVICE_OBJECT DeviceObject
,
778 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
779 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
780 return STATUS_NOT_IMPLEMENTED
;
783 //-----------------------------------------------------------------------------------------
785 CHubController::HandleIsochronousTransfer(
789 PUSBDEVICE UsbDevice
;
790 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
793 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
795 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
799 DPRINT1("[%S] Error No EndpointDesc\n", m_USBType
);
800 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
801 return STATUS_INVALID_PARAMETER
;
807 ASSERT(EndPointDesc
);
808 DPRINT("[%S] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType
, EndPointDesc
, EndPointDesc
->bEndpointAddress
, EndPointDesc
->bmAttributes
);
809 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
812 // check if this is a valid usb device handle
814 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
816 DPRINT1("[%S] HandleIsochronousTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
819 // invalid device handle
821 return STATUS_DEVICE_NOT_CONNECTED
;
827 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
829 return UsbDevice
->SubmitIrp(Irp
);
832 //-----------------------------------------------------------------------------------------
834 CHubController::HandleBulkOrInterruptTransfer(
838 PUSBDEVICE UsbDevice
;
839 PUSB_ENDPOINT EndPointDesc
= NULL
;
841 // First check if the request is for the Status Change Endpoint
845 // Is the Request for the root hub
847 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
849 ASSERT(m_PendingSCEIrp
== NULL
);
850 if (QueryStatusChageEndpoint(Irp
))
852 StatusChangeEndpointCallBack(this);
853 return STATUS_SUCCESS
;
857 // Else pend the IRP, to be completed when a device connects or disconnects.
859 DPRINT("[%S] Pending SCE Irp\n", m_USBType
);
860 m_PendingSCEIrp
= Irp
;
861 IoMarkIrpPending(Irp
);
862 return STATUS_PENDING
;
866 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
868 EndPointDesc
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
873 ASSERT(EndPointDesc
);
874 ASSERT((EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
877 // check if this is a valid usb device handle
879 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
881 DPRINT1("[%S] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
884 // invalid device handle
886 return STATUS_DEVICE_NOT_CONNECTED
;
892 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
893 return UsbDevice
->SubmitIrp(Irp
);
896 //-----------------------------------------------------------------------------------------
898 CHubController::HandleClassOther(
902 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
903 USHORT PortStatus
= 0, PortChange
= 0;
908 DPRINT("[%S] HandleClassOther> Request %x Value %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
911 // get number of ports available
913 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
914 PC_ASSERT(Status
== STATUS_SUCCESS
);
919 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
922 // port range reported start from 1 -n
923 // convert back port id so it matches the hardware
925 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
928 // check request code
930 switch(Urb
->UrbControlVendorClassRequest
.Request
)
932 case USB_REQUEST_GET_STATUS
:
937 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
938 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
943 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
945 if (NT_SUCCESS(Status
))
948 // request contains buffer of 2 ushort which are used from submitting port status and port change status
950 DPRINT("[%S] PortId %x PortStatus %x PortChange %x\n", m_USBType
, PortId
, PortStatus
, PortChange
);
951 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
954 // store status, then port change
956 *Buffer
= PortStatus
;
958 *Buffer
= PortChange
;
966 case USB_REQUEST_CLEAR_FEATURE
:
968 switch (Urb
->UrbControlVendorClassRequest
.Value
)
970 case C_PORT_CONNECTION
:
971 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
974 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
977 DPRINT("[%S] Unknown Value for Clear Feature %x \n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
983 case USB_REQUEST_SET_FEATURE
:
986 // request set feature
988 switch(Urb
->UrbControlVendorClassRequest
.Value
)
993 // port enable is a no-op for EHCI
995 Status
= STATUS_SUCCESS
;
1002 // set suspend port feature
1004 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
1010 // set power feature on port
1012 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1019 // reset port feature
1021 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1022 PC_ASSERT(Status
== STATUS_SUCCESS
);
1026 DPRINT1("[%S] Unsupported request id %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
);
1032 DPRINT1("[%S] HandleClassOther Unknown request code %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
);
1034 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1039 //-----------------------------------------------------------------------------------------
1041 CHubController::HandleSelectConfiguration(
1045 PUSBDEVICE UsbDevice
;
1046 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1050 // is the request for the Root Hub
1052 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1055 // FIXME: support setting device to unconfigured state
1057 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1060 // set device handle
1062 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1065 // copy interface info
1067 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1069 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1070 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1071 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1072 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1073 InterfaceInfo
->Reserved
= 0;
1078 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1083 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1084 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1085 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1086 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1087 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1089 return STATUS_SUCCESS
;
1094 // check if this is a valid usb device handle
1096 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1098 DPRINT1("[%S] HandleSelectConfiguration invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1101 // invalid device handle
1103 return STATUS_DEVICE_NOT_CONNECTED
;
1109 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1112 // select configuration
1114 Status
= UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1115 if (NT_SUCCESS(Status
))
1117 // successfully configured device
1118 Urb
->UrbSelectConfiguration
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1124 //-----------------------------------------------------------------------------------------
1126 CHubController::HandleSelectInterface(
1130 PUSBDEVICE UsbDevice
;
1135 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1138 // is the request for the Root Hub
1140 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1143 // no op for root hub
1145 return STATUS_SUCCESS
;
1150 // check if this is a valid usb device handle
1152 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1154 DPRINT1("[%S] HandleSelectInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1157 // invalid device handle
1159 return STATUS_DEVICE_NOT_CONNECTED
;
1165 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1170 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1174 //-----------------------------------------------------------------------------------------
1176 CHubController::HandleGetStatusFromDevice(
1180 PUSHORT DeviceStatus
;
1181 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1183 PUSBDEVICE UsbDevice
;
1188 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1189 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1192 // get status buffer
1194 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1197 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1200 // FIXME need more flags ?
1202 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1203 return STATUS_SUCCESS
;
1207 // check if this is a valid usb device handle
1209 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1211 DPRINT1("[%S] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1214 // invalid device handle
1216 return STATUS_DEVICE_NOT_CONNECTED
;
1222 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1226 // generate setup packet
1228 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1229 CtrlSetup
.wValue
.LowByte
= 0;
1230 CtrlSetup
.wValue
.HiByte
= 0;
1231 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1232 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1233 CtrlSetup
.bmRequestType
.B
= 0x80;
1235 if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_INTERFACE
)
1238 // add interface type
1240 CtrlSetup
.bmRequestType
.B
|= 0x01;
1242 else if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
)
1245 // add interface type
1247 CtrlSetup
.bmRequestType
.B
|= 0x02;
1251 // submit setup packet
1253 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1254 ASSERT(Status
== STATUS_SUCCESS
);
1255 DPRINT1("[%S] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType
, Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1263 //-----------------------------------------------------------------------------------------
1265 CHubController::HandleClassDevice(
1269 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1270 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1271 ULONG PortCount
, Dummy2
;
1273 PUSBDEVICE UsbDevice
;
1274 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1276 DPRINT("[%S] HandleClassDevice Request %x Class %x\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1279 // check class request type
1281 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1283 case USB_REQUEST_GET_STATUS
:
1286 // check if this is a valid usb device handle
1288 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1290 DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1293 // invalid device handle
1295 return STATUS_DEVICE_NOT_CONNECTED
;
1301 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1305 // generate setup packet
1307 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1308 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1309 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1310 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1311 CtrlSetup
.bmRequestType
.B
= 0xA0;
1314 // submit setup packet
1316 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1317 ASSERT(Status
== STATUS_SUCCESS
);
1320 case USB_REQUEST_GET_DESCRIPTOR
:
1322 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1324 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1325 case USB_DEVICE_CLASS_HUB
:
1327 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1332 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1333 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1336 // get hub descriptor
1338 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1341 // one hub is handled
1343 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1344 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1347 // type should 0x29 according to msdn
1349 UsbHubDescriptor
->bDescriptorType
= 0x29;
1354 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1355 PC_ASSERT(Status
== STATUS_SUCCESS
);
1358 // FIXME: retrieve values
1360 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1361 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1362 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1363 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1368 Status
= STATUS_SUCCESS
;
1372 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1374 DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1376 // invalid device handle
1378 return STATUS_DEVICE_NOT_CONNECTED
;
1382 // FIXME: implement support for real hubs
1385 Status
= STATUS_NOT_IMPLEMENTED
;
1390 DPRINT1("[%S] HandleClassDevice Class %x not implemented\n", m_USBType
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1398 // check if this is a valid usb device handle
1400 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1402 DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1405 // invalid device handle
1407 return STATUS_DEVICE_NOT_CONNECTED
;
1413 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1416 // generate setup packet
1418 CtrlSetup
.bmRequestType
.B
= 0;
1419 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1420 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_CLASS
;
1421 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1422 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1423 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1424 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1426 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1429 // data direction is device to host
1431 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1435 // submit setup packet
1437 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1438 ASSERT(Status
== STATUS_SUCCESS
);
1447 //-----------------------------------------------------------------------------------------
1449 CHubController::HandleGetDescriptorFromInterface(
1453 PUSBDEVICE UsbDevice
;
1454 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1460 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1461 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1464 // check if this is a valid usb device handle
1466 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1468 DPRINT1("[%S] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1471 // invalid device handle
1473 return STATUS_DEVICE_NOT_CONNECTED
;
1479 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1482 // generate setup packet
1484 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1485 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1486 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1487 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1488 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1489 CtrlSetup
.bmRequestType
.B
= 0x81;
1492 // submit setup packet
1494 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1495 if (!NT_SUCCESS(Status
))
1497 DPRINT1("[%S] HandleGetDescriptorFromInterface failed with %x\n", m_USBType
, Status
);
1506 //-----------------------------------------------------------------------------------------
1508 CHubController::HandleGetDescriptor(
1512 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1513 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1515 PUSBDEVICE UsbDevice
;
1516 ULONG Length
, BufferLength
;
1518 DPRINT("[%S] HandleGetDescriptor Type %x\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1521 // check descriptor type
1523 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1525 case USB_DEVICE_DESCRIPTOR_TYPE
:
1530 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1531 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1533 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1536 // copy root hub device descriptor
1538 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1539 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1540 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1541 Status
= STATUS_SUCCESS
;
1546 // check if this is a valid usb device handle
1548 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1550 DPRINT1("[%S] HandleGetDescriptor invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1553 // invalid device handle
1555 return STATUS_DEVICE_NOT_CONNECTED
;
1561 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1564 // retrieve device descriptor from device
1566 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1567 Irp
->IoStatus
.Information
= sizeof(USB_DEVICE_DESCRIPTOR
);
1568 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1569 Status
= STATUS_SUCCESS
;
1573 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1578 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1581 // The caller must allocate a buffer large enough to hold all of this information or the data is truncated without error.
1583 BufferLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1584 Buffer
= (PUCHAR
) Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1586 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1589 // request is for the root bus controller
1591 Length
= BufferLength
> sizeof(USB_CONFIGURATION_DESCRIPTOR
) ?
1592 sizeof(USB_CONFIGURATION_DESCRIPTOR
) : BufferLength
;
1593 RtlCopyMemory(Buffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, Length
);
1596 // Check if we still have some space left
1598 if(Length
== BufferLength
)
1601 // We copied all we could
1603 Status
= STATUS_SUCCESS
;
1610 BufferLength
-= Length
;
1613 // copy interface descriptor template
1615 Length
= BufferLength
> sizeof(USB_INTERFACE_DESCRIPTOR
) ?
1616 sizeof(USB_INTERFACE_DESCRIPTOR
) : BufferLength
;
1617 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, Length
);
1620 // Check if we still have some space left
1622 if(Length
== BufferLength
)
1625 // We copied all we could
1627 Status
= STATUS_SUCCESS
;
1634 BufferLength
-= Length
;
1638 // copy end point descriptor template
1640 Length
= BufferLength
> sizeof(USB_ENDPOINT_DESCRIPTOR
) ?
1641 sizeof(USB_ENDPOINT_DESCRIPTOR
) : BufferLength
;
1642 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, Length
);
1647 Status
= STATUS_SUCCESS
;
1653 // check if this is a valid usb device handle
1655 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1657 DPRINT1("[%S] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1660 // invalid device handle
1662 return STATUS_DEVICE_NOT_CONNECTED
;
1668 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1671 // Allocate temporary buffer
1673 BufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1674 Buffer
= (PUCHAR
)ExAllocatePoolWithTag(NonPagedPool
, BufferLength
, TAG_USBLIB
);
1677 Status
= STATUS_NO_MEMORY
;
1682 // perform work in IUSBDevice
1684 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
, BufferLength
, &Length
);
1689 Length
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
> Length
?
1690 Length
: Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1691 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Buffer
, Length
);
1694 // Free temporary buffer
1696 ExFreePoolWithTag(Buffer
, TAG_USBLIB
);
1699 // store result size
1701 Irp
->IoStatus
.Information
= Length
;
1702 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1703 Urb
->UrbControlDescriptorRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1704 Status
= STATUS_SUCCESS
;
1708 case USB_STRING_DESCRIPTOR_TYPE
:
1713 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1714 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1718 // check if this is a valid usb device handle
1720 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1722 DPRINT1("[%S] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1725 // invalid device handle
1727 return STATUS_DEVICE_NOT_CONNECTED
;
1733 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1736 // generate setup packet
1738 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1739 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1740 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1741 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1742 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1743 CtrlSetup
.bmRequestType
.B
= 0x80;
1746 // submit setup packet
1748 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1752 DPRINT1("[%S] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType
, Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1762 //-----------------------------------------------------------------------------------------
1764 CHubController::HandleClassEndpoint(
1768 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1770 PUSBDEVICE UsbDevice
;
1775 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1776 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1777 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1780 // check if this is a valid usb device handle
1782 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1784 DPRINT1("[%S] HandleClassEndpoint invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1787 // invalid device handle
1789 return STATUS_DEVICE_NOT_CONNECTED
;
1795 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1798 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1799 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1800 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1801 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1802 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1803 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1804 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1805 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1806 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1809 // initialize setup packet
1811 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1812 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1813 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1814 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1815 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1817 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1820 // data direction is device to host
1822 CtrlSetup
.bmRequestType
.B
|= 0x80;
1829 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1832 // assert on failure
1834 PC_ASSERT(NT_SUCCESS(Status
));
1843 //-----------------------------------------------------------------------------------------
1845 CHubController::HandleVendorDevice(
1849 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1850 PUSBDEVICE UsbDevice
;
1851 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1853 //DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1858 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1861 // check if this is a valid usb device handle
1863 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1865 DPRINT1("[%S] HandleVendorDevice invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1868 // invalid device handle
1870 return STATUS_DEVICE_NOT_CONNECTED
;
1876 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1879 // initialize setup packet
1881 CtrlSetup
.bmRequestType
.B
= 0;
1882 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1883 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_VENDOR
;
1884 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1885 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1886 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1887 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1889 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1892 // data direction is device to host
1894 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1900 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1901 if (NT_SUCCESS(Status
))
1904 Urb
->UrbControlVendorClassRequest
.Hdr
.Status
= USBD_STATUS_SUCCESS
;
1905 Irp
->IoStatus
.Information
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1911 //-----------------------------------------------------------------------------------------
1913 CHubController::HandleSyncResetAndClearStall(
1917 NTSTATUS Status
= STATUS_SUCCESS
;
1918 PUSB_ENDPOINT EndpointDescriptor
;
1924 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1925 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1926 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1929 // check if this is a valid usb device handle
1931 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1933 DPRINT1("[%S] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
1936 // invalid device handle
1938 return STATUS_DEVICE_NOT_CONNECTED
;
1944 Status
= HandleAbortPipe(Irp
, Urb
);
1945 if (!NT_SUCCESS(Status
))
1950 DPRINT1("[%S] failed to reset pipe %x\n", m_USBType
, Status
);
1955 // get endpoint descriptor
1957 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1962 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1963 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1968 Status
= HandleClearStall(Irp
, Urb
);
1970 DPRINT1("[%S] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType
, Status
);
1973 // reset data toggle
1975 if (NT_SUCCESS(Status
))
1976 EndpointDescriptor
->DataToggle
= 0x0;
1984 //-----------------------------------------------------------------------------------------
1986 CHubController::HandleAbortPipe(
1991 PUSBDEVICE UsbDevice
;
1992 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1997 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1998 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1999 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
2002 // check if this is a valid usb device handle
2004 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2006 DPRINT1("[%S] HandleAbortPipe invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2009 // invalid device handle
2011 return STATUS_DEVICE_NOT_CONNECTED
;
2015 // get endpoint descriptor
2017 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2022 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2028 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
2029 DPRINT1("[%S] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType
, Status
);
2038 //-----------------------------------------------------------------------------------------
2040 CHubController::HandleClearStall(
2044 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2046 PUSBDEVICE UsbDevice
;
2047 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
2053 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2054 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
2055 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
2058 // check if this is a valid usb device handle
2060 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2062 DPRINT1("[%S] HandleClearStall invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2065 // invalid device handle
2067 return STATUS_DEVICE_NOT_CONNECTED
;
2071 // get endpoint descriptor
2073 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2078 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2079 DPRINT1("[%S] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType
);
2082 // initialize setup packet
2084 CtrlSetup
.bmRequestType
.B
= 0x02;
2085 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
2086 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
2087 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
2088 CtrlSetup
.wLength
= 0;
2089 CtrlSetup
.wValue
.W
= 0;
2094 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
2096 DPRINT1("[%S] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType
, Status
);
2105 //-----------------------------------------------------------------------------------------
2107 CHubController::HandleClassInterface(
2111 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2113 PUSBDEVICE UsbDevice
;
2118 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2119 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2120 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2123 // check if this is a valid usb device handle
2125 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2127 DPRINT1("[%S] HandleClassInterface invalid device handle %p\n", m_USBType
, Urb
->UrbHeader
.UsbdDeviceHandle
);
2130 // invalid device handle
2132 return STATUS_DEVICE_NOT_CONNECTED
;
2138 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2141 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
2142 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
2143 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
2144 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2145 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
2146 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
2147 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
2148 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
2149 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
2152 // initialize setup packet
2154 CtrlSetup
.bmRequestType
.B
= 0x21;
2155 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
2156 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
2157 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
2158 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
2160 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2163 // data direction is device to host
2165 CtrlSetup
.bmRequestType
.B
|= 0x80;
2171 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2174 // assert on failure
2176 if (!NT_SUCCESS(Status
))
2181 DPRINT1("[%S] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType
, Urb
->UrbHeader
.Status
);
2190 //-----------------------------------------------------------------------------------------
2192 CHubController::HandleDeviceControl(
2193 IN PDEVICE_OBJECT DeviceObject
,
2196 PIO_STACK_LOCATION IoStack
;
2197 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
2199 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2202 // get current stack location
2204 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2207 // get device extension
2209 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
2212 // determine which request should be performed
2214 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2216 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2221 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2224 switch (Urb
->UrbHeader
.Function
)
2226 case URB_FUNCTION_SYNC_RESET_PIPE
:
2227 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2228 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2230 case URB_FUNCTION_ABORT_PIPE
:
2231 Status
= HandleAbortPipe(Irp
, Urb
);
2233 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2234 Status
= HandleClearStall(Irp
, Urb
);
2236 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2237 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2239 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2240 Status
= HandleGetDescriptor(Irp
, Urb
);
2242 case URB_FUNCTION_CLASS_DEVICE
:
2243 Status
= HandleClassDevice(Irp
, Urb
);
2245 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2246 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
2247 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
2248 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2250 case URB_FUNCTION_SELECT_CONFIGURATION
:
2251 Status
= HandleSelectConfiguration(Irp
, Urb
);
2253 case URB_FUNCTION_SELECT_INTERFACE
:
2254 Status
= HandleSelectInterface(Irp
, Urb
);
2256 case URB_FUNCTION_CLASS_OTHER
:
2257 Status
= HandleClassOther(Irp
, Urb
);
2259 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2260 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2262 case URB_FUNCTION_ISOCH_TRANSFER
:
2263 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2265 case URB_FUNCTION_CLASS_INTERFACE
:
2266 Status
= HandleClassInterface(Irp
, Urb
);
2268 case URB_FUNCTION_CLASS_ENDPOINT
:
2269 Status
= HandleClassEndpoint(Irp
, Urb
);
2271 case URB_FUNCTION_VENDOR_DEVICE
:
2272 Status
= HandleVendorDevice(Irp
, Urb
);
2275 DPRINT1("[%S] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType
, Urb
->UrbHeader
.Function
);
2279 // request completed
2283 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2285 DPRINT("[%S] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType
, this);
2287 if (IoStack
->Parameters
.Others
.Argument1
)
2290 // store object as device handle
2292 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2293 Status
= STATUS_SUCCESS
;
2298 // mis-behaving hub driver
2300 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2304 // request completed
2308 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2310 DPRINT("[%S] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType
);
2313 // this is the first request send, it delivers the PDO to the caller
2315 if (IoStack
->Parameters
.Others
.Argument1
)
2318 // store root hub pdo object
2320 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2323 if (IoStack
->Parameters
.Others
.Argument2
)
2326 // documentation claims to deliver the hcd controller object, although it is wrong
2328 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2332 // request completed
2334 Status
= STATUS_SUCCESS
;
2337 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2339 DPRINT("[%S] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType
);
2342 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2343 // requests this ioctl to deliver the number of presents.
2345 if (IoStack
->Parameters
.Others
.Argument1
)
2348 // FIXME / verify: there is only one hub
2350 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2354 // request completed
2356 Status
= STATUS_SUCCESS
;
2357 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2360 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2362 DPRINT1("[%S] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType
);
2363 Status
= STATUS_SUCCESS
;
2368 DPRINT1("[%S] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType
,
2369 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2370 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2371 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2375 if (Status
!= STATUS_PENDING
)
2377 Irp
->IoStatus
.Status
= Status
;
2378 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2384 //-----------------------------------------------------------------------------------------
2386 CHubController::GetUsbHardware()
2391 //-----------------------------------------------------------------------------------------
2393 CHubController::AcquireDeviceAddress()
2396 ULONG DeviceAddress
;
2399 // acquire device lock
2401 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2406 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2407 if (DeviceAddress
!= MAXULONG
)
2412 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2415 // device addresses start from 0x1 - 0xFF
2421 // release spin lock
2423 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2426 // return device address
2428 return DeviceAddress
;
2430 //-----------------------------------------------------------------------------------------
2432 CHubController::ReleaseDeviceAddress(
2433 ULONG DeviceAddress
)
2438 // acquire device lock
2440 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2445 PC_ASSERT(DeviceAddress
!= 0);
2448 // convert back to bit number
2455 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2460 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2462 //-----------------------------------------------------------------------------------------
2464 CHubController::RemoveUsbDevice(
2465 PUSBDEVICE UsbDevice
)
2467 PUSBDEVICE_ENTRY DeviceEntry
;
2469 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2475 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2478 // point to first entry
2480 Entry
= m_UsbDeviceList
.Flink
;
2483 // find matching entry
2485 while(Entry
!= &m_UsbDeviceList
)
2490 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2493 // is it current entry
2495 if (DeviceEntry
->Device
== UsbDevice
)
2500 RemoveEntryList(Entry
);
2505 ExFreePoolWithTag(DeviceEntry
, TAG_USBLIB
);
2510 Status
= STATUS_SUCCESS
;
2517 Entry
= Entry
->Flink
;
2523 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2530 //-----------------------------------------------------------------------------------------
2532 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2534 PUSBDEVICE_ENTRY DeviceEntry
;
2537 BOOLEAN Result
= FALSE
;
2542 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2545 // point to first entry
2547 Entry
= m_UsbDeviceList
.Flink
;
2550 // find matching entry
2552 while(Entry
!= &m_UsbDeviceList
)
2557 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2560 // is it current entry
2562 if (DeviceEntry
->Device
== UsbDevice
)
2574 Entry
= Entry
->Flink
;
2580 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2589 //-----------------------------------------------------------------------------------------
2591 CHubController::AddUsbDevice(
2592 PUSBDEVICE UsbDevice
)
2594 PUSBDEVICE_ENTRY DeviceEntry
;
2598 // allocate device entry
2600 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBLIB
);
2606 return STATUS_INSUFFICIENT_RESOURCES
;
2612 DeviceEntry
->Device
= UsbDevice
;
2617 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2622 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2625 // release spin lock
2627 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2632 return STATUS_SUCCESS
;
2635 //-----------------------------------------------------------------------------------------
2637 CHubController::SetNotification(
2638 PVOID CallbackContext
,
2639 PRH_INIT_CALLBACK CallbackRoutine
)
2644 // acquire hub controller lock
2646 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2649 // now set the callback routine and context of the hub
2651 m_HubCallbackContext
= CallbackContext
;
2652 m_HubCallbackRoutine
= CallbackRoutine
;
2655 // release hub controller lock
2657 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2660 //=================================================================================================
2662 // Generic Interface functions
2666 USBI_InterfaceReference(
2669 CHubController
* Controller
= (CHubController
*)BusContext
;
2671 DPRINT1("USBH_InterfaceReference\n");
2676 Controller
->AddRef();
2681 USBI_InterfaceDereference(
2684 CHubController
* Controller
= (CHubController
*)BusContext
;
2686 DPRINT1("USBH_InterfaceDereference\n");
2691 Controller
->Release();
2693 //=================================================================================================
2695 // USB Hub Interface functions
2699 USBHI_CreateUsbDevice(
2701 PUSB_DEVICE_HANDLE
*NewDevice
,
2702 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2706 PUSBDEVICE NewUsbDevice
;
2707 CHubController
* Controller
;
2710 DPRINT1("USBHI_CreateUsbDevice\n");
2713 // first get hub controller
2715 Controller
= (CHubController
*)BusContext
;
2720 PC_ASSERT(Controller
);
2721 PC_ASSERT(BusContext
== HubDeviceHandle
);
2724 // now allocate usb device
2726 Status
= CreateUSBDevice(&NewUsbDevice
);
2729 // check for success
2731 if (!NT_SUCCESS(Status
))
2734 // release controller
2736 Controller
->Release();
2737 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2742 // now initialize device
2744 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(), HubDeviceHandle
, PortNumber
, PortStatus
);
2747 // check for success
2749 if (!NT_SUCCESS(Status
))
2752 // release usb device
2754 NewUsbDevice
->Release();
2755 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2762 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2764 // check for success
2766 if (!NT_SUCCESS(Status
))
2769 // release usb device
2771 NewUsbDevice
->Release();
2773 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2780 *NewDevice
= NewUsbDevice
;
2785 return STATUS_SUCCESS
;
2790 USBHI_InitializeUsbDevice(
2792 PUSB_DEVICE_HANDLE DeviceHandle
)
2794 PUSBDEVICE UsbDevice
;
2795 CHubController
* Controller
;
2796 ULONG DeviceAddress
;
2800 DPRINT("USBHI_InitializeUsbDevice\n");
2803 // first get controller
2805 Controller
= (CHubController
*)BusContext
;
2806 PC_ASSERT(Controller
);
2809 // get device object
2811 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2812 PC_ASSERT(UsbDevice
);
2815 // validate device handle
2817 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2819 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2822 // invalid device handle
2824 return STATUS_DEVICE_NOT_CONNECTED
;
2828 // now reserve an address
2830 DeviceAddress
= Controller
->AcquireDeviceAddress();
2833 // is the device address valid
2835 if (DeviceAddress
== MAXULONG
)
2838 // failed to get an device address from the device address pool
2840 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2841 return STATUS_DEVICE_DATA_ERROR
;
2847 // now set the device address
2849 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2851 if (NT_SUCCESS(Status
))
2854 }while(Index
++ < 3 );
2857 // check for failure
2859 if (!NT_SUCCESS(Status
))
2862 // failed to set device address
2864 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2869 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2874 return STATUS_DEVICE_DATA_ERROR
;
2880 return STATUS_SUCCESS
;
2885 USBHI_GetUsbDescriptors(
2887 PUSB_DEVICE_HANDLE DeviceHandle
,
2888 PUCHAR DeviceDescriptorBuffer
,
2889 PULONG DeviceDescriptorBufferLength
,
2890 PUCHAR ConfigDescriptorBuffer
,
2891 PULONG ConfigDescriptorBufferLength
)
2893 PUSBDEVICE UsbDevice
;
2894 CHubController
* Controller
;
2896 DPRINT("USBHI_GetUsbDescriptors\n");
2901 PC_ASSERT(DeviceDescriptorBuffer
);
2902 PC_ASSERT(DeviceDescriptorBufferLength
);
2903 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2904 PC_ASSERT(ConfigDescriptorBufferLength
);
2905 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2908 // first get controller
2910 Controller
= (CHubController
*)BusContext
;
2911 PC_ASSERT(Controller
);
2915 // get device object
2917 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2918 PC_ASSERT(UsbDevice
);
2921 // validate device handle
2923 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2925 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2928 // invalid device handle
2930 return STATUS_DEVICE_NOT_CONNECTED
;
2934 // get device descriptor
2936 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2939 // store result length
2941 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2944 // get configuration descriptor
2946 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2949 // complete the request
2951 return STATUS_SUCCESS
;
2956 USBHI_RemoveUsbDevice(
2958 PUSB_DEVICE_HANDLE DeviceHandle
,
2961 PUSBDEVICE UsbDevice
;
2962 CHubController
* Controller
;
2965 DPRINT("USBHI_RemoveUsbDevice\n");
2968 // first get controller
2970 Controller
= (CHubController
*)BusContext
;
2971 PC_ASSERT(Controller
);
2974 // get device object
2976 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2977 PC_ASSERT(UsbDevice
);
2980 // validate device handle
2982 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2984 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2987 // invalid device handle
2989 return STATUS_DEVICE_NOT_CONNECTED
;
2993 // check if there were flags passed
2995 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2998 // ignore flags for now
3000 return STATUS_SUCCESS
;
3006 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
3007 if (!NT_SUCCESS(Status
))
3010 // invalid device handle
3012 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
3013 return STATUS_DEVICE_NOT_CONNECTED
;
3017 // release usb device
3019 UsbDevice
->Release();
3024 return STATUS_SUCCESS
;
3029 USBHI_RestoreUsbDevice(
3031 PUSB_DEVICE_HANDLE OldDeviceHandle
,
3032 PUSB_DEVICE_HANDLE NewDeviceHandle
)
3034 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
3035 CHubController
* Controller
;
3037 DPRINT("USBHI_RestoreUsbDevice\n");
3040 // first get controller
3042 Controller
= (CHubController
*)BusContext
;
3043 PC_ASSERT(Controller
);
3046 // get device object
3048 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
3049 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
3050 PC_ASSERT(OldUsbDevice
);
3051 PC_ASSERT(NewDeviceHandle
);
3054 // validate device handle
3056 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
3057 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
3059 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
3060 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
3063 // remove old device handle
3065 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
3067 return STATUS_SUCCESS
;
3072 USBHI_QueryDeviceInformation(
3074 PUSB_DEVICE_HANDLE DeviceHandle
,
3075 PVOID DeviceInformationBuffer
,
3076 ULONG DeviceInformationBufferLength
,
3077 PULONG LengthReturned
)
3079 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
3080 PUSBDEVICE UsbDevice
;
3081 CHubController
* Controller
;
3083 DPRINT("USBHI_QueryDeviceInformation %p\n", BusContext
);
3088 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
3089 PC_ASSERT(DeviceInformationBuffer
);
3090 PC_ASSERT(LengthReturned
);
3093 // get controller object
3095 Controller
= (CHubController
*)BusContext
;
3096 PC_ASSERT(Controller
);
3099 // get device object
3101 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3102 PC_ASSERT(UsbDevice
);
3104 if (BusContext
!= DeviceHandle
)
3107 // validate device handle
3109 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3111 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
3114 // invalid device handle
3116 return STATUS_DEVICE_NOT_CONNECTED
;
3120 // access information buffer
3122 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3125 // initialize with default values
3127 DeviceInfo
->InformationLevel
= 0;
3128 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3129 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
3130 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
3131 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
3132 DeviceInfo
->HubAddress
= 0; //FIXME
3133 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
3134 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
3135 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3138 // get device descriptor
3140 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
3143 // FIXME return pipe information
3147 // store result length
3149 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
3151 return STATUS_SUCCESS
;
3155 // access information buffer
3157 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3160 // initialize with default values
3162 DeviceInfo
->InformationLevel
= 0;
3163 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3164 DeviceInfo
->PortNumber
= 0;
3165 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
3166 DeviceInfo
->DeviceAddress
= 0;
3167 DeviceInfo
->HubAddress
= 0; //FIXME
3168 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
3169 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
3170 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3173 // get device descriptor
3175 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
3178 // FIXME return pipe information
3182 // store result length
3185 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
3187 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
3192 return STATUS_SUCCESS
;
3197 USBHI_GetControllerInformation(
3199 PVOID ControllerInformationBuffer
,
3200 ULONG ControllerInformationBufferLength
,
3201 PULONG LengthReturned
)
3203 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
3205 DPRINT("USBHI_GetControllerInformation\n");
3210 PC_ASSERT(ControllerInformationBuffer
);
3211 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
3214 // get controller info buffer
3216 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3219 // FIXME only version 0 is supported for now
3221 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3224 // fill in information
3226 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3227 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3228 ControllerInfo
->IsHighSpeedController
= TRUE
;
3231 // set length returned
3233 *LengthReturned
= ControllerInfo
->ActualLength
;
3238 return STATUS_SUCCESS
;
3243 USBHI_ControllerSelectiveSuspend(
3248 return STATUS_NOT_IMPLEMENTED
;
3253 USBHI_GetExtendedHubInformation(
3255 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3256 PVOID HubInformationBuffer
,
3257 ULONG HubInformationBufferLength
,
3258 PULONG LengthReturned
)
3260 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3261 CHubController
* Controller
;
3262 PUSBHARDWAREDEVICE Hardware
;
3264 ULONG NumPort
, Dummy2
;
3268 DPRINT("USBHI_GetExtendedHubInformation\n");
3273 PC_ASSERT(HubInformationBuffer
);
3274 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3275 PC_ASSERT(LengthReturned
);
3278 // get hub controller
3280 Controller
= (CHubController
*)BusContext
;
3281 PC_ASSERT(Controller
);
3284 // get usb hardware device
3286 Hardware
= Controller
->GetUsbHardware();
3289 // retrieve number of ports
3291 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3292 if (!NT_SUCCESS(Status
))
3295 // failed to get hardware details, ouch ;)
3297 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3302 // get hub information buffer
3304 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3307 // initialize hub information
3309 HubInfo
->InformationLevel
= 0;
3314 HubInfo
->NumberOfPorts
= NumPort
;
3317 // initialize port information
3319 for(Index
= 0; Index
< NumPort
; Index
++)
3321 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3322 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3323 HubInfo
->Port
[Index
].VidOverride
= 0;
3324 HubInfo
->Port
[Index
].PidOverride
= 0;
3325 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3329 // store result length
3332 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3334 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3340 return STATUS_SUCCESS
;
3345 USBHI_GetRootHubSymbolicName(
3347 PVOID HubSymNameBuffer
,
3348 ULONG HubSymNameBufferLength
,
3349 PULONG HubSymNameActualLength
)
3352 return STATUS_NOT_IMPLEMENTED
;
3357 USBHI_GetDeviceBusContext(
3358 PVOID HubBusContext
,
3367 USBHI_Initialize20Hub(
3369 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3372 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3373 return STATUS_SUCCESS
;
3378 USBHI_RootHubInitNotification(
3380 PVOID CallbackContext
,
3381 PRH_INIT_CALLBACK CallbackRoutine
)
3383 CHubController
* Controller
;
3385 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3388 // get controller object
3390 Controller
= (CHubController
*)BusContext
;
3391 PC_ASSERT(Controller
);
3394 // set notification routine
3396 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3399 // FIXME: determine when to perform callback
3401 CallbackRoutine(CallbackContext
);
3406 return STATUS_SUCCESS
;
3411 USBHI_FlushTransfers(
3420 USBHI_SetDeviceHandleData(
3423 PDEVICE_OBJECT UsbDevicePdo
)
3425 PUSBDEVICE UsbDevice
;
3426 CHubController
* Controller
;
3431 Controller
= (CHubController
*)BusContext
;
3432 PC_ASSERT(Controller
);
3435 // get device handle
3437 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3440 // validate device handle
3442 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3444 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3454 // usbhub sends this request as a part of the Pnp startup sequence
3455 // looks like we need apply a dragon voodoo to fixup the device stack
3456 // otherwise usbhub will cause a bugcheck
3458 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3463 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3466 // should be usbstor
3467 // fixup device stack voodoo part #2
3469 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3472 // set device handle data
3474 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3478 //=================================================================================================
3480 // USB Device Interface functions
3485 USBDI_GetUSBDIVersion(
3487 PUSBD_VERSION_INFORMATION VersionInformation
,
3488 PULONG HcdCapabilites
)
3490 CHubController
* Controller
;
3491 PUSBHARDWAREDEVICE Device
;
3492 ULONG Speed
, Dummy2
;
3495 DPRINT("USBDI_GetUSBDIVersion\n");
3500 Controller
= (CHubController
*)BusContext
;
3505 Device
= Controller
->GetUsbHardware();
3508 if (VersionInformation
)
3511 // windows xp supported
3513 VersionInformation
->USBDI_Version
= 0x00000500;
3518 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3521 // store speed details
3523 VersionInformation
->Supported_USB_Version
= Speed
;
3527 // no flags supported
3529 *HcdCapabilites
= 0;
3536 PULONG CurrentFrame
)
3539 return STATUS_NOT_IMPLEMENTED
;
3544 USBDI_SubmitIsoOutUrb(
3549 return STATUS_NOT_IMPLEMENTED
;
3554 USBDI_QueryBusInformation(
3557 PVOID BusInformationBuffer
,
3558 PULONG BusInformationBufferLength
,
3559 PULONG BusInformationActualLength
)
3562 return STATUS_NOT_IMPLEMENTED
;
3567 USBDI_IsDeviceHighSpeed(
3570 CHubController
* Controller
;
3571 PUSBHARDWAREDEVICE Device
;
3572 ULONG Speed
, Dummy2
;
3575 DPRINT("USBDI_IsDeviceHighSpeed\n");
3580 Controller
= (CHubController
*)BusContext
;
3585 Device
= Controller
->GetUsbHardware();
3591 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3594 // USB 2.0 equals 0x200
3596 return (Speed
== 0x200);
3609 return STATUS_NOT_IMPLEMENTED
;
3613 CHubController::HandleQueryInterface(
3614 PIO_STACK_LOCATION IoStack
)
3616 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3617 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3618 UNICODE_STRING GuidBuffer
;
3621 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3624 // get request parameters
3626 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3627 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3632 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3634 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3637 // version not supported
3639 return STATUS_NOT_SUPPORTED
;
3643 // Interface version 0
3645 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3647 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3648 InterfaceHub
->BusContext
= PVOID(this);
3649 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3650 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3654 // Interface version 1
3656 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3658 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3659 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3660 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3661 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3662 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3663 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3667 // Interface version 2
3669 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3671 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3672 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3673 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3674 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3675 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3676 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3681 // Interface version 3
3683 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3685 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3689 // Interface version 4
3691 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3693 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3697 // Interface version 5
3699 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3701 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3705 // request completed
3707 return STATUS_SUCCESS
;
3709 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3712 // get request parameters
3714 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3715 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3720 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3722 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3725 // version not supported
3727 return STATUS_NOT_SUPPORTED
;
3731 // interface version 0
3733 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3735 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3736 InterfaceDI
->BusContext
= PVOID(this);
3737 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3738 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3739 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3740 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3741 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3742 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3746 // interface version 1
3748 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3750 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3754 // interface version 2
3756 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3758 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3762 // request completed
3764 return STATUS_SUCCESS
;
3769 // convert guid to string
3771 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3772 if (NT_SUCCESS(Status
))
3777 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3782 RtlFreeUnicodeString(&GuidBuffer
);
3785 return STATUS_NOT_SUPPORTED
;
3789 CHubController::SetDeviceInterface(
3792 NTSTATUS Status
= STATUS_SUCCESS
;
3797 // register device interface
3799 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3801 if (NT_SUCCESS(Status
))
3804 // now enable the device interface
3806 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3811 m_InterfaceEnabled
= TRUE
;
3814 else if (m_InterfaceEnabled
)
3817 // disable device interface
3819 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3821 if (NT_SUCCESS(Status
))
3824 // now delete interface string
3826 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3830 // disable interface
3832 m_InterfaceEnabled
= FALSE
;
3838 return STATUS_SUCCESS
;
3842 CHubController::CreatePDO(
3843 PDRIVER_OBJECT DriverObject
,
3844 PDEVICE_OBJECT
* OutDeviceObject
)
3846 WCHAR CharDeviceName
[64];
3848 ULONG UsbDeviceNumber
= 0;
3849 UNICODE_STRING DeviceName
;
3854 // construct device name
3856 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3859 // initialize device name
3861 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3866 Status
= IoCreateDevice(DriverObject
,
3867 sizeof(COMMON_DEVICE_EXTENSION
),
3869 FILE_DEVICE_CONTROLLER
,
3874 /* check for success */
3875 if (NT_SUCCESS(Status
))
3879 // is there a device object with that same name
3881 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3884 // Try the next name
3891 // bail out on other errors
3893 if (!NT_SUCCESS(Status
))
3895 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3900 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3903 // fixup device stack voodoo part #1
3905 (*OutDeviceObject
)->StackSize
++;
3915 CreateHubController(
3916 PHUBCONTROLLER
*OutHcdController
)
3918 PHUBCONTROLLER This
;
3921 // allocate controller
3923 This
= new(NonPagedPool
, TAG_USBLIB
) CHubController(0);
3927 // failed to allocate
3929 return STATUS_INSUFFICIENT_RESOURCES
;
3933 // add reference count
3940 *OutHcdController
= (PHUBCONTROLLER
)This
;
3945 return STATUS_SUCCESS
;
3948 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3950 CHubController
* This
;
3952 This
= (CHubController
*)Context
;
3956 Irp
= This
->m_PendingSCEIrp
;
3959 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3963 This
->m_PendingSCEIrp
= NULL
;
3964 This
->QueryStatusChageEndpoint(Irp
);
3966 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3967 Irp
->IoStatus
.Information
= 0;
3969 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);