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;
1038 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1039 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1041 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1042 return STATUS_INSUFFICIENT_RESOURCES
;
1048 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1049 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1050 ExFreePool(SerialBuffer
);
1052 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension
->usInstanceId
, HubDeviceExtension
->InstanceCount
);
1058 // the device did not provide a serial number, or failed to retrieve the serial number
1059 // lets create a pseudo instance id
1061 Index
= swprintf(Buffer
, L
"%04d&%04d", HubDeviceExtension
->InstanceCount
, UsbChildExtension
->PortNumber
) + 1;
1062 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1063 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1065 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1066 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1073 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1074 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1076 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1077 return STATUS_SUCCESS
;
1081 DestroyUsbChildDeviceObject(
1082 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1085 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1086 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1087 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1090 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1092 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1094 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1096 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1098 /* Check if it matches the port ID */
1099 if (UsbChildExtension
->PortNumber
== PortId
)
1102 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1108 /* Fail the request if the device doesn't exist */
1109 if (!ChildDeviceObject
)
1111 DPRINT1("Removal request for non-existant device!\n");
1112 return STATUS_UNSUCCESSFUL
;
1115 /* Remove the device from the table */
1116 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1118 /* Invalidate device relations for the root hub */
1119 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1121 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1122 return STATUS_SUCCESS
;
1126 CreateUsbChildDeviceObject(
1127 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1129 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1130 IN ULONG PortStatus
)
1133 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1134 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1135 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1136 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1137 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1138 WCHAR CharDeviceName
[64];
1139 UNICODE_STRING DeviceName
;
1140 ULONG ConfigDescSize
, DeviceDescSize
, DeviceInfoSize
;
1141 PVOID HubInterfaceBusContext
;
1142 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1144 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1145 HubInterface
= &HubDeviceExtension
->HubInterface
;
1146 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1147 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1149 // Find an empty slot in the child device array
1151 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1153 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1155 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1161 // Check if the limit has been reached for maximum usb devices
1163 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1165 DPRINT1("USBHUB: Too many child devices!\n");
1166 return STATUS_UNSUCCESSFUL
;
1172 // Create a Device Name
1174 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1177 // Initialize UnicodeString
1179 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1182 // Create a DeviceObject
1184 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1185 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1187 FILE_DEVICE_CONTROLLER
,
1188 FILE_AUTOGENERATED_DEVICE_NAME
,
1190 &NewChildDeviceObject
);
1193 // Check if the name is already in use
1195 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1205 // Check for other errors
1207 if (!NT_SUCCESS(Status
))
1209 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1213 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1217 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1220 // Assign the device extensions
1222 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1223 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1224 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1225 UsbChildExtension
->PortNumber
= PortId
;
1227 // copy device interface
1228 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1232 // Create the UsbDeviceObject
1234 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1235 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1236 HubDeviceExtension
->RootHubHandle
,
1239 if (!NT_SUCCESS(Status
))
1241 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1245 // copy device interface
1246 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->DeviceInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1248 // FIXME replace buscontext
1249 UsbChildExtension
->DeviceInterface
.BusContext
= UsbChildExtension
->UsbDeviceHandle
;
1252 // Initialize UsbDevice
1254 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1255 if (!NT_SUCCESS(Status
))
1257 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1261 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1263 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1264 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1267 // Get the descriptors
1269 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1270 UsbChildExtension
->UsbDeviceHandle
,
1271 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1273 (PUCHAR
)&ConfigDesc
,
1275 if (!NT_SUCCESS(Status
))
1277 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1281 //DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1282 //DumpConfigurationDescriptor(&ConfigDesc);
1285 // FIXME: Support more than one configuration and one interface?
1287 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1289 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1292 if (ConfigDesc
.bNumInterfaces
> 1)
1294 DPRINT1("Warning: Device has more than one interface. Only one interface (the first) is currently supported\n");
1297 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1300 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1302 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1305 // Retrieve the full configuration descriptor
1307 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1308 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1311 UsbChildExtension
->FullConfigDesc
,
1314 if (!NT_SUCCESS(Status
))
1316 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1320 // query device details
1321 Status
= HubInterface
->QueryDeviceInformation(HubInterfaceBusContext
,
1322 UsbChildExtension
->UsbDeviceHandle
,
1323 &UsbChildExtension
->DeviceInformation
,
1324 sizeof(USB_DEVICE_INFORMATION_0
),
1328 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1331 // Construct all the strings that will describe the device to PNP
1333 Status
= CreateDeviceIds(NewChildDeviceObject
);
1334 if (!NT_SUCCESS(Status
))
1336 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1340 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1341 HubDeviceExtension
->InstanceCount
++;
1343 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1344 return STATUS_SUCCESS
;
1349 // Remove the usb device if it was created
1351 if (UsbChildExtension
->UsbDeviceHandle
)
1352 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1355 // Free full configuration descriptor if one was allocated
1357 if (UsbChildExtension
->FullConfigDesc
)
1358 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1361 // Delete the device object
1363 IoDeleteDevice(NewChildDeviceObject
);
1368 USBHUB_FdoQueryBusRelations(
1369 IN PDEVICE_OBJECT DeviceObject
,
1370 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1372 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1373 PDEVICE_RELATIONS DeviceRelations
;
1378 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1381 // Count the number of children
1383 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1386 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1393 NeededSize
= sizeof(DEVICE_RELATIONS
);
1395 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1398 // Allocate DeviceRelations
1400 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1403 if (!DeviceRelations
)
1404 return STATUS_INSUFFICIENT_RESOURCES
;
1405 DeviceRelations
->Count
= Children
;
1409 // Fill in return structure
1411 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1413 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1415 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1416 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1417 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1421 ASSERT(Children
== DeviceRelations
->Count
);
1422 *pDeviceRelations
= DeviceRelations
;
1424 return STATUS_SUCCESS
;
1429 RootHubInitCallbackFunction(
1432 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1435 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1436 PORT_STATUS_CHANGE StatusChange
;
1438 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1440 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1443 // Send the first SCE Request
1445 QueryStatusChangeEndpoint(DeviceObject
);
1447 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1452 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1453 if (NT_SUCCESS(Status
))
1456 // is there a device connected
1458 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1463 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1464 if (!NT_SUCCESS(Status
))
1466 DPRINT1("Failed to reset on port %d\n", PortId
);
1471 // wait for the reset to be handled since we want to enumerate synchronously
1473 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1478 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1486 USBHUB_IsRootHubFDO(
1487 IN PDEVICE_OBJECT DeviceObject
)
1490 PDEVICE_OBJECT RootHubPhysicalDeviceObject
= NULL
;
1491 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1493 // get hub device extension
1494 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1496 // Get the Root Hub Pdo
1497 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1498 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1499 &RootHubPhysicalDeviceObject
,
1502 // FIXME handle error
1503 ASSERT(NT_SUCCESS(Status
));
1505 // physical device object is only obtained for root hubs
1506 return (RootHubPhysicalDeviceObject
!= NULL
);
1511 USBHUB_FdoStartDevice(
1512 IN PDEVICE_OBJECT DeviceObject
,
1516 PUSB_INTERFACE_DESCRIPTOR Pid
;
1517 ULONG Result
= 0, PortId
;
1518 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1519 PURB ConfigUrb
= NULL
;
1521 NTSTATUS Status
= STATUS_SUCCESS
;
1522 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1523 PDEVICE_OBJECT RootHubDeviceObject
;
1524 PVOID HubInterfaceBusContext
;
1525 PORT_STATUS_CHANGE StatusChange
;
1527 // get hub device extension
1528 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1530 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1532 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1533 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1537 return STATUS_INSUFFICIENT_RESOURCES
;
1541 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1543 // Get the Root Hub Pdo
1544 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1545 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1546 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1547 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1548 if (!NT_SUCCESS(Status
))
1550 // failed to obtain hub pdo
1551 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status
);
1557 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1558 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1561 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1563 // Send the StartDevice to RootHub
1564 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1566 if (!NT_SUCCESS(Status
))
1568 // failed to start pdo
1569 DPRINT1("Failed to start the RootHub PDO\n");
1574 // Get the current number of hubs
1575 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1576 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1577 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1578 if (!NT_SUCCESS(Status
))
1580 // failed to get number of hubs
1581 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status
);
1586 // Get the Hub Interface
1587 Status
= QueryInterface(RootHubDeviceObject
,
1588 USB_BUS_INTERFACE_HUB_GUID
,
1589 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1590 USB_BUSIF_HUB_VERSION_5
,
1591 (PVOID
)&HubDeviceExtension
->HubInterface
);
1593 if (!NT_SUCCESS(Status
))
1595 // failed to get root hub interface
1596 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1601 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1603 // Get the USBDI Interface
1604 Status
= QueryInterface(RootHubDeviceObject
,
1605 USB_BUS_INTERFACE_USBDI_GUID
,
1606 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1607 USB_BUSIF_USBDI_VERSION_2
,
1608 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1610 if (!NT_SUCCESS(Status
))
1612 // failed to get usbdi interface
1613 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1618 // Get Root Hub Device Handle
1619 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1620 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1621 &HubDeviceExtension
->RootHubHandle
,
1624 if (!NT_SUCCESS(Status
))
1627 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status
);
1633 // Get Hub Device Information
1635 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1636 HubDeviceExtension
->RootHubHandle
,
1637 &HubDeviceExtension
->DeviceInformation
,
1638 sizeof(USB_DEVICE_INFORMATION_0
),
1641 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1642 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1643 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1644 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1645 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1646 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1647 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1649 // Get Root Hubs Device Descriptor
1650 UsbBuildGetDescriptorRequest(Urb
,
1651 sizeof(Urb
->UrbControlDescriptorRequest
),
1652 USB_DEVICE_DESCRIPTOR_TYPE
,
1655 &HubDeviceExtension
->HubDeviceDescriptor
,
1657 sizeof(USB_DEVICE_DESCRIPTOR
),
1660 // set device handle
1661 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1663 // get hub device descriptor
1664 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1665 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1669 if (!NT_SUCCESS(Status
))
1671 // failed to get device descriptor of hub
1672 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1677 // build configuration request
1678 UsbBuildGetDescriptorRequest(Urb
,
1679 sizeof(Urb
->UrbControlDescriptorRequest
),
1680 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1683 &HubDeviceExtension
->HubConfigDescriptor
,
1685 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1688 // set device handle
1689 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1691 // request configuration descriptor
1692 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1693 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1697 if (!NT_SUCCESS(Status
))
1699 // failed to get configuration descriptor
1700 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1706 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
));
1707 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bDescriptorType
== USB_CONFIGURATION_DESCRIPTOR_TYPE
);
1708 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1709 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bNumInterfaces
== 1);
1710 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
1711 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
1712 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bNumEndpoints
== 1);
1713 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1714 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bLength
== sizeof(USB_ENDPOINT_DESCRIPTOR
));
1715 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bmAttributes
== USB_ENDPOINT_TYPE_INTERRUPT
);
1716 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bEndpointAddress
== 0x81); // interrupt in
1718 // get hub information
1719 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1720 RootHubDeviceObject
,
1721 &HubDeviceExtension
->UsbExtHubInfo
,
1722 sizeof(USB_EXTHUB_INFORMATION_0
),
1724 if (!NT_SUCCESS(Status
))
1726 // failed to get hub information
1727 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1732 if (!HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
)
1734 // bogus port driver
1735 DPRINT1("Failed to retrieve the number of ports\n");
1737 return STATUS_UNSUCCESSFUL
;
1740 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1742 // Build hub descriptor request
1743 UsbBuildVendorRequest(Urb
,
1744 URB_FUNCTION_CLASS_DEVICE
,
1745 sizeof(Urb
->UrbControlVendorClassRequest
),
1746 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1748 USB_REQUEST_GET_DESCRIPTOR
,
1749 USB_DEVICE_CLASS_RESERVED
,
1751 &HubDeviceExtension
->HubDescriptor
,
1753 sizeof(USB_HUB_DESCRIPTOR
),
1756 // set device handle
1757 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1760 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1761 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1765 if (!NT_SUCCESS(Status
))
1767 DPRINT1("Failed to get Hub Descriptor!\n");
1769 return STATUS_UNSUCCESSFUL
;
1773 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorLength
== sizeof(USB_HUB_DESCRIPTOR
));
1774 ASSERT(HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
== HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1775 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorType
== 0x29);
1777 // build get status request
1779 UsbBuildGetStatusRequest(Urb
,
1780 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1785 // set device handle
1786 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1789 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1790 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1793 if (!NT_SUCCESS(Status
))
1795 // failed to get hub status
1796 DPRINT1("Failed to get Hub Status!\n");
1798 return STATUS_UNSUCCESSFUL
;
1801 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1802 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1803 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1806 // Get the first Configuration Descriptor
1807 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1808 &HubDeviceExtension
->HubConfigDescriptor
,
1809 -1, -1, -1, -1, -1);
1812 // failed parse hub descriptor
1813 DPRINT1("Failed to parse configuration descriptor\n");
1815 return STATUS_UNSUCCESSFUL
;
1818 // create configuration request
1819 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1820 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1821 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1822 if (ConfigUrb
== NULL
)
1824 // failed to build urb
1825 DPRINT1("Failed to allocate urb\n");
1827 return STATUS_INSUFFICIENT_RESOURCES
;
1831 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1832 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1835 if (!NT_SUCCESS(Status
))
1837 // failed to select configuration
1838 DPRINT1("Failed to select configuration with %x\n", Status
);
1840 ExFreePool(ConfigUrb
);
1844 // store configuration & pipe handle
1845 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1846 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1847 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1849 FDO_QueryInterface(DeviceObject
, &HubDeviceExtension
->DeviceInterface
);
1853 ExFreePool(ConfigUrb
);
1855 // check if function is available
1856 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1858 // is it high speed bus
1859 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1861 // initialize usb 2.0 hub
1862 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1863 HubDeviceExtension
->RootHubHandle
, 1);
1864 DPRINT("Status %x\n", Status
);
1866 // FIXME handle error
1867 ASSERT(Status
== STATUS_SUCCESS
);
1872 // Enable power on all ports
1873 DPRINT("Enabling PortPower on all ports!\n");
1874 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1876 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1877 if (!NT_SUCCESS(Status
))
1878 DPRINT1("Failed to power on port %d\n", PortId
);
1880 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1881 if (!NT_SUCCESS(Status
))
1882 DPRINT1("Failed to power on port %d\n", PortId
);
1885 // init root hub notification
1886 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1888 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1890 RootHubInitCallbackFunction
);
1891 if (!NT_SUCCESS(Status
))
1893 DPRINT1("Failed to set callback\n");
1900 // Send the first SCE Request
1901 QueryStatusChangeEndpoint(DeviceObject
);
1906 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1911 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1912 if (NT_SUCCESS(Status
))
1915 // is there a device connected
1917 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1922 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1923 if (!NT_SUCCESS(Status
))
1925 DPRINT1("Failed to reset on port %d\n", PortId
);
1930 // wait for the reset to be handled since we want to enumerate synchronously
1932 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1937 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1952 USBHUB_FdoHandlePnp(
1953 IN PDEVICE_OBJECT DeviceObject
,
1956 PIO_STACK_LOCATION Stack
;
1957 NTSTATUS Status
= STATUS_SUCCESS
;
1958 ULONG_PTR Information
= 0;
1959 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1961 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1963 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1965 switch (Stack
->MinorFunction
)
1967 case IRP_MN_START_DEVICE
:
1969 if (USBHUB_IsRootHubFDO(DeviceObject
))
1971 // start root hub fdo
1972 Status
= USBHUB_FdoStartDevice(DeviceObject
, Irp
);
1976 Status
= USBHUB_ParentFDOStartDevice(DeviceObject
, Irp
);
1981 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1983 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1987 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1988 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1990 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1992 Information
= (ULONG_PTR
)DeviceRelations
;
1995 case RemovalRelations
:
1997 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1998 return ForwardIrpAndForget(DeviceObject
, Irp
);
2001 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
2002 Stack
->Parameters
.QueryDeviceRelations
.Type
);
2003 return ForwardIrpAndForget(DeviceObject
, Irp
);
2007 case IRP_MN_QUERY_REMOVE_DEVICE
:
2008 case IRP_MN_QUERY_STOP_DEVICE
:
2010 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2011 return ForwardIrpAndForget(DeviceObject
, Irp
);
2013 case IRP_MN_REMOVE_DEVICE
:
2015 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2016 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2018 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
2019 IoDeleteDevice(DeviceObject
);
2021 return STATUS_SUCCESS
;
2023 case IRP_MN_QUERY_BUS_INFORMATION
:
2025 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2028 case IRP_MN_QUERY_ID
:
2030 DPRINT("IRP_MN_QUERY_ID\n");
2033 case IRP_MN_QUERY_CAPABILITIES
:
2035 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2040 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
2041 return ForwardIrpAndForget(DeviceObject
, Irp
);
2045 Irp
->IoStatus
.Information
= Information
;
2046 Irp
->IoStatus
.Status
= Status
;
2047 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2052 USBHUB_FdoHandleDeviceControl(
2053 IN PDEVICE_OBJECT DeviceObject
,
2056 PIO_STACK_LOCATION IoStack
;
2057 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2058 PUSB_NODE_INFORMATION NodeInformation
;
2059 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2060 PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo
;
2061 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2062 PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey
;
2063 PUSB_NODE_CONNECTION_NAME ConnectionName
;
2064 ULONG Index
, Length
;
2066 // get stack location
2067 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2069 // get device extension
2070 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2072 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_INFORMATION
)
2074 // is the buffer big enough
2075 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_INFORMATION
))
2078 Status
= STATUS_BUFFER_TOO_SMALL
;
2083 NodeInformation
= (PUSB_NODE_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2086 ASSERT(NodeInformation
);
2089 NodeInformation
->NodeType
= UsbHub
;
2090 RtlCopyMemory(&NodeInformation
->u
.HubInformation
.HubDescriptor
, &HubDeviceExtension
->HubDescriptor
, sizeof(USB_HUB_DESCRIPTOR
));
2092 // FIXME is hub powered
2093 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= TRUE
;
2096 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2097 Status
= STATUS_SUCCESS
;
2102 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
)
2104 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2107 Status
= STATUS_BUFFER_TOO_SMALL
;
2111 // get node connection info
2112 NodeConnectionInfo
= (PUSB_NODE_CONNECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2115 ASSERT(NodeConnectionInfo
);
2117 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2119 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2122 // get child device extension
2123 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2125 if (ChildDeviceExtension
->PortNumber
!= NodeConnectionInfo
->ConnectionIndex
)
2128 // init node connection info
2129 RtlCopyMemory(&NodeConnectionInfo
->DeviceDescriptor
, &ChildDeviceExtension
->DeviceDesc
, sizeof(USB_DEVICE_DESCRIPTOR
));
2130 NodeConnectionInfo
->CurrentConfigurationValue
= ChildDeviceExtension
->FullConfigDesc
->bConfigurationValue
;
2131 NodeConnectionInfo
->DeviceIsHub
= FALSE
; //FIXME support hubs
2132 NodeConnectionInfo
->LowSpeed
= ChildDeviceExtension
->DeviceInformation
.DeviceSpeed
== UsbLowSpeed
;
2133 NodeConnectionInfo
->DeviceAddress
= ChildDeviceExtension
->DeviceInformation
.DeviceAddress
;
2134 NodeConnectionInfo
->NumberOfOpenPipes
= ChildDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
;
2135 NodeConnectionInfo
->ConnectionStatus
= DeviceConnected
; //FIXME
2137 if (NodeConnectionInfo
->NumberOfOpenPipes
)
2139 DPRINT1("Need to copy pipe information\n");
2144 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2145 Status
= STATUS_SUCCESS
;
2148 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
)
2150 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2153 Status
= STATUS_BUFFER_TOO_SMALL
;
2157 // get node connection info
2158 NodeKey
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2163 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2165 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2168 // get child device extension
2169 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2171 if (ChildDeviceExtension
->PortNumber
!= NodeKey
->ConnectionIndex
)
2175 Status
= IoGetDeviceProperty(HubDeviceExtension
->ChildDeviceObject
[Index
], DevicePropertyDriverKeyName
,
2176 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
),
2177 NodeKey
->DriverKeyName
,
2180 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2183 Status
= STATUS_SUCCESS
;
2186 if (Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
2188 // terminate node key name
2189 NodeKey
->DriverKeyName
[0] = UNICODE_NULL
;
2190 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2195 Irp
->IoStatus
.Information
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2198 // length of driver name
2199 NodeKey
->ActualLength
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2204 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_NAME
)
2206 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_NAME
))
2209 Status
= STATUS_BUFFER_TOO_SMALL
;
2213 // FIXME support hubs
2214 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2215 ConnectionName
->ActualLength
= 0;
2216 ConnectionName
->NodeName
[0] = UNICODE_NULL
;
2219 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_NAME
);
2220 Status
= STATUS_SUCCESS
;
2225 DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2226 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2230 Irp
->IoStatus
.Status
= Status
;
2231 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);