2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 QueryStatusChangeEndpoint(
16 IN PDEVICE_OBJECT DeviceObject
);
19 CreateUsbChildDeviceObject(
20 IN PDEVICE_OBJECT UsbHubDeviceObject
,
22 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
26 DestroyUsbChildDeviceObject(
27 IN PDEVICE_OBJECT UsbHubDeviceObject
,
31 SubmitRequestToRootHub(
32 IN PDEVICE_OBJECT RootHubDeviceObject
,
33 IN ULONG IoControlCode
,
34 OUT PVOID OutParameter1
,
35 OUT PVOID OutParameter2
)
39 IO_STATUS_BLOCK IoStatus
;
41 PIO_STACK_LOCATION Stack
= NULL
;
43 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
46 // Build Control Request
48 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
58 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
59 return STATUS_INSUFFICIENT_RESOURCES
;
63 // Initialize the status block before sending the IRP
65 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
66 IoStatus
.Information
= 0;
69 // Get Next Stack Location and Initialize it
71 Stack
= IoGetNextIrpStackLocation(Irp
);
72 Stack
->Parameters
.Others
.Argument1
= OutParameter1
;
73 Stack
->Parameters
.Others
.Argument2
= OutParameter2
;
78 Status
= IoCallDriver(RootHubDeviceObject
, Irp
);
81 // Its ok to block here as this function is called in an nonarbitrary thread
83 if (Status
== STATUS_PENDING
)
85 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
86 Status
= IoStatus
.Status
;
90 // The IO Manager will free the IRP
97 GetPortStatusAndChange(
98 IN PDEVICE_OBJECT RootHubDeviceObject
,
100 OUT PPORT_STATUS_CHANGE StatusChange
)
108 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
111 DPRINT1("Failed to allocate memory for URB!\n");
112 return STATUS_INSUFFICIENT_RESOURCES
;
118 RtlZeroMemory(Urb
, sizeof(URB
));
121 // Initialize URB for getting Port Status
123 UsbBuildVendorRequest(Urb
,
124 URB_FUNCTION_CLASS_OTHER
,
125 sizeof(Urb
->UrbControlVendorClassRequest
),
126 USBD_TRANSFER_DIRECTION_OUT
,
128 USB_REQUEST_GET_STATUS
,
133 sizeof(PORT_STATUS_CHANGE
),
137 // Query the Root Hub
139 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
151 IN PDEVICE_OBJECT RootHubDeviceObject
,
161 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
164 DPRINT1("Failed to allocate memory for URB!\n");
165 return STATUS_INSUFFICIENT_RESOURCES
;
171 RtlZeroMemory(Urb
, sizeof(URB
));
174 // Initialize URB for Clearing Port Reset
176 UsbBuildVendorRequest(Urb
,
177 URB_FUNCTION_CLASS_OTHER
,
178 sizeof(Urb
->UrbControlVendorClassRequest
),
179 USBD_TRANSFER_DIRECTION_IN
,
181 USB_REQUEST_SET_FEATURE
,
189 // Query the Root Hub
191 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
203 IN PDEVICE_OBJECT RootHubDeviceObject
,
213 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
216 DPRINT1("Failed to allocate memory for URB!\n");
217 return STATUS_INSUFFICIENT_RESOURCES
;
223 RtlZeroMemory(Urb
, sizeof(URB
));
226 // Initialize URB for Clearing Port Reset
228 UsbBuildVendorRequest(Urb
,
229 URB_FUNCTION_CLASS_OTHER
,
230 sizeof(Urb
->UrbControlVendorClassRequest
),
231 USBD_TRANSFER_DIRECTION_IN
,
233 USB_REQUEST_CLEAR_FEATURE
,
241 // Query the Root Hub
243 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
254 DeviceStatusChangeThread(
258 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
259 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
260 PWORK_ITEM_DATA WorkItemData
;
261 PORT_STATUS_CHANGE PortStatus
;
263 BOOLEAN SignalResetComplete
= FALSE
;
265 DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context
);
267 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
268 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
269 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
270 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
274 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
279 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
280 if (!NT_SUCCESS(Status
))
282 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
283 // FIXME: Do we really want to halt further SCE requests?
287 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
288 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
292 // Check for new device connection
294 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
297 // Clear Port Connect
299 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
300 if (!NT_SUCCESS(Status
))
302 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
307 // Is this a connect or disconnect?
309 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
311 DPRINT1("Device disconnected from port %d\n", PortId
);
313 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
314 if (!NT_SUCCESS(Status
))
316 DPRINT1("Failed to delete child device object after disconnect\n");
322 DPRINT1("Device connected from port %d\n", PortId
);
324 // No SCE completion done for clearing C_PORT_CONNECT
329 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
330 if (!NT_SUCCESS(Status
))
332 DPRINT1("Failed to reset port %d\n", PortId
);
333 SignalResetComplete
= TRUE
;
338 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
343 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
344 if (!NT_SUCCESS(Status
))
346 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
350 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
353 // Request event signalling later
355 SignalResetComplete
= TRUE
;
360 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
361 if (!NT_SUCCESS(Status
))
363 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
370 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
371 if (!NT_SUCCESS(Status
))
373 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
374 // FIXME: Do we really want to halt further SCE requests?
378 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
379 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
382 // Check that reset was cleared
384 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
386 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
391 // Check if the device is still connected
393 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
395 DPRINT1("Device has been disconnected\n");
400 // Make sure its Connected and Enabled
402 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
404 DPRINT1("Usb Device is not connected and enabled!\n");
406 // Attempt another reset
408 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
409 if (!NT_SUCCESS(Status
))
411 DPRINT1("Failed to reset port %d\n", PortId
);
417 // This is a new device
419 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
, PortStatus
.Status
);
423 ExFreePool(WorkItemData
);
426 // Send another SCE Request
428 DPRINT("Sending another SCE!\n");
429 QueryStatusChangeEndpoint(DeviceObject
);
432 // Check if a reset event was satisfied
434 if (SignalResetComplete
)
437 // Signal anyone waiting on it
439 KeSetEvent(&HubDeviceExtension
->ResetComplete
, IO_NO_INCREMENT
, FALSE
);
445 StatusChangeEndpointCompletion(
446 IN PDEVICE_OBJECT DeviceObject
,
450 PDEVICE_OBJECT RealDeviceObject
;
451 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
452 PWORK_ITEM_DATA WorkItemData
;
454 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
455 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
458 // NOTE: USBPORT frees this IRP
460 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
464 // Create and initialize work item data
466 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
469 DPRINT1("Failed to allocate memory!n");
470 return STATUS_INSUFFICIENT_RESOURCES
;
472 WorkItemData
->Context
= RealDeviceObject
;
474 DPRINT("Queuing work item\n");
477 // Queue the work item to handle initializing the device
479 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
480 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
483 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
485 return STATUS_MORE_PROCESSING_REQUIRED
;
489 QueryStatusChangeEndpoint(
490 IN PDEVICE_OBJECT DeviceObject
)
493 PDEVICE_OBJECT RootHubDeviceObject
;
494 PIO_STACK_LOCATION Stack
;
495 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
498 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
499 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
504 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
507 // Initialize URB for Status Change Endpoint request
509 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
510 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
511 HubDeviceExtension
->PipeHandle
,
512 HubDeviceExtension
->PortStatusChange
,
514 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
515 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
519 // Set the device handle to null for roothub
521 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
527 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
528 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
531 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
534 DPRINT("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
536 if (!HubDeviceExtension
->PendingSCEIrp
)
538 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
539 return STATUS_INSUFFICIENT_RESOURCES
;
543 // Initialize the IRP
545 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
546 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
547 RootHubDeviceObject
->StackSize
);
549 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
550 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
551 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
552 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
555 // Get the Next Stack Location and Initialize it
557 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
558 Stack
->DeviceObject
= DeviceObject
;
559 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
560 Stack
->Parameters
.Others
.Argument2
= NULL
;
561 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
562 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
565 // Set the completion routine for when device is connected to root hub
567 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
568 StatusChangeEndpointCompletion
,
577 DPRINT("DeviceObject is %x\n", DeviceObject
);
578 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
579 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
581 return STATUS_PENDING
;
586 IN PDEVICE_OBJECT DeviceObject
,
587 IN CONST GUID InterfaceType
,
594 IO_STATUS_BLOCK IoStatus
;
596 PIO_STACK_LOCATION Stack
= NULL
;
599 // Initialize the Event used to wait for Irp completion
601 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
604 // Build Control Request
606 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
615 // Get Next Stack Location and Initialize it.
617 Stack
= IoGetNextIrpStackLocation(Irp
);
618 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
619 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
620 Stack
->Parameters
.QueryInterface
.Size
= Size
;
621 Stack
->Parameters
.QueryInterface
.Version
= Version
;
622 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
623 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
625 Status
= IoCallDriver(DeviceObject
, Irp
);
627 if (Status
== STATUS_PENDING
)
629 DPRINT("Operation pending\n");
630 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
631 Status
= IoStatus
.Status
;
638 GetUsbDeviceDescriptor(
639 IN PDEVICE_OBJECT ChildDeviceObject
,
640 IN UCHAR DescriptorType
,
643 OUT PVOID TransferBuffer
,
644 IN ULONG TransferBufferLength
)
647 PDEVICE_OBJECT RootHubDeviceObject
;
649 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
650 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
653 // Get the Hubs Device Extension
655 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
656 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
657 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
662 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
665 DPRINT1("Failed to allocate memory for URB!\n");
666 return STATUS_INSUFFICIENT_RESOURCES
;
672 RtlZeroMemory(Urb
, sizeof(URB
));
675 // Initialize URB for getting device descriptor
677 UsbBuildGetDescriptorRequest(Urb
,
678 sizeof(Urb
->UrbControlDescriptorRequest
),
684 TransferBufferLength
,
688 // Set the device handle
690 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
693 // Query the Root Hub
695 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
696 IOCTL_INTERNAL_USB_SUBMIT_URB
,
704 GetUsbStringDescriptor(
705 IN PDEVICE_OBJECT ChildDeviceObject
,
708 OUT PVOID
*TransferBuffer
,
712 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
716 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
717 sizeof(USB_STRING_DESCRIPTOR
),
721 DPRINT1("Failed to allocate buffer for string!\n");
722 return STATUS_INSUFFICIENT_RESOURCES
;
726 // Get the index string descriptor length
727 // FIXME: Implement LangIds
729 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
730 USB_STRING_DESCRIPTOR_TYPE
,
734 sizeof(USB_STRING_DESCRIPTOR
));
735 if (!NT_SUCCESS(Status
))
737 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
738 ExFreePool(StringDesc
);
741 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
744 // Did we get something more than the length of the first two fields of structure?
746 if (StringDesc
->bLength
== 2)
748 DPRINT1("USB Device Error!\n");
749 ExFreePool(StringDesc
);
750 return STATUS_DEVICE_DATA_ERROR
;
752 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
757 ExFreePool(StringDesc
);
760 // Recreate with appropriate size
762 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
767 DPRINT1("Failed to allocate buffer for string!\n");
768 return STATUS_INSUFFICIENT_RESOURCES
;
771 RtlZeroMemory(StringDesc
, SizeNeeded
);
776 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
777 USB_STRING_DESCRIPTOR_TYPE
,
782 if (!NT_SUCCESS(Status
))
784 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
785 ExFreePool(StringDesc
);
790 // Allocate Buffer to return
792 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
797 DPRINT1("Failed to allocate buffer for string!\n");
798 ExFreePool(StringDesc
);
799 return STATUS_INSUFFICIENT_RESOURCES
;
801 DPRINT("Buffer %p\n", Buffer
);
802 RtlZeroMemory(Buffer
, SizeNeeded
);
804 DPRINT("SizeNeeded %lu\n", SizeNeeded
);
805 DPRINT("Offset %lu\n", FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
806 DPRINT("Length %lu\n", SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
809 // Copy the string to destination
811 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
813 *TransferBuffer
= Buffer
;
815 ExFreePool(StringDesc
);
817 return STATUS_SUCCESS
;
822 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
823 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
825 if (DeviceDescriptor
->bNumConfigurations
!= 1)
828 // composite device must have only one configuration
830 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
834 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
837 // composite device must have multiple interfaces
839 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
843 if (DeviceDescriptor
->bDeviceClass
== 0)
848 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
849 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
850 DPRINT1("IsCompositeDevice: TRUE\n");
854 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
855 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
856 DeviceDescriptor
->bDeviceProtocol
== 0x01)
859 // USB-IF association descriptor
861 DPRINT1("IsCompositeDevice: TRUE\n");
865 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
868 // not a composite device
875 PDEVICE_OBJECT UsbChildDeviceObject
)
877 NTSTATUS Status
= STATUS_SUCCESS
;
881 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
882 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
883 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
884 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
887 // get child device extension
889 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
892 // get device descriptor
894 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
897 // get configuration descriptor
899 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
902 // use first interface descriptor available
904 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
905 ASSERT(InterfaceDescriptor
);
908 // Construct the CompatibleIds
910 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
915 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
916 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
917 Index
+= swprintf(&Buffer
[Index
],
918 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
919 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
920 Index
+= swprintf(&Buffer
[Index
],
921 L
"USB\\DevClass_%02x&SubClass_%02x",
922 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
923 Index
+= swprintf(&Buffer
[Index
],
924 L
"USB\\DevClass_%02x",
925 DeviceDescriptor
->bDeviceClass
) + 1;
926 Index
+= swprintf(&Buffer
[Index
],
927 L
"USB\\COMPOSITE") + 1;
932 // sanity checks for simple usb device
934 ASSERT(ConfigurationDescriptor
->bNumInterfaces
== 1);
937 // FIXME: support multiple configurations
939 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
941 if (DeviceDescriptor
->bDeviceClass
== 0)
943 Index
+= swprintf(&Buffer
[Index
],
944 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
945 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
946 Index
+= swprintf(&Buffer
[Index
],
947 L
"USB\\Class_%02x&SubClass_%02x",
948 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
949 Index
+= swprintf(&Buffer
[Index
],
951 InterfaceDescriptor
->bInterfaceClass
) + 1;
955 Index
+= swprintf(&Buffer
[Index
],
956 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
957 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
958 Index
+= swprintf(&Buffer
[Index
],
959 L
"USB\\Class_%02x&SubClass_%02x",
960 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
961 Index
+= swprintf(&Buffer
[Index
],
963 DeviceDescriptor
->bDeviceClass
) + 1;
968 // now allocate the buffer
970 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
976 return STATUS_INSUFFICIENT_RESOURCES
;
982 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
983 DeviceString
[Index
] = UNICODE_NULL
;
984 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
985 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
986 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
987 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
990 // Construct DeviceId string
992 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
995 // now allocate the buffer
997 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1003 return STATUS_INSUFFICIENT_RESOURCES
;
1009 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
1010 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
1011 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
1012 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1013 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
1016 // Construct HardwareIds
1019 Index
+= swprintf(&Buffer
[Index
],
1020 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
1021 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
1022 Index
+= swprintf(&Buffer
[Index
],
1023 L
"USB\\Vid_%04x&Pid_%04x",
1024 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
1027 // now allocate the buffer
1029 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
1035 return STATUS_INSUFFICIENT_RESOURCES
;
1041 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
1042 DeviceString
[Index
] = UNICODE_NULL
;
1043 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
1044 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
1045 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
1046 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
1049 // FIXME: Handle Lang ids
1053 // Get the product string if obe provided
1055 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1057 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1058 UsbChildExtension
->DeviceDesc
.iProduct
,
1060 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1061 &UsbChildExtension
->usTextDescription
.Length
);
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1065 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"");
1069 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1070 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1075 // Get the Serial Number string if obe provided
1077 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1079 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1080 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1082 (PVOID
*)&UsbChildExtension
->usInstanceId
.Buffer
,
1083 &UsbChildExtension
->usInstanceId
.Length
);
1084 if (!NT_SUCCESS(Status
))
1086 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1090 UsbChildExtension
->usInstanceId
.MaximumLength
= UsbChildExtension
->usInstanceId
.Length
;
1091 DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1096 // the device did not provide a serial number, lets create a pseudo instance id
1098 Index
= swprintf(Buffer
, L
"0&%04d", UsbChildExtension
->PortNumber
) + 1;
1099 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1100 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1102 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1103 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1110 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1111 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1113 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1120 DestroyUsbChildDeviceObject(
1121 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1124 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1125 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1126 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1129 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1131 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1133 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1135 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1137 /* Check if it matches the port ID */
1138 if (UsbChildExtension
->PortNumber
== PortId
)
1141 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1147 /* Fail the request if the device doesn't exist */
1148 if (!ChildDeviceObject
)
1150 DPRINT1("Removal request for non-existant device!\n");
1151 return STATUS_UNSUCCESSFUL
;
1154 /* Remove the device from the table */
1155 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1157 /* Invalidate device relations for the root hub */
1158 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1160 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1161 return STATUS_SUCCESS
;
1165 CreateUsbChildDeviceObject(
1166 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1168 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1169 IN ULONG PortStatus
)
1172 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1173 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1174 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1175 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1176 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1177 WCHAR CharDeviceName
[64];
1178 UNICODE_STRING DeviceName
;
1179 ULONG ConfigDescSize
, DeviceDescSize
;
1180 PVOID HubInterfaceBusContext
;
1181 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1183 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1184 HubInterface
= &HubDeviceExtension
->HubInterface
;
1185 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1186 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1188 // Find an empty slot in the child device array
1190 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1192 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1194 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1200 // Check if the limit has been reached for maximum usb devices
1202 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1204 DPRINT1("USBHUB: Too many child devices!\n");
1205 return STATUS_UNSUCCESSFUL
;
1211 // Create a Device Name
1213 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1216 // Initialize UnicodeString
1218 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1221 // Create a DeviceObject
1223 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1224 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1226 FILE_DEVICE_CONTROLLER
,
1227 FILE_AUTOGENERATED_DEVICE_NAME
,
1229 &NewChildDeviceObject
);
1232 // Check if the name is already in use
1234 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1244 // Check for other errors
1246 if (!NT_SUCCESS(Status
))
1248 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1252 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1256 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1259 // Assign the device extensions
1261 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1262 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1263 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1264 UsbChildExtension
->PortNumber
= PortId
;
1267 // Create the UsbDeviceObject
1269 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1270 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1271 HubDeviceExtension
->RootHubHandle
,
1274 if (!NT_SUCCESS(Status
))
1276 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1281 // Initialize UsbDevice
1283 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1284 if (!NT_SUCCESS(Status
))
1286 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1290 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1292 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1293 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1296 // Get the descriptors
1298 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1299 UsbChildExtension
->UsbDeviceHandle
,
1300 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1302 (PUCHAR
)&ConfigDesc
,
1304 if (!NT_SUCCESS(Status
))
1306 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1310 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
1311 DumpConfigurationDescriptor(&ConfigDesc
);
1314 // FIXME: Support more than one configuration and one interface?
1316 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1318 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1321 if (ConfigDesc
.bNumInterfaces
> 1)
1323 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1326 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1329 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1331 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1334 // Retrieve the full configuration descriptor
1336 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1337 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1340 UsbChildExtension
->FullConfigDesc
,
1343 if (!NT_SUCCESS(Status
))
1345 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1349 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1352 // Construct all the strings that will described the device to PNP
1354 Status
= CreateDeviceIds(NewChildDeviceObject
);
1355 if (!NT_SUCCESS(Status
))
1357 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1361 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1363 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1364 return STATUS_SUCCESS
;
1369 // Remove the usb device if it was created
1371 if (UsbChildExtension
->UsbDeviceHandle
)
1372 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1375 // Free full configuration descriptor if one was allocated
1377 if (UsbChildExtension
->FullConfigDesc
)
1378 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1381 // Delete the device object
1383 IoDeleteDevice(NewChildDeviceObject
);
1388 USBHUB_FdoQueryBusRelations(
1389 IN PDEVICE_OBJECT DeviceObject
,
1390 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1392 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1393 PDEVICE_RELATIONS DeviceRelations
;
1398 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1401 // Count the number of children
1403 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1406 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1413 NeededSize
= sizeof(DEVICE_RELATIONS
);
1415 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1418 // Allocate DeviceRelations
1420 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1423 if (!DeviceRelations
)
1424 return STATUS_INSUFFICIENT_RESOURCES
;
1425 DeviceRelations
->Count
= Children
;
1429 // Fill in return structure
1431 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1433 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1435 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1436 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1437 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1441 ASSERT(Children
== DeviceRelations
->Count
);
1442 *pDeviceRelations
= DeviceRelations
;
1444 return STATUS_SUCCESS
;
1449 RootHubInitCallbackFunction(
1452 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1455 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1456 PORT_STATUS_CHANGE StatusChange
;
1458 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1460 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1463 // Send the first SCE Request
1465 QueryStatusChangeEndpoint(DeviceObject
);
1467 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1472 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1473 if (NT_SUCCESS(Status
))
1476 // is there a device connected
1478 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1483 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1484 if (!NT_SUCCESS(Status
))
1486 DPRINT1("Failed to reset on port %d\n", PortId
);
1491 // wait for the reset to be handled since we want to enumerate synchronously
1493 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1498 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1506 USBHUB_FdoHandlePnp(
1507 IN PDEVICE_OBJECT DeviceObject
,
1510 PIO_STACK_LOCATION Stack
;
1511 NTSTATUS Status
= STATUS_SUCCESS
;
1512 ULONG_PTR Information
= 0;
1513 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1514 PDEVICE_OBJECT RootHubDeviceObject
;
1515 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1516 PORT_STATUS_CHANGE StatusChange
;
1518 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1520 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1522 switch (Stack
->MinorFunction
)
1524 case IRP_MN_START_DEVICE
:
1527 PUSB_INTERFACE_DESCRIPTOR Pid
;
1528 ULONG Result
= 0, PortId
;
1529 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1530 PURB ConfigUrb
= NULL
;
1533 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1536 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1538 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1539 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1542 // Get the Root Hub Pdo
1544 SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1545 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1546 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1547 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1549 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1550 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1551 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1552 DPRINT("RootPdo %x, RootFdo %x\n",
1553 HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1554 HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1557 // Send the StartDevice to RootHub
1559 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1561 if (!NT_SUCCESS(Status
))
1563 DPRINT1("Failed to start the RootHub PDO\n");
1568 // Get the current number of hubs
1570 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1571 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1572 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1575 // Get the Hub Interface
1577 Status
= QueryInterface(RootHubDeviceObject
,
1578 USB_BUS_INTERFACE_HUB_GUID
,
1579 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1580 USB_BUSIF_HUB_VERSION_5
,
1581 (PVOID
)&HubDeviceExtension
->HubInterface
);
1583 if (!NT_SUCCESS(Status
))
1585 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1586 return STATUS_UNSUCCESSFUL
;
1589 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1592 // Get the USBDI Interface
1594 Status
= QueryInterface(RootHubDeviceObject
,
1595 USB_BUS_INTERFACE_USBDI_GUID
,
1596 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1597 USB_BUSIF_USBDI_VERSION_2
,
1598 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1600 if (!NT_SUCCESS(Status
))
1602 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1606 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1609 // Get Root Hub Device Handle
1611 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1612 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1613 &HubDeviceExtension
->RootHubHandle
,
1616 if (!NT_SUCCESS(Status
))
1618 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status
);
1623 // Get Hub Device Information
1625 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1626 HubDeviceExtension
->RootHubHandle
,
1627 &HubDeviceExtension
->DeviceInformation
,
1628 sizeof(USB_DEVICE_INFORMATION_0
),
1631 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1632 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1633 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1634 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1635 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1636 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1637 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1640 // Get Root Hubs Device Descriptor
1642 UsbBuildGetDescriptorRequest(Urb
,
1643 sizeof(Urb
->UrbControlDescriptorRequest
),
1644 USB_DEVICE_DESCRIPTOR_TYPE
,
1647 &HubDeviceExtension
->HubDeviceDescriptor
,
1649 sizeof(USB_DEVICE_DESCRIPTOR
),
1652 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1654 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1655 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1659 if (!NT_SUCCESS(Status
))
1661 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1664 DumpDeviceDescriptor(&HubDeviceExtension
->HubDeviceDescriptor
);
1667 // Get Root Hubs Configuration Descriptor
1669 UsbBuildGetDescriptorRequest(Urb
,
1670 sizeof(Urb
->UrbControlDescriptorRequest
),
1671 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1674 &HubDeviceExtension
->HubConfigDescriptor
,
1676 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1679 DPRINT("RootHub Handle %x\n", HubDeviceExtension
->RootHubHandle
);
1680 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1682 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1683 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1687 if (!NT_SUCCESS(Status
))
1689 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1692 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
);
1694 DumpConfigurationDescriptor(&HubDeviceExtension
->HubConfigDescriptor
);
1696 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1697 RootHubDeviceObject
,
1698 &HubDeviceExtension
->UsbExtHubInfo
,
1699 sizeof(USB_EXTHUB_INFORMATION_0
),
1701 if (!NT_SUCCESS(Status
))
1703 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1707 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1710 // Get the Hub Descriptor
1712 UsbBuildVendorRequest(Urb
,
1713 URB_FUNCTION_CLASS_DEVICE
,
1714 sizeof(Urb
->UrbControlVendorClassRequest
),
1715 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1717 USB_REQUEST_GET_DESCRIPTOR
,
1718 USB_DEVICE_CLASS_RESERVED
,
1720 &HubDeviceExtension
->HubDescriptor
,
1722 sizeof(USB_HUB_DESCRIPTOR
),
1725 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1727 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1728 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1732 DPRINT1("bDescriptorType %x\n", HubDeviceExtension
->HubDescriptor
.bDescriptorType
);
1734 if (!NT_SUCCESS(Status
))
1736 DPRINT1("Failed to get Hub Descriptor!\n");
1738 return STATUS_UNSUCCESSFUL
;
1742 UsbBuildGetStatusRequest(Urb
,
1743 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1748 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1750 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1751 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1754 if (!NT_SUCCESS(Status
))
1756 DPRINT1("Failed to get Hub Status!\n");
1758 return STATUS_UNSUCCESSFUL
;
1761 DPRINT1("HubStatus %x\n", HubStatus
);
1764 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1766 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1767 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1771 // Get the first Configuration Descriptor
1773 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1774 &HubDeviceExtension
->HubConfigDescriptor
,
1775 -1, -1, -1, -1, -1);
1777 ASSERT(Pid
!= NULL
);
1779 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1780 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1781 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1782 ASSERT(ConfigUrb
!= NULL
);
1784 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1785 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1789 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1790 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1791 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1794 // check if function is available
1796 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1799 // is it high speed bus
1801 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1804 // initialize usb 2.0 hub
1806 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1807 HubDeviceExtension
->RootHubHandle
, 1);
1808 DPRINT("Status %x\n", Status
);
1811 // FIXME handle error
1813 ASSERT(Status
== STATUS_SUCCESS
);
1817 ExFreePool(ConfigUrb
);
1820 // Enable power on all ports
1823 DPRINT("Enabling PortPower on all ports!\n");
1825 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1827 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1828 if (!NT_SUCCESS(Status
))
1829 DPRINT1("Failed to power on port %d\n", PortId
);
1831 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1832 if (!NT_SUCCESS(Status
))
1833 DPRINT1("Failed to power on port %d\n", PortId
);
1836 DPRINT("RootHubInitNotification %x\n", HubDeviceExtension
->HubInterface
.RootHubInitNotification
);
1839 // init root hub notification
1841 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1843 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1845 RootHubInitCallbackFunction
);
1846 if (!NT_SUCCESS(Status
))
1848 DPRINT1("Failed to set callback\n");
1854 // Send the first SCE Request
1856 QueryStatusChangeEndpoint(DeviceObject
);
1861 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1866 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1867 if (NT_SUCCESS(Status
))
1870 // is there a device connected
1872 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1877 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1878 if (!NT_SUCCESS(Status
))
1880 DPRINT1("Failed to reset on port %d\n", PortId
);
1885 // wait for the reset to be handled since we want to enumerate synchronously
1887 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1892 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1903 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1905 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1909 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1910 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1912 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1914 Information
= (ULONG_PTR
)DeviceRelations
;
1917 case RemovalRelations
:
1919 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1920 return ForwardIrpAndForget(DeviceObject
, Irp
);
1923 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1924 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1925 return ForwardIrpAndForget(DeviceObject
, Irp
);
1929 case IRP_MN_QUERY_REMOVE_DEVICE
:
1930 case IRP_MN_QUERY_STOP_DEVICE
:
1932 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1933 return ForwardIrpAndForget(DeviceObject
, Irp
);
1935 case IRP_MN_REMOVE_DEVICE
:
1937 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1938 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1940 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
1941 IoDeleteDevice(DeviceObject
);
1943 return STATUS_SUCCESS
;
1945 case IRP_MN_QUERY_BUS_INFORMATION
:
1947 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1950 case IRP_MN_QUERY_ID
:
1952 DPRINT("IRP_MN_QUERY_ID\n");
1955 case IRP_MN_QUERY_CAPABILITIES
:
1957 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1962 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
1963 return ForwardIrpAndForget(DeviceObject
, Irp
);
1967 Irp
->IoStatus
.Information
= Information
;
1968 Irp
->IoStatus
.Status
= Status
;
1969 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1974 USBHUB_FdoHandleDeviceControl(
1975 IN PDEVICE_OBJECT DeviceObject
,
1978 DPRINT1("FdoHandleDeviceControl\n");
1980 return STATUS_NOT_IMPLEMENTED
;