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)
17 QueryStatusChangeEndpoint(
18 IN PDEVICE_OBJECT DeviceObject
);
21 CreateUsbChildDeviceObject(
22 IN PDEVICE_OBJECT UsbHubDeviceObject
,
24 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
28 DestroyUsbChildDeviceObject(
29 IN PDEVICE_OBJECT UsbHubDeviceObject
,
34 GetPortStatusAndChange(
35 IN PDEVICE_OBJECT RootHubDeviceObject
,
37 OUT PPORT_STATUS_CHANGE StatusChange
)
45 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
48 DPRINT1("Failed to allocate memory for URB!\n");
49 return STATUS_INSUFFICIENT_RESOURCES
;
55 RtlZeroMemory(Urb
, sizeof(URB
));
58 // Initialize URB for getting Port Status
60 UsbBuildVendorRequest(Urb
,
61 URB_FUNCTION_CLASS_OTHER
,
62 sizeof(Urb
->UrbControlVendorClassRequest
),
63 USBD_TRANSFER_DIRECTION_OUT
,
65 USB_REQUEST_GET_STATUS
,
70 sizeof(PORT_STATUS_CHANGE
),
73 // FIXME: support usb hubs
74 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
80 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
92 IN PDEVICE_OBJECT RootHubDeviceObject
,
102 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
105 DPRINT1("Failed to allocate memory for URB!\n");
106 return STATUS_INSUFFICIENT_RESOURCES
;
112 RtlZeroMemory(Urb
, sizeof(URB
));
115 // Initialize URB for Clearing Port Reset
117 UsbBuildVendorRequest(Urb
,
118 URB_FUNCTION_CLASS_OTHER
,
119 sizeof(Urb
->UrbControlVendorClassRequest
),
120 USBD_TRANSFER_DIRECTION_IN
,
122 USB_REQUEST_SET_FEATURE
,
130 // FIXME support usbhubs
131 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
134 // Query the Root Hub
136 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
148 IN PDEVICE_OBJECT RootHubDeviceObject
,
158 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
161 DPRINT1("Failed to allocate memory for URB!\n");
162 return STATUS_INSUFFICIENT_RESOURCES
;
168 RtlZeroMemory(Urb
, sizeof(URB
));
171 // Initialize URB for Clearing Port Reset
173 UsbBuildVendorRequest(Urb
,
174 URB_FUNCTION_CLASS_OTHER
,
175 sizeof(Urb
->UrbControlVendorClassRequest
),
176 USBD_TRANSFER_DIRECTION_IN
,
178 USB_REQUEST_CLEAR_FEATURE
,
186 // FIXME: support usb hubs
187 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
190 // Query the Root Hub
192 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
203 DeviceStatusChangeThread(
207 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
208 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
209 PWORK_ITEM_DATA WorkItemData
;
210 PORT_STATUS_CHANGE PortStatus
;
212 BOOLEAN SignalResetComplete
= FALSE
;
214 DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context
);
216 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
217 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
218 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
219 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
223 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
228 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
229 if (!NT_SUCCESS(Status
))
231 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
232 // FIXME: Do we really want to halt further SCE requests?
236 DPRINT("Port %d Status %x\n", PortId
, PortStatus
.Status
);
237 DPRINT("Port %d Change %x\n", PortId
, PortStatus
.Change
);
241 // Check for new device connection
243 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
246 // Clear Port Connect
248 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
249 if (!NT_SUCCESS(Status
))
251 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
256 // Is this a connect or disconnect?
258 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
260 DPRINT1("Device disconnected from port %d\n", PortId
);
262 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
263 if (!NT_SUCCESS(Status
))
265 DPRINT1("Failed to delete child device object after disconnect\n");
271 DPRINT1("Device connected from port %d\n", PortId
);
273 // No SCE completion done for clearing C_PORT_CONNECT
278 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("Failed to reset port %d\n", PortId
);
282 SignalResetComplete
= TRUE
;
287 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
292 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
293 if (!NT_SUCCESS(Status
))
295 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
299 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
302 // Request event signalling later
304 SignalResetComplete
= TRUE
;
309 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
310 if (!NT_SUCCESS(Status
))
312 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
319 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
320 if (!NT_SUCCESS(Status
))
322 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
323 // FIXME: Do we really want to halt further SCE requests?
327 DPRINT("Port %d Status %x\n", PortId
, PortStatus
.Status
);
328 DPRINT("Port %d Change %x\n", PortId
, PortStatus
.Change
);
331 // Check that reset was cleared
333 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
335 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
340 // Check if the device is still connected
342 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
344 DPRINT1("Device has been disconnected\n");
349 // Make sure its Connected and Enabled
351 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
353 DPRINT1("Usb Device is not connected and enabled!\n");
355 // Attempt another reset
357 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
358 if (!NT_SUCCESS(Status
))
360 DPRINT1("Failed to reset port %d\n", PortId
);
366 // This is a new device
368 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
, PortStatus
.Status
);
372 ExFreePool(WorkItemData
);
375 // Send another SCE Request
377 DPRINT("Sending another SCE!\n");
378 QueryStatusChangeEndpoint(DeviceObject
);
381 // Check if a reset event was satisfied
383 if (SignalResetComplete
)
386 // Signal anyone waiting on it
388 KeSetEvent(&HubDeviceExtension
->ResetComplete
, IO_NO_INCREMENT
, FALSE
);
394 StatusChangeEndpointCompletion(
395 IN PDEVICE_OBJECT DeviceObject
,
399 PDEVICE_OBJECT RealDeviceObject
;
400 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
401 PWORK_ITEM_DATA WorkItemData
;
403 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
404 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
407 // NOTE: USBPORT frees this IRP
409 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
413 // Create and initialize work item data
415 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
418 DPRINT1("Failed to allocate memory!n");
419 return STATUS_INSUFFICIENT_RESOURCES
;
421 WorkItemData
->Context
= RealDeviceObject
;
423 DPRINT("Queuing work item\n");
426 // Queue the work item to handle initializing the device
428 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
429 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
432 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
434 return STATUS_MORE_PROCESSING_REQUIRED
;
438 QueryStatusChangeEndpoint(
439 IN PDEVICE_OBJECT DeviceObject
)
441 PDEVICE_OBJECT RootHubDeviceObject
;
442 PIO_STACK_LOCATION Stack
;
443 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
446 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
447 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
452 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
455 // Initialize URB for Status Change Endpoint request
457 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
458 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
459 HubDeviceExtension
->PipeHandle
,
460 HubDeviceExtension
->PortStatusChange
,
462 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
463 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
466 // Set the device handle
467 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
472 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
473 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
476 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
479 DPRINT("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
481 if (!HubDeviceExtension
->PendingSCEIrp
)
483 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
484 return STATUS_INSUFFICIENT_RESOURCES
;
488 // Initialize the IRP
490 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
491 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
492 RootHubDeviceObject
->StackSize
);
494 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
495 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
496 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
497 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
500 // Get the Next Stack Location and Initialize it
502 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
503 Stack
->DeviceObject
= DeviceObject
;
504 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
505 Stack
->Parameters
.Others
.Argument2
= NULL
;
506 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
507 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
510 // Set the completion routine for when device is connected to root hub
512 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
513 StatusChangeEndpointCompletion
,
522 DPRINT("DeviceObject is %x\n", DeviceObject
);
523 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
524 IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
526 return STATUS_PENDING
;
531 IN PDEVICE_OBJECT DeviceObject
,
532 IN CONST GUID InterfaceType
,
539 IO_STATUS_BLOCK IoStatus
;
541 PIO_STACK_LOCATION Stack
= NULL
;
544 // Initialize the Event used to wait for Irp completion
546 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
549 // Build Control Request
551 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
560 // Get Next Stack Location and Initialize it.
562 Stack
= IoGetNextIrpStackLocation(Irp
);
563 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
564 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
565 Stack
->Parameters
.QueryInterface
.Size
= Size
;
566 Stack
->Parameters
.QueryInterface
.Version
= Version
;
567 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
568 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
570 Status
= IoCallDriver(DeviceObject
, Irp
);
572 if (Status
== STATUS_PENDING
)
574 DPRINT("Operation pending\n");
575 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
576 Status
= IoStatus
.Status
;
583 GetUsbDeviceDescriptor(
584 IN PDEVICE_OBJECT ChildDeviceObject
,
585 IN UCHAR DescriptorType
,
588 OUT PVOID TransferBuffer
,
589 IN ULONG TransferBufferLength
)
592 PDEVICE_OBJECT RootHubDeviceObject
;
594 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
595 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
598 // Get the Hubs Device Extension
600 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
601 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
602 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
607 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
610 DPRINT1("Failed to allocate memory for URB!\n");
611 return STATUS_INSUFFICIENT_RESOURCES
;
617 RtlZeroMemory(Urb
, sizeof(URB
));
620 // Initialize URB for getting device descriptor
622 UsbBuildGetDescriptorRequest(Urb
,
623 sizeof(Urb
->UrbControlDescriptorRequest
),
629 TransferBufferLength
,
633 // Set the device handle
635 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
638 // Query the Root Hub
640 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
641 IOCTL_INTERNAL_USB_SUBMIT_URB
,
649 GetUsbStringDescriptor(
650 IN PDEVICE_OBJECT ChildDeviceObject
,
653 OUT PVOID
*TransferBuffer
,
657 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
661 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
662 sizeof(USB_STRING_DESCRIPTOR
),
666 DPRINT1("Failed to allocate buffer for string!\n");
667 return STATUS_INSUFFICIENT_RESOURCES
;
671 // Get the index string descriptor length
672 // FIXME: Implement LangIds
674 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
675 USB_STRING_DESCRIPTOR_TYPE
,
679 sizeof(USB_STRING_DESCRIPTOR
));
680 if (!NT_SUCCESS(Status
))
682 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
683 ExFreePool(StringDesc
);
686 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
689 // Did we get something more than the length of the first two fields of structure?
691 if (StringDesc
->bLength
== 2)
693 DPRINT1("USB Device Error!\n");
694 ExFreePool(StringDesc
);
695 return STATUS_DEVICE_DATA_ERROR
;
697 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
702 ExFreePool(StringDesc
);
705 // Recreate with appropriate size
707 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
712 DPRINT1("Failed to allocate buffer for string!\n");
713 return STATUS_INSUFFICIENT_RESOURCES
;
716 RtlZeroMemory(StringDesc
, SizeNeeded
);
721 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
722 USB_STRING_DESCRIPTOR_TYPE
,
727 if (!NT_SUCCESS(Status
))
729 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
730 ExFreePool(StringDesc
);
735 // Allocate Buffer to return
737 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
742 DPRINT1("Failed to allocate buffer for string!\n");
743 ExFreePool(StringDesc
);
744 return STATUS_INSUFFICIENT_RESOURCES
;
747 RtlZeroMemory(Buffer
, SizeNeeded
);
750 // Copy the string to destination
752 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
754 *TransferBuffer
= Buffer
;
756 ExFreePool(StringDesc
);
758 return STATUS_SUCCESS
;
763 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
764 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
766 if (DeviceDescriptor
->bNumConfigurations
!= 1)
769 // composite device must have only one configuration
771 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
775 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
778 // composite device must have multiple interfaces
780 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
784 if (DeviceDescriptor
->bDeviceClass
== 0)
789 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
790 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
791 DPRINT1("IsCompositeDevice: TRUE\n");
795 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
796 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
797 DeviceDescriptor
->bDeviceProtocol
== 0x01)
800 // USB-IF association descriptor
802 DPRINT1("IsCompositeDevice: TRUE\n");
806 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
809 // not a composite device
816 PDEVICE_OBJECT UsbChildDeviceObject
)
818 NTSTATUS Status
= STATUS_SUCCESS
;
822 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
823 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
824 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
825 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
826 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
829 // get child device extension
831 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
833 // get hub device extension
834 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbChildExtension
->ParentDeviceObject
->DeviceExtension
;
837 // get device descriptor
839 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
842 // get configuration descriptor
844 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
847 // use first interface descriptor available
849 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
850 ASSERT(InterfaceDescriptor
);
853 // Construct the CompatibleIds
855 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
860 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
861 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
862 Index
+= swprintf(&Buffer
[Index
],
863 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
864 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
865 Index
+= swprintf(&Buffer
[Index
],
866 L
"USB\\DevClass_%02x&SubClass_%02x",
867 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
868 Index
+= swprintf(&Buffer
[Index
],
869 L
"USB\\DevClass_%02x",
870 DeviceDescriptor
->bDeviceClass
) + 1;
871 Index
+= swprintf(&Buffer
[Index
],
872 L
"USB\\COMPOSITE") + 1;
877 // FIXME: support multiple configurations
879 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
881 if (DeviceDescriptor
->bDeviceClass
== 0)
883 Index
+= swprintf(&Buffer
[Index
],
884 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
885 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
886 Index
+= swprintf(&Buffer
[Index
],
887 L
"USB\\Class_%02x&SubClass_%02x",
888 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
889 Index
+= swprintf(&Buffer
[Index
],
891 InterfaceDescriptor
->bInterfaceClass
) + 1;
895 Index
+= swprintf(&Buffer
[Index
],
896 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
897 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
898 Index
+= swprintf(&Buffer
[Index
],
899 L
"USB\\Class_%02x&SubClass_%02x",
900 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
901 Index
+= swprintf(&Buffer
[Index
],
903 DeviceDescriptor
->bDeviceClass
) + 1;
908 // now allocate the buffer
910 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
916 return STATUS_INSUFFICIENT_RESOURCES
;
922 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
923 DeviceString
[Index
] = UNICODE_NULL
;
924 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
925 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
926 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
927 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
930 // Construct DeviceId string
932 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
935 // now allocate the buffer
937 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
943 return STATUS_INSUFFICIENT_RESOURCES
;
949 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
950 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
951 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
952 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
953 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
956 // Construct HardwareIds
959 Index
+= swprintf(&Buffer
[Index
],
960 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
961 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
962 Index
+= swprintf(&Buffer
[Index
],
963 L
"USB\\Vid_%04x&Pid_%04x",
964 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
967 // now allocate the buffer
969 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
975 return STATUS_INSUFFICIENT_RESOURCES
;
981 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
982 DeviceString
[Index
] = UNICODE_NULL
;
983 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
984 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
985 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
986 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
989 // FIXME: Handle Lang ids
993 // Get the product string if obe provided
995 if (UsbChildExtension
->DeviceDesc
.iProduct
)
997 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
998 UsbChildExtension
->DeviceDesc
.iProduct
,
1000 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1001 &UsbChildExtension
->usTextDescription
.Length
);
1002 if (!NT_SUCCESS(Status
))
1004 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1005 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"USB Device"); // FIXME NON-NLS
1009 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1010 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1015 // Get the Serial Number string if obe provided
1017 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1019 LPWSTR SerialBuffer
= NULL
;
1021 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1022 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1024 (PVOID
*)&SerialBuffer
,
1025 &UsbChildExtension
->usInstanceId
.Length
);
1026 if (NT_SUCCESS(Status
))
1028 // construct instance id buffer
1029 Index
= swprintf(Buffer
, L
"%04d&%s", HubDeviceExtension
->InstanceCount
, SerialBuffer
) + 1;
1030 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1031 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1033 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1034 return STATUS_INSUFFICIENT_RESOURCES
;
1040 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1041 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1042 ExFreePool(SerialBuffer
);
1044 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension
->usInstanceId
, HubDeviceExtension
->InstanceCount
);
1050 // the device did not provide a serial number, or failed to retrieve the serial number
1051 // lets create a pseudo instance id
1053 Index
= swprintf(Buffer
, L
"%04d&%04d", HubDeviceExtension
->InstanceCount
, UsbChildExtension
->PortNumber
) + 1;
1054 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1055 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1057 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1058 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1065 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1066 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1068 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1069 return STATUS_SUCCESS
;
1073 DestroyUsbChildDeviceObject(
1074 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1077 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1078 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1079 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1082 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1084 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1086 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1088 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1090 /* Check if it matches the port ID */
1091 if (UsbChildExtension
->PortNumber
== PortId
)
1094 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1100 /* Fail the request if the device doesn't exist */
1101 if (!ChildDeviceObject
)
1103 DPRINT1("Removal request for non-existant device!\n");
1104 return STATUS_UNSUCCESSFUL
;
1107 /* Remove the device from the table */
1108 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1110 /* Invalidate device relations for the root hub */
1111 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1113 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1114 return STATUS_SUCCESS
;
1118 CreateUsbChildDeviceObject(
1119 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1121 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1122 IN ULONG PortStatus
)
1125 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1126 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1127 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1128 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1129 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1130 WCHAR CharDeviceName
[64];
1131 UNICODE_STRING DeviceName
;
1132 ULONG ConfigDescSize
, DeviceDescSize
, DeviceInfoSize
;
1133 PVOID HubInterfaceBusContext
;
1134 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1136 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1137 HubInterface
= &HubDeviceExtension
->HubInterface
;
1138 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1139 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1141 // Find an empty slot in the child device array
1143 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1145 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1147 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1153 // Check if the limit has been reached for maximum usb devices
1155 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1157 DPRINT1("USBHUB: Too many child devices!\n");
1158 return STATUS_UNSUCCESSFUL
;
1164 // Create a Device Name
1166 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1169 // Initialize UnicodeString
1171 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1174 // Create a DeviceObject
1176 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1177 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1179 FILE_DEVICE_CONTROLLER
,
1180 FILE_AUTOGENERATED_DEVICE_NAME
,
1182 &NewChildDeviceObject
);
1185 // Check if the name is already in use
1187 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1197 // Check for other errors
1199 if (!NT_SUCCESS(Status
))
1201 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1205 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1209 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1212 // Assign the device extensions
1214 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1215 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1216 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1217 UsbChildExtension
->PortNumber
= PortId
;
1219 // copy device interface
1220 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1224 // Create the UsbDeviceObject
1226 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1227 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1228 HubDeviceExtension
->RootHubHandle
,
1231 if (!NT_SUCCESS(Status
))
1233 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1237 // copy device interface
1238 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1240 // FIXME replace buscontext
1241 UsbChildExtension
->DeviceInterface
.BusContext
= UsbChildExtension
->UsbDeviceHandle
;
1244 // Initialize UsbDevice
1246 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1247 if (!NT_SUCCESS(Status
))
1249 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1253 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1255 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1256 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1259 // Get the descriptors
1261 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1262 UsbChildExtension
->UsbDeviceHandle
,
1263 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1265 (PUCHAR
)&ConfigDesc
,
1267 if (!NT_SUCCESS(Status
))
1269 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1273 //DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1274 //DumpConfigurationDescriptor(&ConfigDesc);
1277 // FIXME: Support more than one configuration and one interface?
1279 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1281 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1284 if (ConfigDesc
.bNumInterfaces
> 1)
1286 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1289 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1292 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1294 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1297 // Retrieve the full configuration descriptor
1299 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1300 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1303 UsbChildExtension
->FullConfigDesc
,
1306 if (!NT_SUCCESS(Status
))
1308 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1312 // query device details
1313 Status
= HubInterface
->QueryDeviceInformation(HubInterfaceBusContext
,
1314 UsbChildExtension
->UsbDeviceHandle
,
1315 &UsbChildExtension
->DeviceInformation
,
1316 sizeof(USB_DEVICE_INFORMATION_0
),
1320 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1323 // Construct all the strings that will described the device to PNP
1325 Status
= CreateDeviceIds(NewChildDeviceObject
);
1326 if (!NT_SUCCESS(Status
))
1328 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1332 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1333 HubDeviceExtension
->InstanceCount
++;
1335 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1336 return STATUS_SUCCESS
;
1341 // Remove the usb device if it was created
1343 if (UsbChildExtension
->UsbDeviceHandle
)
1344 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1347 // Free full configuration descriptor if one was allocated
1349 if (UsbChildExtension
->FullConfigDesc
)
1350 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1353 // Delete the device object
1355 IoDeleteDevice(NewChildDeviceObject
);
1360 USBHUB_FdoQueryBusRelations(
1361 IN PDEVICE_OBJECT DeviceObject
,
1362 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1364 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1365 PDEVICE_RELATIONS DeviceRelations
;
1370 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1373 // Count the number of children
1375 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1378 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1385 NeededSize
= sizeof(DEVICE_RELATIONS
);
1387 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1390 // Allocate DeviceRelations
1392 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1395 if (!DeviceRelations
)
1396 return STATUS_INSUFFICIENT_RESOURCES
;
1397 DeviceRelations
->Count
= Children
;
1401 // Fill in return structure
1403 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1405 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1407 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1408 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1409 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1413 ASSERT(Children
== DeviceRelations
->Count
);
1414 *pDeviceRelations
= DeviceRelations
;
1416 return STATUS_SUCCESS
;
1421 RootHubInitCallbackFunction(
1424 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1427 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1428 PORT_STATUS_CHANGE StatusChange
;
1430 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1432 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1435 // Send the first SCE Request
1437 QueryStatusChangeEndpoint(DeviceObject
);
1439 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1444 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1445 if (NT_SUCCESS(Status
))
1448 // is there a device connected
1450 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1455 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1456 if (!NT_SUCCESS(Status
))
1458 DPRINT1("Failed to reset on port %d\n", PortId
);
1463 // wait for the reset to be handled since we want to enumerate synchronously
1465 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1470 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1478 USBHUB_IsRootHubFDO(
1479 IN PDEVICE_OBJECT DeviceObject
)
1482 PDEVICE_OBJECT RootHubPhysicalDeviceObject
= NULL
;
1483 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1485 // get hub device extension
1486 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1488 // Get the Root Hub Pdo
1489 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1490 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1491 &RootHubPhysicalDeviceObject
,
1494 // FIXME handle error
1495 ASSERT(NT_SUCCESS(Status
));
1497 // physical device object is only obtained for root hubs
1498 return (RootHubPhysicalDeviceObject
!= NULL
);
1503 USBHUB_FdoStartDevice(
1504 IN PDEVICE_OBJECT DeviceObject
,
1508 PUSB_INTERFACE_DESCRIPTOR Pid
;
1509 ULONG Result
= 0, PortId
;
1510 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1511 PURB ConfigUrb
= NULL
;
1513 NTSTATUS Status
= STATUS_SUCCESS
;
1514 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1515 PDEVICE_OBJECT RootHubDeviceObject
;
1516 PVOID HubInterfaceBusContext
;
1517 PORT_STATUS_CHANGE StatusChange
;
1519 // get hub device extension
1520 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1522 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1524 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1525 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1529 return STATUS_INSUFFICIENT_RESOURCES
;
1533 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1535 // Get the Root Hub Pdo
1536 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1537 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1538 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1539 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1540 if (!NT_SUCCESS(Status
))
1542 // failed to obtain hub pdo
1543 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status
);
1549 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1550 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1553 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1555 // Send the StartDevice to RootHub
1556 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1558 if (!NT_SUCCESS(Status
))
1560 // failed to start pdo
1561 DPRINT1("Failed to start the RootHub PDO\n");
1566 // Get the current number of hubs
1567 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1568 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1569 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1570 if (!NT_SUCCESS(Status
))
1572 // failed to get number of hubs
1573 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status
);
1578 // Get the Hub Interface
1579 Status
= QueryInterface(RootHubDeviceObject
,
1580 USB_BUS_INTERFACE_HUB_GUID
,
1581 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1582 USB_BUSIF_HUB_VERSION_5
,
1583 (PVOID
)&HubDeviceExtension
->HubInterface
);
1585 if (!NT_SUCCESS(Status
))
1587 // failed to get root hub interface
1588 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1593 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1595 // Get the USBDI Interface
1596 Status
= QueryInterface(RootHubDeviceObject
,
1597 USB_BUS_INTERFACE_USBDI_GUID
,
1598 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1599 USB_BUSIF_USBDI_VERSION_2
,
1600 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1602 if (!NT_SUCCESS(Status
))
1604 // failed to get usbdi interface
1605 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1610 // Get Root Hub Device Handle
1611 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1612 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1613 &HubDeviceExtension
->RootHubHandle
,
1616 if (!NT_SUCCESS(Status
))
1619 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status
);
1625 // Get Hub Device Information
1627 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1628 HubDeviceExtension
->RootHubHandle
,
1629 &HubDeviceExtension
->DeviceInformation
,
1630 sizeof(USB_DEVICE_INFORMATION_0
),
1633 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1634 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1635 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1636 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1637 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1638 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1639 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1641 // Get Root Hubs Device Descriptor
1642 UsbBuildGetDescriptorRequest(Urb
,
1643 sizeof(Urb
->UrbControlDescriptorRequest
),
1644 USB_DEVICE_DESCRIPTOR_TYPE
,
1647 &HubDeviceExtension
->HubDeviceDescriptor
,
1649 sizeof(USB_DEVICE_DESCRIPTOR
),
1652 // set device handle
1653 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1655 // get hub device descriptor
1656 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1657 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1661 if (!NT_SUCCESS(Status
))
1663 // failed to get device descriptor of hub
1664 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1669 // build configuration request
1670 UsbBuildGetDescriptorRequest(Urb
,
1671 sizeof(Urb
->UrbControlDescriptorRequest
),
1672 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1675 &HubDeviceExtension
->HubConfigDescriptor
,
1677 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1680 // set device handle
1681 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1683 // request configuration descriptor
1684 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1685 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1689 if (!NT_SUCCESS(Status
))
1691 // failed to get configuration descriptor
1692 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1698 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
));
1699 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bDescriptorType
== USB_CONFIGURATION_DESCRIPTOR_TYPE
);
1700 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1701 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bNumInterfaces
== 1);
1702 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
1703 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
1704 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bNumEndpoints
== 1);
1705 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1706 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bLength
== sizeof(USB_ENDPOINT_DESCRIPTOR
));
1707 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bmAttributes
== USB_ENDPOINT_TYPE_INTERRUPT
);
1708 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bEndpointAddress
== 0x81); // interrupt in
1710 // get hub information
1711 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1712 RootHubDeviceObject
,
1713 &HubDeviceExtension
->UsbExtHubInfo
,
1714 sizeof(USB_EXTHUB_INFORMATION_0
),
1716 if (!NT_SUCCESS(Status
))
1718 // failed to get hub information
1719 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1724 if (!HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
)
1726 // bogus port driver
1727 DPRINT1("Failed to retrieve the number of ports\n");
1729 return STATUS_UNSUCCESSFUL
;
1732 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1734 // Build hub descriptor request
1735 UsbBuildVendorRequest(Urb
,
1736 URB_FUNCTION_CLASS_DEVICE
,
1737 sizeof(Urb
->UrbControlVendorClassRequest
),
1738 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1740 USB_REQUEST_GET_DESCRIPTOR
,
1741 USB_DEVICE_CLASS_RESERVED
,
1743 &HubDeviceExtension
->HubDescriptor
,
1745 sizeof(USB_HUB_DESCRIPTOR
),
1748 // set device handle
1749 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1752 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1753 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1757 if (!NT_SUCCESS(Status
))
1759 DPRINT1("Failed to get Hub Descriptor!\n");
1761 return STATUS_UNSUCCESSFUL
;
1765 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorLength
== sizeof(USB_HUB_DESCRIPTOR
));
1766 ASSERT(HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
== HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1767 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorType
== 0x29);
1769 // build get status request
1771 UsbBuildGetStatusRequest(Urb
,
1772 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1777 // set device handle
1778 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1781 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1782 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1785 if (!NT_SUCCESS(Status
))
1787 // failed to get hub status
1788 DPRINT1("Failed to get Hub Status!\n");
1790 return STATUS_UNSUCCESSFUL
;
1793 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1794 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1795 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1798 // Get the first Configuration Descriptor
1799 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1800 &HubDeviceExtension
->HubConfigDescriptor
,
1801 -1, -1, -1, -1, -1);
1804 // failed parse hub descriptor
1805 DPRINT1("Failed to parse configuration descriptor\n");
1807 return STATUS_UNSUCCESSFUL
;
1810 // create configuration request
1811 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1812 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1813 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1814 if (ConfigUrb
== NULL
)
1816 // failed to build urb
1817 DPRINT1("Failed to allocate urb\n");
1819 return STATUS_INSUFFICIENT_RESOURCES
;
1823 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1824 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1827 if (!NT_SUCCESS(Status
))
1829 // failed to select configuration
1830 DPRINT1("Failed to select configuration with %x\n", Status
);
1832 ExFreePool(ConfigUrb
);
1836 // store configuration & pipe handle
1837 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1838 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1839 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1841 FDO_QueryInterface(DeviceObject
, &HubDeviceExtension
->DeviceInterface
);
1845 ExFreePool(ConfigUrb
);
1847 // check if function is available
1848 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1850 // is it high speed bus
1851 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1853 // initialize usb 2.0 hub
1854 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1855 HubDeviceExtension
->RootHubHandle
, 1);
1856 DPRINT("Status %x\n", Status
);
1858 // FIXME handle error
1859 ASSERT(Status
== STATUS_SUCCESS
);
1864 // Enable power on all ports
1865 DPRINT("Enabling PortPower on all ports!\n");
1866 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1868 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1869 if (!NT_SUCCESS(Status
))
1870 DPRINT1("Failed to power on port %d\n", PortId
);
1872 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1873 if (!NT_SUCCESS(Status
))
1874 DPRINT1("Failed to power on port %d\n", PortId
);
1877 // init root hub notification
1878 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1880 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1882 RootHubInitCallbackFunction
);
1883 if (!NT_SUCCESS(Status
))
1885 DPRINT1("Failed to set callback\n");
1892 // Send the first SCE Request
1893 QueryStatusChangeEndpoint(DeviceObject
);
1898 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1903 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1904 if (NT_SUCCESS(Status
))
1907 // is there a device connected
1909 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1914 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1915 if (!NT_SUCCESS(Status
))
1917 DPRINT1("Failed to reset on port %d\n", PortId
);
1922 // wait for the reset to be handled since we want to enumerate synchronously
1924 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1929 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1944 USBHUB_FdoHandlePnp(
1945 IN PDEVICE_OBJECT DeviceObject
,
1948 PIO_STACK_LOCATION Stack
;
1949 NTSTATUS Status
= STATUS_SUCCESS
;
1950 ULONG_PTR Information
= 0;
1951 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1953 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1955 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1957 switch (Stack
->MinorFunction
)
1959 case IRP_MN_START_DEVICE
:
1961 if (USBHUB_IsRootHubFDO(DeviceObject
))
1963 // start root hub fdo
1964 Status
= USBHUB_FdoStartDevice(DeviceObject
, Irp
);
1968 Status
= USBHUB_ParentFDOStartDevice(DeviceObject
, Irp
);
1973 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1975 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1979 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1980 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1982 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1984 Information
= (ULONG_PTR
)DeviceRelations
;
1987 case RemovalRelations
:
1989 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1990 return ForwardIrpAndForget(DeviceObject
, Irp
);
1993 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1994 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1995 return ForwardIrpAndForget(DeviceObject
, Irp
);
1999 case IRP_MN_QUERY_REMOVE_DEVICE
:
2000 case IRP_MN_QUERY_STOP_DEVICE
:
2002 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2003 return ForwardIrpAndForget(DeviceObject
, Irp
);
2005 case IRP_MN_REMOVE_DEVICE
:
2007 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2008 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2010 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
2011 IoDeleteDevice(DeviceObject
);
2013 return STATUS_SUCCESS
;
2015 case IRP_MN_QUERY_BUS_INFORMATION
:
2017 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2020 case IRP_MN_QUERY_ID
:
2022 DPRINT("IRP_MN_QUERY_ID\n");
2025 case IRP_MN_QUERY_CAPABILITIES
:
2027 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2032 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
2033 return ForwardIrpAndForget(DeviceObject
, Irp
);
2037 Irp
->IoStatus
.Information
= Information
;
2038 Irp
->IoStatus
.Status
= Status
;
2039 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2044 USBHUB_FdoHandleDeviceControl(
2045 IN PDEVICE_OBJECT DeviceObject
,
2048 PIO_STACK_LOCATION IoStack
;
2049 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2050 PUSB_NODE_INFORMATION NodeInformation
;
2051 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2052 PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo
;
2053 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2054 PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey
;
2055 PUSB_NODE_CONNECTION_NAME ConnectionName
;
2056 ULONG Index
, Length
;
2058 // get stack location
2059 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2061 // get device extension
2062 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2064 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_INFORMATION
)
2066 // is the buffer big enough
2067 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_INFORMATION
))
2070 Status
= STATUS_BUFFER_TOO_SMALL
;
2075 NodeInformation
= (PUSB_NODE_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2078 ASSERT(NodeInformation
);
2081 NodeInformation
->NodeType
= UsbHub
;
2082 RtlCopyMemory(&NodeInformation
->u
.HubInformation
.HubDescriptor
, &HubDeviceExtension
->HubDescriptor
, sizeof(USB_HUB_DESCRIPTOR
));
2084 // FIXME is hub powered
2085 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= TRUE
;
2088 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2089 Status
= STATUS_SUCCESS
;
2094 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
)
2096 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2099 Status
= STATUS_BUFFER_TOO_SMALL
;
2103 // get node connection info
2104 NodeConnectionInfo
= (PUSB_NODE_CONNECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2107 ASSERT(NodeConnectionInfo
);
2109 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2111 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2114 // get child device extension
2115 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2117 if (ChildDeviceExtension
->PortNumber
!= NodeConnectionInfo
->ConnectionIndex
)
2120 // init node connection info
2121 RtlCopyMemory(&NodeConnectionInfo
->DeviceDescriptor
, &ChildDeviceExtension
->DeviceDesc
, sizeof(USB_DEVICE_DESCRIPTOR
));
2122 NodeConnectionInfo
->CurrentConfigurationValue
= ChildDeviceExtension
->FullConfigDesc
->bConfigurationValue
;
2123 NodeConnectionInfo
->DeviceIsHub
= FALSE
; //FIXME support hubs
2124 NodeConnectionInfo
->LowSpeed
= ChildDeviceExtension
->DeviceInformation
.DeviceSpeed
== UsbLowSpeed
;
2125 NodeConnectionInfo
->DeviceAddress
= ChildDeviceExtension
->DeviceInformation
.DeviceAddress
;
2126 NodeConnectionInfo
->NumberOfOpenPipes
= ChildDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
;
2127 NodeConnectionInfo
->ConnectionStatus
= DeviceConnected
; //FIXME
2129 if (NodeConnectionInfo
->NumberOfOpenPipes
)
2131 DPRINT1("Need to copy pipe information\n");
2136 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2137 Status
= STATUS_SUCCESS
;
2140 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
)
2142 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2145 Status
= STATUS_BUFFER_TOO_SMALL
;
2149 // get node connection info
2150 NodeKey
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2155 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2157 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2160 // get child device extension
2161 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2163 if (ChildDeviceExtension
->PortNumber
!= NodeKey
->ConnectionIndex
)
2167 Status
= IoGetDeviceProperty(HubDeviceExtension
->ChildDeviceObject
[Index
], DevicePropertyDriverKeyName
,
2168 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
),
2169 NodeKey
->DriverKeyName
,
2172 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2175 Status
= STATUS_SUCCESS
;
2178 if (Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
2180 // terminate node key name
2181 NodeKey
->DriverKeyName
[0] = UNICODE_NULL
;
2182 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2187 Irp
->IoStatus
.Information
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2190 // length of driver name
2191 NodeKey
->ActualLength
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2196 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_NAME
)
2198 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_NAME
))
2201 Status
= STATUS_BUFFER_TOO_SMALL
;
2205 // FIXME support hubs
2206 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2207 ConnectionName
->ActualLength
= 0;
2208 ConnectionName
->NodeName
[0] = UNICODE_NULL
;
2211 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_NAME
);
2212 Status
= STATUS_SUCCESS
;
2217 DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2218 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2222 Irp
->IoStatus
.Status
= Status
;
2223 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);