2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbohci/hub_controller.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 VOID
StatusChangeEndpointCallBack(
17 class CHubController
: public IHubController
,
21 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
23 STDMETHODIMP_(ULONG
) AddRef()
25 InterlockedIncrement(&m_Ref
);
28 STDMETHODIMP_(ULONG
) Release()
30 InterlockedDecrement(&m_Ref
);
40 // IHubController interface functions
41 virtual NTSTATUS
Initialize(IN PDRIVER_OBJECT DriverObject
, IN PHCDCONTROLLER Controller
, IN PUSBHARDWAREDEVICE Device
, IN BOOLEAN IsRootHubDevice
, IN ULONG DeviceAddress
);
42 virtual NTSTATUS
GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
);
43 virtual NTSTATUS
GetHubControllerSymbolicLink(ULONG BufferLength
, PVOID Buffer
, PULONG RequiredLength
);
45 // IDispatchIrp interface functions
46 virtual NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
47 virtual NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
48 virtual NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
51 NTSTATUS
HandleQueryInterface(PIO_STACK_LOCATION IoStack
);
52 NTSTATUS
SetDeviceInterface(BOOLEAN bEnable
);
53 NTSTATUS
CreatePDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
54 PUSBHARDWAREDEVICE
GetUsbHardware();
55 ULONG
AcquireDeviceAddress();
56 VOID
ReleaseDeviceAddress(ULONG DeviceAddress
);
57 BOOLEAN
ValidateUsbDevice(PUSBDEVICE UsbDevice
);
58 NTSTATUS
AddUsbDevice(PUSBDEVICE UsbDevice
);
59 NTSTATUS
RemoveUsbDevice(PUSBDEVICE UsbDevice
);
60 VOID
SetNotification(PVOID CallbackContext
, PRH_INIT_CALLBACK CallbackRoutine
);
61 // internal ioctl routines
62 NTSTATUS
HandleGetDescriptor(IN OUT PIRP Irp
, PURB Urb
);
63 NTSTATUS
HandleClassDevice(IN OUT PIRP Irp
, PURB Urb
);
64 NTSTATUS
HandleGetStatusFromDevice(IN OUT PIRP Irp
, PURB Urb
);
65 NTSTATUS
HandleSelectConfiguration(IN OUT PIRP Irp
, PURB Urb
);
66 NTSTATUS
HandleSelectInterface(IN OUT PIRP Irp
, PURB Urb
);
67 NTSTATUS
HandleClassOther(IN OUT PIRP Irp
, PURB Urb
);
68 NTSTATUS
HandleClassInterface(IN OUT PIRP Irp
, PURB Urb
);
69 NTSTATUS
HandleClassEndpoint(IN OUT PIRP Irp
, PURB Urb
);
70 NTSTATUS
HandleBulkOrInterruptTransfer(IN OUT PIRP Irp
, PURB Urb
);
71 NTSTATUS
HandleIsochronousTransfer(IN OUT PIRP Irp
, PURB Urb
);
73 friend VOID
StatusChangeEndpointCallBack(PVOID Context
);
75 // constructor / destructor
76 CHubController(IUnknown
*OuterUnknown
){}
77 virtual ~CHubController(){}
81 PHCDCONTROLLER m_Controller
;
82 PUSBHARDWAREDEVICE m_Hardware
;
83 BOOLEAN m_IsRootHubDevice
;
84 ULONG m_DeviceAddress
;
86 BOOLEAN m_InterfaceEnabled
;
87 UNICODE_STRING m_HubDeviceInterfaceString
;
89 PDEVICE_OBJECT m_HubControllerDeviceObject
;
90 PDRIVER_OBJECT m_DriverObject
;
92 PVOID m_HubCallbackContext
;
93 PRH_INIT_CALLBACK m_HubCallbackRoutine
;
95 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
98 RTL_BITMAP m_DeviceAddressBitmap
;
99 PULONG m_DeviceAddressBitmapBuffer
;
100 LIST_ENTRY m_UsbDeviceList
;
101 PIRP m_PendingSCEIrp
;
104 BOOLEAN
QueryStatusChageEndpoint(PIRP Irp
);
111 }USBDEVICE_ENTRY
, *PUSBDEVICE_ENTRY
;
113 /* Lifted from Linux with slight changes */
114 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
117 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
118 0x00, 0x20, /* bcdUSB; v1.1 */
119 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
120 0x01, /* bDeviceSubClass; */
121 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
122 0x08, /* bMaxPacketSize0; 8 Bytes */
123 /* Fill Vendor and Product in when init root hub */
124 0x00, 0x00, /* idVendor; */
125 0x00, 0x00, /* idProduct; */
126 0x00, 0x00, /* bcdDevice */
127 0x00, /* iManufacturer; */
128 0x00, /* iProduct; */
129 0x00, /* iSerialNumber; */
130 0x01 /* bNumConfigurations; */
134 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR
=
136 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
137 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
138 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
142 0x40, /* self powered */
146 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR
=
148 sizeof(USB_INTERFACE_DESCRIPTOR
), /* bLength */
149 USB_INTERFACE_DESCRIPTOR_TYPE
, /* bDescriptorType; Interface */
150 0, /* bInterfaceNumber; */
151 0, /* bAlternateSetting; */
152 0x1, /* bNumEndpoints; */
153 0x09, /* bInterfaceClass; HUB_CLASSCODE */
154 0x01, /* bInterfaceSubClass; */
155 0x00, /* bInterfaceProtocol: */
156 0x00, /* iInterface; */
159 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR
=
161 sizeof(USB_ENDPOINT_DESCRIPTOR
), /* bLength */
162 USB_ENDPOINT_DESCRIPTOR_TYPE
, /* bDescriptorType */
163 0x81, /* bEndPointAddress */
164 USB_ENDPOINT_TYPE_INTERRUPT
, /* bmAttributes */
165 0x01, /* wMaxPacketSize */
169 //----------------------------------------------------------------------------------------
172 CHubController::QueryInterface(
176 return STATUS_UNSUCCESSFUL
;
178 //----------------------------------------------------------------------------------------
180 CHubController::Initialize(
181 IN PDRIVER_OBJECT DriverObject
,
182 IN PHCDCONTROLLER Controller
,
183 IN PUSBHARDWAREDEVICE Device
,
184 IN BOOLEAN IsRootHubDevice
,
185 IN ULONG DeviceAddress
)
188 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
189 USHORT VendorID
, DeviceID
;
192 DPRINT1("CHubController::Initialize\n");
195 // initialize members
197 m_Controller
= Controller
;
199 m_IsRootHubDevice
= IsRootHubDevice
;
200 m_DeviceAddress
= DeviceAddress
;
201 m_DriverObject
= DriverObject
;
202 KeInitializeSpinLock(&m_Lock
);
203 InitializeListHead(&m_UsbDeviceList
);
206 // allocate device address bitmap buffer
208 m_DeviceAddressBitmapBuffer
= (PULONG
)ExAllocatePoolWithTag(NonPagedPool
, 16, TAG_USBOHCI
);
209 if (!m_DeviceAddressBitmapBuffer
)
214 return STATUS_INSUFFICIENT_RESOURCES
;
218 // initialize device address bitmap
220 RtlInitializeBitMap(&m_DeviceAddressBitmap
, m_DeviceAddressBitmapBuffer
, 128);
221 RtlClearAllBits(&m_DeviceAddressBitmap
);
227 Status
= CreatePDO(m_DriverObject
, &m_HubControllerDeviceObject
);
228 if (!NT_SUCCESS(Status
))
231 // failed to create hub device object
237 // get device extension
239 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_HubControllerDeviceObject
->DeviceExtension
;
242 // initialize device extension
244 DeviceExtension
->IsFDO
= FALSE
;
245 DeviceExtension
->IsHub
= TRUE
; //FIXME
246 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
249 // intialize device descriptor
251 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR
) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
252 RtlMoveMemory(&m_DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
254 if (NT_SUCCESS(m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &Dummy1
, &Dummy1
)))
257 // update device descriptor
259 m_DeviceDescriptor
.idVendor
= VendorID
;
260 m_DeviceDescriptor
.idProduct
= DeviceID
;
261 m_DeviceDescriptor
.bcdUSB
= 0x110; //FIXME
265 // Set the SCE Callback that the Hardware Device will call on port status change
267 Device
->SetStatusChangeEndpointCallBack((PVOID
)StatusChangeEndpointCallBack
, this);
272 m_HubControllerDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
274 return STATUS_SUCCESS
;
278 // Queries the ports to see if there has been a device connected or removed.
281 CHubController::QueryStatusChageEndpoint(
284 ULONG PortCount
, PortId
;
285 PIO_STACK_LOCATION IoStack
;
286 USHORT PortStatus
, PortChange
;
288 PUCHAR TransferBuffer
;
289 UCHAR Changed
= FALSE
;
292 // get current stack location
294 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
300 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
304 // Get the number of ports and check each one for device connected
306 m_Hardware
->GetDeviceDetails(NULL
, NULL
, &PortCount
, NULL
);
307 DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
, Urb
->UrbBulkOrInterruptTransfer
.TransferFlags
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
309 TransferBuffer
= (PUCHAR
)Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
;
314 for (PortId
= 0; PortId
< PortCount
; PortId
++)
316 m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
318 DPRINT1("Port %d: Status %x, Change %x\n", PortId
, PortStatus
, PortChange
);
322 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
326 DPRINT1("Change state on port %d\n", PortId
);
327 // Set the value for the port number
328 *TransferBuffer
= 1 << ((PortId
+ 1) & 7);
336 //-----------------------------------------------------------------------------------------
338 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT
* HubDeviceObject
)
341 // store controller object
343 *HubDeviceObject
= m_HubControllerDeviceObject
;
345 return STATUS_SUCCESS
;
347 //-----------------------------------------------------------------------------------------
349 CHubController::GetHubControllerSymbolicLink(
352 PULONG RequiredLength
)
354 if (!m_InterfaceEnabled
)
357 // device interface not yet enabled
359 return STATUS_UNSUCCESSFUL
;
362 if (BufferLength
< (ULONG
)m_HubDeviceInterfaceString
.Length
- 8)
366 // length is without '\??\'
368 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
373 return STATUS_BUFFER_OVERFLOW
;
377 // copy symbolic link
379 RtlCopyMemory(Buffer
, &m_HubDeviceInterfaceString
.Buffer
[4], m_HubDeviceInterfaceString
.Length
- 8);
382 // store length, length is without '\??\'
384 *RequiredLength
= m_HubDeviceInterfaceString
.Length
- 8;
389 return STATUS_SUCCESS
;
392 //-----------------------------------------------------------------------------------------
394 CHubController::HandlePnp(
395 IN PDEVICE_OBJECT DeviceObject
,
398 PIO_STACK_LOCATION IoStack
;
399 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
400 PDEVICE_CAPABILITIES DeviceCapabilities
;
401 PPNP_BUS_INFORMATION BusInformation
;
402 PDEVICE_RELATIONS DeviceRelations
;
404 ULONG Index
= 0, Length
;
405 USHORT VendorID
, DeviceID
;
406 ULONG HiSpeed
, NumPorts
;
411 // get device extension
413 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
418 ASSERT(DeviceExtension
->IsFDO
== FALSE
);
421 // get current stack location
423 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
425 switch(IoStack
->MinorFunction
)
427 case IRP_MN_START_DEVICE
:
429 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
431 // register device interface
433 Status
= SetDeviceInterface(TRUE
);
436 case IRP_MN_QUERY_ID
:
438 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack
->Parameters
.QueryId
.IdType
);
440 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
447 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
449 if (HiSpeed
== 0x200)
454 swprintf(Buffer
, L
"USB\\ROOT_HUB20");
461 swprintf(Buffer
, L
"USB\\ROOT_HUB");
464 DPRINT1("Name %S\n", Buffer
);
469 Length
= (wcslen(Buffer
) + 1);
474 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), TAG_USBOHCI
);
481 Status
= STATUS_INSUFFICIENT_RESOURCES
;
488 wcscpy(DeviceName
, Buffer
);
493 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
494 Status
= STATUS_SUCCESS
;
497 Status
= STATUS_UNSUCCESSFUL
;
502 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
509 Status
= m_Hardware
->GetDeviceDetails(&VendorID
, &DeviceID
, &NumPorts
, &HiSpeed
);
511 if (!NT_SUCCESS(Status
))
513 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status
);
518 if (HiSpeed
== 0x200)
523 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
524 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
525 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
532 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID
, DeviceID
) + 1;
533 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID
, DeviceID
) + 1;
534 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB") + 1;
537 Buffer
[Index
] = UNICODE_NULL
;
541 DPRINT1("Name %S\n", Buffer
);
546 DeviceName
= (LPWSTR
)ExAllocatePoolWithTag(PagedPool
, Index
* sizeof(WCHAR
), TAG_USBOHCI
);
553 Status
= STATUS_INSUFFICIENT_RESOURCES
;
560 RtlMoveMemory(DeviceName
, Buffer
, Index
* sizeof(WCHAR
));
565 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceName
;
566 Status
= STATUS_SUCCESS
;
570 Status
= STATUS_SUCCESS
;
573 case IRP_MN_QUERY_CAPABILITIES
:
575 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
577 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
579 DeviceCapabilities
->LockSupported
= FALSE
;
580 DeviceCapabilities
->EjectSupported
= FALSE
;
581 DeviceCapabilities
->Removable
= FALSE
;
582 DeviceCapabilities
->DockDevice
= FALSE
;
583 DeviceCapabilities
->UniqueID
= FALSE
;
584 DeviceCapabilities
->SilentInstall
= FALSE
;
585 DeviceCapabilities
->RawDeviceOK
= FALSE
;
586 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
587 DeviceCapabilities
->Address
= 0;
588 DeviceCapabilities
->UINumber
= 0;
589 DeviceCapabilities
->DeviceD2
= 1;
592 DeviceCapabilities
->HardwareDisabled
= FALSE
;
593 DeviceCapabilities
->NoDisplayInUI
= FALSE
;
594 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
595 for (Index
= 0; Index
< PowerSystemMaximum
; Index
++)
596 DeviceCapabilities
->DeviceState
[Index
] = PowerDeviceD3
;
597 DeviceCapabilities
->DeviceWake
= PowerDeviceUnspecified
;
598 DeviceCapabilities
->D1Latency
= 0;
599 DeviceCapabilities
->D2Latency
= 0;
600 DeviceCapabilities
->D3Latency
= 0;
602 Status
= STATUS_SUCCESS
;
605 case IRP_MN_QUERY_INTERFACE
:
607 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
610 // handle device interface requests
612 Status
= HandleQueryInterface(IoStack
);
615 case IRP_MN_REMOVE_DEVICE
:
617 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
620 // deactivate device interface for BUS PDO
622 SetDeviceInterface(FALSE
);
625 // complete the request first
627 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
628 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
633 IoDeleteDevice(m_HubControllerDeviceObject
);
638 m_HubControllerDeviceObject
= 0;
643 return STATUS_SUCCESS
;
645 case IRP_MN_QUERY_DEVICE_RELATIONS
:
647 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack
->Parameters
.QueryDeviceRelations
.Type
);
649 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
652 // allocate device relations
654 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), TAG_USBOHCI
);
655 if (!DeviceRelations
)
660 Status
= STATUS_INSUFFICIENT_RESOURCES
;
665 // initialize device relations
667 DeviceRelations
->Count
= 1;
668 DeviceRelations
->Objects
[0] = DeviceObject
;
669 ObReferenceObject(DeviceObject
);
674 Status
= STATUS_SUCCESS
;
675 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
682 Status
= Irp
->IoStatus
.Status
;
686 case IRP_MN_QUERY_BUS_INFORMATION
:
688 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
691 // allocate buffer for bus information
693 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
699 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_USB
, sizeof(GUID
));
704 BusInformation
->LegacyBusType
= PNPBus
;
705 BusInformation
->BusNumber
= 0;
707 Status
= STATUS_SUCCESS
;
708 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
715 Status
= STATUS_INSUFFICIENT_RESOURCES
;
719 case IRP_MN_STOP_DEVICE
:
721 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
725 Status
= STATUS_SUCCESS
;
731 // ignore request with default status
733 Status
= Irp
->IoStatus
.Status
;
741 Irp
->IoStatus
.Status
= Status
;
742 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
750 //-----------------------------------------------------------------------------------------
752 CHubController::HandlePower(
753 IN PDEVICE_OBJECT DeviceObject
,
757 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
758 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
759 return STATUS_NOT_IMPLEMENTED
;
762 //-----------------------------------------------------------------------------------------
764 CHubController::HandleIsochronousTransfer(
768 PUSBDEVICE UsbDevice
;
769 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
772 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
774 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbIsochronousTransfer
.PipeHandle
;
778 DPRINT1("No EndpointDesc\n");
779 Urb
->UrbIsochronousTransfer
.Hdr
.Status
= USBD_STATUS_INVALID_PIPE_HANDLE
;
780 return STATUS_INVALID_PARAMETER
;
786 ASSERT(EndPointDesc
);
787 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_ISOCHRONOUS
);
790 // check if this is a valid usb device handle
792 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
797 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
799 return UsbDevice
->SubmitIrp(Irp
);
802 //-----------------------------------------------------------------------------------------
804 CHubController::HandleBulkOrInterruptTransfer(
808 PUSBDEVICE UsbDevice
;
809 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
811 // First check if the request is for the Status Change Endpoint
815 // Is the Request for the root hub
817 if (Urb
->UrbHeader
.UsbdDeviceHandle
== 0)
819 ASSERT(m_PendingSCEIrp
== NULL
);
820 if (QueryStatusChageEndpoint(Irp
))
822 StatusChangeEndpointCallBack(this);
823 return STATUS_SUCCESS
;
827 // Else pend the IRP, to be completed when a device connects or disconnects.
829 DPRINT1("Pending SCE Irp\n");;
830 m_PendingSCEIrp
= Irp
;
831 IoMarkIrpPending(Irp
);
832 return STATUS_PENDING
;
836 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
838 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
843 ASSERT(EndPointDesc
);
844 ASSERT((EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
|| (EndPointDesc
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
);
847 // check if this is a valid usb device handle
849 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
854 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
856 return UsbDevice
->SubmitIrp(Irp
);
859 //-----------------------------------------------------------------------------------------
861 CHubController::HandleClassOther(
865 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
866 USHORT PortStatus
= 0, PortChange
= 0;
871 DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
);
874 // get number of ports available
876 Status
= m_Hardware
->GetDeviceDetails(NULL
, NULL
, &NumPort
, NULL
);
877 PC_ASSERT(Status
== STATUS_SUCCESS
);
882 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.Index
- 1 < (USHORT
)NumPort
);
885 // port range reported start from 1 -n
886 // convert back port id so it matches the hardware
888 PortId
= Urb
->UrbControlVendorClassRequest
.Index
- 1;
891 // check request code
893 switch(Urb
->UrbControlVendorClassRequest
.Request
)
895 case USB_REQUEST_GET_STATUS
:
900 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
== sizeof(USHORT
) * 2);
901 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
906 Status
= m_Hardware
->GetPortStatus(PortId
, &PortStatus
, &PortChange
);
908 if (NT_SUCCESS(Status
))
911 // request contains buffer of 2 ushort which are used from submitting port status and port change status
913 DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId
, PortStatus
, PortChange
);
914 Buffer
= (PUSHORT
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
917 // store status, then port change
919 *Buffer
= PortStatus
;
921 *Buffer
= PortChange
;
929 case USB_REQUEST_CLEAR_FEATURE
:
931 switch (Urb
->UrbControlVendorClassRequest
.Value
)
933 case C_PORT_CONNECTION
:
934 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_CONNECTION
);
937 Status
= m_Hardware
->ClearPortStatus(PortId
, C_PORT_RESET
);
940 DPRINT("Unknown Value for Clear Feature %x \n", Urb
->UrbControlVendorClassRequest
.Value
);
944 Status
= STATUS_SUCCESS
;
947 case USB_REQUEST_SET_FEATURE
:
950 // request set feature
952 switch(Urb
->UrbControlVendorClassRequest
.Value
)
959 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_ENABLE
);
966 // set suspend port feature
968 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_SUSPEND
);
974 // set power feature on port
976 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_POWER
);
983 // reset port feature
985 Status
= m_Hardware
->SetPortFeature(PortId
, PORT_RESET
);
986 PC_ASSERT(Status
== STATUS_SUCCESS
);
990 DPRINT1("Unsupported request id %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
996 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
998 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1003 //-----------------------------------------------------------------------------------------
1005 CHubController::HandleSelectConfiguration(
1009 PUSBDEVICE UsbDevice
;
1010 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
1013 // is the request for the Root Hub
1015 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1018 // FIXME: support setting device to unconfigured state
1020 PC_ASSERT(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
);
1023 // set device handle
1025 Urb
->UrbSelectConfiguration
.ConfigurationHandle
= (PVOID
)&ROOTHUB2_CONFIGURATION_DESCRIPTOR
;
1028 // copy interface info
1030 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
1032 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)&ROOTHUB2_INTERFACE_DESCRIPTOR
;
1033 InterfaceInfo
->Class
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceClass
;
1034 InterfaceInfo
->SubClass
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceSubClass
;
1035 InterfaceInfo
->Protocol
= ROOTHUB2_INTERFACE_DESCRIPTOR
.bInterfaceProtocol
;
1036 InterfaceInfo
->Reserved
= 0;
1041 PC_ASSERT(InterfaceInfo
->NumberOfPipes
== 1);
1046 InterfaceInfo
->Pipes
[0].MaximumPacketSize
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.wMaxPacketSize
;
1047 InterfaceInfo
->Pipes
[0].EndpointAddress
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bEndpointAddress
;
1048 InterfaceInfo
->Pipes
[0].Interval
= ROOTHUB2_ENDPOINT_DESCRIPTOR
.bInterval
;
1049 InterfaceInfo
->Pipes
[0].PipeType
= (USBD_PIPE_TYPE
)(ROOTHUB2_ENDPOINT_DESCRIPTOR
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
1050 InterfaceInfo
->Pipes
[0].PipeHandle
= (PVOID
)&ROOTHUB2_ENDPOINT_DESCRIPTOR
;
1052 return STATUS_SUCCESS
;
1057 // check if this is a valid usb device handle
1059 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1064 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1067 // select configuration
1069 return UsbDevice
->SelectConfiguration(Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
, &Urb
->UrbSelectConfiguration
.Interface
, &Urb
->UrbSelectConfiguration
.ConfigurationHandle
);
1073 //-----------------------------------------------------------------------------------------
1075 CHubController::HandleSelectInterface(
1079 PUSBDEVICE UsbDevice
;
1084 PC_ASSERT(Urb
->UrbSelectInterface
.ConfigurationHandle
);
1087 // is the request for the Root Hub
1089 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1092 // no op for root hub
1094 return STATUS_SUCCESS
;
1099 // check if this is a valid usb device handle
1101 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1106 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1111 return UsbDevice
->SelectInterface(Urb
->UrbSelectInterface
.ConfigurationHandle
, &Urb
->UrbSelectInterface
.Interface
);
1115 //-----------------------------------------------------------------------------------------
1117 CHubController::HandleGetStatusFromDevice(
1126 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1127 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBufferLength
>= sizeof(USHORT
));
1128 PC_ASSERT(Urb
->UrbControlGetStatusRequest
.TransferBuffer
);
1129 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
);
1132 // get status buffer
1134 Status
= (PUSHORT
)Urb
->UrbControlGetStatusRequest
.TransferBuffer
;
1137 // FIXME need more flags ?
1139 *Status
= USB_PORT_STATUS_CONNECT
;
1144 return STATUS_SUCCESS
;
1147 //-----------------------------------------------------------------------------------------
1149 CHubController::HandleClassDevice(
1153 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1154 PUSB_HUB_DESCRIPTOR UsbHubDescriptor
;
1155 ULONG PortCount
, Dummy2
;
1158 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb
->UrbControlVendorClassRequest
.Request
, Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1161 // check class request type
1163 switch(Urb
->UrbControlVendorClassRequest
.Request
)
1165 case USB_REQUEST_GET_DESCRIPTOR
:
1167 switch (Urb
->UrbControlVendorClassRequest
.Value
>> 8)
1169 case USB_DEVICE_CLASS_RESERVED
: // FALL THROUGH
1170 case USB_DEVICE_CLASS_HUB
:
1175 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1176 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
>= sizeof(USB_HUB_DESCRIPTOR
));
1179 // get hub descriptor
1181 UsbHubDescriptor
= (PUSB_HUB_DESCRIPTOR
)Urb
->UrbControlVendorClassRequest
.TransferBuffer
;
1184 // one hub is handled
1186 UsbHubDescriptor
->bDescriptorLength
= sizeof(USB_HUB_DESCRIPTOR
);
1187 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= sizeof(USB_HUB_DESCRIPTOR
);
1190 // type should 0x29 according to msdn
1192 UsbHubDescriptor
->bDescriptorType
= 0x29;
1197 Status
= m_Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &PortCount
, &Dummy2
);
1198 PC_ASSERT(Status
== STATUS_SUCCESS
);
1201 // FIXME: retrieve values
1203 UsbHubDescriptor
->bNumberOfPorts
= (UCHAR
)PortCount
;
1204 UsbHubDescriptor
->wHubCharacteristics
= 0x00;
1205 UsbHubDescriptor
->bPowerOnToPowerGood
= 0x01;
1206 UsbHubDescriptor
->bHubControlCurrent
= 0x00;
1211 Status
= STATUS_SUCCESS
;
1215 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Value
>> 8);
1221 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb
->UrbControlVendorClassRequest
.Request
);
1226 //-----------------------------------------------------------------------------------------
1228 CHubController::HandleGetDescriptor(
1232 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1233 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
1234 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1236 PUSBDEVICE UsbDevice
;
1239 DPRINT("CHubController::HandleGetDescriptor\n");
1242 // check descriptor type
1244 switch(Urb
->UrbControlDescriptorRequest
.DescriptorType
)
1246 case USB_DEVICE_DESCRIPTOR_TYPE
:
1251 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
1252 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1254 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1257 // copy root hub device descriptor
1259 RtlCopyMemory((PUCHAR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
1260 Status
= STATUS_SUCCESS
;
1265 // check if this is a valid usb device handle
1267 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1272 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1275 // retrieve device descriptor from device
1277 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1278 Status
= STATUS_SUCCESS
;
1282 case USB_CONFIGURATION_DESCRIPTOR_TYPE
:
1287 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1288 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1290 if (Urb
->UrbHeader
.UsbdDeviceHandle
== NULL
)
1293 // request is for the root bus controller
1295 RtlCopyMemory(Urb
->UrbControlDescriptorRequest
.TransferBuffer
, &ROOTHUB2_CONFIGURATION_DESCRIPTOR
, sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1298 // get configuration descriptor, very retarded!
1300 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
;
1303 // check if buffer can hold interface and endpoint descriptor
1305 if (ConfigurationDescriptor
->wTotalLength
> Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1310 Status
= STATUS_SUCCESS
;
1316 // copy interface descriptor template
1318 Buffer
= (PUCHAR
)(ConfigurationDescriptor
+ 1);
1319 RtlCopyMemory(Buffer
, &ROOTHUB2_INTERFACE_DESCRIPTOR
, sizeof(USB_INTERFACE_DESCRIPTOR
));
1322 // copy end point descriptor template
1324 Buffer
+= sizeof(USB_INTERFACE_DESCRIPTOR
);
1325 RtlCopyMemory(Buffer
, &ROOTHUB2_ENDPOINT_DESCRIPTOR
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1330 Status
= STATUS_SUCCESS
;
1336 // check if this is a valid usb device handle
1338 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1343 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1345 if (sizeof(USB_CONFIGURATION_DESCRIPTOR
) > Urb
->UrbControlDescriptorRequest
.TransferBufferLength
)
1350 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= UsbDevice
->GetConfigurationDescriptorsLength();
1355 Status
= STATUS_SUCCESS
;
1360 // perform work in IUSBDevice
1362 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)Urb
->UrbControlDescriptorRequest
.TransferBuffer
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, &Length
);
1365 // store result size
1367 Urb
->UrbControlDescriptorRequest
.TransferBufferLength
= Length
;
1368 Status
= STATUS_SUCCESS
;
1372 case USB_STRING_DESCRIPTOR_TYPE
:
1377 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1378 PC_ASSERT(Urb
->UrbControlDescriptorRequest
.TransferBufferLength
);
1382 // check if this is a valid usb device handle
1384 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1389 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1392 // generate setup packet
1394 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1395 CtrlSetup
.wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1396 CtrlSetup
.wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1397 CtrlSetup
.wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1398 CtrlSetup
.wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1399 CtrlSetup
.bmRequestType
.B
= 0x80;
1402 // submit setup packet
1404 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlDescriptorRequest
.TransferBufferLength
, Urb
->UrbControlDescriptorRequest
.TransferBuffer
);
1408 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb
->UrbControlDescriptorRequest
.DescriptorType
);
1418 //-----------------------------------------------------------------------------------------
1420 CHubController::HandleClassEndpoint(
1424 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1426 PUSBDEVICE UsbDevice
;
1431 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1432 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1433 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1436 // check if this is a valid usb device handle
1438 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1443 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1446 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1447 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1448 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1449 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1450 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1451 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1452 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1453 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1454 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1457 // initialize setup packet
1459 CtrlSetup
.bmRequestType
.B
= 0xa2; //FIXME: Const.
1460 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1461 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1462 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1463 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1468 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1471 // assert on failure
1473 PC_ASSERT(NT_SUCCESS(Status
));
1482 //-----------------------------------------------------------------------------------------
1484 CHubController::HandleClassInterface(
1488 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1490 PUSBDEVICE UsbDevice
;
1495 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1496 PC_ASSERT(Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1497 PC_ASSERT(Urb
->UrbHeader
.UsbdDeviceHandle
);
1500 // check if this is a valid usb device handle
1502 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
)));
1507 UsbDevice
= PUSBDEVICE(Urb
->UrbHeader
.UsbdDeviceHandle
);
1510 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1511 DPRINT1("TransferFlags %x\n", Urb
->UrbControlVendorClassRequest
.TransferFlags
);
1512 DPRINT1("TransferBufferLength %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferLength
);
1513 DPRINT1("TransferBuffer %x\n", Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1514 DPRINT1("TransferBufferMDL %x\n", Urb
->UrbControlVendorClassRequest
.TransferBufferMDL
);
1515 DPRINT1("RequestTypeReservedBits %x\n", Urb
->UrbControlVendorClassRequest
.RequestTypeReservedBits
);
1516 DPRINT1("Request %x\n", Urb
->UrbControlVendorClassRequest
.Request
);
1517 DPRINT1("Value %x\n", Urb
->UrbControlVendorClassRequest
.Value
);
1518 DPRINT1("Index %x\n", Urb
->UrbControlVendorClassRequest
.Index
);
1521 // initialize setup packet
1523 CtrlSetup
.bmRequestType
.B
= 0xa1; //FIXME: Const.
1524 CtrlSetup
.bRequest
= Urb
->UrbControlVendorClassRequest
.Request
;
1525 CtrlSetup
.wValue
.W
= Urb
->UrbControlVendorClassRequest
.Value
;
1526 CtrlSetup
.wIndex
.W
= Urb
->UrbControlVendorClassRequest
.Index
;
1527 CtrlSetup
.wLength
= Urb
->UrbControlVendorClassRequest
.TransferBufferLength
;
1532 Status
= UsbDevice
->SubmitSetupPacket(&CtrlSetup
, Urb
->UrbControlVendorClassRequest
.TransferBufferLength
, Urb
->UrbControlVendorClassRequest
.TransferBuffer
);
1535 // assert on failure
1537 PC_ASSERT(NT_SUCCESS(Status
));
1546 //-----------------------------------------------------------------------------------------
1548 CHubController::HandleDeviceControl(
1549 IN PDEVICE_OBJECT DeviceObject
,
1552 PIO_STACK_LOCATION IoStack
;
1553 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
1555 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1558 // get current stack location
1560 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1563 // get device extension
1565 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1568 // determine which request should be performed
1570 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1572 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
1577 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1580 switch (Urb
->UrbHeader
.Function
)
1582 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1583 Status
= HandleGetDescriptor(Irp
, Urb
);
1585 case URB_FUNCTION_CLASS_DEVICE
:
1586 Status
= HandleClassDevice(Irp
, Urb
);
1588 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1589 Status
= HandleGetStatusFromDevice(Irp
, Urb
);
1591 case URB_FUNCTION_SELECT_CONFIGURATION
:
1592 Status
= HandleSelectConfiguration(Irp
, Urb
);
1594 case URB_FUNCTION_SELECT_INTERFACE
:
1595 Status
= HandleSelectInterface(Irp
, Urb
);
1597 case URB_FUNCTION_CLASS_OTHER
:
1598 Status
= HandleClassOther(Irp
, Urb
);
1600 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
1601 Status
= HandleBulkOrInterruptTransfer(Irp
, Urb
);
1603 case URB_FUNCTION_ISOCH_TRANSFER
:
1604 Status
= HandleIsochronousTransfer(Irp
, Urb
);
1606 case URB_FUNCTION_CLASS_INTERFACE
:
1607 Status
= HandleClassInterface(Irp
, Urb
);
1609 case URB_FUNCTION_CLASS_ENDPOINT
:
1610 Status
= HandleClassEndpoint(Irp
, Urb
);
1613 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
1617 // request completed
1621 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
1623 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
1625 if (IoStack
->Parameters
.Others
.Argument1
)
1628 // store object as device handle
1630 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= (PVOID
)this;
1631 Status
= STATUS_SUCCESS
;
1636 // mis-behaving hub driver
1638 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1642 // request completed
1646 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
1648 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1651 // this is the first request send, it delivers the PDO to the caller
1653 if (IoStack
->Parameters
.Others
.Argument1
)
1656 // store root hub pdo object
1658 *(PVOID
*)IoStack
->Parameters
.Others
.Argument1
= DeviceObject
;
1661 if (IoStack
->Parameters
.Others
.Argument2
)
1664 // documentation claims to deliver the hcd controller object, although it is wrong
1666 *(PVOID
*)IoStack
->Parameters
.Others
.Argument2
= DeviceObject
;
1670 // request completed
1672 Status
= STATUS_SUCCESS
;
1675 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
1677 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1680 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1681 // requests this ioctl to deliver the number of presents.
1683 if (IoStack
->Parameters
.Others
.Argument1
)
1686 // FIXME / verify: there is only one hub
1688 *(PULONG
)IoStack
->Parameters
.Others
.Argument1
= 1;
1692 // request completed
1694 Status
= STATUS_SUCCESS
;
1695 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1698 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
1700 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1701 Status
= STATUS_SUCCESS
;
1706 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1707 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1708 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
1709 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
1713 if (Status
!= STATUS_PENDING
)
1715 Irp
->IoStatus
.Status
= Status
;
1716 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1722 //-----------------------------------------------------------------------------------------
1724 CHubController::GetUsbHardware()
1729 //-----------------------------------------------------------------------------------------
1731 CHubController::AcquireDeviceAddress()
1734 ULONG DeviceAddress
;
1737 // acquire device lock
1739 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1744 DeviceAddress
= RtlFindClearBits(&m_DeviceAddressBitmap
, 1, 0);
1745 if (DeviceAddress
!= MAXULONG
)
1750 RtlSetBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1753 // device addresses start from 0x1 - 0xFF
1759 // release spin lock
1761 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1764 // return device address
1766 return DeviceAddress
;
1768 //-----------------------------------------------------------------------------------------
1770 CHubController::ReleaseDeviceAddress(
1771 ULONG DeviceAddress
)
1776 // acquire device lock
1778 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1783 PC_ASSERT(DeviceAddress
!= 0);
1786 // convert back to bit number
1793 RtlClearBits(&m_DeviceAddressBitmap
, DeviceAddress
, 1);
1798 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1800 //-----------------------------------------------------------------------------------------
1802 CHubController::RemoveUsbDevice(
1803 PUSBDEVICE UsbDevice
)
1805 PUSBDEVICE_ENTRY DeviceEntry
;
1807 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1813 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1816 // point to first entry
1818 Entry
= m_UsbDeviceList
.Flink
;
1821 // find matching entry
1823 while(Entry
!= &m_UsbDeviceList
)
1828 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1831 // is it current entry
1833 if (DeviceEntry
->Device
== UsbDevice
)
1838 RemoveEntryList(Entry
);
1843 ExFreePoolWithTag(DeviceEntry
, TAG_USBOHCI
);
1848 Status
= STATUS_SUCCESS
;
1855 Entry
= Entry
->Flink
;
1861 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1868 //-----------------------------------------------------------------------------------------
1870 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice
)
1872 PUSBDEVICE_ENTRY DeviceEntry
;
1875 BOOLEAN Result
= FALSE
;
1880 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1883 // point to first entry
1885 Entry
= m_UsbDeviceList
.Flink
;
1888 // find matching entry
1890 while(Entry
!= &m_UsbDeviceList
)
1895 DeviceEntry
= (PUSBDEVICE_ENTRY
)CONTAINING_RECORD(Entry
, USBDEVICE_ENTRY
, Entry
);
1898 // is it current entry
1900 if (DeviceEntry
->Device
== UsbDevice
)
1912 Entry
= Entry
->Flink
;
1918 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1927 //-----------------------------------------------------------------------------------------
1929 CHubController::AddUsbDevice(
1930 PUSBDEVICE UsbDevice
)
1932 PUSBDEVICE_ENTRY DeviceEntry
;
1936 // allocate device entry
1938 DeviceEntry
= (PUSBDEVICE_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USBDEVICE_ENTRY
), TAG_USBOHCI
);
1944 return STATUS_INSUFFICIENT_RESOURCES
;
1950 DeviceEntry
->Device
= UsbDevice
;
1955 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1960 InsertTailList(&m_UsbDeviceList
, &DeviceEntry
->Entry
);
1963 // release spin lock
1965 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1970 return STATUS_SUCCESS
;
1973 //-----------------------------------------------------------------------------------------
1975 CHubController::SetNotification(
1976 PVOID CallbackContext
,
1977 PRH_INIT_CALLBACK CallbackRoutine
)
1982 // acquire hub controller lock
1984 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
1987 // now set the callback routine and context of the hub
1989 m_HubCallbackContext
= CallbackContext
;
1990 m_HubCallbackRoutine
= CallbackRoutine
;
1993 // release hub controller lock
1995 KeReleaseSpinLock(&m_Lock
, OldLevel
);
1998 //=================================================================================================
2000 // Generic Interface functions
2004 USBI_InterfaceReference(
2007 CHubController
* Controller
= (CHubController
*)BusContext
;
2009 DPRINT1("USBH_InterfaceReference\n");
2014 Controller
->AddRef();
2019 USBI_InterfaceDereference(
2022 CHubController
* Controller
= (CHubController
*)BusContext
;
2024 DPRINT1("USBH_InterfaceDereference\n");
2029 Controller
->Release();
2031 //=================================================================================================
2033 // USB Hub Interface functions
2037 USBHI_CreateUsbDevice(
2039 PUSB_DEVICE_HANDLE
*NewDevice
,
2040 PUSB_DEVICE_HANDLE HubDeviceHandle
,
2044 PUSBDEVICE NewUsbDevice
;
2045 CHubController
* Controller
;
2048 DPRINT1("USBHI_CreateUsbDevice\n");
2051 // first get hub controller
2053 Controller
= (CHubController
*)BusContext
;
2058 PC_ASSERT(Controller
);
2059 PC_ASSERT(BusContext
== HubDeviceHandle
);
2062 // now allocate usb device
2064 Status
= CreateUSBDevice(&NewUsbDevice
);
2067 // check for success
2069 if (!NT_SUCCESS(Status
))
2072 // release controller
2074 Controller
->Release();
2075 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status
);
2080 // now initialize device
2082 Status
= NewUsbDevice
->Initialize(PHUBCONTROLLER(Controller
), Controller
->GetUsbHardware(),PVOID(Controller
), PortNumber
, PortStatus
);
2085 // check for success
2087 if (!NT_SUCCESS(Status
))
2090 // release usb device
2092 NewUsbDevice
->Release();
2093 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status
);
2100 Status
= Controller
->AddUsbDevice(NewUsbDevice
);
2102 // check for success
2104 if (!NT_SUCCESS(Status
))
2107 // release usb device
2109 NewUsbDevice
->Release();
2111 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status
);
2118 *NewDevice
= NewUsbDevice
;
2123 return STATUS_SUCCESS
;
2128 USBHI_InitializeUsbDevice(
2130 PUSB_DEVICE_HANDLE DeviceHandle
)
2132 PUSBDEVICE UsbDevice
;
2133 CHubController
* Controller
;
2134 ULONG DeviceAddress
;
2138 DPRINT1("USBHI_InitializeUsbDevice\n");
2141 // first get controller
2143 Controller
= (CHubController
*)BusContext
;
2144 PC_ASSERT(Controller
);
2147 // get device object
2149 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2150 PC_ASSERT(UsbDevice
);
2153 // validate device handle
2155 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2157 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle
);
2160 // invalid device handle
2162 return STATUS_DEVICE_NOT_CONNECTED
;
2166 // now reserve an address
2168 DeviceAddress
= Controller
->AcquireDeviceAddress();
2171 // is the device address valid
2173 if (DeviceAddress
== MAXULONG
)
2176 // failed to get an device address from the device address pool
2178 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2179 return STATUS_DEVICE_DATA_ERROR
;
2185 // now set the device address
2187 Status
= UsbDevice
->SetDeviceAddress((UCHAR
)DeviceAddress
);
2189 if (NT_SUCCESS(Status
))
2192 }while(Index
++ < 3 );
2195 // check for failure
2197 if (!NT_SUCCESS(Status
))
2200 // failed to set device address
2202 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status
);
2207 Controller
->ReleaseDeviceAddress(DeviceAddress
);
2212 return STATUS_DEVICE_DATA_ERROR
;
2218 return STATUS_SUCCESS
;
2223 USBHI_GetUsbDescriptors(
2225 PUSB_DEVICE_HANDLE DeviceHandle
,
2226 PUCHAR DeviceDescriptorBuffer
,
2227 PULONG DeviceDescriptorBufferLength
,
2228 PUCHAR ConfigDescriptorBuffer
,
2229 PULONG ConfigDescriptorBufferLength
)
2231 PUSBDEVICE UsbDevice
;
2232 CHubController
* Controller
;
2234 DPRINT1("USBHI_GetUsbDescriptors\n");
2239 PC_ASSERT(DeviceDescriptorBuffer
);
2240 PC_ASSERT(DeviceDescriptorBufferLength
);
2241 PC_ASSERT(*DeviceDescriptorBufferLength
>= sizeof(USB_DEVICE_DESCRIPTOR
));
2242 PC_ASSERT(ConfigDescriptorBufferLength
);
2243 PC_ASSERT(*ConfigDescriptorBufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
2246 // first get controller
2248 Controller
= (CHubController
*)BusContext
;
2249 PC_ASSERT(Controller
);
2253 // get device object
2255 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2256 PC_ASSERT(UsbDevice
);
2259 // validate device handle
2261 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2263 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle
);
2266 // invalid device handle
2268 return STATUS_DEVICE_NOT_CONNECTED
;
2272 // get device descriptor
2274 UsbDevice
->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR
)DeviceDescriptorBuffer
);
2277 // store result length
2279 *DeviceDescriptorBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
2282 // get configuration descriptor
2284 UsbDevice
->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR
)ConfigDescriptorBuffer
, *ConfigDescriptorBufferLength
, ConfigDescriptorBufferLength
);
2287 // complete the request
2289 return STATUS_SUCCESS
;
2294 USBHI_RemoveUsbDevice(
2296 PUSB_DEVICE_HANDLE DeviceHandle
,
2299 PUSBDEVICE UsbDevice
;
2300 CHubController
* Controller
;
2303 DPRINT1("USBHI_RemoveUsbDevice\n");
2306 // first get controller
2308 Controller
= (CHubController
*)BusContext
;
2309 PC_ASSERT(Controller
);
2312 // get device object
2314 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2315 PC_ASSERT(UsbDevice
);
2318 // validate device handle
2320 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2322 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle
);
2325 // invalid device handle
2327 return STATUS_DEVICE_NOT_CONNECTED
;
2331 // check if there were flags passed
2333 if (Flags
& USBD_KEEP_DEVICE_DATA
|| Flags
& USBD_MARK_DEVICE_BUSY
)
2336 // ignore flags for now
2338 return STATUS_SUCCESS
;
2344 Status
= Controller
->RemoveUsbDevice(UsbDevice
);
2345 if (!NT_SUCCESS(Status
))
2348 // invalid device handle
2350 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice
);
2352 return STATUS_DEVICE_NOT_CONNECTED
;
2356 // release usb device
2358 UsbDevice
->Release();
2363 return STATUS_SUCCESS
;
2368 USBHI_RestoreUsbDevice(
2370 PUSB_DEVICE_HANDLE OldDeviceHandle
,
2371 PUSB_DEVICE_HANDLE NewDeviceHandle
)
2373 PUSBDEVICE OldUsbDevice
, NewUsbDevice
;
2374 CHubController
* Controller
;
2376 DPRINT1("USBHI_RestoreUsbDevice\n");
2379 // first get controller
2381 Controller
= (CHubController
*)BusContext
;
2382 PC_ASSERT(Controller
);
2385 // get device object
2387 OldUsbDevice
= (PUSBDEVICE
)OldDeviceHandle
;
2388 NewUsbDevice
= (PUSBDEVICE
)NewDeviceHandle
;
2389 PC_ASSERT(OldUsbDevice
);
2390 PC_ASSERT(NewDeviceHandle
);
2393 // validate device handle
2395 PC_ASSERT(Controller
->ValidateUsbDevice(NewUsbDevice
));
2396 PC_ASSERT(Controller
->ValidateUsbDevice(OldUsbDevice
));
2398 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice
->GetDeviceAddress());
2399 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice
->GetDeviceAddress());
2402 // remove old device handle
2404 USBHI_RemoveUsbDevice(BusContext
, OldDeviceHandle
, 0);
2406 return STATUS_SUCCESS
;
2411 USBHI_QueryDeviceInformation(
2413 PUSB_DEVICE_HANDLE DeviceHandle
,
2414 PVOID DeviceInformationBuffer
,
2415 ULONG DeviceInformationBufferLength
,
2416 PULONG LengthReturned
)
2418 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2419 PUSBDEVICE UsbDevice
;
2420 CHubController
* Controller
;
2422 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext
);
2427 PC_ASSERT(DeviceInformationBufferLength
>= sizeof(USB_DEVICE_INFORMATION_0
));
2428 PC_ASSERT(DeviceInformationBuffer
);
2429 PC_ASSERT(LengthReturned
);
2432 // get controller object
2434 Controller
= (CHubController
*)BusContext
;
2435 PC_ASSERT(Controller
);
2438 // get device object
2440 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2441 PC_ASSERT(UsbDevice
);
2443 if (BusContext
!= DeviceHandle
)
2446 // validate device handle
2448 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2450 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle
);
2453 // invalid device handle
2455 return STATUS_DEVICE_NOT_CONNECTED
;
2459 // access information buffer
2461 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2464 // initialize with default values
2466 DeviceInfo
->InformationLevel
= 0;
2467 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2468 DeviceInfo
->PortNumber
= UsbDevice
->GetPort();
2469 DeviceInfo
->CurrentConfigurationValue
= UsbDevice
->GetConfigurationValue();
2470 DeviceInfo
->DeviceAddress
= UsbDevice
->GetDeviceAddress();
2471 DeviceInfo
->HubAddress
= 0; //FIXME
2472 DeviceInfo
->DeviceSpeed
= UsbDevice
->GetSpeed();
2473 DeviceInfo
->DeviceType
= UsbDevice
->GetType();
2474 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2477 // get device descriptor
2479 UsbDevice
->GetDeviceDescriptor(&DeviceInfo
->DeviceDescriptor
);
2482 // FIXME return pipe information
2486 // store result length
2488 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
);
2490 return STATUS_SUCCESS
;
2494 // access information buffer
2496 DeviceInfo
= (PUSB_DEVICE_INFORMATION_0
)DeviceInformationBuffer
;
2499 // initialize with default values
2501 DeviceInfo
->InformationLevel
= 0;
2502 DeviceInfo
->ActualLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2503 DeviceInfo
->PortNumber
= 0;
2504 DeviceInfo
->CurrentConfigurationValue
= 0; //FIXME;
2505 DeviceInfo
->DeviceAddress
= 0;
2506 DeviceInfo
->HubAddress
= 0; //FIXME
2507 DeviceInfo
->DeviceSpeed
= UsbFullSpeed
; //FIXME
2508 DeviceInfo
->DeviceType
= Usb11Device
; //FIXME
2509 DeviceInfo
->NumberOfOpenPipes
= 0; //FIXME
2512 // get device descriptor
2514 RtlMoveMemory(&DeviceInfo
->DeviceDescriptor
, ROOTHUB2_DEVICE_DESCRIPTOR
, sizeof(USB_DEVICE_DESCRIPTOR
));
2517 // FIXME return pipe information
2521 // store result length
2524 *LengthReturned
= FIELD_OFFSET(USB_DEVICE_INFORMATION_0
, PipeList
[DeviceInfo
->NumberOfOpenPipes
]);
2526 *LengthReturned
= sizeof(USB_DEVICE_INFORMATION_0
) + (DeviceInfo
->NumberOfOpenPipes
> 1 ? (DeviceInfo
->NumberOfOpenPipes
- 1) * sizeof(USB_PIPE_INFORMATION_0
) : 0);
2531 return STATUS_SUCCESS
;
2536 USBHI_GetControllerInformation(
2538 PVOID ControllerInformationBuffer
,
2539 ULONG ControllerInformationBufferLength
,
2540 PULONG LengthReturned
)
2542 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo
;
2544 DPRINT1("USBHI_GetControllerInformation\n");
2549 PC_ASSERT(ControllerInformationBuffer
);
2550 PC_ASSERT(ControllerInformationBufferLength
>= sizeof(USB_CONTROLLER_INFORMATION_0
));
2553 // get controller info buffer
2555 ControllerInfo
= (PUSB_CONTROLLER_INFORMATION_0
)ControllerInformationBuffer
;
2558 // FIXME only version 0 is supported for now
2560 PC_ASSERT(ControllerInfo
->InformationLevel
== 0);
2563 // fill in information
2565 ControllerInfo
->ActualLength
= sizeof(USB_CONTROLLER_INFORMATION_0
);
2566 ControllerInfo
->SelectiveSuspendEnabled
= FALSE
; //FIXME
2567 ControllerInfo
->IsHighSpeedController
= FALSE
;
2570 // set length returned
2572 *LengthReturned
= ControllerInfo
->ActualLength
;
2577 return STATUS_SUCCESS
;
2582 USBHI_ControllerSelectiveSuspend(
2587 return STATUS_NOT_IMPLEMENTED
;
2592 USBHI_GetExtendedHubInformation(
2594 PDEVICE_OBJECT HubPhysicalDeviceObject
,
2595 PVOID HubInformationBuffer
,
2596 ULONG HubInformationBufferLength
,
2597 PULONG LengthReturned
)
2599 PUSB_EXTHUB_INFORMATION_0 HubInfo
;
2600 CHubController
* Controller
;
2601 PUSBHARDWAREDEVICE Hardware
;
2603 ULONG NumPort
, Dummy2
;
2607 DPRINT1("USBHI_GetExtendedHubInformation\n");
2612 PC_ASSERT(HubInformationBuffer
);
2613 PC_ASSERT(HubInformationBufferLength
== sizeof(USB_EXTHUB_INFORMATION_0
));
2614 PC_ASSERT(LengthReturned
);
2617 // get hub controller
2619 Controller
= (CHubController
*)BusContext
;
2620 PC_ASSERT(Controller
);
2623 // get usb hardware device
2625 Hardware
= Controller
->GetUsbHardware();
2628 // retrieve number of ports
2630 Status
= Hardware
->GetDeviceDetails(&Dummy1
, &Dummy1
, &NumPort
, &Dummy2
);
2631 if (!NT_SUCCESS(Status
))
2634 // failed to get hardware details, ouch ;)
2636 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status
);
2641 // get hub information buffer
2643 HubInfo
= (PUSB_EXTHUB_INFORMATION_0
)HubInformationBuffer
;
2646 // initialize hub information
2648 HubInfo
->InformationLevel
= 0;
2653 HubInfo
->NumberOfPorts
= NumPort
;
2656 // initialize port information
2658 for(Index
= 0; Index
< NumPort
; Index
++)
2660 HubInfo
->Port
[Index
].PhysicalPortNumber
= Index
+ 1;
2661 HubInfo
->Port
[Index
].PortLabelNumber
= Index
+ 1;
2662 HubInfo
->Port
[Index
].VidOverride
= 0;
2663 HubInfo
->Port
[Index
].PidOverride
= 0;
2664 HubInfo
->Port
[Index
].PortAttributes
= 0; //FIXME
2668 // store result length
2671 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
[HubInfo
->NumberOfPorts
]);
2673 *LengthReturned
= FIELD_OFFSET(USB_EXTHUB_INFORMATION_0
, Port
) + sizeof(USB_EXTPORT_INFORMATION_0
) * HubInfo
->NumberOfPorts
;
2679 return STATUS_SUCCESS
;
2684 USBHI_GetRootHubSymbolicName(
2686 PVOID HubSymNameBuffer
,
2687 ULONG HubSymNameBufferLength
,
2688 PULONG HubSymNameActualLength
)
2691 return STATUS_NOT_IMPLEMENTED
;
2696 USBHI_GetDeviceBusContext(
2697 PVOID HubBusContext
,
2706 USBHI_RootHubInitNotification(
2708 PVOID CallbackContext
,
2709 PRH_INIT_CALLBACK CallbackRoutine
)
2711 CHubController
* Controller
;
2713 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext
);
2716 // get controller object
2718 Controller
= (CHubController
*)BusContext
;
2719 PC_ASSERT(Controller
);
2722 // set notification routine
2724 Controller
->SetNotification(CallbackContext
, CallbackRoutine
);
2727 // FIXME: determine when to perform callback
2729 CallbackRoutine(CallbackContext
);
2734 return STATUS_SUCCESS
;
2739 USBHI_FlushTransfers(
2748 USBHI_SetDeviceHandleData(
2751 PDEVICE_OBJECT UsbDevicePdo
)
2753 PUSBDEVICE UsbDevice
;
2754 CHubController
* Controller
;
2759 Controller
= (CHubController
*)BusContext
;
2760 PC_ASSERT(Controller
);
2763 // get device handle
2765 UsbDevice
= (PUSBDEVICE
)DeviceHandle
;
2768 // validate device handle
2770 if (!Controller
->ValidateUsbDevice(UsbDevice
))
2772 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle
);
2782 // usbhub sends this request as a part of the Pnp startup sequence
2783 // looks like we need apply a dragon voodoo to fixup the device stack
2784 // otherwise usbhub will cause a bugcheck
2786 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo
);
2791 PC_ASSERT(UsbDevicePdo
->AttachedDevice
);
2794 // should be usbstor
2795 // fixup device stack voodoo part #2
2797 UsbDevicePdo
->AttachedDevice
->StackSize
++;
2800 // set device handle data
2802 UsbDevice
->SetDeviceHandleData(UsbDevicePdo
);
2806 //=================================================================================================
2808 // USB Device Interface functions
2813 USBDI_GetUSBDIVersion(
2815 PUSBD_VERSION_INFORMATION VersionInformation
,
2816 PULONG HcdCapabilites
)
2818 CHubController
* Controller
;
2819 PUSBHARDWAREDEVICE Device
;
2820 ULONG Speed
, Dummy2
;
2823 DPRINT1("USBDI_GetUSBDIVersion\n");
2828 Controller
= (CHubController
*)BusContext
;
2833 Device
= Controller
->GetUsbHardware();
2836 if (VersionInformation
)
2839 // windows xp supported
2841 VersionInformation
->USBDI_Version
= 0x00000500;
2846 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2849 // store speed details
2851 VersionInformation
->Supported_USB_Version
= Speed
;
2855 // no flags supported
2857 *HcdCapabilites
= 0;
2864 PULONG CurrentFrame
)
2867 return STATUS_NOT_IMPLEMENTED
;
2872 USBDI_SubmitIsoOutUrb(
2877 return STATUS_NOT_IMPLEMENTED
;
2882 USBDI_QueryBusInformation(
2885 PVOID BusInformationBuffer
,
2886 PULONG BusInformationBufferLength
,
2887 PULONG BusInformationActualLength
)
2890 return STATUS_NOT_IMPLEMENTED
;
2895 USBDI_IsDeviceHighSpeed(
2898 CHubController
* Controller
;
2899 PUSBHARDWAREDEVICE Device
;
2900 ULONG Speed
, Dummy2
;
2903 DPRINT1("USBDI_IsDeviceHighSpeed\n");
2908 Controller
= (CHubController
*)BusContext
;
2913 Device
= Controller
->GetUsbHardware();
2919 Device
->GetDeviceDetails(&Dummy1
, &Dummy1
, &Dummy2
, &Speed
);
2922 // USB 2.0 equals 0x200
2924 return (Speed
== 0x200);
2937 return STATUS_NOT_IMPLEMENTED
;
2941 CHubController::HandleQueryInterface(
2942 PIO_STACK_LOCATION IoStack
)
2944 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
2945 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
2946 UNICODE_STRING GuidBuffer
;
2949 if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_HUB_GUID
))
2952 // get request parameters
2954 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)IoStack
->Parameters
.QueryInterface
.Interface
;
2955 InterfaceHub
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
2960 if (IoStack
->Parameters
.QueryInterface
.Version
>= 6)
2962 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
2965 // version not supported
2967 return STATUS_NOT_SUPPORTED
;
2971 // Interface version 0
2973 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
2975 InterfaceHub
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
2976 InterfaceHub
->BusContext
= PVOID(this);
2977 InterfaceHub
->InterfaceReference
= USBI_InterfaceReference
;
2978 InterfaceHub
->InterfaceDereference
= USBI_InterfaceDereference
;
2982 // Interface version 1
2984 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
2986 InterfaceHub
->CreateUsbDevice
= USBHI_CreateUsbDevice
;
2987 InterfaceHub
->InitializeUsbDevice
= USBHI_InitializeUsbDevice
;
2988 InterfaceHub
->GetUsbDescriptors
= USBHI_GetUsbDescriptors
;
2989 InterfaceHub
->RemoveUsbDevice
= USBHI_RemoveUsbDevice
;
2990 InterfaceHub
->RestoreUsbDevice
= USBHI_RestoreUsbDevice
;
2991 InterfaceHub
->QueryDeviceInformation
= USBHI_QueryDeviceInformation
;
2995 // Interface version 2
2997 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
2999 InterfaceHub
->GetControllerInformation
= USBHI_GetControllerInformation
;
3000 InterfaceHub
->ControllerSelectiveSuspend
= USBHI_ControllerSelectiveSuspend
;
3001 InterfaceHub
->GetExtendedHubInformation
= USBHI_GetExtendedHubInformation
;
3002 InterfaceHub
->GetRootHubSymbolicName
= USBHI_GetRootHubSymbolicName
;
3003 InterfaceHub
->GetDeviceBusContext
= USBHI_GetDeviceBusContext
;
3007 // Interface version 3
3009 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3011 InterfaceHub
->RootHubInitNotification
= USBHI_RootHubInitNotification
;
3015 // Interface version 4
3017 if (IoStack
->Parameters
.QueryInterface
.Version
>= 4)
3019 InterfaceHub
->FlushTransfers
= USBHI_FlushTransfers
;
3023 // Interface version 5
3025 if (IoStack
->Parameters
.QueryInterface
.Version
>= 5)
3027 InterfaceHub
->SetDeviceHandleData
= USBHI_SetDeviceHandleData
;
3031 // request completed
3033 return STATUS_SUCCESS
;
3035 else if (IsEqualGUIDAligned(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, USB_BUS_INTERFACE_USBDI_GUID
))
3038 // get request parameters
3040 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) IoStack
->Parameters
.QueryInterface
.Interface
;
3041 InterfaceDI
->Version
= IoStack
->Parameters
.QueryInterface
.Version
;
3046 if (IoStack
->Parameters
.QueryInterface
.Version
>= 3)
3048 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack
->Parameters
.QueryInterface
.Version
);
3051 // version not supported
3053 return STATUS_NOT_SUPPORTED
;
3057 // interface version 0
3059 if (IoStack
->Parameters
.QueryInterface
.Version
>= 0)
3061 InterfaceDI
->Size
= IoStack
->Parameters
.QueryInterface
.Size
;
3062 InterfaceDI
->BusContext
= PVOID(this);
3063 InterfaceDI
->InterfaceReference
= USBI_InterfaceReference
;
3064 InterfaceDI
->InterfaceDereference
= USBI_InterfaceDereference
;
3065 InterfaceDI
->GetUSBDIVersion
= USBDI_GetUSBDIVersion
;
3066 InterfaceDI
->QueryBusTime
= USBDI_QueryBusTime
;
3067 InterfaceDI
->SubmitIsoOutUrb
= USBDI_SubmitIsoOutUrb
;
3068 InterfaceDI
->QueryBusInformation
= USBDI_QueryBusInformation
;
3072 // interface version 1
3074 if (IoStack
->Parameters
.QueryInterface
.Version
>= 1)
3076 InterfaceDI
->IsDeviceHighSpeed
= USBDI_IsDeviceHighSpeed
;
3080 // interface version 2
3082 if (IoStack
->Parameters
.QueryInterface
.Version
>= 2)
3084 InterfaceDI
->EnumLogEntry
= USBDI_EnumLogEntry
;
3088 // request completed
3090 return STATUS_SUCCESS
;
3095 // convert guid to string
3097 Status
= RtlStringFromGUID(*IoStack
->Parameters
.QueryInterface
.InterfaceType
, &GuidBuffer
);
3098 if (NT_SUCCESS(Status
))
3103 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer
, IoStack
->Parameters
.QueryInterface
.Version
);
3108 RtlFreeUnicodeString(&GuidBuffer
);
3111 return STATUS_NOT_SUPPORTED
;
3115 CHubController::SetDeviceInterface(
3118 NTSTATUS Status
= STATUS_SUCCESS
;
3123 // register device interface
3125 Status
= IoRegisterDeviceInterface(m_HubControllerDeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, 0, &m_HubDeviceInterfaceString
);
3127 if (NT_SUCCESS(Status
))
3130 // now enable the device interface
3132 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, TRUE
);
3137 m_InterfaceEnabled
= TRUE
;
3140 else if (m_InterfaceEnabled
)
3143 // disable device interface
3145 Status
= IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString
, FALSE
);
3147 if (NT_SUCCESS(Status
))
3150 // now delete interface string
3152 RtlFreeUnicodeString(&m_HubDeviceInterfaceString
);
3156 // disable interface
3158 m_InterfaceEnabled
= FALSE
;
3168 CHubController::CreatePDO(
3169 PDRIVER_OBJECT DriverObject
,
3170 PDEVICE_OBJECT
* OutDeviceObject
)
3172 WCHAR CharDeviceName
[64];
3174 ULONG UsbDeviceNumber
= 0;
3175 UNICODE_STRING DeviceName
;
3180 // construct device name
3182 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
3185 // initialize device name
3187 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
3192 Status
= IoCreateDevice(DriverObject
,
3193 sizeof(COMMON_DEVICE_EXTENSION
),
3195 FILE_DEVICE_CONTROLLER
,
3200 /* check for success */
3201 if (NT_SUCCESS(Status
))
3205 // is there a device object with that same name
3207 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
3210 // Try the next name
3217 // bail out on other errors
3219 if (!NT_SUCCESS(Status
))
3221 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName
, Status
);
3226 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName
);
3229 // fixup device stack voodoo part #1
3231 (*OutDeviceObject
)->StackSize
++;
3240 CreateHubController(
3241 PHUBCONTROLLER
*OutHcdController
)
3243 PHUBCONTROLLER This
;
3246 // allocate controller
3248 This
= new(NonPagedPool
, TAG_USBOHCI
) CHubController(0);
3252 // failed to allocate
3254 return STATUS_INSUFFICIENT_RESOURCES
;
3258 // add reference count
3265 *OutHcdController
= (PHUBCONTROLLER
)This
;
3270 return STATUS_SUCCESS
;
3273 VOID
StatusChangeEndpointCallBack(PVOID Context
)
3275 CHubController
* This
;
3277 This
= (CHubController
*)Context
;
3281 Irp
= This
->m_PendingSCEIrp
;
3284 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3288 This
->m_PendingSCEIrp
= NULL
;
3289 This
->QueryStatusChageEndpoint(Irp
);
3291 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3292 Irp
->IoStatus
.Information
= 0;
3294 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);