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
);
306 // Is this a connect or disconnect?
308 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
310 DPRINT1("Device disconnected from port %d\n", PortId
);
312 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
313 if (!NT_SUCCESS(Status
))
315 DPRINT1("Failed to delete child device object after disconnect\n");
320 DPRINT1("Device connected from port %d\n", PortId
);
322 // No SCE completion done for clearing C_PORT_CONNECT
327 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
328 if (!NT_SUCCESS(Status
))
330 DPRINT1("Failed to reset port %d\n", PortId
);
334 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
339 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
340 if (!NT_SUCCESS(Status
))
342 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
345 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
350 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
351 if (!NT_SUCCESS(Status
))
353 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
359 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
360 if (!NT_SUCCESS(Status
))
362 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
363 // FIXME: Do we really want to halt further SCE requests?
367 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
368 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
371 // Check that reset was cleared
373 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
375 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
379 // Check if the device is still connected
381 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
383 DPRINT1("Device has been disconnected\n");
388 // Make sure its Connected and Enabled
390 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
392 DPRINT1("Usb Device is not connected and enabled!\n");
394 // Attempt another reset
396 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("Failed to reset port %d\n", PortId
);
405 // This is a new device
407 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
, PortStatus
.Status
);
410 // Request event signalling later
412 SignalResetComplete
= TRUE
;
416 ExFreePool(WorkItemData
);
419 // Send another SCE Request
421 DPRINT("Sending another SCE!\n");
422 QueryStatusChangeEndpoint(DeviceObject
);
425 // Check if a reset event was satisfied
427 if (SignalResetComplete
)
430 // Signal anyone waiting on it
432 KeSetEvent(&HubDeviceExtension
->ResetComplete
, IO_NO_INCREMENT
, FALSE
);
438 StatusChangeEndpointCompletion(
439 IN PDEVICE_OBJECT DeviceObject
,
443 PDEVICE_OBJECT RealDeviceObject
;
444 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
445 PWORK_ITEM_DATA WorkItemData
;
447 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
448 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
451 // NOTE: USBPORT frees this IRP
453 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
457 // Create and initialize work item data
459 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
462 DPRINT1("Failed to allocate memory!n");
463 return STATUS_INSUFFICIENT_RESOURCES
;
465 WorkItemData
->Context
= RealDeviceObject
;
467 DPRINT("Queuing work item\n");
470 // Queue the work item to handle initializing the device
472 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
473 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
476 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
478 return STATUS_MORE_PROCESSING_REQUIRED
;
482 QueryStatusChangeEndpoint(
483 IN PDEVICE_OBJECT DeviceObject
)
486 PDEVICE_OBJECT RootHubDeviceObject
;
487 PIO_STACK_LOCATION Stack
;
488 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
491 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
492 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
497 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
500 // Initialize URB for Status Change Endpoint request
502 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
503 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
504 HubDeviceExtension
->PipeHandle
,
505 HubDeviceExtension
->PortStatusChange
,
507 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
508 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
512 // Set the device handle to null for roothub
514 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
520 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
521 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
524 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
527 DPRINT("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
529 if (!HubDeviceExtension
->PendingSCEIrp
)
531 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
532 return STATUS_INSUFFICIENT_RESOURCES
;
536 // Initialize the IRP
538 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
539 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
540 RootHubDeviceObject
->StackSize
);
542 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
543 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
544 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
545 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
548 // Get the Next Stack Location and Initialize it
550 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
551 Stack
->DeviceObject
= DeviceObject
;
552 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
553 Stack
->Parameters
.Others
.Argument2
= NULL
;
554 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
555 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
558 // Set the completion routine for when device is connected to root hub
560 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
561 StatusChangeEndpointCompletion
,
570 DPRINT("DeviceObject is %x\n", DeviceObject
);
571 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
572 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
574 return STATUS_PENDING
;
579 IN PDEVICE_OBJECT DeviceObject
,
580 IN CONST GUID InterfaceType
,
587 IO_STATUS_BLOCK IoStatus
;
589 PIO_STACK_LOCATION Stack
= NULL
;
592 // Initialize the Event used to wait for Irp completion
594 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
597 // Build Control Request
599 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
608 // Get Next Stack Location and Initialize it.
610 Stack
= IoGetNextIrpStackLocation(Irp
);
611 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
612 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
613 Stack
->Parameters
.QueryInterface
.Size
= Size
;
614 Stack
->Parameters
.QueryInterface
.Version
= Version
;
615 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
616 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
618 Status
= IoCallDriver(DeviceObject
, Irp
);
620 if (Status
== STATUS_PENDING
)
622 DPRINT("Operation pending\n");
623 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
624 Status
= IoStatus
.Status
;
631 GetUsbDeviceDescriptor(
632 IN PDEVICE_OBJECT ChildDeviceObject
,
633 IN UCHAR DescriptorType
,
636 OUT PVOID TransferBuffer
,
637 IN ULONG TransferBufferLength
)
640 PDEVICE_OBJECT RootHubDeviceObject
;
642 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
643 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
646 // Get the Hubs Device Extension
648 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
649 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
650 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
655 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
658 DPRINT1("Failed to allocate memory for URB!\n");
659 return STATUS_INSUFFICIENT_RESOURCES
;
665 RtlZeroMemory(Urb
, sizeof(URB
));
668 // Initialize URB for getting device descriptor
670 UsbBuildGetDescriptorRequest(Urb
,
671 sizeof(Urb
->UrbControlDescriptorRequest
),
677 TransferBufferLength
,
681 // Set the device handle
683 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
686 // Query the Root Hub
688 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
689 IOCTL_INTERNAL_USB_SUBMIT_URB
,
697 GetUsbStringDescriptor(
698 IN PDEVICE_OBJECT ChildDeviceObject
,
701 OUT PVOID
*TransferBuffer
,
705 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
709 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
710 sizeof(USB_STRING_DESCRIPTOR
),
714 DPRINT1("Failed to allocate buffer for string!\n");
715 return STATUS_INSUFFICIENT_RESOURCES
;
719 // Get the index string descriptor length
720 // FIXME: Implement LangIds
722 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
723 USB_STRING_DESCRIPTOR_TYPE
,
727 sizeof(USB_STRING_DESCRIPTOR
));
728 if (!NT_SUCCESS(Status
))
730 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
731 ExFreePool(StringDesc
);
734 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
737 // Did we get something more than the length of the first two fields of structure?
739 if (StringDesc
->bLength
== 2)
741 DPRINT1("USB Device Error!\n");
742 ExFreePool(StringDesc
);
743 return STATUS_DEVICE_DATA_ERROR
;
745 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
750 ExFreePool(StringDesc
);
753 // Recreate with appropriate size
755 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
760 DPRINT1("Failed to allocate buffer for string!\n");
761 return STATUS_INSUFFICIENT_RESOURCES
;
764 RtlZeroMemory(StringDesc
, SizeNeeded
);
769 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
770 USB_STRING_DESCRIPTOR_TYPE
,
775 if (!NT_SUCCESS(Status
))
777 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
778 ExFreePool(StringDesc
);
783 // Allocate Buffer to return
785 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
790 DPRINT1("Failed to allocate buffer for string!\n");
791 ExFreePool(StringDesc
);
792 return STATUS_INSUFFICIENT_RESOURCES
;
794 DPRINT("Buffer %p\n", Buffer
);
795 RtlZeroMemory(Buffer
, SizeNeeded
);
797 DPRINT("SizeNeeded %lu\n", SizeNeeded
);
798 DPRINT("Offset %lu\n", FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
799 DPRINT("Length %lu\n", SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
802 // Copy the string to destination
804 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
806 *TransferBuffer
= Buffer
;
808 ExFreePool(StringDesc
);
810 return STATUS_SUCCESS
;
815 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
816 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
818 if (DeviceDescriptor
->bNumConfigurations
!= 1)
821 // composite device must have only one configuration
823 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
827 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
830 // composite device must have multiple interfaces
832 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
836 if (DeviceDescriptor
->bDeviceClass
== 0)
841 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
842 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
843 DPRINT1("IsCompositeDevice: TRUE\n");
847 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
848 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
849 DeviceDescriptor
->bDeviceProtocol
== 0x01)
852 // USB-IF association descriptor
854 DPRINT1("IsCompositeDevice: TRUE\n");
858 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
861 // not a composite device
868 PDEVICE_OBJECT UsbChildDeviceObject
)
870 NTSTATUS Status
= STATUS_SUCCESS
;
874 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
875 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
876 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
877 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
880 // get child device extension
882 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
885 // get device descriptor
887 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
890 // get configuration descriptor
892 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
895 // use first interface descriptor available
897 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
898 ASSERT(InterfaceDescriptor
);
901 // Construct the CompatibleIds
903 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
908 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
909 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
910 Index
+= swprintf(&Buffer
[Index
],
911 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
912 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
913 Index
+= swprintf(&Buffer
[Index
],
914 L
"USB\\DevClass_%02x&SubClass_%02x",
915 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
916 Index
+= swprintf(&Buffer
[Index
],
917 L
"USB\\DevClass_%02x",
918 DeviceDescriptor
->bDeviceClass
) + 1;
919 Index
+= swprintf(&Buffer
[Index
],
920 L
"USB\\COMPOSITE") + 1;
925 // sanity checks for simple usb device
927 ASSERT(ConfigurationDescriptor
->bNumInterfaces
== 1);
930 // FIXME: support multiple configurations
932 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
934 if (DeviceDescriptor
->bDeviceClass
== 0)
936 Index
+= swprintf(&Buffer
[Index
],
937 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
938 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
939 Index
+= swprintf(&Buffer
[Index
],
940 L
"USB\\Class_%02x&SubClass_%02x",
941 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
942 Index
+= swprintf(&Buffer
[Index
],
944 InterfaceDescriptor
->bInterfaceClass
) + 1;
948 Index
+= swprintf(&Buffer
[Index
],
949 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
950 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
951 Index
+= swprintf(&Buffer
[Index
],
952 L
"USB\\Class_%02x&SubClass_%02x",
953 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
954 Index
+= swprintf(&Buffer
[Index
],
956 DeviceDescriptor
->bDeviceClass
) + 1;
961 // now allocate the buffer
963 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
969 return STATUS_INSUFFICIENT_RESOURCES
;
975 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
976 DeviceString
[Index
] = UNICODE_NULL
;
977 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
978 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
979 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
980 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
983 // Construct DeviceId string
985 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
988 // now allocate the buffer
990 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
996 return STATUS_INSUFFICIENT_RESOURCES
;
1002 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
1003 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
1004 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
1005 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1006 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
1009 // Construct HardwareIds
1012 Index
+= swprintf(&Buffer
[Index
],
1013 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
1014 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
1015 Index
+= swprintf(&Buffer
[Index
],
1016 L
"USB\\Vid_%04x&Pid_%04x",
1017 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
1020 // now allocate the buffer
1022 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
1028 return STATUS_INSUFFICIENT_RESOURCES
;
1034 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
1035 DeviceString
[Index
] = UNICODE_NULL
;
1036 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
1037 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
1038 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
1039 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
1042 // FIXME: Handle Lang ids
1046 // Get the product string if obe provided
1048 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1050 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1051 UsbChildExtension
->DeviceDesc
.iProduct
,
1053 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1054 &UsbChildExtension
->usTextDescription
.Length
);
1055 if (!NT_SUCCESS(Status
))
1057 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1058 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"");
1062 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1063 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1068 // Get the Serial Number string if obe provided
1070 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1072 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1073 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1075 (PVOID
*)&UsbChildExtension
->usInstanceId
.Buffer
,
1076 &UsbChildExtension
->usInstanceId
.Length
);
1077 if (!NT_SUCCESS(Status
))
1079 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1083 UsbChildExtension
->usInstanceId
.MaximumLength
= UsbChildExtension
->usInstanceId
.Length
;
1084 DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1089 // the device did not provide a serial number, lets create a pseudo instance id
1091 Index
= swprintf(Buffer
, L
"0&%04d", UsbChildExtension
->PortNumber
) + 1;
1092 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1093 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1095 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1096 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1103 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1104 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1106 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1113 DestroyUsbChildDeviceObject(
1114 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1117 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1118 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1119 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1122 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1124 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1126 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1128 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1130 /* Check if it matches the port ID */
1131 if (UsbChildExtension
->PortNumber
== PortId
)
1134 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1140 /* Fail the request if the device doesn't exist */
1141 if (!ChildDeviceObject
)
1143 DPRINT1("Removal request for non-existant device!\n");
1144 return STATUS_UNSUCCESSFUL
;
1147 /* Remove the device from the table */
1148 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1150 /* Invalidate device relations for the root hub */
1151 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1153 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1154 return STATUS_SUCCESS
;
1158 CreateUsbChildDeviceObject(
1159 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1161 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1162 IN ULONG PortStatus
)
1165 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1166 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1167 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1168 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1169 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1170 WCHAR CharDeviceName
[64];
1171 UNICODE_STRING DeviceName
;
1172 ULONG ConfigDescSize
, DeviceDescSize
;
1173 PVOID HubInterfaceBusContext
;
1174 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1176 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1177 HubInterface
= &HubDeviceExtension
->HubInterface
;
1178 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1179 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1181 // Find an empty slot in the child device array
1183 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1185 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1187 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1193 // Check if the limit has been reached for maximum usb devices
1195 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1197 DPRINT1("USBHUB: Too many child devices!\n");
1198 return STATUS_UNSUCCESSFUL
;
1204 // Create a Device Name
1206 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1209 // Initialize UnicodeString
1211 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1214 // Create a DeviceObject
1216 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1217 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1219 FILE_DEVICE_CONTROLLER
,
1220 FILE_AUTOGENERATED_DEVICE_NAME
,
1222 &NewChildDeviceObject
);
1225 // Check if the name is already in use
1227 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1237 // Check for other errors
1239 if (!NT_SUCCESS(Status
))
1241 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1245 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1249 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1252 // Assign the device extensions
1254 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1255 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1256 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1257 UsbChildExtension
->PortNumber
= PortId
;
1260 // Create the UsbDeviceObject
1262 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1263 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1264 HubDeviceExtension
->RootHubHandle
,
1267 if (!NT_SUCCESS(Status
))
1269 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1274 // Initialize UsbDevice
1276 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1277 if (!NT_SUCCESS(Status
))
1279 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1283 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1285 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1286 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1289 // Get the descriptors
1291 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1292 UsbChildExtension
->UsbDeviceHandle
,
1293 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1295 (PUCHAR
)&ConfigDesc
,
1297 if (!NT_SUCCESS(Status
))
1299 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1303 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
1304 DumpConfigurationDescriptor(&ConfigDesc
);
1307 // FIXME: Support more than one configuration and one interface?
1309 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1311 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1314 if (ConfigDesc
.bNumInterfaces
> 1)
1316 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1319 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1322 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1324 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1327 // Retrieve the full configuration descriptor
1329 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1330 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1333 UsbChildExtension
->FullConfigDesc
,
1336 if (!NT_SUCCESS(Status
))
1338 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1342 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1345 // Construct all the strings that will described the device to PNP
1347 Status
= CreateDeviceIds(NewChildDeviceObject
);
1348 if (!NT_SUCCESS(Status
))
1350 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1354 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1356 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1357 return STATUS_SUCCESS
;
1362 // Remove the usb device if it was created
1364 if (UsbChildExtension
->UsbDeviceHandle
)
1365 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1368 // Free full configuration descriptor if one was allocated
1370 if (UsbChildExtension
->FullConfigDesc
)
1371 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1374 // Delete the device object
1376 IoDeleteDevice(NewChildDeviceObject
);
1381 USBHUB_FdoQueryBusRelations(
1382 IN PDEVICE_OBJECT DeviceObject
,
1383 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1385 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1386 PDEVICE_RELATIONS DeviceRelations
;
1391 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1394 // Count the number of children
1396 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1399 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1406 NeededSize
= sizeof(DEVICE_RELATIONS
);
1408 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1411 // Allocate DeviceRelations
1413 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1416 if (!DeviceRelations
)
1417 return STATUS_INSUFFICIENT_RESOURCES
;
1418 DeviceRelations
->Count
= Children
;
1422 // Fill in return structure
1424 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1426 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1428 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1429 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1430 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1434 ASSERT(Children
== DeviceRelations
->Count
);
1435 *pDeviceRelations
= DeviceRelations
;
1437 return STATUS_SUCCESS
;
1442 RootHubInitCallbackFunction(
1445 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1448 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1449 PORT_STATUS_CHANGE StatusChange
;
1451 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1453 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1456 // Send the first SCE Request
1458 QueryStatusChangeEndpoint(DeviceObject
);
1460 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1465 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1466 if (NT_SUCCESS(Status
))
1469 // is there a device connected
1471 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1476 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1477 if (!NT_SUCCESS(Status
))
1479 DPRINT1("Failed to reset on port %d\n", PortId
);
1484 // wait for the reset to be handled since we want to enumerate synchronously
1486 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1491 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1499 USBHUB_FdoHandlePnp(
1500 IN PDEVICE_OBJECT DeviceObject
,
1503 PIO_STACK_LOCATION Stack
;
1504 NTSTATUS Status
= STATUS_SUCCESS
;
1505 ULONG_PTR Information
= 0;
1506 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1507 PDEVICE_OBJECT RootHubDeviceObject
;
1508 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1509 PORT_STATUS_CHANGE StatusChange
;
1511 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1513 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1515 switch (Stack
->MinorFunction
)
1517 case IRP_MN_START_DEVICE
:
1520 PUSB_INTERFACE_DESCRIPTOR Pid
;
1521 ULONG Result
= 0, PortId
;
1522 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1523 PURB ConfigUrb
= NULL
;
1526 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1529 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1531 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1532 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1535 // Get the Root Hub Pdo
1537 SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1538 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1539 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1540 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1542 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1543 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1544 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1545 DPRINT("RootPdo %x, RootFdo %x\n",
1546 HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1547 HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1550 // Send the StartDevice to RootHub
1552 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1554 if (!NT_SUCCESS(Status
))
1556 DPRINT1("Failed to start the RootHub PDO\n");
1561 // Get the current number of hubs
1563 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1564 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1565 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1568 // Get the Hub Interface
1570 Status
= QueryInterface(RootHubDeviceObject
,
1571 USB_BUS_INTERFACE_HUB_GUID
,
1572 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1573 USB_BUSIF_HUB_VERSION_5
,
1574 (PVOID
)&HubDeviceExtension
->HubInterface
);
1576 if (!NT_SUCCESS(Status
))
1578 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1579 return STATUS_UNSUCCESSFUL
;
1582 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1585 // Get the USBDI Interface
1587 Status
= QueryInterface(RootHubDeviceObject
,
1588 USB_BUS_INTERFACE_USBDI_GUID
,
1589 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1590 USB_BUSIF_USBDI_VERSION_2
,
1591 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1593 if (!NT_SUCCESS(Status
))
1595 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1599 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1602 // Get Root Hub Device Handle
1604 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1605 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1606 &HubDeviceExtension
->RootHubHandle
,
1609 if (!NT_SUCCESS(Status
))
1611 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status
);
1616 // Get Hub Device Information
1618 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1619 HubDeviceExtension
->RootHubHandle
,
1620 &HubDeviceExtension
->DeviceInformation
,
1621 sizeof(USB_DEVICE_INFORMATION_0
),
1624 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1625 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1626 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1627 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1628 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1629 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1630 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1633 // Get Root Hubs Device Descriptor
1635 UsbBuildGetDescriptorRequest(Urb
,
1636 sizeof(Urb
->UrbControlDescriptorRequest
),
1637 USB_DEVICE_DESCRIPTOR_TYPE
,
1640 &HubDeviceExtension
->HubDeviceDescriptor
,
1642 sizeof(USB_DEVICE_DESCRIPTOR
),
1645 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1647 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1648 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1652 if (!NT_SUCCESS(Status
))
1654 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1657 DumpDeviceDescriptor(&HubDeviceExtension
->HubDeviceDescriptor
);
1660 // Get Root Hubs Configuration Descriptor
1662 UsbBuildGetDescriptorRequest(Urb
,
1663 sizeof(Urb
->UrbControlDescriptorRequest
),
1664 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1667 &HubDeviceExtension
->HubConfigDescriptor
,
1669 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1672 DPRINT("RootHub Handle %x\n", HubDeviceExtension
->RootHubHandle
);
1673 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1675 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1676 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1680 if (!NT_SUCCESS(Status
))
1682 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1685 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
);
1687 DumpConfigurationDescriptor(&HubDeviceExtension
->HubConfigDescriptor
);
1689 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1690 RootHubDeviceObject
,
1691 &HubDeviceExtension
->UsbExtHubInfo
,
1692 sizeof(USB_EXTHUB_INFORMATION_0
),
1694 if (!NT_SUCCESS(Status
))
1696 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1700 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1703 // Get the Hub Descriptor
1705 UsbBuildVendorRequest(Urb
,
1706 URB_FUNCTION_CLASS_DEVICE
,
1707 sizeof(Urb
->UrbControlVendorClassRequest
),
1708 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1710 USB_REQUEST_GET_DESCRIPTOR
,
1711 USB_DEVICE_CLASS_RESERVED
,
1713 &HubDeviceExtension
->HubDescriptor
,
1715 sizeof(USB_HUB_DESCRIPTOR
),
1718 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1720 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1721 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1725 DPRINT1("bDescriptorType %x\n", HubDeviceExtension
->HubDescriptor
.bDescriptorType
);
1727 if (!NT_SUCCESS(Status
))
1729 DPRINT1("Failed to get Hub Descriptor!\n");
1731 return STATUS_UNSUCCESSFUL
;
1735 UsbBuildGetStatusRequest(Urb
,
1736 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1741 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1743 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1744 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1747 if (!NT_SUCCESS(Status
))
1749 DPRINT1("Failed to get Hub Status!\n");
1751 return STATUS_UNSUCCESSFUL
;
1754 DPRINT1("HubStatus %x\n", HubStatus
);
1757 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1759 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1760 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1764 // Get the first Configuration Descriptor
1766 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1767 &HubDeviceExtension
->HubConfigDescriptor
,
1768 -1, -1, -1, -1, -1);
1770 ASSERT(Pid
!= NULL
);
1772 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1773 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1774 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1775 ASSERT(ConfigUrb
!= NULL
);
1777 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1778 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1782 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1783 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1784 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1787 // check if function is available
1789 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1792 // is it high speed bus
1794 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1797 // initialize usb 2.0 hub
1799 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1800 HubDeviceExtension
->RootHubHandle
, 1);
1801 DPRINT("Status %x\n", Status
);
1804 // FIXME handle error
1806 ASSERT(Status
== STATUS_SUCCESS
);
1810 ExFreePool(ConfigUrb
);
1813 // Enable power on all ports
1816 DPRINT("Enabling PortPower on all ports!\n");
1818 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1820 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1821 if (!NT_SUCCESS(Status
))
1822 DPRINT1("Failed to power on port %d\n", PortId
);
1824 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1825 if (!NT_SUCCESS(Status
))
1826 DPRINT1("Failed to power on port %d\n", PortId
);
1829 DPRINT("RootHubInitNotification %x\n", HubDeviceExtension
->HubInterface
.RootHubInitNotification
);
1832 // init root hub notification
1834 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1836 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1838 RootHubInitCallbackFunction
);
1839 if (!NT_SUCCESS(Status
))
1841 DPRINT1("Failed to set callback\n");
1847 // Send the first SCE Request
1849 QueryStatusChangeEndpoint(DeviceObject
);
1854 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1859 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1860 if (NT_SUCCESS(Status
))
1863 // is there a device connected
1865 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1870 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1871 if (!NT_SUCCESS(Status
))
1873 DPRINT1("Failed to reset on port %d\n", PortId
);
1878 // wait for the reset to be handled since we want to enumerate synchronously
1880 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1885 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1896 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1898 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1902 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1903 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1905 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1907 Information
= (ULONG_PTR
)DeviceRelations
;
1910 case RemovalRelations
:
1912 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1913 return ForwardIrpAndForget(DeviceObject
, Irp
);
1916 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1917 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1918 return ForwardIrpAndForget(DeviceObject
, Irp
);
1922 case IRP_MN_QUERY_REMOVE_DEVICE
:
1923 case IRP_MN_QUERY_STOP_DEVICE
:
1925 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1926 return ForwardIrpAndForget(DeviceObject
, Irp
);
1928 case IRP_MN_REMOVE_DEVICE
:
1930 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1931 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1933 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
1934 IoDeleteDevice(DeviceObject
);
1936 return STATUS_SUCCESS
;
1938 case IRP_MN_QUERY_BUS_INFORMATION
:
1940 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1943 case IRP_MN_QUERY_ID
:
1945 DPRINT("IRP_MN_QUERY_ID\n");
1948 case IRP_MN_QUERY_CAPABILITIES
:
1950 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1955 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
1956 return ForwardIrpAndForget(DeviceObject
, Irp
);
1960 Irp
->IoStatus
.Information
= Information
;
1961 Irp
->IoStatus
.Status
= Status
;
1962 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1967 USBHUB_FdoHandleDeviceControl(
1968 IN PDEVICE_OBJECT DeviceObject
,
1971 DPRINT1("FdoHandleDeviceControl\n");
1973 return STATUS_NOT_IMPLEMENTED
;