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)
19 QueryStatusChangeEndpoint(
20 IN PDEVICE_OBJECT DeviceObject
);
23 CreateUsbChildDeviceObject(
24 IN PDEVICE_OBJECT UsbHubDeviceObject
,
26 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
30 DestroyUsbChildDeviceObject(
31 IN PDEVICE_OBJECT UsbHubDeviceObject
,
36 GetPortStatusAndChange(
37 IN PDEVICE_OBJECT RootHubDeviceObject
,
39 OUT PPORT_STATUS_CHANGE StatusChange
)
47 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
50 DPRINT1("Failed to allocate memory for URB!\n");
51 return STATUS_INSUFFICIENT_RESOURCES
;
57 RtlZeroMemory(Urb
, sizeof(URB
));
60 // Initialize URB for getting Port Status
62 UsbBuildVendorRequest(Urb
,
63 URB_FUNCTION_CLASS_OTHER
,
64 sizeof(Urb
->UrbControlVendorClassRequest
),
65 USBD_TRANSFER_DIRECTION_OUT
,
67 USB_REQUEST_GET_STATUS
,
72 sizeof(PORT_STATUS_CHANGE
),
75 // FIXME: support usb hubs
76 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
82 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
94 IN PDEVICE_OBJECT RootHubDeviceObject
,
104 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
107 DPRINT1("Failed to allocate memory for URB!\n");
108 return STATUS_INSUFFICIENT_RESOURCES
;
114 RtlZeroMemory(Urb
, sizeof(URB
));
117 // Initialize URB for Clearing Port Reset
119 UsbBuildVendorRequest(Urb
,
120 URB_FUNCTION_CLASS_OTHER
,
121 sizeof(Urb
->UrbControlVendorClassRequest
),
122 USBD_TRANSFER_DIRECTION_IN
,
124 USB_REQUEST_SET_FEATURE
,
132 // FIXME support usbhubs
133 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
136 // Query the Root Hub
138 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
150 IN PDEVICE_OBJECT RootHubDeviceObject
,
160 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
163 DPRINT1("Failed to allocate memory for URB!\n");
164 return STATUS_INSUFFICIENT_RESOURCES
;
170 RtlZeroMemory(Urb
, sizeof(URB
));
173 // Initialize URB for Clearing Port Reset
175 UsbBuildVendorRequest(Urb
,
176 URB_FUNCTION_CLASS_OTHER
,
177 sizeof(Urb
->UrbControlVendorClassRequest
),
178 USBD_TRANSFER_DIRECTION_IN
,
180 USB_REQUEST_CLEAR_FEATURE
,
188 // FIXME: support usb hubs
189 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
192 // Query the Root Hub
194 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
205 DeviceStatusChangeThread(
209 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
210 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
211 PWORK_ITEM_DATA WorkItemData
;
212 PORT_STATUS_CHANGE PortStatus
;
214 BOOLEAN SignalResetComplete
= FALSE
;
216 DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context
);
218 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
219 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
220 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
221 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
225 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
230 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
231 if (!NT_SUCCESS(Status
))
233 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
234 // FIXME: Do we really want to halt further SCE requests?
238 DPRINT("Port %d Status %x\n", PortId
, PortStatus
.Status
);
239 DPRINT("Port %d Change %x\n", PortId
, PortStatus
.Change
);
243 // Check for new device connection
245 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
248 // Clear Port Connect
250 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
251 if (!NT_SUCCESS(Status
))
253 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
258 // Is this a connect or disconnect?
260 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
262 DPRINT1("Device disconnected from port %d\n", PortId
);
264 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
265 if (!NT_SUCCESS(Status
))
267 DPRINT1("Failed to delete child device object after disconnect\n");
273 DPRINT1("Device connected from port %d\n", PortId
);
275 // No SCE completion done for clearing C_PORT_CONNECT
280 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("Failed to reset port %d\n", PortId
);
284 SignalResetComplete
= TRUE
;
289 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
294 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
295 if (!NT_SUCCESS(Status
))
297 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
301 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
304 // Request event signalling later
306 SignalResetComplete
= TRUE
;
311 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
312 if (!NT_SUCCESS(Status
))
314 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
321 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
325 // FIXME: Do we really want to halt further SCE requests?
329 DPRINT("Port %d Status %x\n", PortId
, PortStatus
.Status
);
330 DPRINT("Port %d Change %x\n", PortId
, PortStatus
.Change
);
333 // Check that reset was cleared
335 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
337 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
342 // Check if the device is still connected
344 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
346 DPRINT1("Device has been disconnected\n");
351 // Make sure its Connected and Enabled
353 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
355 DPRINT1("Usb Device is not connected and enabled!\n");
357 // Attempt another reset
359 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
360 if (!NT_SUCCESS(Status
))
362 DPRINT1("Failed to reset port %d\n", PortId
);
368 // This is a new device
370 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
, PortStatus
.Status
);
374 ExFreePool(WorkItemData
);
377 // Send another SCE Request
379 DPRINT("Sending another SCE!\n");
380 QueryStatusChangeEndpoint(DeviceObject
);
383 // Check if a reset event was satisfied
385 if (SignalResetComplete
)
388 // Signal anyone waiting on it
390 KeSetEvent(&HubDeviceExtension
->ResetComplete
, IO_NO_INCREMENT
, FALSE
);
396 StatusChangeEndpointCompletion(
397 IN PDEVICE_OBJECT DeviceObject
,
401 PDEVICE_OBJECT RealDeviceObject
;
402 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
403 PWORK_ITEM_DATA WorkItemData
;
405 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
406 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
409 // NOTE: USBPORT frees this IRP
411 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
415 // Create and initialize work item data
417 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
420 DPRINT1("Failed to allocate memory!n");
421 return STATUS_INSUFFICIENT_RESOURCES
;
423 WorkItemData
->Context
= RealDeviceObject
;
425 DPRINT("Queuing work item\n");
428 // Queue the work item to handle initializing the device
430 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
431 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
434 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
436 return STATUS_MORE_PROCESSING_REQUIRED
;
440 QueryStatusChangeEndpoint(
441 IN PDEVICE_OBJECT DeviceObject
)
443 PDEVICE_OBJECT RootHubDeviceObject
;
444 PIO_STACK_LOCATION Stack
;
445 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
448 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
449 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
454 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
457 // Initialize URB for Status Change Endpoint request
459 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
460 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
461 HubDeviceExtension
->PipeHandle
,
462 HubDeviceExtension
->PortStatusChange
,
464 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
465 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
468 // Set the device handle
469 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
474 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
475 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
478 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
481 DPRINT("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
483 if (!HubDeviceExtension
->PendingSCEIrp
)
485 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
486 return STATUS_INSUFFICIENT_RESOURCES
;
490 // Initialize the IRP
492 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
493 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
494 RootHubDeviceObject
->StackSize
);
496 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
497 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
498 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
499 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
502 // Get the Next Stack Location and Initialize it
504 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
505 Stack
->DeviceObject
= DeviceObject
;
506 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
507 Stack
->Parameters
.Others
.Argument2
= NULL
;
508 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
509 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
512 // Set the completion routine for when device is connected to root hub
514 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
515 StatusChangeEndpointCompletion
,
524 DPRINT("DeviceObject is %x\n", DeviceObject
);
525 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
526 IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
528 return STATUS_PENDING
;
533 IN PDEVICE_OBJECT DeviceObject
,
534 IN CONST GUID InterfaceType
,
541 IO_STATUS_BLOCK IoStatus
;
543 PIO_STACK_LOCATION Stack
= NULL
;
546 // Initialize the Event used to wait for Irp completion
548 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
551 // Build Control Request
553 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
562 // Get Next Stack Location and Initialize it.
564 Stack
= IoGetNextIrpStackLocation(Irp
);
565 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
566 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
567 Stack
->Parameters
.QueryInterface
.Size
= Size
;
568 Stack
->Parameters
.QueryInterface
.Version
= Version
;
569 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
570 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
572 Status
= IoCallDriver(DeviceObject
, Irp
);
574 if (Status
== STATUS_PENDING
)
576 DPRINT("Operation pending\n");
577 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
578 Status
= IoStatus
.Status
;
585 GetUsbDeviceDescriptor(
586 IN PDEVICE_OBJECT ChildDeviceObject
,
587 IN UCHAR DescriptorType
,
590 OUT PVOID TransferBuffer
,
591 IN ULONG TransferBufferLength
)
594 PDEVICE_OBJECT RootHubDeviceObject
;
596 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
597 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
600 // Get the Hubs Device Extension
602 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
603 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
604 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
609 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
612 DPRINT1("Failed to allocate memory for URB!\n");
613 return STATUS_INSUFFICIENT_RESOURCES
;
619 RtlZeroMemory(Urb
, sizeof(URB
));
622 // Initialize URB for getting device descriptor
624 UsbBuildGetDescriptorRequest(Urb
,
625 sizeof(Urb
->UrbControlDescriptorRequest
),
631 TransferBufferLength
,
635 // Set the device handle
637 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
640 // Query the Root Hub
642 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
643 IOCTL_INTERNAL_USB_SUBMIT_URB
,
651 GetUsbStringDescriptor(
652 IN PDEVICE_OBJECT ChildDeviceObject
,
655 OUT PVOID
*TransferBuffer
,
659 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
663 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
664 sizeof(USB_STRING_DESCRIPTOR
),
668 DPRINT1("Failed to allocate buffer for string!\n");
669 return STATUS_INSUFFICIENT_RESOURCES
;
673 // Get the index string descriptor length
674 // FIXME: Implement LangIds
676 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
677 USB_STRING_DESCRIPTOR_TYPE
,
681 sizeof(USB_STRING_DESCRIPTOR
));
682 if (!NT_SUCCESS(Status
))
684 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
685 ExFreePool(StringDesc
);
688 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
691 // Did we get something more than the length of the first two fields of structure?
693 if (StringDesc
->bLength
== 2)
695 DPRINT1("USB Device Error!\n");
696 ExFreePool(StringDesc
);
697 return STATUS_DEVICE_DATA_ERROR
;
699 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
704 ExFreePool(StringDesc
);
707 // Recreate with appropriate size
709 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
714 DPRINT1("Failed to allocate buffer for string!\n");
715 return STATUS_INSUFFICIENT_RESOURCES
;
718 RtlZeroMemory(StringDesc
, SizeNeeded
);
723 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
724 USB_STRING_DESCRIPTOR_TYPE
,
729 if (!NT_SUCCESS(Status
))
731 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
732 ExFreePool(StringDesc
);
737 // Allocate Buffer to return
739 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
744 DPRINT1("Failed to allocate buffer for string!\n");
745 ExFreePool(StringDesc
);
746 return STATUS_INSUFFICIENT_RESOURCES
;
749 RtlZeroMemory(Buffer
, SizeNeeded
);
752 // Copy the string to destination
754 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
756 *TransferBuffer
= Buffer
;
758 ExFreePool(StringDesc
);
760 return STATUS_SUCCESS
;
765 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
766 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
768 if (DeviceDescriptor
->bNumConfigurations
!= 1)
771 // composite device must have only one configuration
773 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
777 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
780 // composite device must have multiple interfaces
782 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
786 if (DeviceDescriptor
->bDeviceClass
== 0)
791 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
792 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
793 DPRINT1("IsCompositeDevice: TRUE\n");
797 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
798 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
799 DeviceDescriptor
->bDeviceProtocol
== 0x01)
802 // USB-IF association descriptor
804 DPRINT1("IsCompositeDevice: TRUE\n");
808 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
811 // not a composite device
818 PDEVICE_OBJECT UsbChildDeviceObject
)
820 NTSTATUS Status
= STATUS_SUCCESS
;
824 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
825 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
826 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
827 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
828 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
831 // get child device extension
833 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
835 // get hub device extension
836 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbChildExtension
->ParentDeviceObject
->DeviceExtension
;
839 // get device descriptor
841 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
844 // get configuration descriptor
846 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
849 // use first interface descriptor available
851 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
852 if (InterfaceDescriptor
== NULL
)
854 DPRINT1("Error USBD_ParseConfigurationDescriptorEx failed to parse interface descriptor\n");
855 return STATUS_INVALID_PARAMETER
;
858 ASSERT(InterfaceDescriptor
);
861 // Construct the CompatibleIds
863 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
868 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
869 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
870 Index
+= swprintf(&Buffer
[Index
],
871 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
872 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
873 Index
+= swprintf(&Buffer
[Index
],
874 L
"USB\\DevClass_%02x&SubClass_%02x",
875 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
876 Index
+= swprintf(&Buffer
[Index
],
877 L
"USB\\DevClass_%02x",
878 DeviceDescriptor
->bDeviceClass
) + 1;
879 Index
+= swprintf(&Buffer
[Index
],
880 L
"USB\\COMPOSITE") + 1;
885 // FIXME: support multiple configurations
887 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
889 if (DeviceDescriptor
->bDeviceClass
== 0)
891 Index
+= swprintf(&Buffer
[Index
],
892 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
893 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
894 Index
+= swprintf(&Buffer
[Index
],
895 L
"USB\\Class_%02x&SubClass_%02x",
896 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
897 Index
+= swprintf(&Buffer
[Index
],
899 InterfaceDescriptor
->bInterfaceClass
) + 1;
903 Index
+= swprintf(&Buffer
[Index
],
904 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
905 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
906 Index
+= swprintf(&Buffer
[Index
],
907 L
"USB\\Class_%02x&SubClass_%02x",
908 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
909 Index
+= swprintf(&Buffer
[Index
],
911 DeviceDescriptor
->bDeviceClass
) + 1;
916 // now allocate the buffer
918 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
924 return STATUS_INSUFFICIENT_RESOURCES
;
930 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
931 DeviceString
[Index
] = UNICODE_NULL
;
932 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
933 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
934 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
935 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
938 // Construct DeviceId string
940 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
943 // now allocate the buffer
945 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
951 return STATUS_INSUFFICIENT_RESOURCES
;
957 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
958 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
959 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
960 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
961 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
964 // Construct HardwareIds
967 Index
+= swprintf(&Buffer
[Index
],
968 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
969 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
970 Index
+= swprintf(&Buffer
[Index
],
971 L
"USB\\Vid_%04x&Pid_%04x",
972 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
975 // now allocate the buffer
977 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
983 return STATUS_INSUFFICIENT_RESOURCES
;
989 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
990 DeviceString
[Index
] = UNICODE_NULL
;
991 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
992 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
993 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
994 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
997 // FIXME: Handle Lang ids
1001 // Get the product string if obe provided
1003 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1005 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1006 UsbChildExtension
->DeviceDesc
.iProduct
,
1008 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1009 &UsbChildExtension
->usTextDescription
.Length
);
1010 if (!NT_SUCCESS(Status
))
1012 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1013 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"USB Device"); // FIXME NON-NLS
1017 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1018 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1023 // Get the Serial Number string if obe provided
1025 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1027 LPWSTR SerialBuffer
= NULL
;
1029 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1030 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1032 (PVOID
*)&SerialBuffer
,
1033 &UsbChildExtension
->usInstanceId
.Length
);
1034 if (NT_SUCCESS(Status
))
1036 // construct instance id buffer
1037 Index
= swprintf(Buffer
, L
"%04d&%s", HubDeviceExtension
->InstanceCount
, SerialBuffer
) + 1;
1039 ExFreePool(SerialBuffer
);
1041 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1042 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1044 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1045 return STATUS_INSUFFICIENT_RESOURCES
;
1051 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1052 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1054 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension
->usInstanceId
, HubDeviceExtension
->InstanceCount
);
1060 // the device did not provide a serial number, or failed to retrieve the serial number
1061 // lets create a pseudo instance id
1063 Index
= swprintf(Buffer
, L
"%04d&%04d", HubDeviceExtension
->InstanceCount
, UsbChildExtension
->PortNumber
) + 1;
1064 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1065 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1067 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1068 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1075 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1076 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1078 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1079 return STATUS_SUCCESS
;
1083 DestroyUsbChildDeviceObject(
1084 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1087 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1088 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1089 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1092 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1094 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1096 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1098 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1100 /* Check if it matches the port ID */
1101 if (UsbChildExtension
->PortNumber
== PortId
)
1104 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1110 /* Fail the request if the device doesn't exist */
1111 if (!ChildDeviceObject
)
1113 DPRINT1("Removal request for non-existant device!\n");
1114 return STATUS_UNSUCCESSFUL
;
1117 /* Remove the device from the table */
1118 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1120 /* Invalidate device relations for the root hub */
1121 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1123 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1124 return STATUS_SUCCESS
;
1128 CreateUsbChildDeviceObject(
1129 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1131 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1132 IN ULONG PortStatus
)
1135 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1136 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1137 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1138 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1139 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1140 WCHAR CharDeviceName
[64];
1141 UNICODE_STRING DeviceName
;
1142 ULONG ConfigDescSize
, DeviceDescSize
, DeviceInfoSize
;
1143 PVOID HubInterfaceBusContext
;
1144 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1146 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1147 HubInterface
= &HubDeviceExtension
->HubInterface
;
1148 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1149 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1151 // Find an empty slot in the child device array
1153 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1155 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1157 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1163 // Check if the limit has been reached for maximum usb devices
1165 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1167 DPRINT1("USBHUB: Too many child devices!\n");
1168 return STATUS_UNSUCCESSFUL
;
1174 // Create a Device Name
1176 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1179 // Initialize UnicodeString
1181 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1184 // Create a DeviceObject
1186 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1187 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1189 FILE_DEVICE_CONTROLLER
,
1190 FILE_AUTOGENERATED_DEVICE_NAME
,
1192 &NewChildDeviceObject
);
1195 // Check if the name is already in use
1197 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1207 // Check for other errors
1209 if (!NT_SUCCESS(Status
))
1211 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1215 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1219 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1222 // Assign the device extensions
1224 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1225 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1226 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1227 UsbChildExtension
->PortNumber
= PortId
;
1229 // copy device interface
1230 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1234 // Create the UsbDeviceObject
1236 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1237 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1238 HubDeviceExtension
->RootHubHandle
,
1241 if (!NT_SUCCESS(Status
))
1243 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1247 // copy device interface
1248 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1250 // FIXME replace buscontext
1251 UsbChildExtension
->DeviceInterface
.BusContext
= UsbChildExtension
->UsbDeviceHandle
;
1254 // Initialize UsbDevice
1256 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1257 if (!NT_SUCCESS(Status
))
1259 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1263 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1265 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1266 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1269 // Get the descriptors
1271 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1272 UsbChildExtension
->UsbDeviceHandle
,
1273 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1275 (PUCHAR
)&ConfigDesc
,
1277 if (!NT_SUCCESS(Status
))
1279 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1283 //DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1284 //DumpConfigurationDescriptor(&ConfigDesc);
1287 // FIXME: Support more than one configuration and one interface?
1289 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1291 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1294 if (ConfigDesc
.bNumInterfaces
> 1)
1296 DPRINT1("Warning: Device has more than one interface. Only one interface (the first) is currently supported\n");
1299 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1302 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1304 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1307 // Retrieve the full configuration descriptor
1309 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1310 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1313 UsbChildExtension
->FullConfigDesc
,
1316 if (!NT_SUCCESS(Status
))
1318 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1322 // query device details
1323 Status
= HubInterface
->QueryDeviceInformation(HubInterfaceBusContext
,
1324 UsbChildExtension
->UsbDeviceHandle
,
1325 &UsbChildExtension
->DeviceInformation
,
1326 sizeof(USB_DEVICE_INFORMATION_0
),
1330 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1333 // Construct all the strings that will describe the device to PNP
1335 Status
= CreateDeviceIds(NewChildDeviceObject
);
1336 if (!NT_SUCCESS(Status
))
1338 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1342 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1343 HubDeviceExtension
->InstanceCount
++;
1345 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1346 return STATUS_SUCCESS
;
1351 // Remove the usb device if it was created
1353 if (UsbChildExtension
->UsbDeviceHandle
)
1354 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1357 // Free full configuration descriptor if one was allocated
1359 if (UsbChildExtension
->FullConfigDesc
)
1360 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1363 // Free ID buffers if they were allocated in CreateDeviceIds()
1365 if (UsbChildExtension
->usCompatibleIds
.Buffer
)
1366 ExFreePool(UsbChildExtension
->usCompatibleIds
.Buffer
);
1368 if (UsbChildExtension
->usDeviceId
.Buffer
)
1369 ExFreePool(UsbChildExtension
->usDeviceId
.Buffer
);
1371 if (UsbChildExtension
->usHardwareIds
.Buffer
)
1372 ExFreePool(UsbChildExtension
->usHardwareIds
.Buffer
);
1374 if (UsbChildExtension
->usInstanceId
.Buffer
)
1375 ExFreePool(UsbChildExtension
->usInstanceId
.Buffer
);
1378 // Delete the device object
1380 IoDeleteDevice(NewChildDeviceObject
);
1385 USBHUB_FdoQueryBusRelations(
1386 IN PDEVICE_OBJECT DeviceObject
,
1387 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1389 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1390 PDEVICE_RELATIONS DeviceRelations
;
1395 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1398 // Count the number of children
1400 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1403 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1410 NeededSize
= sizeof(DEVICE_RELATIONS
);
1412 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1415 // Allocate DeviceRelations
1417 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1420 if (!DeviceRelations
)
1421 return STATUS_INSUFFICIENT_RESOURCES
;
1422 DeviceRelations
->Count
= Children
;
1426 // Fill in return structure
1428 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1430 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1432 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1433 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1434 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1438 ASSERT(Children
== DeviceRelations
->Count
);
1439 *pDeviceRelations
= DeviceRelations
;
1441 return STATUS_SUCCESS
;
1446 RootHubInitCallbackFunction(
1449 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1452 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1453 PORT_STATUS_CHANGE StatusChange
;
1455 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1457 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1460 // Send the first SCE Request
1462 QueryStatusChangeEndpoint(DeviceObject
);
1464 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1469 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1470 if (NT_SUCCESS(Status
))
1473 // is there a device connected
1475 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1480 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1481 if (!NT_SUCCESS(Status
))
1483 DPRINT1("Failed to reset on port %d\n", PortId
);
1488 // wait for the reset to be handled since we want to enumerate synchronously
1490 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1495 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1503 USBHUB_IsRootHubFDO(
1504 IN PDEVICE_OBJECT DeviceObject
)
1507 PDEVICE_OBJECT RootHubPhysicalDeviceObject
= NULL
;
1508 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1510 // get hub device extension
1511 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1513 // Get the Root Hub Pdo
1514 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1515 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1516 &RootHubPhysicalDeviceObject
,
1519 // FIXME handle error
1520 ASSERT(NT_SUCCESS(Status
));
1522 // physical device object is only obtained for root hubs
1523 return (RootHubPhysicalDeviceObject
!= NULL
);
1528 USBHUB_FdoStartDevice(
1529 IN PDEVICE_OBJECT DeviceObject
,
1533 PUSB_INTERFACE_DESCRIPTOR Pid
;
1534 ULONG Result
= 0, PortId
;
1535 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1536 PURB ConfigUrb
= NULL
;
1538 NTSTATUS Status
= STATUS_SUCCESS
;
1539 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1540 PDEVICE_OBJECT RootHubDeviceObject
;
1541 PVOID HubInterfaceBusContext
;
1542 PORT_STATUS_CHANGE StatusChange
;
1544 // get hub device extension
1545 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1547 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1549 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1550 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1554 return STATUS_INSUFFICIENT_RESOURCES
;
1558 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1560 // Get the Root Hub Pdo
1561 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1562 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1563 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1564 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1565 if (!NT_SUCCESS(Status
))
1567 // failed to obtain hub pdo
1568 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status
);
1574 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1575 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1578 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1580 // Send the StartDevice to RootHub
1581 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1583 if (!NT_SUCCESS(Status
))
1585 // failed to start pdo
1586 DPRINT1("Failed to start the RootHub PDO\n");
1591 // Get the current number of hubs
1592 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1593 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1594 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1595 if (!NT_SUCCESS(Status
))
1597 // failed to get number of hubs
1598 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status
);
1603 // Get the Hub Interface
1604 Status
= QueryInterface(RootHubDeviceObject
,
1605 USB_BUS_INTERFACE_HUB_GUID
,
1606 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1607 USB_BUSIF_HUB_VERSION_5
,
1608 (PVOID
)&HubDeviceExtension
->HubInterface
);
1610 if (!NT_SUCCESS(Status
))
1612 // failed to get root hub interface
1613 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1618 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1620 // Get the USBDI Interface
1621 Status
= QueryInterface(RootHubDeviceObject
,
1622 USB_BUS_INTERFACE_USBDI_GUID
,
1623 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1624 USB_BUSIF_USBDI_VERSION_2
,
1625 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1627 if (!NT_SUCCESS(Status
))
1629 // failed to get usbdi interface
1630 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1635 // Get Root Hub Device Handle
1636 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1637 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1638 &HubDeviceExtension
->RootHubHandle
,
1641 if (!NT_SUCCESS(Status
))
1644 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status
);
1650 // Get Hub Device Information
1652 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1653 HubDeviceExtension
->RootHubHandle
,
1654 &HubDeviceExtension
->DeviceInformation
,
1655 sizeof(USB_DEVICE_INFORMATION_0
),
1658 DPRINT("Status %x, Result 0x%08lx\n", Status
, Result
);
1659 DPRINT("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1660 DPRINT("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1661 DPRINT("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1662 DPRINT("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1663 DPRINT("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1664 DPRINT("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1666 // Get Root Hubs Device Descriptor
1667 UsbBuildGetDescriptorRequest(Urb
,
1668 sizeof(Urb
->UrbControlDescriptorRequest
),
1669 USB_DEVICE_DESCRIPTOR_TYPE
,
1672 &HubDeviceExtension
->HubDeviceDescriptor
,
1674 sizeof(USB_DEVICE_DESCRIPTOR
),
1677 // set device handle
1678 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1680 // get hub device descriptor
1681 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1682 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1686 if (!NT_SUCCESS(Status
))
1688 // failed to get device descriptor of hub
1689 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1694 // build configuration request
1695 UsbBuildGetDescriptorRequest(Urb
,
1696 sizeof(Urb
->UrbControlDescriptorRequest
),
1697 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1700 &HubDeviceExtension
->HubConfigDescriptor
,
1702 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1705 // set device handle
1706 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1708 // request configuration descriptor
1709 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1710 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1714 if (!NT_SUCCESS(Status
))
1716 // failed to get configuration descriptor
1717 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1723 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
));
1724 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bDescriptorType
== USB_CONFIGURATION_DESCRIPTOR_TYPE
);
1725 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1726 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bNumInterfaces
== 1);
1727 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
1728 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
1729 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bNumEndpoints
== 1);
1730 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1731 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bLength
== sizeof(USB_ENDPOINT_DESCRIPTOR
));
1732 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bmAttributes
== USB_ENDPOINT_TYPE_INTERRUPT
);
1733 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bEndpointAddress
== 0x81); // interrupt in
1735 // get hub information
1736 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1737 RootHubDeviceObject
,
1738 &HubDeviceExtension
->UsbExtHubInfo
,
1739 sizeof(USB_EXTHUB_INFORMATION_0
),
1741 if (!NT_SUCCESS(Status
))
1743 // failed to get hub information
1744 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1749 if (!HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
)
1751 // bogus port driver
1752 DPRINT1("Failed to retrieve the number of ports\n");
1754 return STATUS_UNSUCCESSFUL
;
1757 DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1759 // Build hub descriptor request
1760 UsbBuildVendorRequest(Urb
,
1761 URB_FUNCTION_CLASS_DEVICE
,
1762 sizeof(Urb
->UrbControlVendorClassRequest
),
1763 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1765 USB_REQUEST_GET_DESCRIPTOR
,
1766 USB_DEVICE_CLASS_RESERVED
,
1768 &HubDeviceExtension
->HubDescriptor
,
1770 sizeof(USB_HUB_DESCRIPTOR
),
1773 // set device handle
1774 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1777 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1778 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1782 if (!NT_SUCCESS(Status
))
1784 DPRINT1("Failed to get Hub Descriptor!\n");
1786 return STATUS_UNSUCCESSFUL
;
1790 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorLength
== sizeof(USB_HUB_DESCRIPTOR
));
1791 ASSERT(HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
== HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1792 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorType
== 0x29);
1794 // build get status request
1796 UsbBuildGetStatusRequest(Urb
,
1797 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1802 // set device handle
1803 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1806 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1807 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1810 if (!NT_SUCCESS(Status
))
1812 // failed to get hub status
1813 DPRINT1("Failed to get Hub Status!\n");
1815 return STATUS_UNSUCCESSFUL
;
1818 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1819 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1820 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1823 // Get the first Configuration Descriptor
1824 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1825 &HubDeviceExtension
->HubConfigDescriptor
,
1826 -1, -1, -1, -1, -1);
1829 // failed parse hub descriptor
1830 DPRINT1("Failed to parse configuration descriptor\n");
1832 return STATUS_UNSUCCESSFUL
;
1835 // create configuration request
1836 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1837 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1838 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1839 if (ConfigUrb
== NULL
)
1841 // failed to build urb
1842 DPRINT1("Failed to allocate urb\n");
1844 return STATUS_INSUFFICIENT_RESOURCES
;
1848 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1849 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1852 if (!NT_SUCCESS(Status
))
1854 // failed to select configuration
1855 DPRINT1("Failed to select configuration with %x\n", Status
);
1857 ExFreePool(ConfigUrb
);
1861 // store configuration & pipe handle
1862 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1863 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1864 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1866 FDO_QueryInterface(DeviceObject
, &HubDeviceExtension
->DeviceInterface
);
1870 ExFreePool(ConfigUrb
);
1872 // check if function is available
1873 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1875 // is it high speed bus
1876 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1878 // initialize usb 2.0 hub
1879 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1880 HubDeviceExtension
->RootHubHandle
, 1);
1881 DPRINT("Status %x\n", Status
);
1883 // FIXME handle error
1884 ASSERT(Status
== STATUS_SUCCESS
);
1889 // Enable power on all ports
1890 DPRINT("Enabling PortPower on all ports!\n");
1891 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1893 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1894 if (!NT_SUCCESS(Status
))
1895 DPRINT1("Failed to power on port %d\n", PortId
);
1897 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1898 if (!NT_SUCCESS(Status
))
1899 DPRINT1("Failed to power on port %d\n", PortId
);
1902 // init root hub notification
1903 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1905 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1907 RootHubInitCallbackFunction
);
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT1("Failed to set callback\n");
1917 // Send the first SCE Request
1918 QueryStatusChangeEndpoint(DeviceObject
);
1923 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1928 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1929 if (NT_SUCCESS(Status
))
1932 // is there a device connected
1934 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1939 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1940 if (!NT_SUCCESS(Status
))
1942 DPRINT1("Failed to reset on port %d\n", PortId
);
1947 // wait for the reset to be handled since we want to enumerate synchronously
1949 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1954 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1969 USBHUB_FdoHandlePnp(
1970 IN PDEVICE_OBJECT DeviceObject
,
1973 PIO_STACK_LOCATION Stack
;
1974 NTSTATUS Status
= STATUS_SUCCESS
;
1975 ULONG_PTR Information
= 0;
1976 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1978 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1980 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1982 switch (Stack
->MinorFunction
)
1984 case IRP_MN_START_DEVICE
:
1986 if (USBHUB_IsRootHubFDO(DeviceObject
))
1988 // start root hub fdo
1989 Status
= USBHUB_FdoStartDevice(DeviceObject
, Irp
);
1993 Status
= USBHUB_ParentFDOStartDevice(DeviceObject
, Irp
);
1998 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2000 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
2004 PDEVICE_RELATIONS DeviceRelations
= NULL
;
2005 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
2007 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
2009 Information
= (ULONG_PTR
)DeviceRelations
;
2012 case RemovalRelations
:
2014 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
2015 return ForwardIrpAndForget(DeviceObject
, Irp
);
2018 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
2019 Stack
->Parameters
.QueryDeviceRelations
.Type
);
2020 return ForwardIrpAndForget(DeviceObject
, Irp
);
2024 case IRP_MN_QUERY_REMOVE_DEVICE
:
2025 case IRP_MN_QUERY_STOP_DEVICE
:
2027 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2028 return ForwardIrpAndForget(DeviceObject
, Irp
);
2030 case IRP_MN_REMOVE_DEVICE
:
2032 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2033 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2035 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
2036 IoDeleteDevice(DeviceObject
);
2038 return STATUS_SUCCESS
;
2040 case IRP_MN_QUERY_BUS_INFORMATION
:
2042 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2045 case IRP_MN_QUERY_ID
:
2047 DPRINT("IRP_MN_QUERY_ID\n");
2050 case IRP_MN_QUERY_CAPABILITIES
:
2052 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2057 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
2058 return ForwardIrpAndForget(DeviceObject
, Irp
);
2062 Irp
->IoStatus
.Information
= Information
;
2063 Irp
->IoStatus
.Status
= Status
;
2064 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2069 USBHUB_FdoHandleDeviceControl(
2070 IN PDEVICE_OBJECT DeviceObject
,
2073 PIO_STACK_LOCATION IoStack
;
2074 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2075 PUSB_NODE_INFORMATION NodeInformation
;
2076 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2077 PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo
;
2078 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2079 PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey
;
2080 PUSB_NODE_CONNECTION_NAME ConnectionName
;
2081 ULONG Index
, Length
;
2083 // get stack location
2084 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2086 // get device extension
2087 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2089 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_INFORMATION
)
2091 // is the buffer big enough
2092 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_INFORMATION
))
2095 Status
= STATUS_BUFFER_TOO_SMALL
;
2100 NodeInformation
= (PUSB_NODE_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2103 ASSERT(NodeInformation
);
2106 NodeInformation
->NodeType
= UsbHub
;
2107 RtlCopyMemory(&NodeInformation
->u
.HubInformation
.HubDescriptor
, &HubDeviceExtension
->HubDescriptor
, sizeof(USB_HUB_DESCRIPTOR
));
2109 // FIXME is hub powered
2110 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= TRUE
;
2113 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2114 Status
= STATUS_SUCCESS
;
2119 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
)
2121 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2124 Status
= STATUS_BUFFER_TOO_SMALL
;
2128 // get node connection info
2129 NodeConnectionInfo
= (PUSB_NODE_CONNECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2132 ASSERT(NodeConnectionInfo
);
2134 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2136 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2139 // get child device extension
2140 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2142 if (ChildDeviceExtension
->PortNumber
!= NodeConnectionInfo
->ConnectionIndex
)
2145 // init node connection info
2146 RtlCopyMemory(&NodeConnectionInfo
->DeviceDescriptor
, &ChildDeviceExtension
->DeviceDesc
, sizeof(USB_DEVICE_DESCRIPTOR
));
2147 NodeConnectionInfo
->CurrentConfigurationValue
= ChildDeviceExtension
->FullConfigDesc
->bConfigurationValue
;
2148 NodeConnectionInfo
->DeviceIsHub
= FALSE
; //FIXME support hubs
2149 NodeConnectionInfo
->LowSpeed
= ChildDeviceExtension
->DeviceInformation
.DeviceSpeed
== UsbLowSpeed
;
2150 NodeConnectionInfo
->DeviceAddress
= ChildDeviceExtension
->DeviceInformation
.DeviceAddress
;
2151 NodeConnectionInfo
->NumberOfOpenPipes
= ChildDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
;
2152 NodeConnectionInfo
->ConnectionStatus
= DeviceConnected
; //FIXME
2154 if (NodeConnectionInfo
->NumberOfOpenPipes
)
2156 DPRINT1("Need to copy pipe information\n");
2161 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2162 Status
= STATUS_SUCCESS
;
2165 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
)
2167 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2170 Status
= STATUS_BUFFER_TOO_SMALL
;
2174 // get node connection info
2175 NodeKey
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2180 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2182 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2185 // get child device extension
2186 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2188 if (ChildDeviceExtension
->PortNumber
!= NodeKey
->ConnectionIndex
)
2192 Status
= IoGetDeviceProperty(HubDeviceExtension
->ChildDeviceObject
[Index
], DevicePropertyDriverKeyName
,
2193 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
),
2194 NodeKey
->DriverKeyName
,
2197 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2200 Status
= STATUS_SUCCESS
;
2203 if (Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
2205 // terminate node key name
2206 NodeKey
->DriverKeyName
[0] = UNICODE_NULL
;
2207 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2212 Irp
->IoStatus
.Information
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2215 // length of driver name
2216 NodeKey
->ActualLength
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2221 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_NAME
)
2223 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_NAME
))
2226 Status
= STATUS_BUFFER_TOO_SMALL
;
2230 // FIXME support hubs
2231 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2232 ConnectionName
->ActualLength
= 0;
2233 ConnectionName
->NodeName
[0] = UNICODE_NULL
;
2236 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_NAME
);
2237 Status
= STATUS_SUCCESS
;
2242 DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2243 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2247 Irp
->IoStatus
.Status
= Status
;
2248 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);