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
;
110 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
117 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
119 /* Lifted from Linux with slight changes */
120 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
123 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
124 0x00, 0x20, /* bcdUSB; v1.1 */
125 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
126 0x01, /* bDeviceSubClass; */
127 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
128 0x08, /* bMaxPacketSize0; 8 Bytes */
129 /* Fill Vendor and Product in when init root hub */
130 0x00, 0x00, /* idVendor; */
131 0x00, 0x00, /* idProduct; */
132 0x00, 0x00, /* bcdDevice */
133 0x00, /* iManufacturer; */
134 0x00, /* iProduct; */
135 0x00, /* iSerialNumber; */
136 0x01 /* bNumConfigurations; */
140 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
142 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
143 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
144 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
148 0x40, /* self powered */
152 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
154 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
155 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
156 0, /* bInterfaceNumber; */
157 0, /* bAlternateSetting; */
158 0x1, /* bNumEndpoints; */
159 0x09, /* bInterfaceClass; HUB_CLASSCODE */
160 0x01, /* bInterfaceSubClass; */
161 0x00, /* bInterfaceProtocol: */
162 0x00, /* iInterface; */
165 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
167 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
168 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
169 0x81, /* bEndPointAddress */
170 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
171 0x01, /* wMaxPacketSize */
175 //----------------------------------------------------------------------------------------
178 CHubController::QueryInterface(
182 return STATUS_UNSUCCESSFUL
;
184 //----------------------------------------------------------------------------------------
186 CHubController::Initialize(
187 IN PDRIVER_OBJECT DriverObject
,
188 IN PHCDCONTROLLER Controller
,
189 IN PUSBHARDWAREDEVICE Device
,
190 IN BOOLEAN IsRootHubDevice
,
191 IN ULONG DeviceAddress
)
194 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
195 USHORT VendorID
, DeviceID
;
198 DPRINT1("CHubController::Initialize\n");
201 // initialize members
203 m_Controller
= Controller
;
205 m_IsRootHubDevice
= IsRootHubDevice
;
206 m_DeviceAddress
= DeviceAddress
;
207 m_DriverObject
= DriverObject
;
208 KeInitializeSpinLock(&m_Lock
);
209 InitializeListHead(&m_UsbDeviceList
);
212 // allocate device address bitmap buffer
214 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBLIB
);
215 if (!m_DeviceAddressBitmapBuffer
)
220 return STATUS_INSUFFICIENT_RESOURCES
;
224 // initialize device address bitmap
226 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
227 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("[USBLIB] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", 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("[USBLIB] Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
328 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
332 DPRINT1("[USBLIB] Change state on port %d\n", 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("[USBLIB] HandlePnp IRP_MN_START_DEVICE\n");
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("[USBLIB] HandlePnp IRP_MN_QUERY_ID Type %x\n", 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("[USBLIB] HandlePnp> failed to get hardware id %x\n", 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("[USBLIB] Name %S\n", 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("[USBLIB] HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
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("[USBLIB] HandlePnp IRP_MN_QUERY_INTERFACE\n");
625 // handle device interface requests
627 Status
= HandleQueryInterface(IoStack
);
630 case IRP_MN_REMOVE_DEVICE
:
632 DPRINT("[USBLIB] HandlePnp IRP_MN_REMOVE_DEVICE\n");
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("[USBLIB] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", 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("[USBLIB] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
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("[USBLIB] HandlePnp IRP_MN_STOP_DEVICE\n");
740 Status
= STATUS_SUCCESS
;
746 // ignore request with default status
748 Status
= Irp
->IoStatus
.Status
;
756 Irp
->IoStatus
.Status
= Status
;
757 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
765 //-----------------------------------------------------------------------------------------
767 CHubController::HandlePower(
768 IN PDEVICE_OBJECT DeviceObject
,
772 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
773 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
774 return STATUS_NOT_IMPLEMENTED
;
777 //-----------------------------------------------------------------------------------------
779 CHubController::HandleIsochronousTransfer(
783 PUSBDEVICE UsbDevice
;
784 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
787 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
789 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
793 DPRINT1("[USBLIB] Error No EndpointDesc\n");
794 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
795 return STATUS_INVALID_PARAMETER
;
801 ASSERT(EndPointDesc
);
802 DPRINT("HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", EndPointDesc
, EndPointDesc
->bEndpointAddress
, EndPointDesc
->bmAttributes
);
803 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
806 // check if this is a valid usb device handle
808 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
810 DPRINT1("[USBLIB] HandleIsochronousTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
813 // invalid device handle
815 return STATUS_DEVICE_NOT_CONNECTED
;
821 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
823 return UsbDevice
->SubmitIrp(Irp
);
826 //-----------------------------------------------------------------------------------------
828 CHubController::HandleBulkOrInterruptTransfer(
832 PUSBDEVICE UsbDevice
;
833 PUSB_ENDPOINT EndPointDesc
= NULL
;
835 // First check if the request is for the Status Change Endpoint
839 // Is the Request for the root hub
841 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
843 ASSERT(m_PendingSCEIrp
== NULL
);
844 if (QueryStatusChageEndpoint(Irp
))
846 StatusChangeEndpointCallBack(this);
847 return STATUS_SUCCESS
;
851 // Else pend the IRP, to be completed when a device connects or disconnects.
853 DPRINT("[USBLIB] Pending SCE Irp\n");
854 m_PendingSCEIrp
= Irp
;
855 IoMarkIrpPending(Irp
);
856 return STATUS_PENDING
;
860 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
862 EndPointDesc
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
867 ASSERT(EndPointDesc
);
868 ASSERT((EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
871 // check if this is a valid usb device handle
873 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
875 DPRINT1("[USBLIB] HandleBulkOrInterruptTransfer invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
878 // invalid device handle
880 return STATUS_DEVICE_NOT_CONNECTED
;
886 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
887 return UsbDevice
->SubmitIrp(Irp
);
890 //-----------------------------------------------------------------------------------------
892 CHubController::HandleClassOther(
896 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
897 USHORT PortStatus
= 0, PortChange
= 0;
902 DPRINT("[USBLIB] HandleClassOther> Request %x Value %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
905 // get number of ports available
907 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
908 PC_ASSERT(Status
== STATUS_SUCCESS
);
913 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
916 // port range reported start from 1 -n
917 // convert back port id so it matches the hardware
919 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
922 // check request code
924 switch(Urb
->UrbControlVendorClassRequest
.Request
)
926 case USB_REQUEST_GET_STATUS
:
931 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
932 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
937 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
939 if (NT_SUCCESS(Status
))
942 // request contains buffer of 2 ushort which are used from submitting port status and port change status
944 DPRINT("[USBLIB] PortId %x PortStatus %x PortChange %x\n", PortId
, PortStatus
, PortChange
);
945 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
948 // store status, then port change
950 *Buffer
= PortStatus
;
952 *Buffer
= PortChange
;
960 case USB_REQUEST_CLEAR_FEATURE
:
962 switch (Urb
->UrbControlVendorClassRequest
.Value
)
964 case C_PORT_CONNECTION
:
965 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
968 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
971 DPRINT("[USBLIB] Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
977 case USB_REQUEST_SET_FEATURE
:
980 // request set feature
982 switch(Urb
->UrbControlVendorClassRequest
.Value
)
987 // port enable is a no-op for EHCI
989 Status
= STATUS_SUCCESS
;
996 // set suspend port feature
998 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
1004 // set power feature on port
1006 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
1013 // reset port feature
1015 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
1016 PC_ASSERT(Status
== STATUS_SUCCESS
);
1020 DPRINT1("[USBLIB] Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1026 DPRINT1("[USBLIB] HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1028 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1033 //-----------------------------------------------------------------------------------------
1035 CHubController::HandleSelectConfiguration(
1039 PUSBDEVICE UsbDevice
;
1040 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1043 // is the request for the Root Hub
1045 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1048 // FIXME: support setting device to unconfigured state
1050 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1053 // set device handle
1055 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1058 // copy interface info
1060 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1062 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1063 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1064 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1065 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1066 InterfaceInfo
->Reserved
= 0;
1071 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1076 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1077 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1078 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1079 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1080 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1082 return STATUS_SUCCESS
;
1087 // check if this is a valid usb device handle
1089 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1091 DPRINT1("[USBLIB] HandleSelectConfiguration invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1094 // invalid device handle
1096 return STATUS_DEVICE_NOT_CONNECTED
;
1102 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1105 // select configuration
1107 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1111 //-----------------------------------------------------------------------------------------
1113 CHubController::HandleSelectInterface(
1117 PUSBDEVICE UsbDevice
;
1122 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1125 // is the request for the Root Hub
1127 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1130 // no op for root hub
1132 return STATUS_SUCCESS
;
1137 // check if this is a valid usb device handle
1139 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1141 DPRINT1("[USBLIB] HandleSelectInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1144 // invalid device handle
1146 return STATUS_DEVICE_NOT_CONNECTED
;
1152 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1157 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1161 //-----------------------------------------------------------------------------------------
1163 CHubController::HandleGetStatusFromDevice(
1167 PUSHORT DeviceStatus
;
1168 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1170 PUSBDEVICE UsbDevice
;
1175 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1176 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1179 // get status buffer
1181 DeviceStatus
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1184 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1187 // FIXME need more flags ?
1189 *DeviceStatus
= USB_PORT_STATUS_CONNECT
;
1190 return STATUS_SUCCESS
;
1194 // check if this is a valid usb device handle
1196 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1198 DPRINT1("[USBLIB] HandleGetStatusFromDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1201 // invalid device handle
1203 return STATUS_DEVICE_NOT_CONNECTED
;
1209 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1213 // generate setup packet
1215 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1216 CtrlSetup
.wValue
.LowByte
= 0;
1217 CtrlSetup
.wValue
.HiByte
= 0;
1218 CtrlSetup
.wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1219 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1220 CtrlSetup
.bmRequestType
.B
= 0x80;
1222 if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_INTERFACE
)
1225 // add interface type
1227 CtrlSetup
.bmRequestType
.B
|= 0x01;
1229 else if (Urb
->UrbHeader
.Function
== URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
)
1232 // add interface type
1234 CtrlSetup
.bmRequestType
.B
|= 0x02;
1238 // submit setup packet
1240 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1241 ASSERT(Status
== STATUS_SUCCESS
);
1242 DPRINT1("[USBLIB] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, *DeviceStatus
);
1250 //-----------------------------------------------------------------------------------------
1252 CHubController::HandleClassDevice(
1256 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1257 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1258 ULONG PortCount
, Dummy2
;
1260 PUSBDEVICE UsbDevice
;
1261 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1263 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1266 // check class request type
1268 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1270 case USB_REQUEST_GET_STATUS
:
1273 // check if this is a valid usb device handle
1275 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1277 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1280 // invalid device handle
1282 return STATUS_DEVICE_NOT_CONNECTED
;
1288 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1292 // generate setup packet
1294 CtrlSetup
.bRequest
= USB_REQUEST_GET_STATUS
;
1295 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1296 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1297 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlGetStatusRequest
.TransferBufferLength
;
1298 CtrlSetup
.bmRequestType
.B
= 0xA0;
1301 // submit setup packet
1303 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1304 ASSERT(Status
== STATUS_SUCCESS
);
1307 case USB_REQUEST_GET_DESCRIPTOR
:
1309 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1311 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1312 case USB_DEVICE_CLASS_HUB
:
1314 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1319 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1320 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1323 // get hub descriptor
1325 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1328 // one hub is handled
1330 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1331 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1334 // type should 0x29 according to msdn
1336 UsbHubDescriptor
->bDescriptorType
= 0x29;
1341 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1342 PC_ASSERT(Status
== STATUS_SUCCESS
);
1345 // FIXME: retrieve values
1347 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1348 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1349 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1350 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1355 Status
= STATUS_SUCCESS
;
1359 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1361 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1363 // invalid device handle
1365 return STATUS_DEVICE_NOT_CONNECTED
;
1369 // FIXME: implement support for real hubs
1372 Status
= STATUS_NOT_IMPLEMENTED
;
1377 DPRINT1("[USBLIB] HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1385 // check if this is a valid usb device handle
1387 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1389 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1392 // invalid device handle
1394 return STATUS_DEVICE_NOT_CONNECTED
;
1400 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1403 // generate setup packet
1405 CtrlSetup
.bmRequestType
.B
= 0;
1406 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1407 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_CLASS
;
1408 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1409 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1410 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1411 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1413 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1416 // data direction is device to host
1418 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1422 // submit setup packet
1424 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1425 ASSERT(Status
== STATUS_SUCCESS
);
1434 //-----------------------------------------------------------------------------------------
1436 CHubController::HandleGetDescriptorFromInterface(
1440 PUSBDEVICE UsbDevice
;
1441 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1447 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1448 ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1451 // check if this is a valid usb device handle
1453 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1455 DPRINT1("[USBLIB] HandleGetDescriptorFromInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1458 // invalid device handle
1460 return STATUS_DEVICE_NOT_CONNECTED
;
1466 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1469 // generate setup packet
1471 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1472 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1473 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1474 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1475 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1476 CtrlSetup
.bmRequestType
.B
= 0x81;
1479 // submit setup packet
1481 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1482 ASSERT(Status
== STATUS_SUCCESS
);
1490 //-----------------------------------------------------------------------------------------
1492 CHubController::HandleGetDescriptor(
1496 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1497 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1498 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1500 PUSBDEVICE UsbDevice
;
1503 DPRINT("[USBLIB] HandleGetDescriptor\n");
1506 // check descriptor type
1508 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1510 case USB_DEVICE_DESCRIPTOR_TYPE
:
1515 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1516 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1518 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1521 // copy root hub device descriptor
1523 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1524 Status
= STATUS_SUCCESS
;
1529 // check if this is a valid usb device handle
1531 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1533 DPRINT1("[USBLIB] HandleGetDescriptor invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1536 // invalid device handle
1538 return STATUS_DEVICE_NOT_CONNECTED
;
1544 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1547 // retrieve device descriptor from device
1549 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1550 Status
= STATUS_SUCCESS
;
1554 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1559 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1560 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1562 if (Urb
->UrbHeader
.UsbdDeviceHandle
== PVOID(this))
1565 // request is for the root bus controller
1567 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1570 // get configuration descriptor, very retarded!
1572 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1575 // check if buffer can hold interface and endpoint descriptor
1577 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1582 Status
= STATUS_SUCCESS
;
1588 // copy interface descriptor template
1590 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1591 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1594 // copy end point descriptor template
1596 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1597 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1602 Status
= STATUS_SUCCESS
;
1608 // check if this is a valid usb device handle
1610 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1612 DPRINT1("[USBLIB] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1615 // invalid device handle
1617 return STATUS_DEVICE_NOT_CONNECTED
;
1623 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1625 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1630 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1635 Status
= STATUS_SUCCESS
;
1640 // perform work in IUSBDevice
1642 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1645 // store result size
1647 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1648 Status
= STATUS_SUCCESS
;
1652 case USB_STRING_DESCRIPTOR_TYPE
:
1657 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1658 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1662 // check if this is a valid usb device handle
1664 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1666 DPRINT1("[USBLIB] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1669 // invalid device handle
1671 return STATUS_DEVICE_NOT_CONNECTED
;
1677 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1680 // generate setup packet
1682 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1683 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1684 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1685 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1686 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1687 CtrlSetup
.bmRequestType
.B
= 0x80;
1690 // submit setup packet
1692 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1696 DPRINT1("[USBLIB] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1706 //-----------------------------------------------------------------------------------------
1708 CHubController::HandleClassEndpoint(
1712 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1714 PUSBDEVICE UsbDevice
;
1719 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1720 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1721 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1724 // check if this is a valid usb device handle
1726 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1728 DPRINT1("[USBLIB] HandleClassEndpoint invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1731 // invalid device handle
1733 return STATUS_DEVICE_NOT_CONNECTED
;
1739 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1742 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1743 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1744 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1745 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1746 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1747 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1748 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1749 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1750 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1753 // initialize setup packet
1755 CtrlSetup
.bmRequestType
.B
= 0x22; //FIXME: Const.
1756 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1757 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1758 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1759 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1761 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1764 // data direction is device to host
1766 CtrlSetup
.bmRequestType
.B
|= 0x80;
1773 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1776 // assert on failure
1778 PC_ASSERT(NT_SUCCESS(Status
));
1787 //-----------------------------------------------------------------------------------------
1789 CHubController::HandleVendorDevice(
1793 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1794 PUSBDEVICE UsbDevice
;
1795 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1797 DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1802 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1805 // check if this is a valid usb device handle
1807 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1809 DPRINT1("[USBLIB] HandleVendorDevice invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1812 // invalid device handle
1814 return STATUS_DEVICE_NOT_CONNECTED
;
1820 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1823 // initialize setup packet
1825 CtrlSetup
.bmRequestType
.B
= 0;
1826 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
1827 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_VENDOR
;
1828 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1829 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1830 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1831 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1833 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1836 // data direction is device to host
1838 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1844 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1845 PC_ASSERT(NT_SUCCESS(Status
));
1850 //-----------------------------------------------------------------------------------------
1852 CHubController::HandleSyncResetAndClearStall(
1856 NTSTATUS Status
= STATUS_SUCCESS
;
1857 PUSB_ENDPOINT EndpointDescriptor
;
1863 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1864 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1865 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1868 // check if this is a valid usb device handle
1870 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1872 DPRINT1("[USBLIB] HandleSyncResetAndClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1875 // invalid device handle
1877 return STATUS_DEVICE_NOT_CONNECTED
;
1883 Status
= HandleAbortPipe(Irp
, Urb
);
1884 if (!NT_SUCCESS(Status
))
1889 DPRINT1("[USBLIB] failed to reset pipe %x\n", Status
);
1894 // get endpoint descriptor
1896 EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbPipeRequest
.PipeHandle
;
1901 Type
= (EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1902 if (Type
!= USB_ENDPOINT_TYPE_ISOCHRONOUS
)
1907 Status
= HandleClearStall(Irp
, Urb
);
1909 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status
);
1912 // reset data toggle
1914 if (NT_SUCCESS(Status
))
1915 EndpointDescriptor
->DataToggle
= 0x0;
1923 //-----------------------------------------------------------------------------------------
1925 CHubController::HandleAbortPipe(
1930 PUSBDEVICE UsbDevice
;
1931 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1936 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1937 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1938 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1941 // check if this is a valid usb device handle
1943 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
1945 DPRINT1("[USBLIB] HandleAbortPipe invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
1948 // invalid device handle
1950 return STATUS_DEVICE_NOT_CONNECTED
;
1954 // get endpoint descriptor
1956 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
1961 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1967 Status
= UsbDevice
->AbortPipe(EndpointDescriptor
);
1968 DPRINT1("[USBLIB] URB_FUNCTION_ABORT_PIPE Status %x\n", Status
);
1977 //-----------------------------------------------------------------------------------------
1979 CHubController::HandleClearStall(
1983 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1985 PUSBDEVICE UsbDevice
;
1986 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1992 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1993 PC_ASSERT(Urb
->UrbHeader
.Length
== sizeof(struct _URB_PIPE_REQUEST
));
1994 PC_ASSERT(Urb
->UrbPipeRequest
.PipeHandle
);
1997 // check if this is a valid usb device handle
1999 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2001 DPRINT1("[USBLIB] HandleClearStall invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
2004 // invalid device handle
2006 return STATUS_DEVICE_NOT_CONNECTED
;
2010 // get endpoint descriptor
2012 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbPipeRequest
.PipeHandle
;
2017 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2018 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_CLEAR_STALL\n");
2021 // initialize setup packet
2023 CtrlSetup
.bmRequestType
.B
= 0x02;
2024 CtrlSetup
.bRequest
= USB_REQUEST_CLEAR_FEATURE
;
2025 CtrlSetup
.wValue
.W
= USB_FEATURE_ENDPOINT_STALL
;
2026 CtrlSetup
.wIndex
.W
= EndpointDescriptor
->bEndpointAddress
;
2027 CtrlSetup
.wLength
= 0;
2028 CtrlSetup
.wValue
.W
= 0;
2033 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, 0, 0);
2035 DPRINT1("[USBLIB] URB_FUNCTION_CLEAR_STALL Status %x\n", Status
);
2044 //-----------------------------------------------------------------------------------------
2046 CHubController::HandleClassInterface(
2050 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
2052 PUSBDEVICE UsbDevice
;
2057 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2058 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2059 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
2062 // check if this is a valid usb device handle
2064 if (!ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)))
2066 DPRINT1("[USBLIB] HandleClassInterface invalid device handle %p\n", Urb
->UrbHeader
.UsbdDeviceHandle
);
2069 // invalid device handle
2071 return STATUS_DEVICE_NOT_CONNECTED
;
2077 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
2080 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
2081 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
2082 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
2083 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2084 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
2085 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
2086 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
2087 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
2088 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
2091 // initialize setup packet
2093 CtrlSetup
.bmRequestType
.B
= 0x21;
2094 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
2095 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
2096 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
2097 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
2099 if (Urb
->UrbControlVendorClassRequest
.TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2102 // data direction is device to host
2104 CtrlSetup
.bmRequestType
.B
|= 0x80;
2110 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
2113 // assert on failure
2115 if (!NT_SUCCESS(Status
))
2120 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb
->UrbHeader
.Status
);
2129 //-----------------------------------------------------------------------------------------
2131 CHubController::HandleDeviceControl(
2132 IN PDEVICE_OBJECT DeviceObject
,
2135 PIO_STACK_LOCATION IoStack
;
2136 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
2138 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2141 // get current stack location
2143 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2146 // get device extension
2148 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
2151 // determine which request should be performed
2153 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
2155 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
2160 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
2163 switch (Urb
->UrbHeader
.Function
)
2165 case URB_FUNCTION_SYNC_RESET_PIPE
:
2166 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
2167 Status
= HandleSyncResetAndClearStall(Irp
, Urb
);
2169 case URB_FUNCTION_ABORT_PIPE
:
2170 Status
= HandleAbortPipe(Irp
, Urb
);
2172 case URB_FUNCTION_SYNC_CLEAR_STALL
:
2173 Status
= HandleClearStall(Irp
, Urb
);
2175 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
:
2176 Status
= HandleGetDescriptorFromInterface(Irp
, Urb
);
2178 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
2179 Status
= HandleGetDescriptor(Irp
, Urb
);
2181 case URB_FUNCTION_CLASS_DEVICE
:
2182 Status
= HandleClassDevice(Irp
, Urb
);
2184 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
2185 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
2186 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
2187 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
2189 case URB_FUNCTION_SELECT_CONFIGURATION
:
2190 Status
= HandleSelectConfiguration(Irp
, Urb
);
2192 case URB_FUNCTION_SELECT_INTERFACE
:
2193 Status
= HandleSelectInterface(Irp
, Urb
);
2195 case URB_FUNCTION_CLASS_OTHER
:
2196 Status
= HandleClassOther(Irp
, Urb
);
2198 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
2199 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
2201 case URB_FUNCTION_ISOCH_TRANSFER
:
2202 Status
= HandleIsochronousTransfer(Irp
, Urb
);
2204 case URB_FUNCTION_CLASS_INTERFACE
:
2205 Status
= HandleClassInterface(Irp
, Urb
);
2207 case URB_FUNCTION_CLASS_ENDPOINT
:
2208 Status
= HandleClassEndpoint(Irp
, Urb
);
2210 case URB_FUNCTION_VENDOR_DEVICE
:
2211 Status
= HandleVendorDevice(Irp
, Urb
);
2214 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
2218 // request completed
2222 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
2224 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2226 if (IoStack
->Parameters
.Others
.Argument1
)
2229 // store object as device handle
2231 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
2232 Status
= STATUS_SUCCESS
;
2237 // mis-behaving hub driver
2239 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2243 // request completed
2247 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
2249 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2252 // this is the first request send, it delivers the PDO to the caller
2254 if (IoStack
->Parameters
.Others
.Argument1
)
2257 // store root hub pdo object
2259 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
2262 if (IoStack
->Parameters
.Others
.Argument2
)
2265 // documentation claims to deliver the hcd controller object, although it is wrong
2267 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
2271 // request completed
2273 Status
= STATUS_SUCCESS
;
2276 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
2278 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2281 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2282 // requests this ioctl to deliver the number of presents.
2284 if (IoStack
->Parameters
.Others
.Argument1
)
2287 // FIXME / verify: there is only one hub
2289 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
2293 // request completed
2295 Status
= STATUS_SUCCESS
;
2296 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2299 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
2301 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2302 Status
= STATUS_SUCCESS
;
2307 DPRINT1("[USBLIB] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2308 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2309 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
2310 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2314 if (Status
!= STATUS_PENDING
)
2316 Irp
->IoStatus
.Status
= Status
;
2317 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2323 //-----------------------------------------------------------------------------------------
2325 CHubController::GetUsbHardware()
2330 //-----------------------------------------------------------------------------------------
2332 CHubController::AcquireDeviceAddress()
2335 ULONG DeviceAddress
;
2338 // acquire device lock
2340 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2345 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
2346 if (DeviceAddress
!= MAXULONG
)
2351 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2354 // device addresses start from 0x1 - 0xFF
2360 // release spin lock
2362 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2365 // return device address
2367 return DeviceAddress
;
2369 //-----------------------------------------------------------------------------------------
2371 CHubController::ReleaseDeviceAddress(
2372 ULONG DeviceAddress
)
2377 // acquire device lock
2379 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2384 PC_ASSERT(DeviceAddress
!= 0);
2387 // convert back to bit number
2394 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
2399 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2401 //-----------------------------------------------------------------------------------------
2403 CHubController::RemoveUsbDevice(
2404 PUSBDEVICE UsbDevice
)
2406 PUSBDEVICE_ENTRY DeviceEntry
;
2408 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2414 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2417 // point to first entry
2419 Entry
= m_UsbDeviceList
.Flink
;
2422 // find matching entry
2424 while(Entry
!= &m_UsbDeviceList
)
2429 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2432 // is it current entry
2434 if (DeviceEntry
->Device
== UsbDevice
)
2439 RemoveEntryList(Entry
);
2444 ExFreePoolWithTag(DeviceEntry
, TAG_USBLIB
);
2449 Status
= STATUS_SUCCESS
;
2456 Entry
= Entry
->Flink
;
2462 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2469 //-----------------------------------------------------------------------------------------
2471 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
2473 PUSBDEVICE_ENTRY DeviceEntry
;
2476 BOOLEAN Result
= FALSE
;
2481 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2484 // point to first entry
2486 Entry
= m_UsbDeviceList
.Flink
;
2489 // find matching entry
2491 while(Entry
!= &m_UsbDeviceList
)
2496 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
2499 // is it current entry
2501 if (DeviceEntry
->Device
== UsbDevice
)
2513 Entry
= Entry
->Flink
;
2519 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2528 //-----------------------------------------------------------------------------------------
2530 CHubController::AddUsbDevice(
2531 PUSBDEVICE UsbDevice
)
2533 PUSBDEVICE_ENTRY DeviceEntry
;
2537 // allocate device entry
2539 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBLIB
);
2545 return STATUS_INSUFFICIENT_RESOURCES
;
2551 DeviceEntry
->Device
= UsbDevice
;
2556 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2561 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
2564 // release spin lock
2566 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2571 return STATUS_SUCCESS
;
2574 //-----------------------------------------------------------------------------------------
2576 CHubController::SetNotification(
2577 PVOID CallbackContext
,
2578 PRH_INIT_CALLBACK CallbackRoutine
)
2583 // acquire hub controller lock
2585 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
2588 // now set the callback routine and context of the hub
2590 m_HubCallbackContext
= CallbackContext
;
2591 m_HubCallbackRoutine
= CallbackRoutine
;
2594 // release hub controller lock
2596 KeReleaseSpinLock(&m_Lock
, OldLevel
);
2599 //=================================================================================================
2601 // Generic Interface functions
2605 USBI_InterfaceReference(
2608 CHubController
* Controller
= (CHubController
*)BusContext
;
2610 DPRINT1("USBH_InterfaceReference\n");
2615 Controller
->AddRef();
2620 USBI_InterfaceDereference(
2623 CHubController
* Controller
= (CHubController
*)BusContext
;
2625 DPRINT1("USBH_InterfaceDereference\n");
2630 Controller
->Release();
2632 //=================================================================================================
2634 // USB Hub Interface functions
2638 USBHI_CreateUsbDevice(
2640 PUSB_DEVICE_HANDLE
*NewDevice
,
2641 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2645 PUSBDEVICE NewUsbDevice
;
2646 CHubController
* Controller
;
2649 DPRINT1("USBHI_CreateUsbDevice\n");
2652 // first get hub controller
2654 Controller
= (CHubController
*)BusContext
;
2659 PC_ASSERT(Controller
);
2660 PC_ASSERT(BusContext
== HubDeviceHandle
);
2663 // now allocate usb device
2665 Status
= CreateUSBDevice(&NewUsbDevice
);
2668 // check for success
2670 if (!NT_SUCCESS(Status
))
2673 // release controller
2675 Controller
->Release();
2676 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2681 // now initialize device
2683 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(), HubDeviceHandle
, PortNumber
, PortStatus
);
2686 // check for success
2688 if (!NT_SUCCESS(Status
))
2691 // release usb device
2693 NewUsbDevice
->Release();
2694 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2701 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2703 // check for success
2705 if (!NT_SUCCESS(Status
))
2708 // release usb device
2710 NewUsbDevice
->Release();
2712 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2719 *NewDevice
= NewUsbDevice
;
2724 return STATUS_SUCCESS
;
2729 USBHI_InitializeUsbDevice(
2731 PUSB_DEVICE_HANDLE DeviceHandle
)
2733 PUSBDEVICE UsbDevice
;
2734 CHubController
* Controller
;
2735 ULONG DeviceAddress
;
2739 DPRINT1("USBHI_InitializeUsbDevice\n");
2742 // first get controller
2744 Controller
= (CHubController
*)BusContext
;
2745 PC_ASSERT(Controller
);
2748 // get device object
2750 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2751 PC_ASSERT(UsbDevice
);
2754 // validate device handle
2756 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2758 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2761 // invalid device handle
2763 return STATUS_DEVICE_NOT_CONNECTED
;
2767 // now reserve an address
2769 DeviceAddress
= Controller
->AcquireDeviceAddress();
2772 // is the device address valid
2774 if (DeviceAddress
== MAXULONG
)
2777 // failed to get an device address from the device address pool
2779 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2780 return STATUS_DEVICE_DATA_ERROR
;
2786 // now set the device address
2788 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2790 if (NT_SUCCESS(Status
))
2793 }while(Index
++ < 3 );
2796 // check for failure
2798 if (!NT_SUCCESS(Status
))
2801 // failed to set device address
2803 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2808 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2813 return STATUS_DEVICE_DATA_ERROR
;
2819 return STATUS_SUCCESS
;
2824 USBHI_GetUsbDescriptors(
2826 PUSB_DEVICE_HANDLE DeviceHandle
,
2827 PUCHAR DeviceDescriptorBuffer
,
2828 PULONG DeviceDescriptorBufferLength
,
2829 PUCHAR ConfigDescriptorBuffer
,
2830 PULONG ConfigDescriptorBufferLength
)
2832 PUSBDEVICE UsbDevice
;
2833 CHubController
* Controller
;
2835 DPRINT1("USBHI_GetUsbDescriptors\n");
2840 PC_ASSERT(DeviceDescriptorBuffer
);
2841 PC_ASSERT(DeviceDescriptorBufferLength
);
2842 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2843 PC_ASSERT(ConfigDescriptorBufferLength
);
2844 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2847 // first get controller
2849 Controller
= (CHubController
*)BusContext
;
2850 PC_ASSERT(Controller
);
2854 // get device object
2856 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2857 PC_ASSERT(UsbDevice
);
2860 // validate device handle
2862 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2864 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2867 // invalid device handle
2869 return STATUS_DEVICE_NOT_CONNECTED
;
2873 // get device descriptor
2875 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2878 // store result length
2880 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2883 // get configuration descriptor
2885 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2888 // complete the request
2890 return STATUS_SUCCESS
;
2895 USBHI_RemoveUsbDevice(
2897 PUSB_DEVICE_HANDLE DeviceHandle
,
2900 PUSBDEVICE UsbDevice
;
2901 CHubController
* Controller
;
2904 DPRINT1("USBHI_RemoveUsbDevice\n");
2907 // first get controller
2909 Controller
= (CHubController
*)BusContext
;
2910 PC_ASSERT(Controller
);
2913 // get device object
2915 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2916 PC_ASSERT(UsbDevice
);
2919 // validate device handle
2921 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2923 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2926 // invalid device handle
2928 return STATUS_DEVICE_NOT_CONNECTED
;
2932 // check if there were flags passed
2934 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2937 // ignore flags for now
2939 return STATUS_SUCCESS
;
2945 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2946 if (!NT_SUCCESS(Status
))
2949 // invalid device handle
2951 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2953 return STATUS_DEVICE_NOT_CONNECTED
;
2957 // release usb device
2959 UsbDevice
->Release();
2964 return STATUS_SUCCESS
;
2969 USBHI_RestoreUsbDevice(
2971 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2972 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2974 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2975 CHubController
* Controller
;
2977 DPRINT1("USBHI_RestoreUsbDevice\n");
2980 // first get controller
2982 Controller
= (CHubController
*)BusContext
;
2983 PC_ASSERT(Controller
);
2986 // get device object
2988 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2989 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2990 PC_ASSERT(OldUsbDevice
);
2991 PC_ASSERT(NewDeviceHandle
);
2994 // validate device handle
2996 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2997 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2999 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
3000 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
3003 // remove old device handle
3005 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
3007 return STATUS_SUCCESS
;
3012 USBHI_QueryDeviceInformation(
3014 PUSB_DEVICE_HANDLE DeviceHandle
,
3015 PVOID DeviceInformationBuffer
,
3016 ULONG DeviceInformationBufferLength
,
3017 PULONG LengthReturned
)
3019 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
3020 PUSBDEVICE UsbDevice
;
3021 CHubController
* Controller
;
3023 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
3028 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
3029 PC_ASSERT(DeviceInformationBuffer
);
3030 PC_ASSERT(LengthReturned
);
3033 // get controller object
3035 Controller
= (CHubController
*)BusContext
;
3036 PC_ASSERT(Controller
);
3039 // get device object
3041 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3042 PC_ASSERT(UsbDevice
);
3044 if (BusContext
!= DeviceHandle
)
3047 // validate device handle
3049 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3051 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
3054 // invalid device handle
3056 return STATUS_DEVICE_NOT_CONNECTED
;
3060 // access information buffer
3062 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3065 // initialize with default values
3067 DeviceInfo
->InformationLevel
= 0;
3068 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3069 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
3070 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
3071 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
3072 DeviceInfo
->HubAddress
= 0; //FIXME
3073 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
3074 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
3075 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3078 // get device descriptor
3080 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
3083 // FIXME return pipe information
3087 // store result length
3089 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
3091 return STATUS_SUCCESS
;
3095 // access information buffer
3097 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
3100 // initialize with default values
3102 DeviceInfo
->InformationLevel
= 0;
3103 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
3104 DeviceInfo
->PortNumber
= 0;
3105 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
3106 DeviceInfo
->DeviceAddress
= 0;
3107 DeviceInfo
->HubAddress
= 0; //FIXME
3108 DeviceInfo
->DeviceSpeed
= UsbHighSpeed
; //FIXME
3109 DeviceInfo
->DeviceType
= Usb20Device
; //FIXME
3110 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
3113 // get device descriptor
3115 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
3118 // FIXME return pipe information
3122 // store result length
3125 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
3127 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
3132 return STATUS_SUCCESS
;
3137 USBHI_GetControllerInformation(
3139 PVOID ControllerInformationBuffer
,
3140 ULONG ControllerInformationBufferLength
,
3141 PULONG LengthReturned
)
3143 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
3145 DPRINT1("USBHI_GetControllerInformation\n");
3150 PC_ASSERT(ControllerInformationBuffer
);
3151 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
3154 // get controller info buffer
3156 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
3159 // FIXME only version 0 is supported for now
3161 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
3164 // fill in information
3166 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
3167 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
3168 ControllerInfo
->IsHighSpeedController
= TRUE
;
3171 // set length returned
3173 *LengthReturned
= ControllerInfo
->ActualLength
;
3178 return STATUS_SUCCESS
;
3183 USBHI_ControllerSelectiveSuspend(
3188 return STATUS_NOT_IMPLEMENTED
;
3193 USBHI_GetExtendedHubInformation(
3195 PDEVICE_OBJECT HubPhysicalDeviceObject
,
3196 PVOID HubInformationBuffer
,
3197 ULONG HubInformationBufferLength
,
3198 PULONG LengthReturned
)
3200 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
3201 CHubController
* Controller
;
3202 PUSBHARDWAREDEVICE Hardware
;
3204 ULONG NumPort
, Dummy2
;
3208 DPRINT1("USBHI_GetExtendedHubInformation\n");
3213 PC_ASSERT(HubInformationBuffer
);
3214 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
3215 PC_ASSERT(LengthReturned
);
3218 // get hub controller
3220 Controller
= (CHubController
*)BusContext
;
3221 PC_ASSERT(Controller
);
3224 // get usb hardware device
3226 Hardware
= Controller
->GetUsbHardware();
3229 // retrieve number of ports
3231 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
3232 if (!NT_SUCCESS(Status
))
3235 // failed to get hardware details, ouch ;)
3237 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
3242 // get hub information buffer
3244 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
3247 // initialize hub information
3249 HubInfo
->InformationLevel
= 0;
3254 HubInfo
->NumberOfPorts
= NumPort
;
3257 // initialize port information
3259 for(Index
= 0; Index
< NumPort
; Index
++)
3261 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
3262 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
3263 HubInfo
->Port
[Index
].VidOverride
= 0;
3264 HubInfo
->Port
[Index
].PidOverride
= 0;
3265 HubInfo
->Port
[Index
].PortAttributes
= USB_PORTATTR_SHARED_USB2
; //FIXME
3269 // store result length
3272 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
3274 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
3280 return STATUS_SUCCESS
;
3285 USBHI_GetRootHubSymbolicName(
3287 PVOID HubSymNameBuffer
,
3288 ULONG HubSymNameBufferLength
,
3289 PULONG HubSymNameActualLength
)
3292 return STATUS_NOT_IMPLEMENTED
;
3297 USBHI_GetDeviceBusContext(
3298 PVOID HubBusContext
,
3307 USBHI_Initialize20Hub(
3309 PUSB_DEVICE_HANDLE HubDeviceHandle
,
3312 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle
, TtCount
);
3313 return STATUS_SUCCESS
;
3318 USBHI_RootHubInitNotification(
3320 PVOID CallbackContext
,
3321 PRH_INIT_CALLBACK CallbackRoutine
)
3323 CHubController
* Controller
;
3325 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
3328 // get controller object
3330 Controller
= (CHubController
*)BusContext
;
3331 PC_ASSERT(Controller
);
3334 // set notification routine
3336 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
3339 // FIXME: determine when to perform callback
3341 CallbackRoutine(CallbackContext
);
3346 return STATUS_SUCCESS
;
3351 USBHI_FlushTransfers(
3360 USBHI_SetDeviceHandleData(
3363 PDEVICE_OBJECT UsbDevicePdo
)
3365 PUSBDEVICE UsbDevice
;
3366 CHubController
* Controller
;
3371 Controller
= (CHubController
*)BusContext
;
3372 PC_ASSERT(Controller
);
3375 // get device handle
3377 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
3380 // validate device handle
3382 if (!Controller
->ValidateUsbDevice(UsbDevice
))
3384 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
3394 // usbhub sends this request as a part of the Pnp startup sequence
3395 // looks like we need apply a dragon voodoo to fixup the device stack
3396 // otherwise usbhub will cause a bugcheck
3398 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
3403 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
3406 // should be usbstor
3407 // fixup device stack voodoo part #2
3409 UsbDevicePdo
->AttachedDevice
->StackSize
++;
3412 // set device handle data
3414 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
3418 //=================================================================================================
3420 // USB Device Interface functions
3425 USBDI_GetUSBDIVersion(
3427 PUSBD_VERSION_INFORMATION VersionInformation
,
3428 PULONG HcdCapabilites
)
3430 CHubController
* Controller
;
3431 PUSBHARDWAREDEVICE Device
;
3432 ULONG Speed
, Dummy2
;
3435 DPRINT1("USBDI_GetUSBDIVersion\n");
3440 Controller
= (CHubController
*)BusContext
;
3445 Device
= Controller
->GetUsbHardware();
3448 if (VersionInformation
)
3451 // windows xp supported
3453 VersionInformation
->USBDI_Version
= 0x00000500;
3458 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3461 // store speed details
3463 VersionInformation
->Supported_USB_Version
= Speed
;
3467 // no flags supported
3469 *HcdCapabilites
= 0;
3476 PULONG CurrentFrame
)
3479 return STATUS_NOT_IMPLEMENTED
;
3484 USBDI_SubmitIsoOutUrb(
3489 return STATUS_NOT_IMPLEMENTED
;
3494 USBDI_QueryBusInformation(
3497 PVOID BusInformationBuffer
,
3498 PULONG BusInformationBufferLength
,
3499 PULONG BusInformationActualLength
)
3502 return STATUS_NOT_IMPLEMENTED
;
3507 USBDI_IsDeviceHighSpeed(
3510 CHubController
* Controller
;
3511 PUSBHARDWAREDEVICE Device
;
3512 ULONG Speed
, Dummy2
;
3515 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3520 Controller
= (CHubController
*)BusContext
;
3525 Device
= Controller
->GetUsbHardware();
3531 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
3534 // USB 2.0 equals 0x200
3536 return (Speed
== 0x200);
3549 return STATUS_NOT_IMPLEMENTED
;
3553 CHubController::HandleQueryInterface(
3554 PIO_STACK_LOCATION IoStack
)
3556 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
3557 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
3558 UNICODE_STRING GuidBuffer
;
3561 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
3564 // get request parameters
3566 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
3567 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3572 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
3574 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3577 // version not supported
3579 return STATUS_NOT_SUPPORTED
;
3583 // Interface version 0
3585 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3587 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3588 InterfaceHub
->BusContext
= PVOID(this);
3589 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
3590 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
3594 // Interface version 1
3596 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3598 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
3599 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
3600 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
3601 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
3602 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
3603 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
3607 // Interface version 2
3609 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3611 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3612 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3613 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3614 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3615 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3616 InterfaceHub
->Initialize20Hub
= USBHI_Initialize20Hub
;
3621 // Interface version 3
3623 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3625 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3629 // Interface version 4
3631 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3633 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3637 // Interface version 5
3639 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3641 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3645 // request completed
3647 return STATUS_SUCCESS
;
3649 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3652 // get request parameters
3654 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3655 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3660 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3662 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3665 // version not supported
3667 return STATUS_NOT_SUPPORTED
;
3671 // interface version 0
3673 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3675 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3676 InterfaceDI
->BusContext
= PVOID(this);
3677 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3678 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3679 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3680 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3681 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3682 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3686 // interface version 1
3688 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3690 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3694 // interface version 2
3696 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3698 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3702 // request completed
3704 return STATUS_SUCCESS
;
3709 // convert guid to string
3711 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3712 if (NT_SUCCESS(Status
))
3717 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3722 RtlFreeUnicodeString(&GuidBuffer
);
3725 return STATUS_NOT_SUPPORTED
;
3729 CHubController::SetDeviceInterface(
3732 NTSTATUS Status
= STATUS_SUCCESS
;
3737 // register device interface
3739 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3741 if (NT_SUCCESS(Status
))
3744 // now enable the device interface
3746 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3751 m_InterfaceEnabled
= TRUE
;
3754 else if (m_InterfaceEnabled
)
3757 // disable device interface
3759 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3761 if (NT_SUCCESS(Status
))
3764 // now delete interface string
3766 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3770 // disable interface
3772 m_InterfaceEnabled
= FALSE
;
3778 return STATUS_SUCCESS
;
3782 CHubController::CreatePDO(
3783 PDRIVER_OBJECT DriverObject
,
3784 PDEVICE_OBJECT
* OutDeviceObject
)
3786 WCHAR CharDeviceName
[64];
3788 ULONG UsbDeviceNumber
= 0;
3789 UNICODE_STRING DeviceName
;
3794 // construct device name
3796 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3799 // initialize device name
3801 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3806 Status
= IoCreateDevice(DriverObject
,
3807 sizeof(COMMON_DEVICE_EXTENSION
),
3809 FILE_DEVICE_CONTROLLER
,
3814 /* check for success */
3815 if (NT_SUCCESS(Status
))
3819 // is there a device object with that same name
3821 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3824 // Try the next name
3831 // bail out on other errors
3833 if (!NT_SUCCESS(Status
))
3835 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3840 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3843 // fixup device stack voodoo part #1
3845 (*OutDeviceObject
)->StackSize
++;
3855 CreateHubController(
3856 PHUBCONTROLLER
*OutHcdController
)
3858 PHUBCONTROLLER This
;
3861 // allocate controller
3863 This
= new(NonPagedPool
, TAG_USBLIB
) CHubController(0);
3867 // failed to allocate
3869 return STATUS_INSUFFICIENT_RESOURCES
;
3873 // add reference count
3880 *OutHcdController
= (PHUBCONTROLLER
)This
;
3885 return STATUS_SUCCESS
;
3888 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3890 CHubController
* This
;
3892 This
= (CHubController
*)Context
;
3896 Irp
= This
->m_PendingSCEIrp
;
3899 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3903 This
->m_PendingSCEIrp
= NULL
;
3904 This
->QueryStatusChageEndpoint(Irp
);
3906 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3907 Irp
->IoStatus
.Information
= 0;
3909 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);