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
,
32 GetPortStatusAndChange(
33 IN PDEVICE_OBJECT RootHubDeviceObject
,
35 OUT PPORT_STATUS_CHANGE StatusChange
)
43 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
46 DPRINT1("Failed to allocate memory for URB!\n");
47 return STATUS_INSUFFICIENT_RESOURCES
;
53 RtlZeroMemory(Urb
, sizeof(URB
));
56 // Initialize URB for getting Port Status
58 UsbBuildVendorRequest(Urb
,
59 URB_FUNCTION_CLASS_OTHER
,
60 sizeof(Urb
->UrbControlVendorClassRequest
),
61 USBD_TRANSFER_DIRECTION_OUT
,
63 USB_REQUEST_GET_STATUS
,
68 sizeof(PORT_STATUS_CHANGE
),
71 // FIXME: support usb hubs
72 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
78 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
90 IN PDEVICE_OBJECT RootHubDeviceObject
,
100 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
103 DPRINT1("Failed to allocate memory for URB!\n");
104 return STATUS_INSUFFICIENT_RESOURCES
;
110 RtlZeroMemory(Urb
, sizeof(URB
));
113 // Initialize URB for Clearing Port Reset
115 UsbBuildVendorRequest(Urb
,
116 URB_FUNCTION_CLASS_OTHER
,
117 sizeof(Urb
->UrbControlVendorClassRequest
),
118 USBD_TRANSFER_DIRECTION_IN
,
120 USB_REQUEST_SET_FEATURE
,
128 // FIXME support usbhubs
129 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
132 // Query the Root Hub
134 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
146 IN PDEVICE_OBJECT RootHubDeviceObject
,
156 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
159 DPRINT1("Failed to allocate memory for URB!\n");
160 return STATUS_INSUFFICIENT_RESOURCES
;
166 RtlZeroMemory(Urb
, sizeof(URB
));
169 // Initialize URB for Clearing Port Reset
171 UsbBuildVendorRequest(Urb
,
172 URB_FUNCTION_CLASS_OTHER
,
173 sizeof(Urb
->UrbControlVendorClassRequest
),
174 USBD_TRANSFER_DIRECTION_IN
,
176 USB_REQUEST_CLEAR_FEATURE
,
184 // FIXME: support usb hubs
185 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
188 // Query the Root Hub
190 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
201 DeviceStatusChangeThread(
205 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
206 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
207 PWORK_ITEM_DATA WorkItemData
;
208 PORT_STATUS_CHANGE PortStatus
;
210 BOOLEAN SignalResetComplete
= FALSE
;
212 DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context
);
214 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
215 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
216 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
217 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
221 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
226 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
227 if (!NT_SUCCESS(Status
))
229 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
230 // FIXME: Do we really want to halt further SCE requests?
234 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
235 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
239 // Check for new device connection
241 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
244 // Clear Port Connect
246 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
247 if (!NT_SUCCESS(Status
))
249 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
254 // Is this a connect or disconnect?
256 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
258 DPRINT1("Device disconnected from port %d\n", PortId
);
260 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
261 if (!NT_SUCCESS(Status
))
263 DPRINT1("Failed to delete child device object after disconnect\n");
269 DPRINT1("Device connected from port %d\n", PortId
);
271 // No SCE completion done for clearing C_PORT_CONNECT
276 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
277 if (!NT_SUCCESS(Status
))
279 DPRINT1("Failed to reset port %d\n", PortId
);
280 SignalResetComplete
= TRUE
;
285 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
290 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
291 if (!NT_SUCCESS(Status
))
293 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
297 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
300 // Request event signalling later
302 SignalResetComplete
= TRUE
;
307 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
308 if (!NT_SUCCESS(Status
))
310 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
317 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
318 if (!NT_SUCCESS(Status
))
320 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
321 // FIXME: Do we really want to halt further SCE requests?
325 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
326 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
329 // Check that reset was cleared
331 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
333 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
338 // Check if the device is still connected
340 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
342 DPRINT1("Device has been disconnected\n");
347 // Make sure its Connected and Enabled
349 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
351 DPRINT1("Usb Device is not connected and enabled!\n");
353 // Attempt another reset
355 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
356 if (!NT_SUCCESS(Status
))
358 DPRINT1("Failed to reset port %d\n", PortId
);
364 // This is a new device
366 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
, PortStatus
.Status
);
370 ExFreePool(WorkItemData
);
373 // Send another SCE Request
375 DPRINT("Sending another SCE!\n");
376 QueryStatusChangeEndpoint(DeviceObject
);
379 // Check if a reset event was satisfied
381 if (SignalResetComplete
)
384 // Signal anyone waiting on it
386 KeSetEvent(&HubDeviceExtension
->ResetComplete
, IO_NO_INCREMENT
, FALSE
);
392 StatusChangeEndpointCompletion(
393 IN PDEVICE_OBJECT DeviceObject
,
397 PDEVICE_OBJECT RealDeviceObject
;
398 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
399 PWORK_ITEM_DATA WorkItemData
;
401 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
402 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
405 // NOTE: USBPORT frees this IRP
407 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
411 // Create and initialize work item data
413 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
416 DPRINT1("Failed to allocate memory!n");
417 return STATUS_INSUFFICIENT_RESOURCES
;
419 WorkItemData
->Context
= RealDeviceObject
;
421 DPRINT("Queuing work item\n");
424 // Queue the work item to handle initializing the device
426 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
427 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
430 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
432 return STATUS_MORE_PROCESSING_REQUIRED
;
436 QueryStatusChangeEndpoint(
437 IN PDEVICE_OBJECT DeviceObject
)
440 PDEVICE_OBJECT RootHubDeviceObject
;
441 PIO_STACK_LOCATION Stack
;
442 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
445 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
446 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
451 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
454 // Initialize URB for Status Change Endpoint request
456 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
457 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
458 HubDeviceExtension
->PipeHandle
,
459 HubDeviceExtension
->PortStatusChange
,
461 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
462 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
465 // Set the device handle
466 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
471 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
472 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
475 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
478 DPRINT("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
480 if (!HubDeviceExtension
->PendingSCEIrp
)
482 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
483 return STATUS_INSUFFICIENT_RESOURCES
;
487 // Initialize the IRP
489 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
490 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
491 RootHubDeviceObject
->StackSize
);
493 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
494 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
495 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
496 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
499 // Get the Next Stack Location and Initialize it
501 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
502 Stack
->DeviceObject
= DeviceObject
;
503 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
504 Stack
->Parameters
.Others
.Argument2
= NULL
;
505 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
506 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
509 // Set the completion routine for when device is connected to root hub
511 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
512 StatusChangeEndpointCompletion
,
521 DPRINT("DeviceObject is %x\n", DeviceObject
);
522 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
523 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
525 return STATUS_PENDING
;
530 IN PDEVICE_OBJECT DeviceObject
,
531 IN CONST GUID InterfaceType
,
538 IO_STATUS_BLOCK IoStatus
;
540 PIO_STACK_LOCATION Stack
= NULL
;
543 // Initialize the Event used to wait for Irp completion
545 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
548 // Build Control Request
550 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
559 // Get Next Stack Location and Initialize it.
561 Stack
= IoGetNextIrpStackLocation(Irp
);
562 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
563 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
564 Stack
->Parameters
.QueryInterface
.Size
= Size
;
565 Stack
->Parameters
.QueryInterface
.Version
= Version
;
566 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
567 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
569 Status
= IoCallDriver(DeviceObject
, Irp
);
571 if (Status
== STATUS_PENDING
)
573 DPRINT("Operation pending\n");
574 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
575 Status
= IoStatus
.Status
;
582 GetUsbDeviceDescriptor(
583 IN PDEVICE_OBJECT ChildDeviceObject
,
584 IN UCHAR DescriptorType
,
587 OUT PVOID TransferBuffer
,
588 IN ULONG TransferBufferLength
)
591 PDEVICE_OBJECT RootHubDeviceObject
;
593 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
594 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
597 // Get the Hubs Device Extension
599 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
600 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
601 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
606 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
609 DPRINT1("Failed to allocate memory for URB!\n");
610 return STATUS_INSUFFICIENT_RESOURCES
;
616 RtlZeroMemory(Urb
, sizeof(URB
));
619 // Initialize URB for getting device descriptor
621 UsbBuildGetDescriptorRequest(Urb
,
622 sizeof(Urb
->UrbControlDescriptorRequest
),
628 TransferBufferLength
,
632 // Set the device handle
634 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
637 // Query the Root Hub
639 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
640 IOCTL_INTERNAL_USB_SUBMIT_URB
,
648 GetUsbStringDescriptor(
649 IN PDEVICE_OBJECT ChildDeviceObject
,
652 OUT PVOID
*TransferBuffer
,
656 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
660 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
661 sizeof(USB_STRING_DESCRIPTOR
),
665 DPRINT1("Failed to allocate buffer for string!\n");
666 return STATUS_INSUFFICIENT_RESOURCES
;
670 // Get the index string descriptor length
671 // FIXME: Implement LangIds
673 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
674 USB_STRING_DESCRIPTOR_TYPE
,
678 sizeof(USB_STRING_DESCRIPTOR
));
679 if (!NT_SUCCESS(Status
))
681 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
682 ExFreePool(StringDesc
);
685 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
688 // Did we get something more than the length of the first two fields of structure?
690 if (StringDesc
->bLength
== 2)
692 DPRINT1("USB Device Error!\n");
693 ExFreePool(StringDesc
);
694 return STATUS_DEVICE_DATA_ERROR
;
696 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
701 ExFreePool(StringDesc
);
704 // Recreate with appropriate size
706 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
711 DPRINT1("Failed to allocate buffer for string!\n");
712 return STATUS_INSUFFICIENT_RESOURCES
;
715 RtlZeroMemory(StringDesc
, SizeNeeded
);
720 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
721 USB_STRING_DESCRIPTOR_TYPE
,
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
729 ExFreePool(StringDesc
);
734 // Allocate Buffer to return
736 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
741 DPRINT1("Failed to allocate buffer for string!\n");
742 ExFreePool(StringDesc
);
743 return STATUS_INSUFFICIENT_RESOURCES
;
746 RtlZeroMemory(Buffer
, SizeNeeded
);
749 // Copy the string to destination
751 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
753 *TransferBuffer
= Buffer
;
755 ExFreePool(StringDesc
);
757 return STATUS_SUCCESS
;
762 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
763 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
765 if (DeviceDescriptor
->bNumConfigurations
!= 1)
768 // composite device must have only one configuration
770 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
774 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
777 // composite device must have multiple interfaces
779 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
783 if (DeviceDescriptor
->bDeviceClass
== 0)
788 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
789 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
790 DPRINT1("IsCompositeDevice: TRUE\n");
794 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
795 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
796 DeviceDescriptor
->bDeviceProtocol
== 0x01)
799 // USB-IF association descriptor
801 DPRINT1("IsCompositeDevice: TRUE\n");
805 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
808 // not a composite device
815 PDEVICE_OBJECT UsbChildDeviceObject
)
817 NTSTATUS Status
= STATUS_SUCCESS
;
821 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
822 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
823 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
824 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
825 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
828 // get child device extension
830 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
832 // get hub device extension
833 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbChildExtension
->ParentDeviceObject
->DeviceExtension
;
836 // get device descriptor
838 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
841 // get configuration descriptor
843 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
846 // use first interface descriptor available
848 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
849 ASSERT(InterfaceDescriptor
);
852 // Construct the CompatibleIds
854 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
859 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
860 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
861 Index
+= swprintf(&Buffer
[Index
],
862 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
863 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
864 Index
+= swprintf(&Buffer
[Index
],
865 L
"USB\\DevClass_%02x&SubClass_%02x",
866 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
867 Index
+= swprintf(&Buffer
[Index
],
868 L
"USB\\DevClass_%02x",
869 DeviceDescriptor
->bDeviceClass
) + 1;
870 Index
+= swprintf(&Buffer
[Index
],
871 L
"USB\\COMPOSITE") + 1;
876 // FIXME: support multiple configurations
878 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
880 if (DeviceDescriptor
->bDeviceClass
== 0)
882 Index
+= swprintf(&Buffer
[Index
],
883 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
884 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
885 Index
+= swprintf(&Buffer
[Index
],
886 L
"USB\\Class_%02x&SubClass_%02x",
887 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
888 Index
+= swprintf(&Buffer
[Index
],
890 InterfaceDescriptor
->bInterfaceClass
) + 1;
894 Index
+= swprintf(&Buffer
[Index
],
895 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
896 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
897 Index
+= swprintf(&Buffer
[Index
],
898 L
"USB\\Class_%02x&SubClass_%02x",
899 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
900 Index
+= swprintf(&Buffer
[Index
],
902 DeviceDescriptor
->bDeviceClass
) + 1;
907 // now allocate the buffer
909 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
915 return STATUS_INSUFFICIENT_RESOURCES
;
921 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
922 DeviceString
[Index
] = UNICODE_NULL
;
923 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
924 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
925 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
926 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
929 // Construct DeviceId string
931 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
934 // now allocate the buffer
936 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
942 return STATUS_INSUFFICIENT_RESOURCES
;
948 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
949 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
950 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
951 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
952 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
955 // Construct HardwareIds
958 Index
+= swprintf(&Buffer
[Index
],
959 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
960 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
961 Index
+= swprintf(&Buffer
[Index
],
962 L
"USB\\Vid_%04x&Pid_%04x",
963 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
966 // now allocate the buffer
968 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
974 return STATUS_INSUFFICIENT_RESOURCES
;
980 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
981 DeviceString
[Index
] = UNICODE_NULL
;
982 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
983 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
984 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
985 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
988 // FIXME: Handle Lang ids
992 // Get the product string if obe provided
994 if (UsbChildExtension
->DeviceDesc
.iProduct
)
996 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
997 UsbChildExtension
->DeviceDesc
.iProduct
,
999 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1000 &UsbChildExtension
->usTextDescription
.Length
);
1001 if (!NT_SUCCESS(Status
))
1003 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1004 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"USB Device"); // FIXME NON-NLS
1008 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1009 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1014 // Get the Serial Number string if obe provided
1016 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1018 LPWSTR SerialBuffer
= NULL
;
1020 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1021 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1023 (PVOID
*)&SerialBuffer
,
1024 &UsbChildExtension
->usInstanceId
.Length
);
1025 if (NT_SUCCESS(Status
))
1027 // construct instance id buffer
1028 Index
= swprintf(Buffer
, L
"%04d&%s", HubDeviceExtension
->InstanceCount
, SerialBuffer
) + 1;
1029 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1030 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1032 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1033 return STATUS_INSUFFICIENT_RESOURCES
;
1039 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1040 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1041 ExFreePool(SerialBuffer
);
1043 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension
->usInstanceId
, HubDeviceExtension
->InstanceCount
);
1049 // the device did not provide a serial number, or failed to retrieve the serial number
1050 // lets create a pseudo instance id
1052 Index
= swprintf(Buffer
, L
"%04d&%04d", HubDeviceExtension
->InstanceCount
, UsbChildExtension
->PortNumber
) + 1;
1053 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1054 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1056 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1057 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1064 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1065 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1067 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1068 return STATUS_SUCCESS
;
1072 DestroyUsbChildDeviceObject(
1073 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1076 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1077 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1078 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1081 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1083 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1085 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1087 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1089 /* Check if it matches the port ID */
1090 if (UsbChildExtension
->PortNumber
== PortId
)
1093 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1099 /* Fail the request if the device doesn't exist */
1100 if (!ChildDeviceObject
)
1102 DPRINT1("Removal request for non-existant device!\n");
1103 return STATUS_UNSUCCESSFUL
;
1106 /* Remove the device from the table */
1107 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1109 /* Invalidate device relations for the root hub */
1110 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1112 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1113 return STATUS_SUCCESS
;
1117 CreateUsbChildDeviceObject(
1118 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1120 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1121 IN ULONG PortStatus
)
1124 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1125 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1126 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1127 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1128 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1129 WCHAR CharDeviceName
[64];
1130 UNICODE_STRING DeviceName
;
1131 ULONG ConfigDescSize
, DeviceDescSize
, DeviceInfoSize
;
1132 PVOID HubInterfaceBusContext
;
1133 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1135 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1136 HubInterface
= &HubDeviceExtension
->HubInterface
;
1137 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1138 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1140 // Find an empty slot in the child device array
1142 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1144 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1146 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1152 // Check if the limit has been reached for maximum usb devices
1154 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1156 DPRINT1("USBHUB: Too many child devices!\n");
1157 return STATUS_UNSUCCESSFUL
;
1163 // Create a Device Name
1165 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1168 // Initialize UnicodeString
1170 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1173 // Create a DeviceObject
1175 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1176 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1178 FILE_DEVICE_CONTROLLER
,
1179 FILE_AUTOGENERATED_DEVICE_NAME
,
1181 &NewChildDeviceObject
);
1184 // Check if the name is already in use
1186 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1196 // Check for other errors
1198 if (!NT_SUCCESS(Status
))
1200 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1204 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1208 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1211 // Assign the device extensions
1213 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1214 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1215 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1216 UsbChildExtension
->PortNumber
= PortId
;
1218 // copy device interface
1219 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1223 // Create the UsbDeviceObject
1225 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1226 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1227 HubDeviceExtension
->RootHubHandle
,
1230 if (!NT_SUCCESS(Status
))
1232 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1236 // copy device interface
1237 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1239 // FIXME replace buscontext
1240 UsbChildExtension
->DeviceInterface
.BusContext
= UsbChildExtension
->UsbDeviceHandle
;
1243 // Initialize UsbDevice
1245 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1246 if (!NT_SUCCESS(Status
))
1248 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1252 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1254 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1255 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1258 // Get the descriptors
1260 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1261 UsbChildExtension
->UsbDeviceHandle
,
1262 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1264 (PUCHAR
)&ConfigDesc
,
1266 if (!NT_SUCCESS(Status
))
1268 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1272 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
1273 DumpConfigurationDescriptor(&ConfigDesc
);
1276 // FIXME: Support more than one configuration and one interface?
1278 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1280 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1283 if (ConfigDesc
.bNumInterfaces
> 1)
1285 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1288 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1291 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1293 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1296 // Retrieve the full configuration descriptor
1298 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1299 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1302 UsbChildExtension
->FullConfigDesc
,
1305 if (!NT_SUCCESS(Status
))
1307 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1311 // query device details
1312 Status
= HubInterface
->QueryDeviceInformation(HubInterfaceBusContext
,
1313 UsbChildExtension
->UsbDeviceHandle
,
1314 &UsbChildExtension
->DeviceInformation
,
1315 sizeof(USB_DEVICE_INFORMATION_0
),
1319 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1322 // Construct all the strings that will described the device to PNP
1324 Status
= CreateDeviceIds(NewChildDeviceObject
);
1325 if (!NT_SUCCESS(Status
))
1327 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1331 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1332 HubDeviceExtension
->InstanceCount
++;
1334 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1335 return STATUS_SUCCESS
;
1340 // Remove the usb device if it was created
1342 if (UsbChildExtension
->UsbDeviceHandle
)
1343 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1346 // Free full configuration descriptor if one was allocated
1348 if (UsbChildExtension
->FullConfigDesc
)
1349 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1352 // Delete the device object
1354 IoDeleteDevice(NewChildDeviceObject
);
1359 USBHUB_FdoQueryBusRelations(
1360 IN PDEVICE_OBJECT DeviceObject
,
1361 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1363 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1364 PDEVICE_RELATIONS DeviceRelations
;
1369 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1372 // Count the number of children
1374 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1377 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1384 NeededSize
= sizeof(DEVICE_RELATIONS
);
1386 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1389 // Allocate DeviceRelations
1391 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1394 if (!DeviceRelations
)
1395 return STATUS_INSUFFICIENT_RESOURCES
;
1396 DeviceRelations
->Count
= Children
;
1400 // Fill in return structure
1402 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1404 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1406 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1407 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1408 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1412 ASSERT(Children
== DeviceRelations
->Count
);
1413 *pDeviceRelations
= DeviceRelations
;
1415 return STATUS_SUCCESS
;
1420 RootHubInitCallbackFunction(
1423 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1426 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1427 PORT_STATUS_CHANGE StatusChange
;
1429 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1431 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1434 // Send the first SCE Request
1436 QueryStatusChangeEndpoint(DeviceObject
);
1438 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1443 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1444 if (NT_SUCCESS(Status
))
1447 // is there a device connected
1449 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1454 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1455 if (!NT_SUCCESS(Status
))
1457 DPRINT1("Failed to reset on port %d\n", PortId
);
1462 // wait for the reset to be handled since we want to enumerate synchronously
1464 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1469 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1477 USBHUB_IsRootHubFDO(
1478 IN PDEVICE_OBJECT DeviceObject
)
1481 PDEVICE_OBJECT RootHubPhysicalDeviceObject
= NULL
;
1482 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1484 // get hub device extension
1485 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1487 // Get the Root Hub Pdo
1488 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1489 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1490 &RootHubPhysicalDeviceObject
,
1493 // FIXME handle error
1494 ASSERT(NT_SUCCESS(Status
));
1496 // physical device object is only obtained for root hubs
1497 return (RootHubPhysicalDeviceObject
!= NULL
);
1502 USBHUB_FdoStartDevice(
1503 IN PDEVICE_OBJECT DeviceObject
,
1507 PUSB_INTERFACE_DESCRIPTOR Pid
;
1508 ULONG Result
= 0, PortId
;
1509 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1510 PURB ConfigUrb
= NULL
;
1512 PIO_STACK_LOCATION Stack
;
1513 NTSTATUS Status
= STATUS_SUCCESS
;
1514 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1515 PDEVICE_OBJECT RootHubDeviceObject
;
1516 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1517 PORT_STATUS_CHANGE StatusChange
;
1519 // get current stack location
1520 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1522 // get hub device extension
1523 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1525 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1527 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1528 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1532 return STATUS_INSUFFICIENT_RESOURCES
;
1536 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1538 // Get the Root Hub Pdo
1539 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1540 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1541 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1542 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1543 if (!NT_SUCCESS(Status
))
1545 // failed to obtain hub pdo
1546 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status
);
1552 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1553 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1556 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1558 // Send the StartDevice to RootHub
1559 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1561 if (!NT_SUCCESS(Status
))
1563 // failed to start pdo
1564 DPRINT1("Failed to start the RootHub PDO\n");
1569 // Get the current number of hubs
1570 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1571 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1572 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1573 if (!NT_SUCCESS(Status
))
1575 // failed to get number of hubs
1576 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status
);
1581 // Get the Hub Interface
1582 Status
= QueryInterface(RootHubDeviceObject
,
1583 USB_BUS_INTERFACE_HUB_GUID
,
1584 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1585 USB_BUSIF_HUB_VERSION_5
,
1586 (PVOID
)&HubDeviceExtension
->HubInterface
);
1588 if (!NT_SUCCESS(Status
))
1590 // failed to get root hub interface
1591 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1596 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1598 // Get the USBDI Interface
1599 Status
= QueryInterface(RootHubDeviceObject
,
1600 USB_BUS_INTERFACE_USBDI_GUID
,
1601 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1602 USB_BUSIF_USBDI_VERSION_2
,
1603 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1605 if (!NT_SUCCESS(Status
))
1607 // failed to get usbdi interface
1608 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1613 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1615 // Get Root Hub Device Handle
1616 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1617 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1618 &HubDeviceExtension
->RootHubHandle
,
1621 if (!NT_SUCCESS(Status
))
1624 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status
);
1630 // Get Hub Device Information
1632 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1633 HubDeviceExtension
->RootHubHandle
,
1634 &HubDeviceExtension
->DeviceInformation
,
1635 sizeof(USB_DEVICE_INFORMATION_0
),
1638 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1639 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1640 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1641 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1642 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1643 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1644 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1646 // Get Root Hubs Device Descriptor
1647 UsbBuildGetDescriptorRequest(Urb
,
1648 sizeof(Urb
->UrbControlDescriptorRequest
),
1649 USB_DEVICE_DESCRIPTOR_TYPE
,
1652 &HubDeviceExtension
->HubDeviceDescriptor
,
1654 sizeof(USB_DEVICE_DESCRIPTOR
),
1657 // set device handle
1658 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1660 // get hub device descriptor
1661 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1662 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1666 if (!NT_SUCCESS(Status
))
1668 // failed to get device descriptor of hub
1669 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1674 // build configuration request
1675 UsbBuildGetDescriptorRequest(Urb
,
1676 sizeof(Urb
->UrbControlDescriptorRequest
),
1677 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1680 &HubDeviceExtension
->HubConfigDescriptor
,
1682 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1685 // set device handle
1686 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1688 // request configuration descriptor
1689 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1690 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1694 if (!NT_SUCCESS(Status
))
1696 // failed to get configuration descriptor
1697 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1703 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
));
1704 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bDescriptorType
== USB_CONFIGURATION_DESCRIPTOR_TYPE
);
1705 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1706 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bNumInterfaces
== 1);
1707 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
1708 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
1709 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bNumEndpoints
== 1);
1710 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1711 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bLength
== sizeof(USB_ENDPOINT_DESCRIPTOR
));
1712 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bmAttributes
== USB_ENDPOINT_TYPE_INTERRUPT
);
1713 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bEndpointAddress
== 0x81); // interrupt in
1715 // get hub information
1716 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1717 RootHubDeviceObject
,
1718 &HubDeviceExtension
->UsbExtHubInfo
,
1719 sizeof(USB_EXTHUB_INFORMATION_0
),
1721 if (!NT_SUCCESS(Status
))
1723 // failed to get hub information
1724 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1729 if (!HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
)
1731 // bogus port driver
1732 DPRINT1("Failed to retrieve the number of ports\n");
1734 return STATUS_UNSUCCESSFUL
;
1737 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1739 // Build hub descriptor request
1740 UsbBuildVendorRequest(Urb
,
1741 URB_FUNCTION_CLASS_DEVICE
,
1742 sizeof(Urb
->UrbControlVendorClassRequest
),
1743 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1745 USB_REQUEST_GET_DESCRIPTOR
,
1746 USB_DEVICE_CLASS_RESERVED
,
1748 &HubDeviceExtension
->HubDescriptor
,
1750 sizeof(USB_HUB_DESCRIPTOR
),
1753 // set device handle
1754 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1757 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1758 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1762 if (!NT_SUCCESS(Status
))
1764 DPRINT1("Failed to get Hub Descriptor!\n");
1766 return STATUS_UNSUCCESSFUL
;
1770 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorLength
== sizeof(USB_HUB_DESCRIPTOR
));
1771 ASSERT(HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
== HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1772 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorType
== 0x29);
1774 // build get status request
1776 UsbBuildGetStatusRequest(Urb
,
1777 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1782 // set device handle
1783 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1786 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1787 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1790 if (!NT_SUCCESS(Status
))
1792 // failed to get hub status
1793 DPRINT1("Failed to get Hub Status!\n");
1795 return STATUS_UNSUCCESSFUL
;
1798 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1799 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1800 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1803 // Get the first Configuration Descriptor
1804 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1805 &HubDeviceExtension
->HubConfigDescriptor
,
1806 -1, -1, -1, -1, -1);
1809 // failed parse hub descriptor
1810 DPRINT1("Failed to parse configuration descriptor\n");
1812 return STATUS_UNSUCCESSFUL
;
1815 // create configuration request
1816 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1817 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1818 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1819 if (ConfigUrb
== NULL
)
1821 // failed to build urb
1822 DPRINT1("Failed to allocate urb\n");
1824 return STATUS_INSUFFICIENT_RESOURCES
;
1828 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1829 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1832 if (!NT_SUCCESS(Status
))
1834 // failed to select configuration
1835 DPRINT1("Failed to select configuration with %x\n", Status
);
1837 ExFreePool(ConfigUrb
);
1841 // store configuration & pipe handle
1842 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1843 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1844 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1846 FDO_QueryInterface(DeviceObject
, &HubDeviceExtension
->DeviceInterface
);
1850 ExFreePool(ConfigUrb
);
1852 // check if function is available
1853 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1855 // is it high speed bus
1856 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1858 // initialize usb 2.0 hub
1859 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1860 HubDeviceExtension
->RootHubHandle
, 1);
1861 DPRINT("Status %x\n", Status
);
1863 // FIXME handle error
1864 ASSERT(Status
== STATUS_SUCCESS
);
1869 // Enable power on all ports
1870 DPRINT("Enabling PortPower on all ports!\n");
1871 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1873 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1874 if (!NT_SUCCESS(Status
))
1875 DPRINT1("Failed to power on port %d\n", PortId
);
1877 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1878 if (!NT_SUCCESS(Status
))
1879 DPRINT1("Failed to power on port %d\n", PortId
);
1882 // init root hub notification
1883 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1885 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1887 RootHubInitCallbackFunction
);
1888 if (!NT_SUCCESS(Status
))
1890 DPRINT1("Failed to set callback\n");
1897 // Send the first SCE Request
1898 QueryStatusChangeEndpoint(DeviceObject
);
1903 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1908 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1909 if (NT_SUCCESS(Status
))
1912 // is there a device connected
1914 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1919 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1920 if (!NT_SUCCESS(Status
))
1922 DPRINT1("Failed to reset on port %d\n", PortId
);
1927 // wait for the reset to be handled since we want to enumerate synchronously
1929 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1934 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1949 USBHUB_FdoHandlePnp(
1950 IN PDEVICE_OBJECT DeviceObject
,
1953 PIO_STACK_LOCATION Stack
;
1954 NTSTATUS Status
= STATUS_SUCCESS
;
1955 ULONG_PTR Information
= 0;
1956 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1958 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1960 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1962 switch (Stack
->MinorFunction
)
1964 case IRP_MN_START_DEVICE
:
1966 if (USBHUB_IsRootHubFDO(DeviceObject
))
1968 // start root hub fdo
1969 Status
= USBHUB_FdoStartDevice(DeviceObject
, Irp
);
1973 Status
= USBHUB_ParentFDOStartDevice(DeviceObject
, Irp
);
1978 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1980 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1984 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1985 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1987 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1989 Information
= (ULONG_PTR
)DeviceRelations
;
1992 case RemovalRelations
:
1994 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1995 return ForwardIrpAndForget(DeviceObject
, Irp
);
1998 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1999 Stack
->Parameters
.QueryDeviceRelations
.Type
);
2000 return ForwardIrpAndForget(DeviceObject
, Irp
);
2004 case IRP_MN_QUERY_REMOVE_DEVICE
:
2005 case IRP_MN_QUERY_STOP_DEVICE
:
2007 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2008 return ForwardIrpAndForget(DeviceObject
, Irp
);
2010 case IRP_MN_REMOVE_DEVICE
:
2012 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2013 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2015 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
2016 IoDeleteDevice(DeviceObject
);
2018 return STATUS_SUCCESS
;
2020 case IRP_MN_QUERY_BUS_INFORMATION
:
2022 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2025 case IRP_MN_QUERY_ID
:
2027 DPRINT("IRP_MN_QUERY_ID\n");
2030 case IRP_MN_QUERY_CAPABILITIES
:
2032 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2037 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
2038 return ForwardIrpAndForget(DeviceObject
, Irp
);
2042 Irp
->IoStatus
.Information
= Information
;
2043 Irp
->IoStatus
.Status
= Status
;
2044 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2049 USBHUB_FdoHandleDeviceControl(
2050 IN PDEVICE_OBJECT DeviceObject
,
2053 PIO_STACK_LOCATION IoStack
;
2054 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2055 PUSB_NODE_INFORMATION NodeInformation
;
2056 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2057 PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo
;
2058 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2059 PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey
;
2060 PUSB_NODE_CONNECTION_NAME ConnectionName
;
2061 ULONG Index
, Length
;
2063 // get stack location
2064 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2066 // get device extension
2067 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2069 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_INFORMATION
)
2071 // is the buffer big enough
2072 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_INFORMATION
))
2075 Status
= STATUS_BUFFER_TOO_SMALL
;
2080 NodeInformation
= (PUSB_NODE_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2083 ASSERT(NodeInformation
);
2086 NodeInformation
->NodeType
= UsbHub
;
2087 RtlCopyMemory(&NodeInformation
->u
.HubInformation
.HubDescriptor
, &HubDeviceExtension
->HubDescriptor
, sizeof(USB_HUB_DESCRIPTOR
));
2089 // FIXME is hub powered
2090 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= TRUE
;
2093 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2094 Status
= STATUS_SUCCESS
;
2099 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
)
2101 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2104 Status
= STATUS_BUFFER_TOO_SMALL
;
2108 // get node connection info
2109 NodeConnectionInfo
= (PUSB_NODE_CONNECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2112 ASSERT(NodeConnectionInfo
);
2114 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2116 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2119 // get child device extension
2120 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2122 if (ChildDeviceExtension
->PortNumber
!= NodeConnectionInfo
->ConnectionIndex
)
2125 // init node connection info
2126 RtlCopyMemory(&NodeConnectionInfo
->DeviceDescriptor
, &ChildDeviceExtension
->DeviceDesc
, sizeof(USB_DEVICE_DESCRIPTOR
));
2127 NodeConnectionInfo
->CurrentConfigurationValue
= ChildDeviceExtension
->FullConfigDesc
->bConfigurationValue
;
2128 NodeConnectionInfo
->DeviceIsHub
= FALSE
; //FIXME support hubs
2129 NodeConnectionInfo
->LowSpeed
= ChildDeviceExtension
->DeviceInformation
.DeviceSpeed
== UsbLowSpeed
;
2130 NodeConnectionInfo
->DeviceAddress
= ChildDeviceExtension
->DeviceInformation
.DeviceAddress
;
2131 NodeConnectionInfo
->NumberOfOpenPipes
= ChildDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
;
2132 NodeConnectionInfo
->ConnectionStatus
= DeviceConnected
; //FIXME
2134 if (NodeConnectionInfo
->NumberOfOpenPipes
)
2136 DPRINT1("Need to copy pipe information\n");
2141 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2142 Status
= STATUS_SUCCESS
;
2145 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
)
2147 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2150 Status
= STATUS_BUFFER_TOO_SMALL
;
2154 // get node connection info
2155 NodeKey
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2160 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2162 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2165 // get child device extension
2166 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2168 if (ChildDeviceExtension
->PortNumber
!= NodeKey
->ConnectionIndex
)
2172 Status
= IoGetDeviceProperty(HubDeviceExtension
->ChildDeviceObject
[Index
], DevicePropertyDriverKeyName
,
2173 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
),
2174 NodeKey
->DriverKeyName
,
2177 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2180 Status
= STATUS_SUCCESS
;
2183 if (Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
2185 // terminate node key name
2186 NodeKey
->DriverKeyName
[0] = UNICODE_NULL
;
2187 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2192 Irp
->IoStatus
.Information
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2195 // length of driver name
2196 NodeKey
->ActualLength
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2201 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_NAME
)
2203 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_NAME
))
2206 Status
= STATUS_BUFFER_TOO_SMALL
;
2210 // FIXME support hubs
2211 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2212 ConnectionName
->ActualLength
= 0;
2213 ConnectionName
->NodeName
[0] = UNICODE_NULL
;
2216 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_NAME
);
2217 Status
= STATUS_SUCCESS
;
2222 DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2223 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2227 Irp
->IoStatus
.Status
= Status
;
2228 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);