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
;
573 // Initialize the status block before sending the IRP
575 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
577 Status
= IoCallDriver(DeviceObject
, Irp
);
579 if (Status
== STATUS_PENDING
)
581 DPRINT("Operation pending\n");
582 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
583 Status
= IoStatus
.Status
;
590 GetUsbDeviceDescriptor(
591 IN PDEVICE_OBJECT ChildDeviceObject
,
592 IN UCHAR DescriptorType
,
595 OUT PVOID TransferBuffer
,
596 IN ULONG TransferBufferLength
)
599 PDEVICE_OBJECT RootHubDeviceObject
;
601 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
602 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
605 // Get the Hubs Device Extension
607 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
608 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
609 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
614 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
617 DPRINT1("Failed to allocate memory for URB!\n");
618 return STATUS_INSUFFICIENT_RESOURCES
;
624 RtlZeroMemory(Urb
, sizeof(URB
));
627 // Initialize URB for getting device descriptor
629 UsbBuildGetDescriptorRequest(Urb
,
630 sizeof(Urb
->UrbControlDescriptorRequest
),
636 TransferBufferLength
,
640 // Set the device handle
642 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
645 // Query the Root Hub
647 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
648 IOCTL_INTERNAL_USB_SUBMIT_URB
,
656 GetUsbStringDescriptor(
657 IN PDEVICE_OBJECT ChildDeviceObject
,
660 OUT PVOID
*TransferBuffer
,
664 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
668 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
669 sizeof(USB_STRING_DESCRIPTOR
),
673 DPRINT1("Failed to allocate buffer for string!\n");
674 return STATUS_INSUFFICIENT_RESOURCES
;
678 // Get the index string descriptor length
679 // FIXME: Implement LangIds
681 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
682 USB_STRING_DESCRIPTOR_TYPE
,
686 sizeof(USB_STRING_DESCRIPTOR
));
687 if (!NT_SUCCESS(Status
))
689 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
690 ExFreePool(StringDesc
);
693 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
696 // Did we get something more than the length of the first two fields of structure?
698 if (StringDesc
->bLength
== 2)
700 DPRINT1("USB Device Error!\n");
701 ExFreePool(StringDesc
);
702 return STATUS_DEVICE_DATA_ERROR
;
704 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
709 ExFreePool(StringDesc
);
712 // Recreate with appropriate size
714 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
719 DPRINT1("Failed to allocate buffer for string!\n");
720 return STATUS_INSUFFICIENT_RESOURCES
;
723 RtlZeroMemory(StringDesc
, SizeNeeded
);
728 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
729 USB_STRING_DESCRIPTOR_TYPE
,
734 if (!NT_SUCCESS(Status
))
736 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
737 ExFreePool(StringDesc
);
742 // Allocate Buffer to return
744 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
749 DPRINT1("Failed to allocate buffer for string!\n");
750 ExFreePool(StringDesc
);
751 return STATUS_INSUFFICIENT_RESOURCES
;
754 RtlZeroMemory(Buffer
, SizeNeeded
);
757 // Copy the string to destination
759 RtlCopyMemory(Buffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
));
761 *TransferBuffer
= Buffer
;
763 ExFreePool(StringDesc
);
765 return STATUS_SUCCESS
;
770 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
771 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
773 if (DeviceDescriptor
->bNumConfigurations
!= 1)
776 // composite device must have only one configuration
778 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
782 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
785 // composite device must have multiple interfaces
787 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
791 if (DeviceDescriptor
->bDeviceClass
== 0)
796 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
797 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
798 DPRINT1("IsCompositeDevice: TRUE\n");
802 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
803 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
804 DeviceDescriptor
->bDeviceProtocol
== 0x01)
807 // USB-IF association descriptor
809 DPRINT1("IsCompositeDevice: TRUE\n");
813 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
);
816 // not a composite device
823 PDEVICE_OBJECT UsbChildDeviceObject
)
825 NTSTATUS Status
= STATUS_SUCCESS
;
829 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
830 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
831 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
832 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
833 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
836 // get child device extension
838 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
840 // get hub device extension
841 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbChildExtension
->ParentDeviceObject
->DeviceExtension
;
844 // get device descriptor
846 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
849 // get configuration descriptor
851 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
854 // use first interface descriptor available
856 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, 0, -1, -1, -1, -1);
857 if (InterfaceDescriptor
== NULL
)
859 DPRINT1("Error USBD_ParseConfigurationDescriptorEx failed to parse interface descriptor\n");
860 return STATUS_INVALID_PARAMETER
;
863 ASSERT(InterfaceDescriptor
);
866 // Construct the CompatibleIds
868 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
873 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
874 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
875 Index
+= swprintf(&Buffer
[Index
],
876 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
877 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
878 Index
+= swprintf(&Buffer
[Index
],
879 L
"USB\\DevClass_%02x&SubClass_%02x",
880 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
881 Index
+= swprintf(&Buffer
[Index
],
882 L
"USB\\DevClass_%02x",
883 DeviceDescriptor
->bDeviceClass
) + 1;
884 Index
+= swprintf(&Buffer
[Index
],
885 L
"USB\\COMPOSITE") + 1;
890 // FIXME: support multiple configurations
892 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
894 if (DeviceDescriptor
->bDeviceClass
== 0)
896 Index
+= swprintf(&Buffer
[Index
],
897 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
898 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
899 Index
+= swprintf(&Buffer
[Index
],
900 L
"USB\\Class_%02x&SubClass_%02x",
901 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
902 Index
+= swprintf(&Buffer
[Index
],
904 InterfaceDescriptor
->bInterfaceClass
) + 1;
908 Index
+= swprintf(&Buffer
[Index
],
909 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
910 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
911 Index
+= swprintf(&Buffer
[Index
],
912 L
"USB\\Class_%02x&SubClass_%02x",
913 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
914 Index
+= swprintf(&Buffer
[Index
],
916 DeviceDescriptor
->bDeviceClass
) + 1;
921 // now allocate the buffer
923 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
929 return STATUS_INSUFFICIENT_RESOURCES
;
935 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
936 DeviceString
[Index
] = UNICODE_NULL
;
937 UsbChildExtension
->usCompatibleIds
.Buffer
= DeviceString
;
938 UsbChildExtension
->usCompatibleIds
.Length
= Index
* sizeof(WCHAR
);
939 UsbChildExtension
->usCompatibleIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
940 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
943 // Construct DeviceId string
945 Index
= swprintf(Buffer
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
948 // now allocate the buffer
950 DeviceString
= ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
956 return STATUS_INSUFFICIENT_RESOURCES
;
962 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
963 UsbChildExtension
->usDeviceId
.Buffer
= DeviceString
;
964 UsbChildExtension
->usDeviceId
.Length
= (Index
-1) * sizeof(WCHAR
);
965 UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
966 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
969 // Construct HardwareIds
972 Index
+= swprintf(&Buffer
[Index
],
973 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
974 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
975 Index
+= swprintf(&Buffer
[Index
],
976 L
"USB\\Vid_%04x&Pid_%04x",
977 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
980 // now allocate the buffer
982 DeviceString
= ExAllocatePool(NonPagedPool
, (Index
+ 1) * sizeof(WCHAR
));
988 return STATUS_INSUFFICIENT_RESOURCES
;
994 RtlCopyMemory(DeviceString
, Buffer
, Index
* sizeof(WCHAR
));
995 DeviceString
[Index
] = UNICODE_NULL
;
996 UsbChildExtension
->usHardwareIds
.Buffer
= DeviceString
;
997 UsbChildExtension
->usHardwareIds
.Length
= (Index
+ 1) * sizeof(WCHAR
);
998 UsbChildExtension
->usHardwareIds
.MaximumLength
= (Index
+ 1) * sizeof(WCHAR
);
999 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
1002 // FIXME: Handle Lang ids
1006 // Get the product string if obe provided
1008 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1010 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1011 UsbChildExtension
->DeviceDesc
.iProduct
,
1013 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1014 &UsbChildExtension
->usTextDescription
.Length
);
1015 if (!NT_SUCCESS(Status
))
1017 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1018 RtlInitUnicodeString(&UsbChildExtension
->usTextDescription
, L
"USB Device"); // FIXME NON-NLS
1022 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1023 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1028 // Get the Serial Number string if obe provided
1030 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1032 LPWSTR SerialBuffer
= NULL
;
1034 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1035 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1037 (PVOID
*)&SerialBuffer
,
1038 &UsbChildExtension
->usInstanceId
.Length
);
1039 if (NT_SUCCESS(Status
))
1041 // construct instance id buffer
1042 Index
= swprintf(Buffer
, L
"%04d&%s", HubDeviceExtension
->InstanceCount
, SerialBuffer
) + 1;
1044 ExFreePool(SerialBuffer
);
1046 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1047 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1049 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1050 return STATUS_INSUFFICIENT_RESOURCES
;
1056 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1057 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1059 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension
->usInstanceId
, HubDeviceExtension
->InstanceCount
);
1065 // the device did not provide a serial number, or failed to retrieve the serial number
1066 // lets create a pseudo instance id
1068 Index
= swprintf(Buffer
, L
"%04d&%04d", HubDeviceExtension
->InstanceCount
, UsbChildExtension
->PortNumber
) + 1;
1069 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1070 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1072 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1073 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1080 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1081 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usInstanceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1083 DPRINT("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1084 return STATUS_SUCCESS
;
1088 DestroyUsbChildDeviceObject(
1089 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1092 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1093 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1094 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1097 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1098 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1100 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1102 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1104 /* Check if it matches the port ID */
1105 if (UsbChildExtension
->PortNumber
== PortId
)
1108 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1114 /* Fail the request if the device doesn't exist */
1115 if (!ChildDeviceObject
)
1117 DPRINT1("Removal request for non-existant device!\n");
1118 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1119 return STATUS_UNSUCCESSFUL
;
1122 DPRINT("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1124 /* Remove the device from the table */
1125 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1127 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1129 /* Invalidate device relations for the root hub */
1130 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1132 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1133 return STATUS_SUCCESS
;
1137 CreateUsbChildDeviceObject(
1138 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1140 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
,
1141 IN ULONG PortStatus
)
1144 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1145 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1146 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1147 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1148 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1149 WCHAR CharDeviceName
[64];
1150 UNICODE_STRING DeviceName
;
1151 ULONG ConfigDescSize
, DeviceDescSize
, DeviceInfoSize
;
1152 PVOID HubInterfaceBusContext
;
1153 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1155 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1156 HubInterface
= &HubDeviceExtension
->HubInterface
;
1157 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1158 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1163 // Create a Device Name
1165 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1168 // Initialize UnicodeString
1170 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1173 // Create a DeviceObject
1175 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1176 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1178 FILE_DEVICE_CONTROLLER
,
1179 FILE_AUTOGENERATED_DEVICE_NAME
,
1181 &NewChildDeviceObject
);
1184 // Check if the name is already in use
1186 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1196 // Check for other errors
1198 if (!NT_SUCCESS(Status
))
1200 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1204 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1208 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1211 // Assign the device extensions
1213 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1214 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1215 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1216 UsbChildExtension
->PortNumber
= PortId
;
1219 // Create the UsbDeviceObject
1221 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1222 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1223 HubDeviceExtension
->RootHubHandle
,
1226 if (!NT_SUCCESS(Status
))
1228 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1233 // Initialize UsbDevice
1235 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1236 if (!NT_SUCCESS(Status
))
1238 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1242 DPRINT("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1244 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1245 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1248 // Get the descriptors
1250 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1251 UsbChildExtension
->UsbDeviceHandle
,
1252 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1254 (PUCHAR
)&ConfigDesc
,
1256 if (!NT_SUCCESS(Status
))
1258 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1262 //DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1263 //DumpConfigurationDescriptor(&ConfigDesc);
1266 // FIXME: Support more than one configuration and one interface?
1268 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1270 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1273 if (ConfigDesc
.bNumInterfaces
> 1)
1275 DPRINT1("Warning: Device has more than one interface. Only one interface (the first) is currently supported\n");
1278 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1281 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1283 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1286 // Retrieve the full configuration descriptor
1288 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1289 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1292 UsbChildExtension
->FullConfigDesc
,
1295 if (!NT_SUCCESS(Status
))
1297 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1301 // query device details
1302 Status
= HubInterface
->QueryDeviceInformation(HubInterfaceBusContext
,
1303 UsbChildExtension
->UsbDeviceHandle
,
1304 &UsbChildExtension
->DeviceInformation
,
1305 sizeof(USB_DEVICE_INFORMATION_0
),
1309 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1312 // Construct all the strings that will describe the device to PNP
1314 Status
= CreateDeviceIds(NewChildDeviceObject
);
1315 if (!NT_SUCCESS(Status
))
1317 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1321 // copy device interface
1322 RtlCopyMemory(&UsbChildExtension
->DeviceInterface
, &HubDeviceExtension
->UsbDInterface
, sizeof(USB_BUS_INTERFACE_USBDI_V2
));
1323 UsbChildExtension
->DeviceInterface
.InterfaceReference(UsbChildExtension
->DeviceInterface
.BusContext
);
1325 INITIALIZE_PNP_STATE(UsbChildExtension
->Common
);
1327 IoInitializeRemoveLock(&UsbChildExtension
->Common
.RemoveLock
, 'pbuH', 0, 0);
1329 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1332 // Find an empty slot in the child device array
1334 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1336 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1338 DPRINT("Found unused entry at %d\n", ChildDeviceCount
);
1344 // Check if the limit has been reached for maximum usb devices
1346 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1348 DPRINT1("USBHUB: Too many child devices!\n");
1349 Status
= STATUS_UNSUCCESSFUL
;
1350 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1351 UsbChildExtension
->DeviceInterface
.InterfaceDereference(UsbChildExtension
->DeviceInterface
.BusContext
);
1355 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1356 HubDeviceExtension
->InstanceCount
++;
1357 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1359 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1360 return STATUS_SUCCESS
;
1365 // Remove the usb device if it was created
1367 if (UsbChildExtension
->UsbDeviceHandle
)
1368 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1371 // Free full configuration descriptor if one was allocated
1373 if (UsbChildExtension
->FullConfigDesc
)
1374 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1377 // Free ID buffers if they were allocated in CreateDeviceIds()
1379 if (UsbChildExtension
->usCompatibleIds
.Buffer
)
1380 ExFreePool(UsbChildExtension
->usCompatibleIds
.Buffer
);
1382 if (UsbChildExtension
->usDeviceId
.Buffer
)
1383 ExFreePool(UsbChildExtension
->usDeviceId
.Buffer
);
1385 if (UsbChildExtension
->usHardwareIds
.Buffer
)
1386 ExFreePool(UsbChildExtension
->usHardwareIds
.Buffer
);
1388 if (UsbChildExtension
->usInstanceId
.Buffer
)
1389 ExFreePool(UsbChildExtension
->usInstanceId
.Buffer
);
1392 // Delete the device object
1394 IoDeleteDevice(NewChildDeviceObject
);
1399 USBHUB_FdoQueryBusRelations(
1400 IN PDEVICE_OBJECT DeviceObject
,
1401 IN PDEVICE_RELATIONS RelationsFromTop
,
1402 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1404 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1405 PDEVICE_RELATIONS DeviceRelations
;
1407 ULONG ChildrenFromTop
= 0;
1411 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1413 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1416 // Count the number of children
1418 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1421 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1428 if (RelationsFromTop
)
1430 ChildrenFromTop
= RelationsFromTop
->Count
;
1433 // We have nothing to add
1434 *pDeviceRelations
= RelationsFromTop
;
1435 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1436 return STATUS_SUCCESS
;
1440 NeededSize
= sizeof(DEVICE_RELATIONS
) + (Children
+ ChildrenFromTop
- 1) * sizeof(PDEVICE_OBJECT
);
1443 // Allocate DeviceRelations
1445 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1448 if (!DeviceRelations
)
1450 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1451 if (!RelationsFromTop
)
1452 return STATUS_INSUFFICIENT_RESOURCES
;
1454 return STATUS_NOT_SUPPORTED
;
1456 // Copy the objects coming from top
1457 if (ChildrenFromTop
)
1459 RtlCopyMemory(DeviceRelations
->Objects
, RelationsFromTop
->Objects
,
1460 ChildrenFromTop
* sizeof(PDEVICE_OBJECT
));
1463 DeviceRelations
->Count
= Children
+ ChildrenFromTop
;
1464 Children
= ChildrenFromTop
;
1467 // Fill in return structure
1469 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1471 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1473 // The PnP Manager removes the reference when appropriate.
1474 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1475 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1476 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1480 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
1482 // We should do this, because replaced this with our's one
1483 if (RelationsFromTop
)
1484 ExFreePool(RelationsFromTop
);
1486 ASSERT(Children
== DeviceRelations
->Count
);
1487 *pDeviceRelations
= DeviceRelations
;
1489 return STATUS_SUCCESS
;
1494 RootHubInitCallbackFunction(
1497 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1500 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1501 PORT_STATUS_CHANGE StatusChange
;
1503 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1505 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1508 // Send the first SCE Request
1510 QueryStatusChangeEndpoint(DeviceObject
);
1512 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1517 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1518 if (NT_SUCCESS(Status
))
1521 // is there a device connected
1523 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1528 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1529 if (!NT_SUCCESS(Status
))
1531 DPRINT1("Failed to reset on port %d\n", PortId
);
1536 // wait for the reset to be handled since we want to enumerate synchronously
1538 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1543 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
1551 USBHUB_IsRootHubFDO(
1552 IN PDEVICE_OBJECT DeviceObject
)
1555 PDEVICE_OBJECT RootHubPhysicalDeviceObject
= NULL
;
1556 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1558 // get hub device extension
1559 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1561 // Get the Root Hub Pdo
1562 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1563 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1564 &RootHubPhysicalDeviceObject
,
1567 // FIXME handle error
1568 ASSERT(NT_SUCCESS(Status
));
1570 // physical device object is only obtained for root hubs
1571 return (RootHubPhysicalDeviceObject
!= NULL
);
1576 USBHUB_FdoStartDevice(
1577 IN PDEVICE_OBJECT DeviceObject
,
1581 PUSB_INTERFACE_DESCRIPTOR Pid
;
1582 ULONG Result
= 0, PortId
;
1583 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1584 PURB ConfigUrb
= NULL
;
1586 NTSTATUS Status
= STATUS_SUCCESS
;
1587 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1588 PDEVICE_OBJECT RootHubDeviceObject
;
1589 PVOID HubInterfaceBusContext
;
1590 PORT_STATUS_CHANGE StatusChange
;
1592 // get hub device extension
1593 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1595 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1597 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1598 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1602 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1607 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1609 // Get the Root Hub Pdo
1610 Status
= SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1611 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1612 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1613 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1614 if (!NT_SUCCESS(Status
))
1616 // failed to obtain hub pdo
1617 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status
);
1622 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1623 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1626 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1628 // Send the StartDevice to RootHub
1629 Status
= ForwardIrpAndWait(HubDeviceExtension
->LowerDeviceObject
, Irp
);
1631 if (!NT_SUCCESS(Status
))
1633 // failed to start pdo
1634 DPRINT1("Failed to start the RootHub PDO\n");
1638 // Get the current number of hubs
1639 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1640 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1641 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1642 if (!NT_SUCCESS(Status
))
1644 // failed to get number of hubs
1645 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status
);
1649 // Get the Hub Interface
1650 Status
= QueryInterface(RootHubDeviceObject
,
1651 USB_BUS_INTERFACE_HUB_GUID
,
1652 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1653 USB_BUSIF_HUB_VERSION_5
,
1654 (PVOID
)&HubDeviceExtension
->HubInterface
);
1656 if (!NT_SUCCESS(Status
))
1658 // failed to get root hub interface
1659 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1663 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1665 // Get the USBDI Interface
1666 Status
= QueryInterface(RootHubDeviceObject
,
1667 USB_BUS_INTERFACE_USBDI_GUID
,
1668 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1669 USB_BUSIF_USBDI_VERSION_2
,
1670 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1672 if (!NT_SUCCESS(Status
))
1674 // failed to get usbdi interface
1675 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1679 // Get Root Hub Device Handle
1680 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1681 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1682 &HubDeviceExtension
->RootHubHandle
,
1685 if (!NT_SUCCESS(Status
))
1688 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status
);
1693 // Get Hub Device Information
1695 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1696 HubDeviceExtension
->RootHubHandle
,
1697 &HubDeviceExtension
->DeviceInformation
,
1698 sizeof(USB_DEVICE_INFORMATION_0
),
1701 DPRINT("Status %x, Result 0x%08lx\n", Status
, Result
);
1702 DPRINT("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1703 DPRINT("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1704 DPRINT("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1705 DPRINT("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1706 DPRINT("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1707 DPRINT("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1709 // Get Root Hubs Device Descriptor
1710 UsbBuildGetDescriptorRequest(Urb
,
1711 sizeof(Urb
->UrbControlDescriptorRequest
),
1712 USB_DEVICE_DESCRIPTOR_TYPE
,
1715 &HubDeviceExtension
->HubDeviceDescriptor
,
1717 sizeof(USB_DEVICE_DESCRIPTOR
),
1720 // set device handle
1721 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1723 // get hub device descriptor
1724 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1725 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1729 if (!NT_SUCCESS(Status
))
1731 // failed to get device descriptor of hub
1732 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1736 // build configuration request
1737 UsbBuildGetDescriptorRequest(Urb
,
1738 sizeof(Urb
->UrbControlDescriptorRequest
),
1739 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1742 &HubDeviceExtension
->HubConfigDescriptor
,
1744 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1747 // set device handle
1748 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1750 // request configuration descriptor
1751 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1752 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1756 if (!NT_SUCCESS(Status
))
1758 // failed to get configuration descriptor
1759 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1764 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
));
1765 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bDescriptorType
== USB_CONFIGURATION_DESCRIPTOR_TYPE
);
1766 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
1767 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.bNumInterfaces
== 1);
1768 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
1769 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
1770 ASSERT(HubDeviceExtension
->HubInterfaceDescriptor
.bNumEndpoints
== 1);
1771 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1772 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bLength
== sizeof(USB_ENDPOINT_DESCRIPTOR
));
1773 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bmAttributes
== USB_ENDPOINT_TYPE_INTERRUPT
);
1774 ASSERT(HubDeviceExtension
->HubEndPointDescriptor
.bEndpointAddress
== 0x81); // interrupt in
1776 // get hub information
1777 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1778 RootHubDeviceObject
,
1779 &HubDeviceExtension
->UsbExtHubInfo
,
1780 sizeof(USB_EXTHUB_INFORMATION_0
),
1782 if (!NT_SUCCESS(Status
))
1784 // failed to get hub information
1785 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1789 if (!HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
)
1791 // bogus port driver
1792 DPRINT1("Failed to retrieve the number of ports\n");
1793 Status
= STATUS_UNSUCCESSFUL
;
1797 DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1799 // Build hub descriptor request
1800 UsbBuildVendorRequest(Urb
,
1801 URB_FUNCTION_CLASS_DEVICE
,
1802 sizeof(Urb
->UrbControlVendorClassRequest
),
1803 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1805 USB_REQUEST_GET_DESCRIPTOR
,
1806 USB_DEVICE_CLASS_RESERVED
,
1808 &HubDeviceExtension
->HubDescriptor
,
1810 sizeof(USB_HUB_DESCRIPTOR
),
1813 // set device handle
1814 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1817 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1818 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1822 if (!NT_SUCCESS(Status
))
1824 DPRINT1("Failed to get Hub Descriptor!\n");
1825 Status
= STATUS_UNSUCCESSFUL
;
1830 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorLength
== sizeof(USB_HUB_DESCRIPTOR
));
1831 ASSERT(HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
== HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1832 ASSERT(HubDeviceExtension
->HubDescriptor
.bDescriptorType
== 0x29);
1834 // build get status request
1836 UsbBuildGetStatusRequest(Urb
,
1837 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1842 // set device handle
1843 Urb
->UrbHeader
.UsbdDeviceHandle
= HubDeviceExtension
->RootHubHandle
;
1846 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1847 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1850 if (!NT_SUCCESS(Status
))
1852 // failed to get hub status
1853 DPRINT1("Failed to get Hub Status!\n");
1854 Status
= STATUS_UNSUCCESSFUL
;
1858 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1859 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1860 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1863 if (!HubDeviceExtension
->PortStatusChange
)
1865 DPRINT1("Failed to allocate pool for PortStatusChange!\n");
1866 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1870 // Get the first Configuration Descriptor
1871 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1872 &HubDeviceExtension
->HubConfigDescriptor
,
1873 -1, -1, -1, -1, -1);
1876 // failed parse hub descriptor
1877 DPRINT1("Failed to parse configuration descriptor\n");
1878 Status
= STATUS_UNSUCCESSFUL
;
1882 // create configuration request
1883 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1884 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1885 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1886 if (ConfigUrb
== NULL
)
1888 // failed to build urb
1889 DPRINT1("Failed to allocate urb\n");
1890 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1895 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1896 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1899 if (!NT_SUCCESS(Status
))
1901 // failed to select configuration
1902 DPRINT1("Failed to select configuration with %x\n", Status
);
1906 // store configuration & pipe handle
1907 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1908 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1909 DPRINT("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1911 // check if function is available
1912 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1914 // is it high speed bus
1915 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1917 // initialize usb 2.0 hub
1918 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1919 HubDeviceExtension
->RootHubHandle
, 1);
1920 DPRINT("Status %x\n", Status
);
1922 // FIXME handle error
1923 ASSERT(Status
== STATUS_SUCCESS
);
1928 // Enable power on all ports
1929 DPRINT("Enabling PortPower on all ports!\n");
1930 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1932 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1933 if (!NT_SUCCESS(Status
))
1934 DPRINT1("Failed to power on port %d\n", PortId
);
1936 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1937 if (!NT_SUCCESS(Status
))
1938 DPRINT1("Failed to power on port %d\n", PortId
);
1941 // init root hub notification
1942 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1944 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1946 RootHubInitCallbackFunction
);
1947 if (!NT_SUCCESS(Status
))
1949 DPRINT1("Failed to set callback\n");
1955 // Send the first SCE Request
1956 QueryStatusChangeEndpoint(DeviceObject
);
1961 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1966 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1967 if (NT_SUCCESS(Status
))
1970 // is there a device connected
1972 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1977 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1978 if (!NT_SUCCESS(Status
))
1980 DPRINT1("Failed to reset on port %d\n", PortId
);
1985 // wait for the reset to be handled since we want to enumerate synchronously
1987 KeWaitForSingleObject(&HubDeviceExtension
->ResetComplete
,
1992 KeClearEvent(&HubDeviceExtension
->ResetComplete
);
2003 ExFreePool(ConfigUrb
);
2012 // Dereference interfaces
2013 if (HubDeviceExtension
->HubInterface
.Size
)
2014 HubDeviceExtension
->HubInterface
.InterfaceDereference(HubDeviceExtension
->HubInterface
.BusContext
);
2016 if (HubDeviceExtension
->UsbDInterface
.Size
)
2017 HubDeviceExtension
->UsbDInterface
.InterfaceDereference(HubDeviceExtension
->UsbDInterface
.BusContext
);
2019 if (HubDeviceExtension
->PortStatusChange
)
2020 ExFreePool(HubDeviceExtension
->PortStatusChange
);
2023 ExFreePool(ConfigUrb
);
2029 USBHUB_FdoHandlePnp(
2030 IN PDEVICE_OBJECT DeviceObject
,
2033 PIO_STACK_LOCATION Stack
;
2034 NTSTATUS Status
= STATUS_SUCCESS
;
2035 PDEVICE_OBJECT ChildDeviceObject
;
2036 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2037 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
2038 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2040 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2042 HubInterface
= &HubDeviceExtension
->HubInterface
;
2043 Stack
= IoGetCurrentIrpStackLocation(Irp
);
2045 Status
= IoAcquireRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2046 if (!NT_SUCCESS(Status
))
2048 Irp
->IoStatus
.Status
= Status
;
2049 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2053 switch (Stack
->MinorFunction
)
2057 case IRP_MN_START_DEVICE
:
2059 DPRINT("IRP_MN_START_DEVICE\n");
2060 if (USBHUB_IsRootHubFDO(DeviceObject
))
2062 // start root hub fdo
2063 Status
= USBHUB_FdoStartDevice(DeviceObject
, Irp
);
2067 Status
= USBHUB_ParentFDOStartDevice(DeviceObject
, Irp
);
2070 SET_NEW_PNP_STATE(HubDeviceExtension
->Common
, Started
);
2072 Irp
->IoStatus
.Status
= Status
;
2073 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2074 IoReleaseRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2078 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2080 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
2084 PDEVICE_RELATIONS DeviceRelations
= NULL
;
2085 PDEVICE_RELATIONS RelationsFromTop
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
2086 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
2088 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, RelationsFromTop
, &DeviceRelations
);
2090 if (!NT_SUCCESS(Status
))
2092 if (Status
== STATUS_NOT_SUPPORTED
)
2094 // We should process this to not lose relations from top.
2095 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2098 // We should fail an IRP
2099 Irp
->IoStatus
.Status
= Status
;
2100 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2101 IoReleaseRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2105 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
2106 Irp
->IoStatus
.Status
= Status
;
2109 case RemovalRelations
:
2111 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
2115 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
2116 Stack
->Parameters
.QueryDeviceRelations
.Type
);
2121 case IRP_MN_QUERY_STOP_DEVICE
:
2124 // We should fail this request, because we're not handling
2125 // IRP_MN_STOP_DEVICE for now.We'll receive this IRP ONLY when
2126 // PnP manager rebalances resources.
2128 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
2129 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2130 return STATUS_NOT_SUPPORTED
;
2132 case IRP_MN_QUERY_REMOVE_DEVICE
:
2134 // No action is required from FDO because it have nothing to free.
2135 DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
2137 SET_NEW_PNP_STATE(HubDeviceExtension
->Common
, RemovePending
);
2139 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2142 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2144 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
2146 if (HubDeviceExtension
->Common
.PnPState
== RemovePending
)
2147 RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension
->Common
);
2149 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2152 case IRP_MN_SURPRISE_REMOVAL
:
2155 // We'll receive this IRP on HUB unexpected removal, or on USB
2156 // controller removal from PCI port. Here we should "let know" all
2157 // our children that their parent is removed and on next removal
2158 // they also can be removed.
2160 SET_NEW_PNP_STATE(HubDeviceExtension
->Common
, SurpriseRemovePending
);
2162 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2164 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
2166 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[i
];
2167 if (ChildDeviceObject
)
2169 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceObjectExtension
;
2170 ChildDeviceExtension
->ParentDeviceObject
= NULL
;
2174 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2176 // This IRP can't be failed
2177 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2180 case IRP_MN_REMOVE_DEVICE
:
2182 DPRINT("IRP_MN_REMOVE_DEVICE\n");
2184 SET_NEW_PNP_STATE(HubDeviceExtension
->Common
, Deleted
);
2186 IoReleaseRemoveLockAndWait(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2189 // Here we should remove all child PDOs. At this point all children
2190 // received and returned from IRP_MN_REMOVE so remove synchronization
2191 // isn't needed here
2194 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2196 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
2198 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[i
];
2199 if (ChildDeviceObject
)
2201 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
2203 SET_NEW_PNP_STATE(UsbChildExtension
->Common
, Deleted
);
2205 // Remove the usb device
2206 if (UsbChildExtension
->UsbDeviceHandle
)
2208 Status
= HubInterface
->RemoveUsbDevice(HubInterface
->BusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
2209 ASSERT(Status
== STATUS_SUCCESS
);
2212 // Free full configuration descriptor
2213 if (UsbChildExtension
->FullConfigDesc
)
2214 ExFreePool(UsbChildExtension
->FullConfigDesc
);
2217 if (UsbChildExtension
->usCompatibleIds
.Buffer
)
2218 ExFreePool(UsbChildExtension
->usCompatibleIds
.Buffer
);
2220 if (UsbChildExtension
->usDeviceId
.Buffer
)
2221 ExFreePool(UsbChildExtension
->usDeviceId
.Buffer
);
2223 if (UsbChildExtension
->usHardwareIds
.Buffer
)
2224 ExFreePool(UsbChildExtension
->usHardwareIds
.Buffer
);
2226 if (UsbChildExtension
->usInstanceId
.Buffer
)
2227 ExFreePool(UsbChildExtension
->usInstanceId
.Buffer
);
2229 DPRINT("Deleting child PDO\n");
2230 IoDeleteDevice(DeviceObject
);
2231 ChildDeviceObject
= NULL
;
2235 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2237 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2238 Status
= ForwardIrpAndForget(DeviceObject
, Irp
);
2240 IoDetachDevice(HubDeviceExtension
->LowerDeviceObject
);
2241 DPRINT("Deleting FDO 0x%p\n", DeviceObject
);
2242 IoDeleteDevice(DeviceObject
);
2246 case IRP_MN_QUERY_BUS_INFORMATION
:
2248 // Function drivers and filter drivers do not handle this IRP.
2249 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2252 case IRP_MN_QUERY_ID
:
2254 DPRINT("IRP_MN_QUERY_ID\n");
2255 // Function drivers and filter drivers do not handle this IRP.
2258 case IRP_MN_QUERY_CAPABILITIES
:
2261 // If a function or filter driver does not handle this IRP, it
2262 // should pass that down.
2264 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2269 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
2274 Status
= ForwardIrpAndForget(DeviceObject
, Irp
);
2275 IoReleaseRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2280 USBHUB_FdoHandleDeviceControl(
2281 IN PDEVICE_OBJECT DeviceObject
,
2284 PIO_STACK_LOCATION IoStack
;
2285 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
2286 PUSB_NODE_INFORMATION NodeInformation
;
2287 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
2288 PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo
;
2289 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
2290 PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey
;
2291 PUSB_NODE_CONNECTION_NAME ConnectionName
;
2292 ULONG Index
, Length
;
2294 // get stack location
2295 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2297 // get device extension
2298 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
2300 Status
= IoAcquireRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2301 if (!NT_SUCCESS(Status
))
2303 Irp
->IoStatus
.Status
= Status
;
2304 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2308 // Prevent handling of control requests in remove pending state
2309 if (HubDeviceExtension
->Common
.PnPState
== RemovePending
)
2311 DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject
);
2312 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_CONNECTED
;
2313 Irp
->IoStatus
.Information
= 0;
2314 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2315 IoReleaseRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);
2316 return STATUS_DEVICE_NOT_CONNECTED
;
2319 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_INFORMATION
)
2321 // is the buffer big enough
2322 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_INFORMATION
))
2325 Status
= STATUS_BUFFER_TOO_SMALL
;
2330 NodeInformation
= (PUSB_NODE_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2333 ASSERT(NodeInformation
);
2336 NodeInformation
->NodeType
= UsbHub
;
2337 RtlCopyMemory(&NodeInformation
->u
.HubInformation
.HubDescriptor
, &HubDeviceExtension
->HubDescriptor
, sizeof(USB_HUB_DESCRIPTOR
));
2339 // FIXME is hub powered
2340 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= TRUE
;
2343 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2344 Status
= STATUS_SUCCESS
;
2349 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
)
2351 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2354 Status
= STATUS_BUFFER_TOO_SMALL
;
2358 // get node connection info
2359 NodeConnectionInfo
= (PUSB_NODE_CONNECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
2362 ASSERT(NodeConnectionInfo
);
2364 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2365 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2367 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2370 // get child device extension
2371 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2373 if (ChildDeviceExtension
->PortNumber
!= NodeConnectionInfo
->ConnectionIndex
)
2376 // init node connection info
2377 RtlCopyMemory(&NodeConnectionInfo
->DeviceDescriptor
, &ChildDeviceExtension
->DeviceDesc
, sizeof(USB_DEVICE_DESCRIPTOR
));
2378 NodeConnectionInfo
->CurrentConfigurationValue
= ChildDeviceExtension
->FullConfigDesc
->bConfigurationValue
;
2379 NodeConnectionInfo
->DeviceIsHub
= FALSE
; //FIXME support hubs
2380 NodeConnectionInfo
->LowSpeed
= ChildDeviceExtension
->DeviceInformation
.DeviceSpeed
== UsbLowSpeed
;
2381 NodeConnectionInfo
->DeviceAddress
= ChildDeviceExtension
->DeviceInformation
.DeviceAddress
;
2382 NodeConnectionInfo
->NumberOfOpenPipes
= ChildDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
;
2383 NodeConnectionInfo
->ConnectionStatus
= DeviceConnected
; //FIXME
2385 if (NodeConnectionInfo
->NumberOfOpenPipes
)
2387 DPRINT1("Need to copy pipe information\n");
2391 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2393 Irp
->IoStatus
.Information
= sizeof(USB_NODE_INFORMATION
);
2394 Status
= STATUS_SUCCESS
;
2397 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
)
2399 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
2402 Status
= STATUS_BUFFER_TOO_SMALL
;
2406 // get node connection info
2407 NodeKey
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2412 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2413 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
2415 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == NULL
)
2418 // get child device extension
2419 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
2421 if (ChildDeviceExtension
->PortNumber
!= NodeKey
->ConnectionIndex
)
2425 Status
= IoGetDeviceProperty(HubDeviceExtension
->ChildDeviceObject
[Index
], DevicePropertyDriverKeyName
,
2426 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
),
2427 NodeKey
->DriverKeyName
,
2430 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2433 Status
= STATUS_SUCCESS
;
2436 if (Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
2438 // terminate node key name
2439 NodeKey
->DriverKeyName
[0] = UNICODE_NULL
;
2440 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2445 Irp
->IoStatus
.Information
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2448 // length of driver name
2449 NodeKey
->ActualLength
= Length
+ sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
);
2452 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
2455 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_NODE_CONNECTION_NAME
)
2457 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(USB_NODE_CONNECTION_NAME
))
2460 Status
= STATUS_BUFFER_TOO_SMALL
;
2464 // FIXME support hubs
2465 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
2466 ConnectionName
->ActualLength
= 0;
2467 ConnectionName
->NodeName
[0] = UNICODE_NULL
;
2470 Irp
->IoStatus
.Information
= sizeof(USB_NODE_CONNECTION_NAME
);
2471 Status
= STATUS_SUCCESS
;
2476 DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2477 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
2481 Irp
->IoStatus
.Status
= Status
;
2482 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2484 IoReleaseRemoveLock(&HubDeviceExtension
->Common
.RemoveLock
, Irp
);