2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 QueryStatusChangeEndpoint(
16 IN PDEVICE_OBJECT DeviceObject
);
19 CreateUsbChildDeviceObject(
20 IN PDEVICE_OBJECT UsbHubDeviceObject
,
22 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
);
25 DestroyUsbChildDeviceObject(
26 IN PDEVICE_OBJECT UsbHubDeviceObject
,
30 SubmitRequestToRootHub(
31 IN PDEVICE_OBJECT RootHubDeviceObject
,
32 IN ULONG IoControlCode
,
33 OUT PVOID OutParameter1
,
34 OUT PVOID OutParameter2
)
38 IO_STATUS_BLOCK IoStatus
;
40 PIO_STACK_LOCATION Stack
= NULL
;
42 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
45 // Build Control Request
47 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
57 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
58 return STATUS_INSUFFICIENT_RESOURCES
;
62 // Initialize the status block before sending the IRP
64 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
65 IoStatus
.Information
= 0;
68 // Get Next Stack Location and Initialize it
70 Stack
= IoGetNextIrpStackLocation(Irp
);
71 Stack
->Parameters
.Others
.Argument1
= OutParameter1
;
72 Stack
->Parameters
.Others
.Argument2
= OutParameter2
;
77 Status
= IoCallDriver(RootHubDeviceObject
, Irp
);
80 // Its ok to block here as this function is called in an nonarbitrary thread
82 if (Status
== STATUS_PENDING
)
84 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
85 Status
= IoStatus
.Status
;
89 // The IO Manager will free the IRP
96 GetPortStatusAndChange(
97 IN PDEVICE_OBJECT RootHubDeviceObject
,
99 OUT PPORT_STATUS_CHANGE StatusChange
)
107 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
110 DPRINT1("Failed to allocate memory for URB!\n");
111 return STATUS_INSUFFICIENT_RESOURCES
;
117 RtlZeroMemory(Urb
, sizeof(URB
));
120 // Initialize URB for getting Port Status
122 UsbBuildVendorRequest(Urb
,
123 URB_FUNCTION_CLASS_OTHER
,
124 sizeof(Urb
->UrbControlVendorClassRequest
),
125 USBD_TRANSFER_DIRECTION_OUT
,
127 USB_REQUEST_GET_STATUS
,
132 sizeof(PORT_STATUS_CHANGE
),
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_SET_FEATURE
,
188 // Query the Root Hub
190 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
202 IN PDEVICE_OBJECT RootHubDeviceObject
,
212 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
215 DPRINT1("Failed to allocate memory for URB!\n");
216 return STATUS_INSUFFICIENT_RESOURCES
;
222 RtlZeroMemory(Urb
, sizeof(URB
));
225 // Initialize URB for Clearing Port Reset
227 UsbBuildVendorRequest(Urb
,
228 URB_FUNCTION_CLASS_OTHER
,
229 sizeof(Urb
->UrbControlVendorClassRequest
),
230 USBD_TRANSFER_DIRECTION_IN
,
232 USB_REQUEST_CLEAR_FEATURE
,
240 // Query the Root Hub
242 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
253 DeviceStatusChangeThread(
257 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
258 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
259 PWORK_ITEM_DATA WorkItemData
;
260 PORT_STATUS_CHANGE PortStatus
;
263 static LONG failsafe
= 0;
265 DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context
);
267 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
268 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
269 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
270 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
274 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
279 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
280 if (!NT_SUCCESS(Status
))
282 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
283 // FIXME: Do we really want to halt further SCE requests?
287 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
288 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
292 // Check for new device connection
294 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
297 // Clear Port Connect
299 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
300 if (!NT_SUCCESS(Status
))
302 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
306 // Is this a connect or disconnect?
308 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
310 DPRINT1("Device disconnected from port %d\n", PortId
);
312 Status
= DestroyUsbChildDeviceObject(DeviceObject
, PortId
);
313 if (!NT_SUCCESS(Status
))
315 DPRINT1("Failed to delete child device object after disconnect\n");
320 DPRINT1("Device connected from port %d\n", PortId
);
322 // No SCE completion done for clearing C_PORT_CONNECT
327 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
328 if (!NT_SUCCESS(Status
))
330 DPRINT1("Failed to reset port %d\n", PortId
);
334 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
339 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
340 if (!NT_SUCCESS(Status
))
342 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
345 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
350 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
351 if (!NT_SUCCESS(Status
))
353 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
359 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
360 if (!NT_SUCCESS(Status
))
362 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
363 // FIXME: Do we really want to halt further SCE requests?
367 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
368 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
371 // Check that reset was cleared
373 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
375 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
379 // Check if the device is still connected
381 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
383 DPRINT1("Device has been disconnected\n");
388 // Make sure its Connected and Enabled
390 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
392 DPRINT1("Usb Device is not connected and enabled!\n");
394 // Attempt another reset
396 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("Failed to reset port %d\n", PortId
);
405 // This is a new device
407 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
);
412 // FIXME: Still in testing
417 DPRINT1("SCE completed over 100 times but no action has been taken to clear the Change of any ports.\n");
419 // Return and dont send any more SCE Requests
424 ExFreePool(WorkItemData
);
427 // Send another SCE Request
429 DPRINT1("Sending another SCE!\n");
430 QueryStatusChangeEndpoint(DeviceObject
);
435 StatusChangeEndpointCompletion(
436 IN PDEVICE_OBJECT DeviceObject
,
440 PDEVICE_OBJECT RealDeviceObject
;
441 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
442 PWORK_ITEM_DATA WorkItemData
;
444 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
445 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
448 // NOTE: USBPORT frees this IRP
450 DPRINT1("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
454 // Create and initialize work item data
456 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
459 DPRINT1("Failed to allocate memory!n");
460 return STATUS_INSUFFICIENT_RESOURCES
;
462 WorkItemData
->Context
= RealDeviceObject
;
463 DPRINT1("Initialize work item\n");
464 ExInitializeWorkItem(&WorkItemData
->WorkItem
, DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
467 // Queue the work item to handle initializing the device
469 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
472 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
474 return STATUS_MORE_PROCESSING_REQUIRED
;
478 QueryStatusChangeEndpoint(
479 IN PDEVICE_OBJECT DeviceObject
)
482 PDEVICE_OBJECT RootHubDeviceObject
;
483 PIO_STACK_LOCATION Stack
;
484 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
487 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
488 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
493 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
496 // Initialize URB for Status Change Endpoint request
498 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
499 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
500 HubDeviceExtension
->PipeHandle
,
501 HubDeviceExtension
->PortStatusChange
,
503 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
504 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
508 // Set the device handle to null for roothub
510 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
516 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
517 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
520 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
523 DPRINT1("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
525 if (!HubDeviceExtension
->PendingSCEIrp
)
527 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
528 return STATUS_INSUFFICIENT_RESOURCES
;
532 // Initialize the IRP
534 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
535 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
536 RootHubDeviceObject
->StackSize
);
538 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
539 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
540 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
541 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
544 // Get the Next Stack Location and Initialize it
546 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
547 Stack
->DeviceObject
= DeviceObject
;
548 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
549 Stack
->Parameters
.Others
.Argument2
= NULL
;
550 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
551 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
554 // Set the completion routine for when device is connected to root hub
556 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
557 StatusChangeEndpointCompletion
,
566 DPRINT1("DeviceObject is %x\n", DeviceObject
);
567 DPRINT1("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
568 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
570 return STATUS_PENDING
;
575 IN PDEVICE_OBJECT DeviceObject
,
576 IN CONST GUID InterfaceType
,
583 IO_STATUS_BLOCK IoStatus
;
585 PIO_STACK_LOCATION Stack
= NULL
;
588 // Initialize the Event used to wait for Irp completion
590 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
593 // Build Control Request
595 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
604 // Get Next Stack Location and Initialize it.
606 Stack
= IoGetNextIrpStackLocation(Irp
);
607 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
608 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
609 Stack
->Parameters
.QueryInterface
.Size
= Size
;
610 Stack
->Parameters
.QueryInterface
.Version
= Version
;
611 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
612 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
614 Status
= IoCallDriver(DeviceObject
, Irp
);
616 if (Status
== STATUS_PENDING
)
618 DPRINT("Operation pending\n");
619 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
620 Status
= IoStatus
.Status
;
627 GetUsbDeviceDescriptor(
628 IN PDEVICE_OBJECT ChildDeviceObject
,
629 IN UCHAR DescriptorType
,
632 OUT PVOID TransferBuffer
,
633 IN ULONG TransferBufferLength
)
636 PDEVICE_OBJECT RootHubDeviceObject
;
638 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
639 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
642 // Get the Hubs Device Extension
644 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
645 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
646 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
651 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
654 DPRINT1("Failed to allocate memory for URB!\n");
655 return STATUS_INSUFFICIENT_RESOURCES
;
661 RtlZeroMemory(Urb
, sizeof(URB
));
664 // Initialize URB for getting device descriptor
666 UsbBuildGetDescriptorRequest(Urb
,
667 sizeof(Urb
->UrbControlDescriptorRequest
),
673 TransferBufferLength
,
677 // Set the device handle
679 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
682 // Query the Root Hub
684 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
685 IOCTL_INTERNAL_USB_SUBMIT_URB
,
693 GetUsbStringDescriptor(
694 IN PDEVICE_OBJECT ChildDeviceObject
,
697 OUT PVOID
*TransferBuffer
,
701 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
704 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
705 sizeof(USB_STRING_DESCRIPTOR
),
709 DPRINT1("Failed to allocate buffer for string!\n");
710 return STATUS_INSUFFICIENT_RESOURCES
;
714 // Get the index string descriptor length
715 // FIXME: Implement LangIds
717 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
718 USB_STRING_DESCRIPTOR_TYPE
,
722 sizeof(USB_STRING_DESCRIPTOR
));
723 if (!NT_SUCCESS(Status
))
725 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
726 ExFreePool(StringDesc
);
729 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
732 // Did we get something more than the length of the first two fields of structure?
734 if (StringDesc
->bLength
== 2)
736 DPRINT1("USB Device Error!\n");
737 ExFreePool(StringDesc
);
738 return STATUS_DEVICE_DATA_ERROR
;
740 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
745 ExFreePool(StringDesc
);
748 // Recreate with appropriate size
750 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
755 DPRINT1("Failed to allocate buffer for string!\n");
756 return STATUS_INSUFFICIENT_RESOURCES
;
759 RtlZeroMemory(StringDesc
, SizeNeeded
);
764 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
765 USB_STRING_DESCRIPTOR_TYPE
,
770 if (!NT_SUCCESS(Status
))
772 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status
);
773 ExFreePool(StringDesc
);
778 // Allocate Buffer to return
780 *TransferBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
783 if (!*TransferBuffer
)
785 DPRINT1("Failed to allocate buffer for string!\n");
786 ExFreePool(StringDesc
);
787 return STATUS_INSUFFICIENT_RESOURCES
;
790 RtlZeroMemory(*TransferBuffer
, SizeNeeded
);
793 // Copy the string to destination
795 RtlCopyMemory(*TransferBuffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
798 ExFreePool(StringDesc
);
800 return STATUS_SUCCESS
;
805 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
,
806 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
808 if (DeviceDescriptor
->bNumConfigurations
!= 1)
811 // composite device must have only one configuration
816 if (ConfigurationDescriptor
->bNumInterfaces
< 2)
819 // composite device must have multiple interfaces
824 if (DeviceDescriptor
->bDeviceClass
== 0)
829 ASSERT(DeviceDescriptor
->bDeviceSubClass
== 0);
830 ASSERT(DeviceDescriptor
->bDeviceProtocol
== 0);
834 if (DeviceDescriptor
->bDeviceClass
== 0xEF &&
835 DeviceDescriptor
->bDeviceSubClass
== 0x02 &&
836 DeviceDescriptor
->bDeviceProtocol
== 0x01)
839 // USB-IF association descriptor
845 // not a composite device
852 PDEVICE_OBJECT UsbChildDeviceObject
)
854 NTSTATUS Status
= STATUS_SUCCESS
;
858 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
859 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
860 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
861 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
864 // get child device extension
866 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)UsbChildDeviceObject
->DeviceExtension
;
869 // Initialize the CompatibleIds String
871 UsbChildExtension
->usCompatibleIds
.Length
= 188; //FIXME
872 UsbChildExtension
->usCompatibleIds
.MaximumLength
= UsbChildExtension
->usCompatibleIds
.Length
;
875 // allocate mem for compatible id string
877 BufferPtr
= ExAllocatePoolWithTag(NonPagedPool
,
878 UsbChildExtension
->usCompatibleIds
.Length
,
882 DPRINT1("Failed to allocate memory\n");
883 return STATUS_INSUFFICIENT_RESOURCES
;
886 RtlZeroMemory(BufferPtr
, UsbChildExtension
->usCompatibleIds
.Length
);
890 // get device descriptor
892 DeviceDescriptor
= &UsbChildExtension
->DeviceDesc
;
895 // get configuration descriptor
897 ConfigurationDescriptor
= UsbChildExtension
->FullConfigDesc
;
900 // get interface descriptor
902 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)(ConfigurationDescriptor
+ 1);
905 // Construct the CompatibleIds
907 if (IsCompositeDevice(DeviceDescriptor
, ConfigurationDescriptor
))
912 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
913 ASSERT(ConfigurationDescriptor
->bNumInterfaces
> 1);
915 Index
+= swprintf(&BufferPtr
[Index
],
916 L
"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
917 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
918 Index
+= swprintf(&BufferPtr
[Index
],
919 L
"USB\\DevClass_%02x&SubClass_%02x",
920 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
921 Index
+= swprintf(&BufferPtr
[Index
],
922 L
"USB\\DevClass_%02x",
923 DeviceDescriptor
->bDeviceClass
) + 1;
924 Index
+= swprintf(&BufferPtr
[Index
],
925 L
"USB\\COMPOSITE") + 1;
930 // sanity checks for simple usb device
932 ASSERT(ConfigurationDescriptor
->bNumInterfaces
== 1);
935 // FIXME: support multiple configurations
937 ASSERT(DeviceDescriptor
->bNumConfigurations
== 1);
939 if (DeviceDescriptor
->bDeviceClass
== 0)
941 Index
+= swprintf(&BufferPtr
[Index
],
942 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
943 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
, InterfaceDescriptor
->bInterfaceProtocol
) + 1;
944 Index
+= swprintf(&BufferPtr
[Index
],
945 L
"USB\\Class_%02x&SubClass_%02x",
946 InterfaceDescriptor
->bInterfaceClass
, InterfaceDescriptor
->bInterfaceSubClass
) + 1;
947 Index
+= swprintf(&BufferPtr
[Index
],
949 InterfaceDescriptor
->bInterfaceClass
) + 1;
953 Index
+= swprintf(&BufferPtr
[Index
],
954 L
"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
955 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
, DeviceDescriptor
->bDeviceProtocol
) + 1;
956 Index
+= swprintf(&BufferPtr
[Index
],
957 L
"USB\\Class_%02x&SubClass_%02x",
958 DeviceDescriptor
->bDeviceClass
, DeviceDescriptor
->bDeviceSubClass
) + 1;
959 Index
+= swprintf(&BufferPtr
[Index
],
961 DeviceDescriptor
->bDeviceClass
) + 1;
967 BufferPtr
[Index
] = UNICODE_NULL
;
968 UsbChildExtension
->usCompatibleIds
.Buffer
= BufferPtr
;
969 DPRINT1("usCompatibleIds %wZ\n", &UsbChildExtension
->usCompatibleIds
);
972 // Initialize the DeviceId String
974 UsbChildExtension
->usDeviceId
.Length
= 44;
975 UsbChildExtension
->usDeviceId
.MaximumLength
= UsbChildExtension
->usDeviceId
.Length
;
976 BufferPtr
= ExAllocatePoolWithTag(NonPagedPool
,
977 UsbChildExtension
->usDeviceId
.Length
,
981 DPRINT1("Failed to allocate memory\n");
982 Status
= STATUS_INSUFFICIENT_RESOURCES
;
987 // Construct DeviceId
989 swprintf(BufferPtr
, L
"USB\\Vid_%04x&Pid_%04x\0", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
);
990 UsbChildExtension
->usDeviceId
.Buffer
= BufferPtr
;
991 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension
->usDeviceId
);
994 // Initialize the HardwareId String
996 UsbChildExtension
->usHardwareIds
.Length
= 110;
997 UsbChildExtension
->usHardwareIds
.MaximumLength
= UsbChildExtension
->usHardwareIds
.Length
;
998 BufferPtr
= ExAllocatePoolWithTag(NonPagedPool
, UsbChildExtension
->usHardwareIds
.Length
, USB_HUB_TAG
);
1001 DPRINT1("Failed to allocate memory\n");
1002 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1006 RtlZeroMemory(BufferPtr
, UsbChildExtension
->usHardwareIds
.Length
);
1009 // Consturct HardwareIds
1012 Index
+= swprintf(&BufferPtr
[Index
],
1013 L
"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
1014 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
, UsbChildExtension
->DeviceDesc
.bcdDevice
) + 1;
1015 Index
+= swprintf(&BufferPtr
[Index
],
1016 L
"USB\\Vid_%04x&Pid_%04x",
1017 UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
) + 1;
1018 BufferPtr
[Index
] = UNICODE_NULL
;
1019 UsbChildExtension
->usHardwareIds
.Buffer
= BufferPtr
;
1020 DPRINT1("usHardWareIds %wZ\n", &UsbChildExtension
->usHardwareIds
);
1023 // FIXME: Handle Lang ids
1027 // Get the product string if obe provided
1029 if (UsbChildExtension
->DeviceDesc
.iProduct
)
1031 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1032 UsbChildExtension
->DeviceDesc
.iProduct
,
1034 (PVOID
*)&UsbChildExtension
->usTextDescription
.Buffer
,
1035 &UsbChildExtension
->usTextDescription
.Length
);
1036 if (!NT_SUCCESS(Status
))
1038 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1042 UsbChildExtension
->usTextDescription
.MaximumLength
= UsbChildExtension
->usTextDescription
.Length
;
1043 DPRINT1("Usb TextDescription %wZ\n", &UsbChildExtension
->usTextDescription
);
1047 // Get the Serial Number string if obe provided
1049 if (UsbChildExtension
->DeviceDesc
.iSerialNumber
)
1051 Status
= GetUsbStringDescriptor(UsbChildDeviceObject
,
1052 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
1054 (PVOID
*)&UsbChildExtension
->usInstanceId
.Buffer
,
1055 &UsbChildExtension
->usInstanceId
.Length
);
1056 if (!NT_SUCCESS(Status
))
1058 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
1062 UsbChildExtension
->usInstanceId
.MaximumLength
= UsbChildExtension
->usInstanceId
.Length
;
1063 DPRINT1("Usb InstanceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1068 // the device did not provide a serial number, lets create a pseudo instance id
1070 Index
= swprintf(Buffer
, L
"0&%04d", UsbChildExtension
->PortNumber
) + 1;
1071 UsbChildExtension
->usInstanceId
.Buffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, Index
* sizeof(WCHAR
));
1072 if (UsbChildExtension
->usInstanceId
.Buffer
== NULL
)
1074 DPRINT1("Error: failed to allocate %lu bytes\n", Index
* sizeof(WCHAR
));
1075 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1082 RtlCopyMemory(UsbChildExtension
->usInstanceId
.Buffer
, Buffer
, Index
* sizeof(WCHAR
));
1083 UsbChildExtension
->usInstanceId
.Length
= UsbChildExtension
->usDeviceId
.MaximumLength
= Index
* sizeof(WCHAR
);
1085 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension
->usInstanceId
);
1095 if (UsbChildExtension
->usCompatibleIds
.Buffer
)
1096 ExFreePool(UsbChildExtension
->usCompatibleIds
.Buffer
);
1097 if (UsbChildExtension
->usDeviceId
.Buffer
)
1098 ExFreePool(UsbChildExtension
->usDeviceId
.Buffer
);
1099 if (UsbChildExtension
->usHardwareIds
.Buffer
)
1100 ExFreePool(UsbChildExtension
->usHardwareIds
.Buffer
);
1101 if (UsbChildExtension
->usTextDescription
.Buffer
)
1102 ExFreePool(UsbChildExtension
->usTextDescription
.Buffer
);
1103 if (UsbChildExtension
->usInstanceId
.Buffer
)
1104 ExFreePool(UsbChildExtension
->usInstanceId
.Buffer
);
1110 DestroyUsbChildDeviceObject(
1111 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1114 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbHubDeviceObject
->DeviceExtension
;
1115 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
= NULL
;
1116 PDEVICE_OBJECT ChildDeviceObject
= NULL
;
1119 DPRINT1("Removing device on port %d (Child index: %d)\n", PortId
, Index
);
1121 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
1123 if (HubDeviceExtension
->ChildDeviceObject
[Index
])
1125 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)HubDeviceExtension
->ChildDeviceObject
[Index
]->DeviceExtension
;
1127 /* Check if it matches the port ID */
1128 if (UsbChildExtension
->PortNumber
== PortId
)
1131 ChildDeviceObject
= HubDeviceExtension
->ChildDeviceObject
[Index
];
1137 /* Fail the request if the device doesn't exist */
1138 if (!ChildDeviceObject
)
1140 DPRINT1("Removal request for non-existant device!\n");
1141 return STATUS_UNSUCCESSFUL
;
1144 /* Remove the device from the table */
1145 HubDeviceExtension
->ChildDeviceObject
[Index
] = NULL
;
1147 /* Invalidate device relations for the root hub */
1148 IoInvalidateDeviceRelations(HubDeviceExtension
->RootHubPhysicalDeviceObject
, BusRelations
);
1150 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1151 return STATUS_SUCCESS
;
1155 CreateUsbChildDeviceObject(
1156 IN PDEVICE_OBJECT UsbHubDeviceObject
,
1158 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
)
1161 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
1162 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1163 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
1164 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
1165 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
1166 WCHAR CharDeviceName
[64];
1167 UNICODE_STRING DeviceName
;
1168 ULONG ConfigDescSize
, DeviceDescSize
;
1169 PVOID HubInterfaceBusContext
;
1170 USB_CONFIGURATION_DESCRIPTOR ConfigDesc
;
1172 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
1173 HubInterface
= &HubDeviceExtension
->HubInterface
;
1174 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1175 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1177 // Find an empty slot in the child device array
1179 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
1181 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
1183 DPRINT1("Found unused entry at %d\n", ChildDeviceCount
);
1189 // Check if the limit has been reached for maximum usb devices
1191 if (ChildDeviceCount
== USB_MAXCHILDREN
)
1193 DPRINT1("USBHUB: Too many child devices!\n");
1194 return STATUS_UNSUCCESSFUL
;
1200 // Create a Device Name
1202 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
1205 // Initialize UnicodeString
1207 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
1210 // Create a DeviceObject
1212 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
1213 sizeof(HUB_CHILDDEVICE_EXTENSION
),
1215 FILE_DEVICE_CONTROLLER
,
1216 FILE_AUTOGENERATED_DEVICE_NAME
,
1218 &NewChildDeviceObject
);
1221 // Check if the name is already in use
1223 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
1233 // Check for other errors
1235 if (!NT_SUCCESS(Status
))
1237 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
1241 DPRINT1("USBHUB: Created Device %x\n", NewChildDeviceObject
);
1245 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1248 // Assign the device extensions
1250 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
1251 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
1252 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
1253 UsbChildExtension
->PortNumber
= PortId
;
1256 // Create the UsbDeviceObject
1258 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
1259 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
1260 HubDeviceExtension
->RootHubHandle
,
1263 if (!NT_SUCCESS(Status
))
1265 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
1270 // Initialize UsbDevice
1272 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
1273 if (!NT_SUCCESS(Status
))
1275 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
1279 DPRINT1("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
1281 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
1282 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
1285 // Get the descriptors
1287 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
1288 UsbChildExtension
->UsbDeviceHandle
,
1289 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
1291 (PUCHAR
)&ConfigDesc
,
1293 if (!NT_SUCCESS(Status
))
1295 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
1299 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
1300 DumpConfigurationDescriptor(&ConfigDesc
);
1303 // FIXME: Support more than one configuration and one interface?
1305 if (UsbChildExtension
->DeviceDesc
.bNumConfigurations
> 1)
1307 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1310 if (ConfigDesc
.bNumInterfaces
> 1)
1312 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1315 ConfigDescSize
= ConfigDesc
.wTotalLength
;
1318 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1320 UsbChildExtension
->FullConfigDesc
= ExAllocatePoolWithTag(PagedPool
, ConfigDescSize
, USB_HUB_TAG
);
1323 // Retrieve the full configuration descriptor
1325 Status
= GetUsbDeviceDescriptor(NewChildDeviceObject
,
1326 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1329 UsbChildExtension
->FullConfigDesc
,
1332 if (!NT_SUCCESS(Status
))
1334 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status
);
1338 DumpFullConfigurationDescriptor(UsbChildExtension
->FullConfigDesc
);
1341 // Construct all the strings that will described the device to PNP
1343 Status
= CreateDeviceIds(NewChildDeviceObject
);
1344 if (!NT_SUCCESS(Status
))
1346 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1350 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
1352 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
1353 return STATUS_SUCCESS
;
1358 // Remove the usb device if it was created
1360 if (UsbChildExtension
->UsbDeviceHandle
)
1361 HubInterface
->RemoveUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
1364 // Free full configuration descriptor if one was allocated
1366 if (UsbChildExtension
->FullConfigDesc
)
1367 ExFreePool(UsbChildExtension
->FullConfigDesc
);
1370 // Delete the device object
1372 IoDeleteDevice(NewChildDeviceObject
);
1377 USBHUB_FdoQueryBusRelations(
1378 IN PDEVICE_OBJECT DeviceObject
,
1379 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
1381 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1382 PDEVICE_RELATIONS DeviceRelations
;
1387 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1390 // Count the number of children
1392 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1395 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
1402 NeededSize
= sizeof(DEVICE_RELATIONS
);
1404 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1407 // Allocate DeviceRelations
1409 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1412 if (!DeviceRelations
)
1413 return STATUS_INSUFFICIENT_RESOURCES
;
1414 DeviceRelations
->Count
= Children
;
1418 // Fill in return structure
1420 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1422 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1424 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1425 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1426 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1430 ASSERT(Children
== DeviceRelations
->Count
);
1431 *pDeviceRelations
= DeviceRelations
;
1433 return STATUS_SUCCESS
;
1438 RootHubInitCallbackFunction(
1441 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1444 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1445 PORT_STATUS_CHANGE StatusChange
;
1447 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1449 DPRINT1("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject
);
1451 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1456 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1457 if (NT_SUCCESS(Status
))
1460 // is there a device connected
1462 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1467 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1468 if (!NT_SUCCESS(Status
))
1469 DPRINT1("Failed to reset on port %d\n", PortId
);
1475 // Send the first SCE Request
1477 QueryStatusChangeEndpoint(DeviceObject
);
1481 USBHUB_FdoHandlePnp(
1482 IN PDEVICE_OBJECT DeviceObject
,
1485 PIO_STACK_LOCATION Stack
;
1486 NTSTATUS Status
= STATUS_SUCCESS
;
1487 ULONG_PTR Information
= 0;
1488 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1489 PDEVICE_OBJECT RootHubDeviceObject
;
1490 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1491 PORT_STATUS_CHANGE StatusChange
;
1493 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1495 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1497 switch (Stack
->MinorFunction
)
1499 case IRP_MN_START_DEVICE
:
1502 PUSB_INTERFACE_DESCRIPTOR Pid
;
1503 ULONG Result
= 0, PortId
;
1504 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1505 PURB ConfigUrb
= NULL
;
1508 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1511 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1513 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1514 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1517 // Get the Root Hub Pdo
1519 SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1520 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1521 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1522 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1524 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1525 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1526 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1527 DPRINT1("RootPdo %x, RootFdo %x\n",
1528 HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1529 HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1532 // Send the StartDevice to RootHub
1534 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1536 if (!NT_SUCCESS(Status
))
1538 DPRINT1("Failed to start the RootHub PDO\n");
1543 // Get the current number of hubs
1545 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1546 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1547 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1550 // Get the Hub Interface
1552 Status
= QueryInterface(RootHubDeviceObject
,
1553 USB_BUS_INTERFACE_HUB_GUID
,
1554 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1556 (PVOID
)&HubDeviceExtension
->HubInterface
);
1558 if (!NT_SUCCESS(Status
))
1560 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1561 return STATUS_UNSUCCESSFUL
;
1564 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1567 // Get the USBDI Interface
1569 Status
= QueryInterface(RootHubDeviceObject
,
1570 USB_BUS_INTERFACE_USBDI_GUID
,
1571 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1573 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1575 if (!NT_SUCCESS(Status
))
1577 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1581 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1584 // Get Root Hub Device Handle
1586 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1587 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1588 &HubDeviceExtension
->RootHubHandle
,
1591 if (!NT_SUCCESS(Status
))
1593 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status
);
1598 // Get Hub Device Information
1600 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1601 HubDeviceExtension
->RootHubHandle
,
1602 &HubDeviceExtension
->DeviceInformation
,
1603 sizeof(USB_DEVICE_INFORMATION_0
),
1606 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1607 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1608 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1609 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1610 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1611 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1612 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1615 // Get Root Hubs Device Descriptor
1617 UsbBuildGetDescriptorRequest(Urb
,
1618 sizeof(Urb
->UrbControlDescriptorRequest
),
1619 USB_DEVICE_DESCRIPTOR_TYPE
,
1622 &HubDeviceExtension
->HubDeviceDescriptor
,
1624 sizeof(USB_DEVICE_DESCRIPTOR
),
1627 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1629 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1630 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1634 if (!NT_SUCCESS(Status
))
1636 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1639 DumpDeviceDescriptor(&HubDeviceExtension
->HubDeviceDescriptor
);
1642 // Get Root Hubs Configuration Descriptor
1644 UsbBuildGetDescriptorRequest(Urb
,
1645 sizeof(Urb
->UrbControlDescriptorRequest
),
1646 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1649 &HubDeviceExtension
->HubConfigDescriptor
,
1651 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1654 DPRINT1("RootHub Handle %x\n", HubDeviceExtension
->RootHubHandle
);
1655 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1657 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1658 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1662 if (!NT_SUCCESS(Status
))
1664 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1667 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
);
1669 DumpConfigurationDescriptor(&HubDeviceExtension
->HubConfigDescriptor
);
1671 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1672 RootHubDeviceObject
,
1673 &HubDeviceExtension
->UsbExtHubInfo
,
1674 sizeof(USB_EXTHUB_INFORMATION_0
),
1676 if (!NT_SUCCESS(Status
))
1678 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1682 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1685 // Get the Hub Descriptor
1687 UsbBuildVendorRequest(Urb
,
1688 URB_FUNCTION_CLASS_DEVICE
,
1689 sizeof(Urb
->UrbControlVendorClassRequest
),
1690 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1692 USB_REQUEST_GET_DESCRIPTOR
,
1693 USB_DEVICE_CLASS_RESERVED
,
1695 &HubDeviceExtension
->HubDescriptor
,
1697 sizeof(USB_HUB_DESCRIPTOR
),
1700 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1702 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1703 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1707 DPRINT1("bDescriptorType %x\n", HubDeviceExtension
->HubDescriptor
.bDescriptorType
);
1709 if (!NT_SUCCESS(Status
))
1711 DPRINT1("Failed to get Hub Descriptor!\n");
1713 return STATUS_UNSUCCESSFUL
;
1717 UsbBuildGetStatusRequest(Urb
,
1718 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1723 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1725 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1726 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1729 if (!NT_SUCCESS(Status
))
1731 DPRINT1("Failed to get Hub Status!\n");
1733 return STATUS_UNSUCCESSFUL
;
1736 DPRINT1("HubStatus %x\n", HubStatus
);
1739 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1741 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1742 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1746 // Get the first Configuration Descriptor
1748 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1749 &HubDeviceExtension
->HubConfigDescriptor
,
1750 -1, -1, -1, -1, -1);
1752 ASSERT(Pid
!= NULL
);
1754 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1755 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1756 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1757 ASSERT(ConfigUrb
!= NULL
);
1759 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1760 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1764 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1765 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1766 DPRINT1("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1769 // check if function is available
1771 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed
)
1774 // is it high speed bus
1776 if (HubDeviceExtension
->UsbDInterface
.IsDeviceHighSpeed(HubInterfaceBusContext
))
1779 // initialize usb 2.0 hub
1781 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1782 HubDeviceExtension
->RootHubHandle
, 1);
1783 DPRINT1("Status %x\n", Status
);
1786 // FIXME handle error
1788 ASSERT(Status
== STATUS_SUCCESS
);
1792 ExFreePool(ConfigUrb
);
1795 // Enable power on all ports
1798 DPRINT1("Enabling PortPower on all ports!\n");
1800 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1802 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1803 if (!NT_SUCCESS(Status
))
1804 DPRINT1("Failed to power on port %d\n", PortId
);
1806 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1807 if (!NT_SUCCESS(Status
))
1808 DPRINT1("Failed to power on port %d\n", PortId
);
1811 DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension
->HubInterface
.RootHubInitNotification
);
1814 // init roo hub notification
1816 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1818 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1820 RootHubInitCallbackFunction
);
1821 if (!NT_SUCCESS(Status
))
1823 DPRINT1("Failed to set callback\n");
1831 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1836 Status
= GetPortStatusAndChange(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, &StatusChange
);
1837 if (NT_SUCCESS(Status
))
1840 // is there a device connected
1842 if (StatusChange
.Status
& USB_PORT_STATUS_CONNECT
)
1847 Status
= SetPortFeature(HubDeviceExtension
->RootHubPhysicalDeviceObject
, PortId
, PORT_RESET
);
1848 if (!NT_SUCCESS(Status
))
1849 DPRINT1("Failed to reset on port %d\n", PortId
);
1855 // Send the first SCE Request
1857 QueryStatusChangeEndpoint(DeviceObject
);
1864 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1866 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1870 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1871 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1873 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1875 Information
= (ULONG_PTR
)DeviceRelations
;
1878 case RemovalRelations
:
1880 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1881 return ForwardIrpAndForget(DeviceObject
, Irp
);
1884 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1885 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1886 return ForwardIrpAndForget(DeviceObject
, Irp
);
1890 case IRP_MN_QUERY_BUS_INFORMATION
:
1892 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
1895 case IRP_MN_QUERY_ID
:
1897 DPRINT1("IRP_MN_QUERY_ID\n");
1900 case IRP_MN_QUERY_CAPABILITIES
:
1902 DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
1907 DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
1908 return ForwardIrpAndForget(DeviceObject
, Irp
);
1912 Irp
->IoStatus
.Information
= Information
;
1913 Irp
->IoStatus
.Status
= Status
;
1914 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1919 USBHUB_FdoHandleDeviceControl(
1920 IN PDEVICE_OBJECT DeviceObject
,
1923 DPRINT1("FdoHandleDeviceControl\n");
1925 return STATUS_NOT_IMPLEMENTED
;