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
);
25 DestroyUsbChildDeviceObject(
26 IN PDEVICE_OBJECT UsbHubDeviceObject
,
30 SubmitRequestToRootHub(
31 IN PDEVICE_OBJECT RootHubDeviceObject
,
32 IN ULONG IoControlCode
,
33 OUT PVOID OutParameter1
,
34 OUT PVOID OutParameter2
)
38 IO_STATUS_BLOCK IoStatus
;
40 PIO_STACK_LOCATION Stack
= NULL
;
42 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
45 // Build Control Request
47 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
57 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
58 return STATUS_INSUFFICIENT_RESOURCES
;
62 // Initialize the status block before sending the IRP
64 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
65 IoStatus
.Information
= 0;
68 // Get Next Stack Location and Initialize it
70 Stack
= IoGetNextIrpStackLocation(Irp
);
71 Stack
->Parameters
.Others
.Argument1
= OutParameter1
;
72 Stack
->Parameters
.Others
.Argument2
= OutParameter2
;
77 Status
= IoCallDriver(RootHubDeviceObject
, Irp
);
80 // Its ok to block here as this function is called in an nonarbitrary thread
82 if (Status
== STATUS_PENDING
)
84 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
85 Status
= IoStatus
.Status
;
89 // The IO Manager will free the IRP
96 GetPortStatusAndChange(
97 IN PDEVICE_OBJECT RootHubDeviceObject
,
99 OUT PPORT_STATUS_CHANGE StatusChange
)
107 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
110 DPRINT1("Failed to allocate memory for URB!\n");
111 return STATUS_INSUFFICIENT_RESOURCES
;
117 RtlZeroMemory(Urb
, sizeof(URB
));
120 // Initialize URB for getting Port Status
122 UsbBuildVendorRequest(Urb
,
123 URB_FUNCTION_CLASS_OTHER
,
124 sizeof(Urb
->UrbControlVendorClassRequest
),
125 USBD_TRANSFER_DIRECTION_OUT
,
127 USB_REQUEST_GET_STATUS
,
132 sizeof(PORT_STATUS_CHANGE
),
136 // Query the Root Hub
138 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
150 IN PDEVICE_OBJECT RootHubDeviceObject
,
160 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
163 DPRINT1("Failed to allocate memory for URB!\n");
164 return STATUS_INSUFFICIENT_RESOURCES
;
170 RtlZeroMemory(Urb
, sizeof(URB
));
173 // Initialize URB for Clearing Port Reset
175 UsbBuildVendorRequest(Urb
,
176 URB_FUNCTION_CLASS_OTHER
,
177 sizeof(Urb
->UrbControlVendorClassRequest
),
178 USBD_TRANSFER_DIRECTION_IN
,
180 USB_REQUEST_SET_FEATURE
,
188 // Query the Root Hub
190 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
202 IN PDEVICE_OBJECT RootHubDeviceObject
,
212 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
215 DPRINT1("Failed to allocate memory for URB!\n");
216 return STATUS_INSUFFICIENT_RESOURCES
;
222 RtlZeroMemory(Urb
, sizeof(URB
));
225 // Initialize URB for Clearing Port Reset
227 UsbBuildVendorRequest(Urb
,
228 URB_FUNCTION_CLASS_OTHER
,
229 sizeof(Urb
->UrbControlVendorClassRequest
),
230 USBD_TRANSFER_DIRECTION_IN
,
232 USB_REQUEST_CLEAR_FEATURE
,
240 // Query the Root Hub
242 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
253 DeviceStatusChangeThread(
257 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
258 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
259 PWORK_ITEM_DATA WorkItemData
;
260 PORT_STATUS_CHANGE PortStatus
;
263 DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context
);
265 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
266 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
267 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
268 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
272 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
277 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
278 if (!NT_SUCCESS(Status
))
280 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
281 // FIXME: Do we really want to halt further SCE requests?
285 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
286 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
290 // Check for new device connection
292 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
295 // Clear Port Connect
297 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
298 if (!NT_SUCCESS(Status
))
300 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
304 // Is this a connect or disconnect?
306 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
308 DPRINT1("Device disconnected from port %d\n", PortId
);
310 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
311 if (!NT_SUCCESS(Status
))
313 DPRINT1("Failed to delete child device object after disconnect\n");
318 DPRINT1("Device connected from port %d\n", PortId
);
320 // No SCE completion done for clearing C_PORT_CONNECT
325 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
326 if (!NT_SUCCESS(Status
))
328 DPRINT1("Failed to reset port %d\n", PortId
);
332 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
337 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
338 if (!NT_SUCCESS(Status
))
340 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
343 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
348 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
349 if (!NT_SUCCESS(Status
))
351 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
357 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
358 if (!NT_SUCCESS(Status
))
360 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
361 // FIXME: Do we really want to halt further SCE requests?
365 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
366 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
369 // Check that reset was cleared
371 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
373 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
377 // Check if the device is still connected
379 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
381 DPRINT1("Device has been disconnected\n");
386 // Make sure its Connected and Enabled
388 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
390 DPRINT1("Usb Device is not connected and enabled!\n");
392 // Attempt another reset
394 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
395 if (!NT_SUCCESS(Status
))
397 DPRINT1("Failed to reset port %d\n", PortId
);
403 // This is a new device
405 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
);
409 KeSetEvent(&WorkItemData
->Event
, IO_NO_INCREMENT
, FALSE
);
412 // Send another SCE Request
414 DPRINT1("Sending another SCE!\n");
415 QueryStatusChangeEndpoint(DeviceObject
);
420 StatusChangeEndpointCompletion(
421 IN PDEVICE_OBJECT DeviceObject
,
425 PDEVICE_OBJECT RealDeviceObject
;
426 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
427 PWORK_ITEM_DATA WorkItemData
;
429 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
430 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
433 // NOTE: USBPORT frees this IRP
435 DPRINT1("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
439 // Create and initialize work item data
441 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
444 DPRINT1("Failed to allocate memory!n");
445 return STATUS_INSUFFICIENT_RESOURCES
;
447 WorkItemData
->Context
= RealDeviceObject
;
448 KeInitializeEvent(&WorkItemData
->Event
, NotificationEvent
, FALSE
);
449 DPRINT1("Initialize work item\n");
450 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
453 // Queue the work item to handle initializing the device
455 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
458 // Wait for the work item
460 KeWaitForSingleObject(&WorkItemData
->Event
,
465 ExFreePool(WorkItemData
);
468 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
470 return STATUS_MORE_PROCESSING_REQUIRED
;
474 QueryStatusChangeEndpoint(
475 IN PDEVICE_OBJECT DeviceObject
)
478 PDEVICE_OBJECT RootHubDeviceObject
;
479 PIO_STACK_LOCATION Stack
;
480 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
483 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
484 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
489 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
492 // Initialize URB for Status Change Endpoint request
494 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
495 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
496 HubDeviceExtension
->PipeHandle
,
497 HubDeviceExtension
->PortStatusChange
,
499 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
500 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
504 // Set the device handle to null for roothub
506 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
512 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
513 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
516 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
519 DPRINT1("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
521 if (!HubDeviceExtension
->PendingSCEIrp
)
523 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
524 return STATUS_INSUFFICIENT_RESOURCES
;
528 // Initialize the IRP
530 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
531 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
532 RootHubDeviceObject
->StackSize
);
534 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
535 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
536 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
537 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
540 // Get the Next Stack Location and Initialize it
542 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
543 Stack
->DeviceObject
= DeviceObject
;
544 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
545 Stack
->Parameters
.Others
.Argument2
= NULL
;
546 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
547 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
550 // Set the completion routine for when device is connected to root hub
552 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
553 StatusChangeEndpointCompletion
,
562 DPRINT1("DeviceObject is %x\n", DeviceObject
);
563 DPRINT1("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
564 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
566 return STATUS_PENDING
;
571 IN PDEVICE_OBJECT DeviceObject
,
572 IN CONST GUID InterfaceType
,
579 IO_STATUS_BLOCK IoStatus
;
581 PIO_STACK_LOCATION Stack
= NULL
;
584 // Initialize the Event used to wait for Irp completion
586 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
589 // Build Control Request
591 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
600 // Get Next Stack Location and Initialize it.
602 Stack
= IoGetNextIrpStackLocation(Irp
);
603 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
604 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
605 Stack
->Parameters
.QueryInterface
.Size
= Size
;
606 Stack
->Parameters
.QueryInterface
.Version
= Version
;
607 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
608 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
610 Status
= IoCallDriver(DeviceObject
, Irp
);
612 if (Status
== STATUS_PENDING
)
614 DPRINT("Operation pending\n");
615 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
616 Status
= IoStatus
.Status
;
623 GetUsbDeviceDescriptor(
624 IN PDEVICE_OBJECT ChildDeviceObject
,
625 IN UCHAR DescriptorType
,
628 OUT PVOID TransferBuffer
,
629 IN ULONG TransferBufferLength
)
632 PDEVICE_OBJECT RootHubDeviceObject
;
634 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
635 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
638 // Get the Hubs Device Extension
640 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
641 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
642 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
647 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
650 DPRINT1("Failed to allocate memory for URB!\n");
651 return STATUS_INSUFFICIENT_RESOURCES
;
657 RtlZeroMemory(Urb
, sizeof(URB
));
660 // Initialize URB for getting device descriptor
662 UsbBuildGetDescriptorRequest(Urb
,
663 sizeof(Urb
->UrbControlDescriptorRequest
),
669 TransferBufferLength
,
673 // Set the device handle
675 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
678 // Query the Root Hub
680 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
681 IOCTL_INTERNAL_USB_SUBMIT_URB
,
689 GetUsbStringDescriptor(
690 IN PDEVICE_OBJECT ChildDeviceObject
,
693 OUT PVOID
*TransferBuffer
,
697 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
701 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
702 sizeof(USB_STRING_DESCRIPTOR
),
706 DPRINT1("Failed to allocate buffer for string!\n");
707 return STATUS_INSUFFICIENT_RESOURCES
;
711 // Get the index string descriptor length
712 // FIXME: Implement LangIds
714 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
715 USB_STRING_DESCRIPTOR_TYPE
,
719 sizeof(USB_STRING_DESCRIPTOR
));
720 if (!NT_SUCCESS(Status
))
722 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
723 ExFreePool(StringDesc
);
726 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
729 // Did we get something more than the length of the first two fields of structure?
731 if (StringDesc
->bLength
== 2)
733 DPRINT1("USB Device Error!\n");
734 ExFreePool(StringDesc
);
735 return STATUS_DEVICE_DATA_ERROR
;
737 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
742 ExFreePool(StringDesc
);
745 // Recreate with appropriate size
747 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
752 DPRINT1("Failed to allocate buffer for string!\n");
753 return STATUS_INSUFFICIENT_RESOURCES
;
756 RtlZeroMemory(StringDesc
, SizeNeeded
);
761 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
762 USB_STRING_DESCRIPTOR_TYPE
,
767 if (!NT_SUCCESS(Status
))
769 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
770 ExFreePool(StringDesc
);
775 // Allocate Buffer to return
777 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
782 DPRINT1("Failed to allocate buffer for string!\n");
783 ExFreePool(StringDesc
);
784 return STATUS_INSUFFICIENT_RESOURCES
;
786 DPRINT1("Buffer %p\n", Buffer
);
787 RtlZeroMemory(Buffer
, SizeNeeded
);
789 DPRINT1("Buffer %p\n", Buffer
);
790 DPRINT1("SizeNeeded %lu\n", SizeNeeded
);
791 DPRINT1("Offset %lu\n", FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
792 DPRINT1("Length %lu\n", SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
795 // Copy the string to destination
797 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
799 *TransferBuffer
= Buffer
;
801 ExFreePool(StringDesc
);
803 return STATUS_SUCCESS
;
808 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
809 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
811 if (DeviceDescriptor
->bNumConfigurations
!= 1)
814 // composite device must have only one configuration
816 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
820 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
823 // composite device must have multiple interfaces
825 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
829 if (DeviceDescriptor
->bDeviceClass
== 0)
834 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
835 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
836 DPRINT1("IsCompositeDevice: TRUE\n");
840 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
841 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
842 DeviceDescriptor
->bDeviceProtocol
== 0x01)
845 // USB-IF association descriptor
847 DPRINT1("IsCompositeDevice: TRUE\n");
851 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
854 // not a composite device
861 PDEVICE_OBJECT UsbChildDeviceObject
)
863 NTSTATUS Status
= STATUS_SUCCESS
;
867 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
868 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
869 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
870 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
873 // get child device extension
875 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
878 // get device descriptor
880 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
883 // get configuration descriptor
885 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
888 // use first interface descriptor available
890 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
891 ASSERT(InterfaceDescriptor
);
894 // Construct the CompatibleIds
896 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
901 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
902 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
903 Index
+= swprintf(&Buffer
[Index
],
904 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
905 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
906 Index
+= swprintf(&Buffer
[Index
],
907 L
"USB\\DevClass_%02x&SubClass_%02x",
908 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
909 Index
+= swprintf(&Buffer
[Index
],
910 L
"USB\\DevClass_%02x",
911 DeviceDescriptor
->bDeviceClass
) + 1;
912 Index
+= swprintf(&Buffer
[Index
],
913 L
"USB\\COMPOSITE") + 1;
918 // sanity checks for simple usb device
920 ASSERT(ConfigurationDescriptor
->bNumInterfaces
== 1);
923 // FIXME: support multiple configurations
925 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
927 if (DeviceDescriptor
->bDeviceClass
== 0)
929 Index
+= swprintf(&Buffer
[Index
],
930 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
931 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
932 Index
+= swprintf(&Buffer
[Index
],
933 L
"USB\\Class_%02x&SubClass_%02x",
934 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
935 Index
+= swprintf(&Buffer
[Index
],
937 InterfaceDescriptor
->bInterfaceClass
) + 1;
941 Index
+= swprintf(&Buffer
[Index
],
942 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
943 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
944 Index
+= swprintf(&Buffer
[Index
],
945 L
"USB\\Class_%02x&SubClass_%02x",
946 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
947 Index
+= swprintf(&Buffer
[Index
],
949 DeviceDescriptor
->bDeviceClass
) + 1;
954 // now allocate the buffer
956 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
962 return STATUS_INSUFFICIENT_RESOURCES
;
968 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
969 DeviceString
[Index
] = UNICODE_NULL
;
970 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
971 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
972 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
973 DPRINT1("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
976 // Construct DeviceId string
978 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
981 // now allocate the buffer
983 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
989 return STATUS_INSUFFICIENT_RESOURCES
;
995 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
996 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
997 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
998 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
999 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
1002 // Construct HardwareIds
1005 Index
+= swprintf(&Buffer
[Index
],
1006 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
1007 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
1008 Index
+= swprintf(&Buffer
[Index
],
1009 L
"USB\\Vid_%04x&Pid_%04x",
1010 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
1013 // now allocate the buffer
1015 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
1021 return STATUS_INSUFFICIENT_RESOURCES
;
1027 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
1028 DeviceString
[Index
] = UNICODE_NULL
;
1029 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
1030 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
1031 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
1032 DPRINT1("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
1035 // FIXME: Handle Lang ids
1039 // Get the product string if obe provided
1041 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1043 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1044 UsbChildExtension
->DeviceDesc
.iProduct
,
1046 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1047 &UsbChildExtension
->usTextDescription
.Length
);
1048 if (!NT_SUCCESS(Status
))
1050 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1054 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1055 DPRINT1("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1059 // Get the Serial Number string if obe provided
1061 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1063 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1064 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1066 (PVOID
*)&UsbChildExtension
->usInstanceId
.Buffer
,
1067 &UsbChildExtension
->usInstanceId
.Length
);
1068 if (!NT_SUCCESS(Status
))
1070 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1074 UsbChildExtension
->usInstanceId
.MaximumLength
= UsbChildExtension
->usInstanceId
.Length
;
1075 DPRINT1("Usb InstanceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1080 // the device did not provide a serial number, lets create a pseudo instance id
1082 Index
= swprintf(Buffer
, L
"0&%04d", UsbChildExtension
->PortNumber
) + 1;
1083 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1084 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1086 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1087 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1094 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1095 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1097 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1104 DestroyUsbChildDeviceObject(
1105 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1108 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1109 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1110 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1113 DPRINT1("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1115 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1117 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1119 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1121 /* Check if it matches the port ID */
1122 if (UsbChildExtension
->PortNumber
== PortId
)
1125 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1131 /* Fail the request if the device doesn't exist */
1132 if (!ChildDeviceObject
)
1134 DPRINT1("Removal request for non-existant device!\n");
1135 return STATUS_UNSUCCESSFUL
;
1138 /* Remove the device from the table */
1139 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1141 /* Invalidate device relations for the root hub */
1142 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1144 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1145 return STATUS_SUCCESS
;
1149 CreateUsbChildDeviceObject(
1150 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1152 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
)
1155 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1156 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1157 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1158 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1159 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1160 WCHAR CharDeviceName
[64];
1161 UNICODE_STRING DeviceName
;
1162 ULONG ConfigDescSize
, DeviceDescSize
;
1163 PVOID HubInterfaceBusContext
;
1164 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1166 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1167 HubInterface
= &HubDeviceExtension
->HubInterface
;
1168 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1169 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1171 // Find an empty slot in the child device array
1173 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1175 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1177 DPRINT1("Found unused entry at %d\n", ChildDeviceCount
);
1183 // Check if the limit has been reached for maximum usb devices
1185 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1187 DPRINT1("USBHUB: Too many child devices!\n");
1188 return STATUS_UNSUCCESSFUL
;
1194 // Create a Device Name
1196 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1199 // Initialize UnicodeString
1201 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1204 // Create a DeviceObject
1206 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1207 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1209 FILE_DEVICE_CONTROLLER
,
1210 FILE_AUTOGENERATED_DEVICE_NAME
,
1212 &NewChildDeviceObject
);
1215 // Check if the name is already in use
1217 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1227 // Check for other errors
1229 if (!NT_SUCCESS(Status
))
1231 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1235 DPRINT1("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1239 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1242 // Assign the device extensions
1244 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1245 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1246 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1247 UsbChildExtension
->PortNumber
= PortId
;
1250 // Create the UsbDeviceObject
1252 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1253 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1254 HubDeviceExtension
->RootHubHandle
,
1257 if (!NT_SUCCESS(Status
))
1259 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1264 // Initialize UsbDevice
1266 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1267 if (!NT_SUCCESS(Status
))
1269 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1273 DPRINT1("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1275 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1276 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1279 // Get the descriptors
1281 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1282 UsbChildExtension
->UsbDeviceHandle
,
1283 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1285 (PUCHAR
)&ConfigDesc
,
1287 if (!NT_SUCCESS(Status
))
1289 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1293 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
1294 DumpConfigurationDescriptor(&ConfigDesc
);
1297 // FIXME: Support more than one configuration and one interface?
1299 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1301 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1304 if (ConfigDesc
.bNumInterfaces
> 1)
1306 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1309 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1312 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1314 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1317 // Retrieve the full configuration descriptor
1319 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1320 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1323 UsbChildExtension
->FullConfigDesc
,
1326 if (!NT_SUCCESS(Status
))
1328 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1332 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1335 // Construct all the strings that will described the device to PNP
1337 Status
= CreateDeviceIds(NewChildDeviceObject
);
1338 if (!NT_SUCCESS(Status
))
1340 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1344 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1346 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1347 return STATUS_SUCCESS
;
1352 // Remove the usb device if it was created
1354 if (UsbChildExtension
->UsbDeviceHandle
)
1355 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1358 // Free full configuration descriptor if one was allocated
1360 if (UsbChildExtension
->FullConfigDesc
)
1361 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1364 // Delete the device object
1366 IoDeleteDevice(NewChildDeviceObject
);
1371 USBHUB_FdoQueryBusRelations(
1372 IN PDEVICE_OBJECT DeviceObject
,
1373 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1375 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1376 PDEVICE_RELATIONS DeviceRelations
;
1381 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1384 // Count the number of children
1386 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1389 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1396 NeededSize
= sizeof(DEVICE_RELATIONS
);
1398 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1401 // Allocate DeviceRelations
1403 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1406 if (!DeviceRelations
)
1407 return STATUS_INSUFFICIENT_RESOURCES
;
1408 DeviceRelations
->Count
= Children
;
1412 // Fill in return structure
1414 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1416 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1418 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1419 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1420 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1424 ASSERT(Children
== DeviceRelations
->Count
);
1425 *pDeviceRelations
= DeviceRelations
;
1427 return STATUS_SUCCESS
;
1432 RootHubInitCallbackFunction(
1435 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1438 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1439 PORT_STATUS_CHANGE StatusChange
;
1441 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1443 DPRINT1("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1446 // Send the first SCE Request
1448 QueryStatusChangeEndpoint(DeviceObject
);
1450 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1455 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1456 if (NT_SUCCESS(Status
))
1459 // is there a device connected
1461 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1466 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1467 if (!NT_SUCCESS(Status
))
1468 DPRINT1("Failed to reset on port %d\n", PortId
);
1475 USBHUB_FdoHandlePnp(
1476 IN PDEVICE_OBJECT DeviceObject
,
1479 PIO_STACK_LOCATION Stack
;
1480 NTSTATUS Status
= STATUS_SUCCESS
;
1481 ULONG_PTR Information
= 0;
1482 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1483 PDEVICE_OBJECT RootHubDeviceObject
;
1484 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1485 PORT_STATUS_CHANGE StatusChange
;
1487 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1489 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1491 switch (Stack
->MinorFunction
)
1493 case IRP_MN_START_DEVICE
:
1496 PUSB_INTERFACE_DESCRIPTOR Pid
;
1497 ULONG Result
= 0, PortId
;
1498 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1499 PURB ConfigUrb
= NULL
;
1502 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1505 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1507 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1508 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1511 // Get the Root Hub Pdo
1513 SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1514 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1515 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1516 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1518 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1519 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1520 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1521 DPRINT1("RootPdo %x, RootFdo %x\n",
1522 HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1523 HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1526 // Send the StartDevice to RootHub
1528 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1530 if (!NT_SUCCESS(Status
))
1532 DPRINT1("Failed to start the RootHub PDO\n");
1537 // Get the current number of hubs
1539 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1540 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1541 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1544 // Get the Hub Interface
1546 Status
= QueryInterface(RootHubDeviceObject
,
1547 USB_BUS_INTERFACE_HUB_GUID
,
1548 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1550 (PVOID
)&HubDeviceExtension
->HubInterface
);
1552 if (!NT_SUCCESS(Status
))
1554 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1555 return STATUS_UNSUCCESSFUL
;
1558 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1561 // Get the USBDI Interface
1563 Status
= QueryInterface(RootHubDeviceObject
,
1564 USB_BUS_INTERFACE_USBDI_GUID
,
1565 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1567 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1569 if (!NT_SUCCESS(Status
))
1571 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1575 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1578 // Get Root Hub Device Handle
1580 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1581 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1582 &HubDeviceExtension
->RootHubHandle
,
1585 if (!NT_SUCCESS(Status
))
1587 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status
);
1592 // Get Hub Device Information
1594 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1595 HubDeviceExtension
->RootHubHandle
,
1596 &HubDeviceExtension
->DeviceInformation
,
1597 sizeof(USB_DEVICE_INFORMATION_0
),
1600 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1601 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1602 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1603 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1604 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1605 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1606 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1609 // Get Root Hubs Device Descriptor
1611 UsbBuildGetDescriptorRequest(Urb
,
1612 sizeof(Urb
->UrbControlDescriptorRequest
),
1613 USB_DEVICE_DESCRIPTOR_TYPE
,
1616 &HubDeviceExtension
->HubDeviceDescriptor
,
1618 sizeof(USB_DEVICE_DESCRIPTOR
),
1621 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1623 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1624 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1628 if (!NT_SUCCESS(Status
))
1630 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1633 DumpDeviceDescriptor(&HubDeviceExtension
->HubDeviceDescriptor
);
1636 // Get Root Hubs Configuration Descriptor
1638 UsbBuildGetDescriptorRequest(Urb
,
1639 sizeof(Urb
->UrbControlDescriptorRequest
),
1640 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1643 &HubDeviceExtension
->HubConfigDescriptor
,
1645 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1648 DPRINT1("RootHub Handle %x\n", HubDeviceExtension
->RootHubHandle
);
1649 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1651 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1652 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1656 if (!NT_SUCCESS(Status
))
1658 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1661 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
);
1663 DumpConfigurationDescriptor(&HubDeviceExtension
->HubConfigDescriptor
);
1665 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1666 RootHubDeviceObject
,
1667 &HubDeviceExtension
->UsbExtHubInfo
,
1668 sizeof(USB_EXTHUB_INFORMATION_0
),
1670 if (!NT_SUCCESS(Status
))
1672 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1676 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1679 // Get the Hub Descriptor
1681 UsbBuildVendorRequest(Urb
,
1682 URB_FUNCTION_CLASS_DEVICE
,
1683 sizeof(Urb
->UrbControlVendorClassRequest
),
1684 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1686 USB_REQUEST_GET_DESCRIPTOR
,
1687 USB_DEVICE_CLASS_RESERVED
,
1689 &HubDeviceExtension
->HubDescriptor
,
1691 sizeof(USB_HUB_DESCRIPTOR
),
1694 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1696 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1697 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1701 DPRINT1("bDescriptorType %x\n", HubDeviceExtension
->HubDescriptor
.bDescriptorType
);
1703 if (!NT_SUCCESS(Status
))
1705 DPRINT1("Failed to get Hub Descriptor!\n");
1707 return STATUS_UNSUCCESSFUL
;
1711 UsbBuildGetStatusRequest(Urb
,
1712 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1717 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1719 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1720 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1723 if (!NT_SUCCESS(Status
))
1725 DPRINT1("Failed to get Hub Status!\n");
1727 return STATUS_UNSUCCESSFUL
;
1730 DPRINT1("HubStatus %x\n", HubStatus
);
1733 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1735 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1736 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1740 // Get the first Configuration Descriptor
1742 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1743 &HubDeviceExtension
->HubConfigDescriptor
,
1744 -1, -1, -1, -1, -1);
1746 ASSERT(Pid
!= NULL
);
1748 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1749 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1750 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1751 ASSERT(ConfigUrb
!= NULL
);
1753 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1754 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1758 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1759 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1760 DPRINT1("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1763 // check if function is available
1765 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1768 // is it high speed bus
1770 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1773 // initialize usb 2.0 hub
1775 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1776 HubDeviceExtension
->RootHubHandle
, 1);
1777 DPRINT1("Status %x\n", Status
);
1780 // FIXME handle error
1782 ASSERT(Status
== STATUS_SUCCESS
);
1786 ExFreePool(ConfigUrb
);
1789 // Enable power on all ports
1792 DPRINT1("Enabling PortPower on all ports!\n");
1794 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1796 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1797 if (!NT_SUCCESS(Status
))
1798 DPRINT1("Failed to power on port %d\n", PortId
);
1800 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1801 if (!NT_SUCCESS(Status
))
1802 DPRINT1("Failed to power on port %d\n", PortId
);
1805 DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension
->HubInterface
.RootHubInitNotification
);
1808 // init roo hub notification
1810 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1812 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1814 RootHubInitCallbackFunction
);
1815 if (!NT_SUCCESS(Status
))
1817 DPRINT1("Failed to set callback\n");
1823 // Send the first SCE Request
1825 QueryStatusChangeEndpoint(DeviceObject
);
1830 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1835 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1836 if (NT_SUCCESS(Status
))
1839 // is there a device connected
1841 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1846 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1847 if (!NT_SUCCESS(Status
))
1848 DPRINT1("Failed to reset on port %d\n", PortId
);
1858 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1860 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1864 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1865 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1867 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1869 Information
= (ULONG_PTR
)DeviceRelations
;
1872 case RemovalRelations
:
1874 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1875 return ForwardIrpAndForget(DeviceObject
, Irp
);
1878 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1879 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1880 return ForwardIrpAndForget(DeviceObject
, Irp
);
1884 case IRP_MN_QUERY_BUS_INFORMATION
:
1886 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
1889 case IRP_MN_QUERY_ID
:
1891 DPRINT1("IRP_MN_QUERY_ID\n");
1894 case IRP_MN_QUERY_CAPABILITIES
:
1896 DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
1901 DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
1902 return ForwardIrpAndForget(DeviceObject
, Irp
);
1906 Irp
->IoStatus
.Information
= Information
;
1907 Irp
->IoStatus
.Status
= Status
;
1908 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1913 USBHUB_FdoHandleDeviceControl(
1914 IN PDEVICE_OBJECT DeviceObject
,
1917 DPRINT1("FdoHandleDeviceControl\n");
1919 return STATUS_NOT_IMPLEMENTED
;