2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
17 QueryStatusChangeEndpoint(
18 IN PDEVICE_OBJECT DeviceObject
);
21 CreateUsbChildDeviceObject(
22 IN PDEVICE_OBJECT UsbHubDeviceObject
,
24 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
);
27 SubmitRequestToRootHub(
28 IN PDEVICE_OBJECT RootHubDeviceObject
,
29 IN ULONG IoControlCode
,
30 OUT PVOID OutParameter1
,
31 OUT PVOID OutParameter2
)
35 IO_STATUS_BLOCK IoStatus
;
37 PIO_STACK_LOCATION Stack
= NULL
;
39 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
42 // Build Control Request
44 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
54 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
55 return STATUS_INSUFFICIENT_RESOURCES
;
59 // Initialize the status block before sending the IRP
61 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
62 IoStatus
.Information
= 0;
65 // Get Next Stack Location and Initialize it
67 Stack
= IoGetNextIrpStackLocation(Irp
);
68 Stack
->Parameters
.Others
.Argument1
= OutParameter1
;
69 Stack
->Parameters
.Others
.Argument2
= OutParameter2
;
74 Status
= IoCallDriver(RootHubDeviceObject
, Irp
);
76 if (Status
== STATUS_PENDING
)
78 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
79 Status
= IoStatus
.Status
;
86 GetPortStatusAndChange(
87 IN PDEVICE_OBJECT RootHubDeviceObject
,
89 OUT PPORT_STATUS_CHANGE StatusChange
)
97 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
100 DPRINT1("Failed to allocate memory for URB!\n");
101 return STATUS_INSUFFICIENT_RESOURCES
;
107 RtlZeroMemory(Urb
, sizeof(URB
));
110 // Create URB for getting Port Status
112 UsbBuildVendorRequest(Urb
,
113 URB_FUNCTION_CLASS_OTHER
,
114 sizeof(Urb
->UrbControlVendorClassRequest
),
115 USBD_TRANSFER_DIRECTION_OUT
,
117 USB_REQUEST_GET_STATUS
,
122 sizeof(PORT_STATUS_CHANGE
),
126 // Query the Root Hub
128 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
140 IN PDEVICE_OBJECT RootHubDeviceObject
,
150 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
153 DPRINT1("Failed to allocate memory for URB!\n");
154 return STATUS_INSUFFICIENT_RESOURCES
;
160 RtlZeroMemory(Urb
, sizeof(URB
));
163 // Create URB for Clearing Port Reset
165 UsbBuildVendorRequest(Urb
,
166 URB_FUNCTION_CLASS_OTHER
,
167 sizeof(Urb
->UrbControlVendorClassRequest
),
168 USBD_TRANSFER_DIRECTION_IN
,
170 USB_REQUEST_SET_FEATURE
,
178 // Query the Root Hub
180 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
192 IN PDEVICE_OBJECT RootHubDeviceObject
,
202 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
205 DPRINT1("Failed to allocate memory for URB!\n");
206 return STATUS_INSUFFICIENT_RESOURCES
;
212 RtlZeroMemory(Urb
, sizeof(URB
));
215 // Create URB for Clearing Port Reset
217 UsbBuildVendorRequest(Urb
,
218 URB_FUNCTION_CLASS_OTHER
,
219 sizeof(Urb
->UrbControlVendorClassRequest
),
220 USBD_TRANSFER_DIRECTION_IN
,
222 USB_REQUEST_CLEAR_FEATURE
,
230 // Query the Root Hub
232 Status
= SubmitRequestToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Urb
, NULL
);
243 DeviceStatusChangeThread(
247 PDEVICE_OBJECT DeviceObject
, RootHubDeviceObject
;
248 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
249 PWORK_ITEM_DATA WorkItemData
;
250 PORT_STATUS_CHANGE PortStatus
;
252 DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context
);
253 static LONG failsafe
= 0;
255 WorkItemData
= (PWORK_ITEM_DATA
)Context
;
256 DeviceObject
= (PDEVICE_OBJECT
)WorkItemData
->Context
;
257 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
258 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
262 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
267 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
268 if (!NT_SUCCESS(Status
))
270 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
271 // FIXME: Do we really want to halt further SCE requests?
275 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
276 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
280 // Check for new device connection
282 if (PortStatus
.Change
& USB_PORT_STATUS_CONNECT
)
285 // Clear Port Connect
287 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
288 if (!NT_SUCCESS(Status
))
290 DPRINT1("Failed to clear connection change for port %d\n", PortId
);
294 // Is this a connect or disconnect?
296 if (!(PortStatus
.Status
& USB_PORT_STATUS_CONNECT
))
298 DPRINT1("Device disconnected from port %d\n", PortId
);
301 // FIXME: Remove the device, and deallocate memory
306 DPRINT1("Device connected from port %d\n", PortId
);
308 // No SCE completion done for clearing C_PORT_CONNECT
313 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
314 if (!NT_SUCCESS(Status
))
316 DPRINT1("Failed to reset port %d\n", PortId
);
320 else if (PortStatus
.Change
& USB_PORT_STATUS_ENABLE
)
325 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_ENABLE
);
326 if (!NT_SUCCESS(Status
))
328 DPRINT1("Failed to clear enable change on port %d\n", PortId
);
331 else if (PortStatus
.Change
& USB_PORT_STATUS_RESET
)
336 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_RESET
);
337 if (!NT_SUCCESS(Status
))
339 DPRINT1("Failed to clear reset change on port %d\n", PortId
);
345 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
346 if (!NT_SUCCESS(Status
))
348 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId
, Status
);
349 // FIXME: Do we really want to halt further SCE requests?
353 DPRINT1("Port %d Status %x\n", PortId
, PortStatus
.Status
);
354 DPRINT1("Port %d Change %x\n", PortId
, PortStatus
.Change
);
356 if(PortStatus
.Change
& USB_PORT_STATUS_RESET
)
358 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
362 // Make sure its Connected and Enabled
364 if (!(PortStatus
.Status
& (USB_PORT_STATUS_CONNECT
| USB_PORT_STATUS_ENABLE
)))
366 DPRINT1("Usb Device is not connected and enabled!\n");
368 // Attempt another reset
370 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_RESET
);
371 if (!NT_SUCCESS(Status
))
373 DPRINT1("Failed to reset port %d\n", PortId
);
379 // Create the device object only if the port manipulation was started by a device connect
381 if (HubDeviceExtension
->PortStatusChange
[PortId
-1].Status
)
383 HubDeviceExtension
->PortStatusChange
[PortId
-1].Status
= 0;
384 Status
= CreateUsbChildDeviceObject(DeviceObject
, PortId
, NULL
);
390 // FIXME: Still in testing
395 DPRINT1("SCE completed over 100 times but no action has been taken to clear the Change of any ports.\n");
397 // Return and dont send any more SCE Requests
402 ExFreePool(WorkItemData
);
405 // Send another SCE Request
407 DPRINT1("Sending another SCE!\n");
408 QueryStatusChangeEndpoint(DeviceObject
);
412 StatusChangeEndpointCompletion(
413 IN PDEVICE_OBJECT DeviceObject
,
417 PDEVICE_OBJECT RealDeviceObject
;
418 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
419 PWORK_ITEM_DATA WorkItemData
;
421 RealDeviceObject
= (PDEVICE_OBJECT
)Context
;
422 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)RealDeviceObject
->DeviceExtension
;
425 // NOTE: USBPORT frees this IRP
427 DPRINT1("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp
, HubDeviceExtension
->PendingSCEIrp
);
431 // Create and initialize work item data
433 WorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(WORK_ITEM_DATA
), USB_HUB_TAG
);
436 DPRINT1("Failed to allocate memory!n");
437 return STATUS_INSUFFICIENT_RESOURCES
;
439 WorkItemData
->Context
= RealDeviceObject
;
440 DPRINT1("Initialize work item\n");
441 ExInitializeWorkItem(&WorkItemData
->WorkItem
, (PWORKER_THREAD_ROUTINE
)DeviceStatusChangeThread
, (PVOID
)WorkItemData
);
444 // Queue the work item to handle initializing the device
446 ExQueueWorkItem(&WorkItemData
->WorkItem
, DelayedWorkQueue
);
449 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
451 return STATUS_MORE_PROCESSING_REQUIRED
;
455 QueryStatusChangeEndpoint(
456 IN PDEVICE_OBJECT DeviceObject
)
459 PDEVICE_OBJECT RootHubDeviceObject
;
460 PIO_STACK_LOCATION Stack
;
461 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
464 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
465 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
470 PendingSCEUrb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
473 // Initialize URB for Status Change Endpoint request
475 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb
,
476 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
477 HubDeviceExtension
->PipeHandle
,
478 HubDeviceExtension
->PortStatusChange
,
480 sizeof(USHORT
) * 2 * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
481 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
485 // Set the device handle to null for roothub
487 PendingSCEUrb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
493 HubDeviceExtension
->PendingSCEIrp
= ExAllocatePoolWithTag(NonPagedPool
,
494 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
497 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
500 DPRINT1("Allocated IRP %x\n", HubDeviceExtension
->PendingSCEIrp
);
502 if (!HubDeviceExtension
->PendingSCEIrp
)
504 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
505 return STATUS_INSUFFICIENT_RESOURCES
;
509 // Initialize the IRP
511 IoInitializeIrp(HubDeviceExtension
->PendingSCEIrp
,
512 IoSizeOfIrp(RootHubDeviceObject
->StackSize
),
513 RootHubDeviceObject
->StackSize
);
515 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
516 HubDeviceExtension
->PendingSCEIrp
->IoStatus
.Information
= 0;
517 HubDeviceExtension
->PendingSCEIrp
->Flags
= 0;
518 HubDeviceExtension
->PendingSCEIrp
->UserBuffer
= NULL
;
521 // Get the Next Stack Location and Initialize it
523 Stack
= IoGetNextIrpStackLocation(HubDeviceExtension
->PendingSCEIrp
);
524 Stack
->DeviceObject
= DeviceObject
;
525 Stack
->Parameters
.Others
.Argument1
= PendingSCEUrb
;
526 Stack
->Parameters
.Others
.Argument2
= NULL
;
527 Stack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
528 Stack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
531 // Set the completion routine for when device is connected to root hub
533 IoSetCompletionRoutine(HubDeviceExtension
->PendingSCEIrp
,
534 (PIO_COMPLETION_ROUTINE
) StatusChangeEndpointCompletion
,
543 DPRINT1("DeviceObject is %x\n", DeviceObject
);
544 DPRINT1("Iocalldriver %x with irp %x\n", RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
545 Status
= IoCallDriver(RootHubDeviceObject
, HubDeviceExtension
->PendingSCEIrp
);
547 return STATUS_PENDING
;
552 IN PDEVICE_OBJECT DeviceObject
,
553 IN CONST GUID InterfaceType
,
560 IO_STATUS_BLOCK IoStatus
;
562 PIO_STACK_LOCATION Stack
= NULL
;
565 // Initialize the Event used to wait for Irp completion
567 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
570 // Build Control Request
572 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
581 // Get Next Stack Location and Initialize it.
583 Stack
= IoGetNextIrpStackLocation(Irp
);
584 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
585 Stack
->Parameters
.QueryInterface
.InterfaceType
= &InterfaceType
;//USB_BUS_INTERFACE_HUB_GUID;
586 Stack
->Parameters
.QueryInterface
.Size
= Size
;
587 Stack
->Parameters
.QueryInterface
.Version
= Version
;
588 Stack
->Parameters
.QueryInterface
.Interface
= Interface
;
589 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
591 Status
= IoCallDriver(DeviceObject
, Irp
);
593 if (Status
== STATUS_PENDING
)
595 DPRINT("Operation pending\n");
596 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
597 Status
= IoStatus
.Status
;
604 GetUsbDeviceDescriptor(
605 IN PDEVICE_OBJECT ChildDeviceObject
,
606 IN UCHAR DescriptorType
,
609 OUT PVOID TransferBuffer
,
610 IN ULONG TransferBufferLength
)
613 PDEVICE_OBJECT RootHubDeviceObject
;
615 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
616 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
619 // Get the Hubs Device Extension
621 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)ChildDeviceObject
->DeviceExtension
;
622 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
623 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
628 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
), USB_HUB_TAG
);
631 DPRINT1("Failed to allocate memory for URB!\n");
632 return STATUS_INSUFFICIENT_RESOURCES
;
638 RtlZeroMemory(Urb
, sizeof(URB
));
641 // Create URB for getting device descriptor
643 UsbBuildGetDescriptorRequest(Urb
,
644 sizeof(Urb
->UrbControlDescriptorRequest
),
650 TransferBufferLength
,
654 // Set the device handle
656 Urb
->UrbHeader
.UsbdDeviceHandle
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
659 // Query the Root Hub
661 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
662 IOCTL_INTERNAL_USB_SUBMIT_URB
,
670 GetUsbStringDescriptor(
671 IN PDEVICE_OBJECT ChildDeviceObject
,
674 OUT PVOID
*TransferBuffer
)
677 PUSB_STRING_DESCRIPTOR StringDesc
= NULL
;
680 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
681 sizeof(USB_STRING_DESCRIPTOR
),
685 DPRINT1("Failed to allocate buffer for string!\n");
686 return STATUS_INSUFFICIENT_RESOURCES
;
690 // Get the index string descriptor length
692 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
693 USB_STRING_DESCRIPTOR_TYPE
,
697 sizeof(USB_STRING_DESCRIPTOR
));
700 // If lenght is 4 only then either this is a bad index or the device is not reporting
702 if (StringDesc
->bLength
== 4)
704 DPRINT1("USBHUB: Device Data Error\n");
705 return STATUS_UNSUCCESSFUL
;
708 DPRINT1("StringDesc->bLength %d\n", StringDesc
->bLength
);
709 SizeNeeded
= StringDesc
->bLength
+ sizeof(WCHAR
);
714 ExFreePool(StringDesc
);
717 // Recreate with appropriate size
719 StringDesc
= ExAllocatePoolWithTag(NonPagedPool
,
724 DPRINT1("Failed to allocate buffer for string!\n");
725 return STATUS_INSUFFICIENT_RESOURCES
;
727 RtlZeroMemory(StringDesc
, SizeNeeded
);
731 Status
= GetUsbDeviceDescriptor(ChildDeviceObject
,
732 USB_STRING_DESCRIPTOR_TYPE
,
737 if (!NT_SUCCESS(Status
))
739 DPRINT1("Failed to get string from device\n");
740 ExFreePool(StringDesc
);
745 // Allocate Buffer to return
747 *TransferBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
750 if (!*TransferBuffer
)
752 DPRINT1("Failed to allocate buffer for string!\n");
753 ExFreePool(StringDesc
);
754 return STATUS_INSUFFICIENT_RESOURCES
;
757 RtlZeroMemory(*TransferBuffer
, SizeNeeded
);
760 // Copy the string to destination
762 RtlCopyMemory(*TransferBuffer
, StringDesc
->bString
, SizeNeeded
- FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bLength
));
764 ExFreePool(StringDesc
);
766 return STATUS_SUCCESS
;
770 CreateUsbChildDeviceObject(
771 IN PDEVICE_OBJECT UsbHubDeviceObject
,
773 OUT PDEVICE_OBJECT
*UsbChildDeviceObject
)
776 PDEVICE_OBJECT RootHubDeviceObject
, NewChildDeviceObject
;
777 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
778 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
779 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
;
780 ULONG ChildDeviceCount
, UsbDeviceNumber
= 0;
781 WCHAR CharDeviceName
[64];
782 UNICODE_STRING DeviceName
;
783 ULONG ConfigDescSize
, DeviceDescSize
;
784 PVOID HubInterfaceBusContext
;
786 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) UsbHubDeviceObject
->DeviceExtension
;
787 HubInterface
= &HubDeviceExtension
->HubInterface
;
788 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
789 HubInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
791 // Find an empty slot in the child device array
793 for (ChildDeviceCount
= 0; ChildDeviceCount
< USB_MAXCHILDREN
; ChildDeviceCount
++)
795 if (HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] == NULL
)
797 DPRINT1("Found unused entry at %d\n", ChildDeviceCount
);
803 // Check if the limit has been reached for maximum usb devices
805 if (ChildDeviceCount
== USB_MAXCHILDREN
)
807 DPRINT1("USBHUB: Too many child devices!\n");
808 return STATUS_UNSUCCESSFUL
;
814 // Create a Device Name
816 swprintf(CharDeviceName
, L
"\\Device\\USBPDO-%d", UsbDeviceNumber
);
819 // Initialize UnicodeString
821 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
824 // Create a DeviceObject
827 Status
= IoCreateDevice(UsbHubDeviceObject
->DriverObject
,
828 sizeof(HUB_CHILDDEVICE_EXTENSION
),
830 FILE_DEVICE_CONTROLLER
,
831 FILE_AUTOGENERATED_DEVICE_NAME
,
833 &NewChildDeviceObject
);
836 // Check if the name is already in use
838 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
848 // Check for other errors
850 if (!NT_SUCCESS(Status
))
852 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status
);
856 DPRINT1("USBHUB: Created Device %x\n", NewChildDeviceObject
);
860 NewChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
863 // Assign the device extensions
865 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)NewChildDeviceObject
->DeviceExtension
;
866 RtlZeroMemory(UsbChildExtension
, sizeof(HUB_CHILDDEVICE_EXTENSION
));
867 UsbChildExtension
->ParentDeviceObject
= UsbHubDeviceObject
;
870 // Create the UsbDeviceObject
872 Status
= HubInterface
->CreateUsbDevice(HubInterfaceBusContext
,
873 (PVOID
)&UsbChildExtension
->UsbDeviceHandle
,
874 HubDeviceExtension
->RootHubHandle
,
877 if (!NT_SUCCESS(Status
))
879 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status
);
884 // Initialize UsbDevice
886 Status
= HubInterface
->InitializeUsbDevice(HubInterfaceBusContext
, UsbChildExtension
->UsbDeviceHandle
);
887 if (!NT_SUCCESS(Status
))
889 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status
);
893 DPRINT1("Usb Device Handle %x\n", UsbChildExtension
->UsbDeviceHandle
);
895 ConfigDescSize
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
896 DeviceDescSize
= sizeof(USB_DEVICE_DESCRIPTOR
);
899 // Get the descriptors
901 Status
= HubInterface
->GetUsbDescriptors(HubInterfaceBusContext
,
902 UsbChildExtension
->UsbDeviceHandle
,
903 (PUCHAR
)&UsbChildExtension
->DeviceDesc
,
905 (PUCHAR
)&UsbChildExtension
->ConfigDesc
,
907 if (!NT_SUCCESS(Status
))
909 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status
);
913 DumpDeviceDescriptor(&UsbChildExtension
->DeviceDesc
);
916 // Allocate memory for DeviceId
918 UsbChildExtension
->DeviceId
= ExAllocatePoolWithTag(NonPagedPool
, 32 * sizeof(WCHAR
), USB_HUB_TAG
);
921 // Construct DeviceId from vendor and product values
923 swprintf(UsbChildExtension
->DeviceId
, L
"USB\\Vid_%04x&Pid_%04x", UsbChildExtension
->DeviceDesc
.idVendor
, UsbChildExtension
->DeviceDesc
.idProduct
);
925 DPRINT1("Usb Device Id %S\n", UsbChildExtension
->DeviceId
);
928 // FIXME: Handle Lang ids, will use default for now
932 // Get the product string
934 Status
= GetUsbStringDescriptor(NewChildDeviceObject
,
935 UsbChildExtension
->DeviceDesc
.iProduct
,
937 (PVOID
*)&UsbChildExtension
->TextDescription
);
938 if (!NT_SUCCESS(Status
))
940 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
944 DPRINT1("Usb TextDescription %S\n", UsbChildExtension
->TextDescription
);
946 Status
= GetUsbStringDescriptor(NewChildDeviceObject
,
947 UsbChildExtension
->DeviceDesc
.iSerialNumber
,
949 (PVOID
*)&UsbChildExtension
->InstanceId
);
951 DPRINT1("Usb InstanceId %S\n", UsbChildExtension
->InstanceId
);
952 if (!NT_SUCCESS(Status
))
954 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status
);
958 HubDeviceExtension
->ChildDeviceObject
[ChildDeviceCount
] = NewChildDeviceObject
;
960 IoInvalidateDeviceRelations(RootHubDeviceObject
, BusRelations
);
961 return STATUS_SUCCESS
;
965 IoDeleteDevice(NewChildDeviceObject
);
970 USBHUB_FdoQueryBusRelations(
971 IN PDEVICE_OBJECT DeviceObject
,
972 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
974 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
975 PDEVICE_RELATIONS DeviceRelations
;
980 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
983 // Count the number of children
985 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
988 if (HubDeviceExtension
->ChildDeviceObject
[i
] == NULL
)
995 NeededSize
= sizeof(DEVICE_RELATIONS
);
997 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
1000 // Allocate DeviceRelations
1002 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
,
1005 if (!DeviceRelations
)
1006 return STATUS_INSUFFICIENT_RESOURCES
;
1007 DeviceRelations
->Count
= Children
;
1011 // Fill in return structure
1013 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
1015 if (HubDeviceExtension
->ChildDeviceObject
[i
])
1017 ObReferenceObject(HubDeviceExtension
->ChildDeviceObject
[i
]);
1018 HubDeviceExtension
->ChildDeviceObject
[i
]->Flags
&= ~DO_DEVICE_INITIALIZING
;
1019 DeviceRelations
->Objects
[Children
++] = HubDeviceExtension
->ChildDeviceObject
[i
];
1023 ASSERT(Children
== DeviceRelations
->Count
);
1024 *pDeviceRelations
= DeviceRelations
;
1026 return STATUS_SUCCESS
;
1030 RootHubInitCallbackFunction(
1033 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)Context
;
1035 DPRINT1("Sending the initial SCE Request %x\n", DeviceObject
);
1038 // Send the first SCE Request
1040 QueryStatusChangeEndpoint(DeviceObject
);
1044 USBHUB_FdoHandlePnp(
1045 IN PDEVICE_OBJECT DeviceObject
,
1048 PIO_STACK_LOCATION Stack
;
1049 NTSTATUS Status
= STATUS_SUCCESS
;
1050 ULONG_PTR Information
= 0;
1051 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
1052 PDEVICE_OBJECT RootHubDeviceObject
;
1053 PVOID HubInterfaceBusContext
, UsbDInterfaceBusContext
;
1055 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1057 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1059 switch (Stack
->MinorFunction
)
1061 case IRP_MN_START_DEVICE
:
1064 PUSB_INTERFACE_DESCRIPTOR Pid
;
1065 ULONG Result
= 0, PortId
;
1066 USBD_INTERFACE_LIST_ENTRY InterfaceList
[2] = {{NULL
, NULL
}, {NULL
, NULL
}};
1067 PURB ConfigUrb
= NULL
;
1070 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1073 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1075 Urb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
), USB_HUB_TAG
);
1076 RtlZeroMemory(Urb
, sizeof(URB
) + sizeof(USBD_INTERFACE_LIST_ENTRY
));
1079 // Get the Root Hub Pdo
1081 SubmitRequestToRootHub(HubDeviceExtension
->LowerDeviceObject
,
1082 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
1083 &HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1084 &HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1086 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
1087 ASSERT(HubDeviceExtension
->RootHubPhysicalDeviceObject
);
1088 ASSERT(HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1089 DPRINT1("RootPdo %x, RootFdo %x\n",
1090 HubDeviceExtension
->RootHubPhysicalDeviceObject
,
1091 HubDeviceExtension
->RootHubFunctionalDeviceObject
);
1094 // Send the StartDevice to RootHub
1096 Status
= ForwardIrpAndWait(RootHubDeviceObject
, Irp
);
1098 if (!NT_SUCCESS(Status
))
1100 DPRINT1("Failed to start the RootHub PDO\n");
1105 // Get the current number of hubs
1107 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1108 IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
1109 &HubDeviceExtension
->NumberOfHubs
, NULL
);
1112 // Get the Hub Interface
1114 Status
= QueryInterface(RootHubDeviceObject
,
1115 USB_BUS_INTERFACE_HUB_GUID
,
1116 sizeof(USB_BUS_INTERFACE_HUB_V5
),
1118 (PVOID
)&HubDeviceExtension
->HubInterface
);
1120 if (!NT_SUCCESS(Status
))
1122 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status
);
1123 return STATUS_UNSUCCESSFUL
;
1126 HubInterfaceBusContext
= HubDeviceExtension
->HubInterface
.BusContext
;
1129 // Get the USBDI Interface
1131 Status
= QueryInterface(RootHubDeviceObject
,
1132 USB_BUS_INTERFACE_USBDI_GUID
,
1133 sizeof(USB_BUS_INTERFACE_USBDI_V2
),
1135 (PVOID
)&HubDeviceExtension
->UsbDInterface
);
1137 if (!NT_SUCCESS(Status
))
1139 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status
);
1143 UsbDInterfaceBusContext
= HubDeviceExtension
->UsbDInterface
.BusContext
;
1146 // Get Root Hub Device Handle
1148 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1149 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
1150 &HubDeviceExtension
->RootHubHandle
,
1153 if (!NT_SUCCESS(Status
))
1155 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status
);
1160 // Get Hub Device Information
1162 Status
= HubDeviceExtension
->HubInterface
.QueryDeviceInformation(HubInterfaceBusContext
,
1163 HubDeviceExtension
->RootHubHandle
,
1164 &HubDeviceExtension
->DeviceInformation
,
1165 sizeof(USB_DEVICE_INFORMATION_0
),
1168 DPRINT1("Status %x, Result 0x%08lx\n", Status
, Result
);
1169 DPRINT1("InformationLevel %x\n", HubDeviceExtension
->DeviceInformation
.InformationLevel
);
1170 DPRINT1("ActualLength %x\n", HubDeviceExtension
->DeviceInformation
.ActualLength
);
1171 DPRINT1("PortNumber %x\n", HubDeviceExtension
->DeviceInformation
.PortNumber
);
1172 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension
->DeviceInformation
.DeviceDescriptor
);
1173 DPRINT1("HubAddress %x\n", HubDeviceExtension
->DeviceInformation
.HubAddress
);
1174 DPRINT1("NumberofPipes %x\n", HubDeviceExtension
->DeviceInformation
.NumberOfOpenPipes
);
1177 // Get Root Hubs Device Descriptor
1179 UsbBuildGetDescriptorRequest(Urb
,
1180 sizeof(Urb
->UrbControlDescriptorRequest
),
1181 USB_DEVICE_DESCRIPTOR_TYPE
,
1184 &HubDeviceExtension
->HubDeviceDescriptor
,
1186 sizeof(USB_DEVICE_DESCRIPTOR
),
1189 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1191 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1192 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1196 if (!NT_SUCCESS(Status
))
1198 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1201 DumpDeviceDescriptor(&HubDeviceExtension
->HubDeviceDescriptor
);
1204 // Get Root Hubs Configuration Descriptor
1206 UsbBuildGetDescriptorRequest(Urb
,
1207 sizeof(Urb
->UrbControlDescriptorRequest
),
1208 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
1211 &HubDeviceExtension
->HubConfigDescriptor
,
1213 sizeof(USB_CONFIGURATION_DESCRIPTOR
) + sizeof(USB_INTERFACE_DESCRIPTOR
) + sizeof(USB_ENDPOINT_DESCRIPTOR
),
1216 DPRINT1("RootHub Handle %x\n", HubDeviceExtension
->RootHubHandle
);
1217 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1219 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1220 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1224 if (!NT_SUCCESS(Status
))
1226 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status
);
1229 ASSERT(HubDeviceExtension
->HubConfigDescriptor
.wTotalLength
);
1231 DumpConfigurationDescriptor(&HubDeviceExtension
->HubConfigDescriptor
);
1233 Status
= HubDeviceExtension
->HubInterface
.GetExtendedHubInformation(HubInterfaceBusContext
,
1234 RootHubDeviceObject
,
1235 &HubDeviceExtension
->UsbExtHubInfo
,
1236 sizeof(USB_EXTHUB_INFORMATION_0
),
1238 if (!NT_SUCCESS(Status
))
1240 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1244 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
);
1247 // Get the Hub Descriptor
1249 UsbBuildVendorRequest(Urb
,
1250 URB_FUNCTION_CLASS_DEVICE
,
1251 sizeof(Urb
->UrbControlVendorClassRequest
),
1252 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
1254 USB_REQUEST_GET_DESCRIPTOR
,
1255 USB_DEVICE_CLASS_RESERVED
,
1257 &HubDeviceExtension
->HubDescriptor
,
1259 sizeof(USB_HUB_DESCRIPTOR
),
1262 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1264 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1265 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1269 DPRINT1("bDescriptorType %x\n", HubDeviceExtension
->HubDescriptor
.bDescriptorType
);
1271 if (!NT_SUCCESS(Status
))
1273 DPRINT1("Failed to get Hub Descriptor!\n");
1275 return STATUS_UNSUCCESSFUL
;
1279 UsbBuildGetStatusRequest(Urb
,
1280 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1285 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;//HubDeviceExtension->RootHubHandle;
1287 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1288 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1291 if (!NT_SUCCESS(Status
))
1293 DPRINT1("Failed to get Hub Status!\n");
1295 return STATUS_UNSUCCESSFUL
;
1298 DPRINT1("HubStatus %x\n", HubStatus
);
1301 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1303 HubDeviceExtension
->PortStatusChange
= ExAllocatePoolWithTag(NonPagedPool
,
1304 sizeof(ULONG
) * HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
,
1308 // Get the first Configuration Descriptor
1310 Pid
= USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension
->HubConfigDescriptor
,
1311 &HubDeviceExtension
->HubConfigDescriptor
,
1312 -1, -1, -1, -1, -1);
1314 ASSERT(Pid
!= NULL
);
1316 InterfaceList
[0].InterfaceDescriptor
= Pid
;
1317 ConfigUrb
= USBD_CreateConfigurationRequestEx(&HubDeviceExtension
->HubConfigDescriptor
,
1318 (PUSBD_INTERFACE_LIST_ENTRY
)&InterfaceList
);
1319 ASSERT(ConfigUrb
!= NULL
);
1321 Status
= SubmitRequestToRootHub(RootHubDeviceObject
,
1322 IOCTL_INTERNAL_USB_SUBMIT_URB
,
1326 HubDeviceExtension
->ConfigurationHandle
= ConfigUrb
->UrbSelectConfiguration
.ConfigurationHandle
;
1327 HubDeviceExtension
->PipeHandle
= ConfigUrb
->UrbSelectConfiguration
.Interface
.Pipes
[0].PipeHandle
;
1328 DPRINT1("Configuration Handle %x\n", HubDeviceExtension
->ConfigurationHandle
);
1331 // Initialize the Hub
1333 Status
= HubDeviceExtension
->HubInterface
.Initialize20Hub(HubInterfaceBusContext
,
1334 HubDeviceExtension
->RootHubHandle
, 1);
1335 DPRINT1("Status %x\n", Status
);
1337 ExFreePool(ConfigUrb
);
1340 // Enable power on all ports
1343 DPRINT1("Enabling PortPower on all ports!\n");
1345 for (PortId
= 1; PortId
<= HubDeviceExtension
->HubDescriptor
.bNumberOfPorts
; PortId
++)
1347 Status
= SetPortFeature(RootHubDeviceObject
, PortId
, PORT_POWER
);
1348 if (!NT_SUCCESS(Status
))
1349 DPRINT1("Failed to power on port %d\n", PortId
);
1351 Status
= ClearPortFeature(RootHubDeviceObject
, PortId
, C_PORT_CONNECTION
);
1352 if (!NT_SUCCESS(Status
))
1353 DPRINT1("Failed to power on port %d\n", PortId
);
1356 DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension
->HubInterface
.RootHubInitNotification
);
1360 if (HubDeviceExtension
->HubInterface
.RootHubInitNotification
)
1362 Status
= HubDeviceExtension
->HubInterface
.RootHubInitNotification(HubInterfaceBusContext
,
1364 (PRH_INIT_CALLBACK
)RootHubInitCallbackFunction
);
1369 // Send the first SCE Request
1371 QueryStatusChangeEndpoint(DeviceObject
);
1374 if (!NT_SUCCESS(Status
))
1376 DPRINT1("Failed to set callback\n");
1383 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1385 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
1389 PDEVICE_RELATIONS DeviceRelations
= NULL
;
1390 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1392 Status
= USBHUB_FdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
1394 Information
= (ULONG_PTR
)DeviceRelations
;
1397 case RemovalRelations
:
1399 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1400 return ForwardIrpAndForget(DeviceObject
, Irp
);
1403 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1404 Stack
->Parameters
.QueryDeviceRelations
.Type
);
1405 return ForwardIrpAndForget(DeviceObject
, Irp
);
1409 case IRP_MN_QUERY_BUS_INFORMATION
:
1411 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
1414 case IRP_MN_QUERY_ID
:
1416 DPRINT1("IRP_MN_QUERY_ID\n");
1419 case IRP_MN_QUERY_CAPABILITIES
:
1421 DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
1426 DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack
->MinorFunction
);
1427 return ForwardIrpAndForget(DeviceObject
, Irp
);
1431 Irp
->IoStatus
.Information
= Information
;
1432 Irp
->IoStatus
.Status
= Status
;
1433 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1438 USBHUB_FdoHandleDeviceControl(
1439 IN PDEVICE_OBJECT DeviceObject
,
1442 DPRINT1("FdoHandleDeviceControl\n");
1444 return STATUS_NOT_IMPLEMENTED
;