2 * PROJECT: ReactOS USB Hub Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBHub main driver functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
13 #define NDEBUG_USBHUB_SCE
14 #define NDEBUG_USBHUB_PNP
19 PWSTR GenericUSBDeviceString
= NULL
;
23 USBH_Wait(IN ULONG Milliseconds
)
25 LARGE_INTEGER Interval
;
27 DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds
);
28 Interval
.QuadPart
= -10000LL * Milliseconds
- ((ULONGLONG
)KeQueryTimeIncrement() - 1);
29 return KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
34 USBH_GetConfigValue(IN PWSTR ValueName
,
39 IN PVOID EntryContext
)
41 NTSTATUS Status
= STATUS_SUCCESS
;
43 DPRINT("USBHUB_GetConfigValue: ... \n");
45 if (ValueType
== REG_BINARY
)
47 *(PUCHAR
)EntryContext
= *(PUCHAR
)ValueData
;
49 else if (ValueType
== REG_DWORD
)
51 *(PULONG
)EntryContext
= *(PULONG
)ValueData
;
55 Status
= STATUS_INVALID_PARAMETER
;
63 USBH_CompleteIrp(IN PIRP Irp
,
64 IN NTSTATUS CompleteStatus
)
66 if (CompleteStatus
!= STATUS_SUCCESS
)
68 DPRINT1("USBH_CompleteIrp: Irp - %p, CompleteStatus - %X\n",
73 Irp
->IoStatus
.Status
= CompleteStatus
;
74 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
79 USBH_PassIrp(IN PDEVICE_OBJECT DeviceObject
,
82 DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n",
86 IoSkipCurrentIrpStackLocation(Irp
);
87 return IoCallDriver(DeviceObject
, Irp
);
92 USBH_SyncIrpComplete(IN PDEVICE_OBJECT DeviceObject
,
96 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext
;
98 BOOLEAN TimerCancelled
;
100 DPRINT("USBH_SyncIrpComplete: ... \n");
102 HubTimeoutContext
= Context
;
104 KeAcquireSpinLock(&HubTimeoutContext
->UrbTimeoutSpinLock
, &OldIrql
);
105 HubTimeoutContext
->IsNormalCompleted
= TRUE
;
106 TimerCancelled
= KeCancelTimer(&HubTimeoutContext
->UrbTimeoutTimer
);
107 KeReleaseSpinLock(&HubTimeoutContext
->UrbTimeoutSpinLock
, OldIrql
);
111 KeSetEvent(&HubTimeoutContext
->UrbTimeoutEvent
,
116 return STATUS_SUCCESS
;
121 IsBitSet(IN PUCHAR BitMapAddress
,
126 IsSet
= (BitMapAddress
[Bit
/ 8] & (1 << (Bit
& 7))) != 0;
127 DPRINT("IsBitSet: Bit - %lX, IsSet - %x\n", Bit
, IsSet
);
131 PUSBHUB_PORT_PDO_EXTENSION
133 PdoExt(IN PDEVICE_OBJECT DeviceObject
)
137 DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject
);
141 PdoExtension
= DeviceObject
->DeviceExtension
;
148 return (PUSBHUB_PORT_PDO_EXTENSION
)PdoExtension
;
153 USBH_WriteFailReasonID(IN PDEVICE_OBJECT DeviceObject
,
158 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"FailReasonID");
160 DPRINT("USBH_WriteFailReason: ID - %x\n", FailReason
);
162 Status
= IoOpenDeviceRegistryKey(DeviceObject
,
163 PLUGPLAY_REGKEY_DEVICE
,
167 if (NT_SUCCESS(Status
))
169 ZwSetValueKey(KeyHandle
,
184 USBH_UrbTimeoutDPC(IN PKDPC Dpc
,
185 IN PVOID DeferredContext
,
186 IN PVOID SystemArgument1
,
187 IN PVOID SystemArgument2
)
189 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext
;
193 DPRINT("USBH_TimeoutDPC ... \n");
195 HubTimeoutContext
= DeferredContext
;
197 KeAcquireSpinLock(&HubTimeoutContext
->UrbTimeoutSpinLock
, &OldIrql
);
198 IsCompleted
= HubTimeoutContext
->IsNormalCompleted
;
199 KeReleaseSpinLock(&HubTimeoutContext
->UrbTimeoutSpinLock
, OldIrql
);
203 IoCancelIrp(HubTimeoutContext
->Irp
);
206 KeSetEvent(&HubTimeoutContext
->UrbTimeoutEvent
,
213 USBH_SetPdoRegistryParameter(IN PDEVICE_OBJECT DeviceObject
,
218 IN ULONG DevInstKeyType
)
221 UNICODE_STRING ValueNameString
;
224 DPRINT("USBH_SetPdoRegistryParameter ... \n");
226 RtlInitUnicodeString(&ValueNameString
, ValueName
);
228 Status
= IoOpenDeviceRegistryKey(DeviceObject
,
233 if (NT_SUCCESS(Status
))
235 ZwSetValueKey(KeyHandle
,
250 USBH_SyncSubmitUrb(IN PDEVICE_OBJECT DeviceObject
,
254 IO_STATUS_BLOCK IoStatusBlock
;
256 PIO_STACK_LOCATION IoStack
;
257 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext
;
258 BOOLEAN IsWaitTimeout
= FALSE
;
259 LARGE_INTEGER DueTime
;
262 DPRINT("USBH_SyncSubmitUrb: ... \n");
264 Urb
->UrbHeader
.UsbdDeviceHandle
= NULL
;
266 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
268 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB
,
280 return STATUS_INSUFFICIENT_RESOURCES
;
283 IoStack
= IoGetNextIrpStackLocation(Irp
);
284 IoStack
->Parameters
.Others
.Argument1
= Urb
;
286 HubTimeoutContext
= ExAllocatePoolWithTag(NonPagedPool
,
287 sizeof(USBHUB_URB_TIMEOUT_CONTEXT
),
290 if (HubTimeoutContext
)
292 RtlZeroMemory(HubTimeoutContext
, sizeof(USBHUB_URB_TIMEOUT_CONTEXT
));
294 HubTimeoutContext
->Irp
= Irp
;
295 HubTimeoutContext
->IsNormalCompleted
= FALSE
;
297 KeInitializeEvent(&HubTimeoutContext
->UrbTimeoutEvent
,
301 KeInitializeSpinLock(&HubTimeoutContext
->UrbTimeoutSpinLock
);
302 KeInitializeTimer(&HubTimeoutContext
->UrbTimeoutTimer
);
304 KeInitializeDpc(&HubTimeoutContext
->UrbTimeoutDPC
,
308 DueTime
.QuadPart
= -5000 * 10000; // Timeout 5 sec.
310 KeSetTimer(&HubTimeoutContext
->UrbTimeoutTimer
,
312 &HubTimeoutContext
->UrbTimeoutDPC
);
314 IoSetCompletionRoutine(Irp
,
315 USBH_SyncIrpComplete
,
321 IsWaitTimeout
= TRUE
;
324 Status
= IoCallDriver(DeviceObject
, Irp
);
326 if (Status
== STATUS_PENDING
)
328 KeWaitForSingleObject(&Event
,
336 IoStatusBlock
.Status
= Status
;
341 KeWaitForSingleObject(&HubTimeoutContext
->UrbTimeoutEvent
,
347 ExFreePoolWithTag(HubTimeoutContext
, USB_HUB_TAG
);
350 return IoStatusBlock
.Status
;
355 USBH_FdoSyncSubmitUrb(IN PDEVICE_OBJECT FdoDevice
,
358 PUSBHUB_FDO_EXTENSION HubExtension
;
360 DPRINT("USBH_FdoSyncSubmitUrb: FdoDevice - %p, Urb - %p\n",
364 HubExtension
= FdoDevice
->DeviceExtension
;
365 return USBH_SyncSubmitUrb(HubExtension
->LowerDevice
, Urb
);
370 USBH_Transact(IN PUSBHUB_FDO_EXTENSION HubExtension
,
371 IN PVOID TransferBuffer
,
373 IN BOOLEAN IsDeviceToHost
,
375 IN BM_REQUEST_TYPE RequestType
,
377 IN USHORT RequestValue
,
378 IN USHORT RequestIndex
)
380 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
* Urb
;
386 DPRINT("USBH_Transact: ... \n");
390 Length
= ALIGN_DOWN_BY(BufferLen
+ sizeof(ULONG
), sizeof(ULONG
));
392 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, Length
, USB_HUB_TAG
);
396 return STATUS_INSUFFICIENT_RESOURCES
;
399 RtlZeroMemory(Buffer
, Length
);
402 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
403 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
410 ExFreePoolWithTag(Buffer
, USB_HUB_TAG
);
413 return STATUS_INSUFFICIENT_RESOURCES
;
416 RtlZeroMemory(Urb
, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
422 RtlZeroMemory(TransferBuffer
, BufferLen
);
425 TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
;
431 RtlCopyMemory(Buffer
, TransferBuffer
, BufferLen
);
434 TransferFlags
= USBD_TRANSFER_DIRECTION_OUT
;
437 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
438 Urb
->Hdr
.Function
= Function
;
439 Urb
->Hdr
.UsbdDeviceHandle
= NULL
;
441 Urb
->TransferFlags
= TransferFlags
;
442 Urb
->TransferBuffer
= BufferLen
!= 0 ? Buffer
: NULL
;
443 Urb
->TransferBufferLength
= BufferLen
;
444 Urb
->TransferBufferMDL
= NULL
;
447 Urb
->RequestTypeReservedBits
= RequestType
.B
;
448 Urb
->Request
= Request
;
449 Urb
->Value
= RequestValue
;
450 Urb
->Index
= RequestIndex
;
452 Status
= USBH_FdoSyncSubmitUrb(HubExtension
->Common
.SelfDevice
, (PURB
)Urb
);
454 if (IsDeviceToHost
&& BufferLen
)
456 RtlCopyMemory(TransferBuffer
, Buffer
, BufferLen
);
461 ExFreePoolWithTag(Buffer
, USB_HUB_TAG
);
464 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
471 USBH_SyncResetPort(IN PUSBHUB_FDO_EXTENSION HubExtension
,
474 USB_PORT_STATUS_AND_CHANGE PortStatus
;
476 LARGE_INTEGER Timeout
;
477 ULONG ResetRetry
= 0;
480 DPRINT("USBH_SyncResetPort: Port - %x\n", Port
);
482 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
484 KeWaitForSingleObject(&HubExtension
->HubPortSemaphore
,
490 Status
= USBH_SyncGetPortStatus(HubExtension
,
493 sizeof(USB_PORT_STATUS_AND_CHANGE
));
495 if (NT_SUCCESS(Status
) &&
496 (PortStatus
.PortStatus
.Usb20PortStatus
.CurrentConnectStatus
== 0))
498 Status
= STATUS_UNSUCCESSFUL
;
502 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_RESET_PORT_LOCK
;
506 BM_REQUEST_TYPE RequestType
;
508 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
510 InterlockedExchangePointer((PVOID
)&HubExtension
->pResetPortEvent
,
514 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
515 RequestType
.Type
= BMREQUEST_CLASS
;
516 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
518 Status
= USBH_Transact(HubExtension
,
521 BMREQUEST_HOST_TO_DEVICE
,
522 URB_FUNCTION_CLASS_OTHER
,
524 USB_REQUEST_SET_FEATURE
,
525 USBHUB_FEATURE_PORT_RESET
,
528 Timeout
.QuadPart
= -5000 * 10000;
530 if (!NT_SUCCESS(Status
))
532 InterlockedExchangePointer((PVOID
)&HubExtension
->pResetPortEvent
,
536 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK
;
541 Status
= KeWaitForSingleObject(&Event
,
547 if (Status
!= STATUS_TIMEOUT
)
552 Status
= USBH_SyncGetPortStatus(HubExtension
,
555 sizeof(USB_PORT_STATUS_AND_CHANGE
));
557 if (!NT_SUCCESS(Status
) ||
558 (PortStatus
.PortStatus
.Usb20PortStatus
.CurrentConnectStatus
== 0) ||
559 ResetRetry
>= USBHUB_RESET_PORT_MAX_RETRY
)
561 InterlockedExchangePointer((PVOID
)&HubExtension
->pResetPortEvent
,
565 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK
;
567 Status
= STATUS_DEVICE_DATA_ERROR
;
574 Status
= USBH_SyncGetPortStatus(HubExtension
,
577 sizeof(USB_PORT_STATUS_AND_CHANGE
));
579 if ((PortStatus
.PortStatus
.Usb20PortStatus
.CurrentConnectStatus
== 0) &&
580 NT_SUCCESS(Status
) &&
581 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_USB20_HUB
)
583 Status
= STATUS_DEVICE_DATA_ERROR
;
587 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK
;
591 KeReleaseSemaphore(&HubExtension
->HubPortSemaphore
,
592 LOW_REALTIME_PRIORITY
,
596 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
598 KeSetEvent(&HubExtension
->PendingRequestEvent
,
608 USBH_GetDeviceType(IN PUSBHUB_FDO_EXTENSION HubExtension
,
609 IN PUSB_DEVICE_HANDLE DeviceHandle
,
610 OUT USB_DEVICE_TYPE
* OutDeviceType
)
612 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation
;
613 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
614 SIZE_T DeviceInformationBufferLength
;
615 USB_DEVICE_TYPE DeviceType
= Usb11Device
;
619 DPRINT("USBH_GetDeviceType: ... \n");
621 QueryDeviceInformation
= HubExtension
->BusInterface
.QueryDeviceInformation
;
623 if (!QueryDeviceInformation
)
625 DPRINT1("USBH_GetDeviceType: no QueryDeviceInformation()\n");
626 return STATUS_NOT_IMPLEMENTED
;
629 DeviceInformationBufferLength
= sizeof(USB_DEVICE_INFORMATION_0
);
633 DeviceInfo
= ExAllocatePoolWithTag(PagedPool
,
634 DeviceInformationBufferLength
,
639 DPRINT1("USBH_GetDeviceType: ExAllocatePoolWithTag() failed\n");
640 Status
= STATUS_INSUFFICIENT_RESOURCES
;
644 RtlZeroMemory(DeviceInfo
, DeviceInformationBufferLength
);
646 DeviceInfo
->InformationLevel
= 0;
648 Status
= QueryDeviceInformation(HubExtension
->BusInterface
.BusContext
,
651 DeviceInformationBufferLength
,
654 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
656 if (NT_SUCCESS(Status
))
658 DeviceType
= DeviceInfo
->DeviceType
;
661 ExFreePoolWithTag(DeviceInfo
, USB_HUB_TAG
);
665 DeviceInformationBufferLength
= DeviceInfo
->ActualLength
;
666 ExFreePoolWithTag(DeviceInfo
, USB_HUB_TAG
);
671 *OutDeviceType
= DeviceType
;
672 DPRINT("USBH_GetDeviceType: DeviceType - %x\n", DeviceType
);
680 USBHUB_GetExtendedHubInfo(IN PUSBHUB_FDO_EXTENSION HubExtension
,
681 IN PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer
)
683 PUSB_BUSIFFN_GET_EXTENDED_HUB_INFO GetExtendedHubInformation
;
686 DPRINT("USBHUB_GetExtendedHubInfo: ... \n");
688 GetExtendedHubInformation
= HubExtension
->BusInterface
.GetExtendedHubInformation
;
690 return GetExtendedHubInformation(HubExtension
->BusInterface
.BusContext
,
691 HubExtension
->LowerPDO
,
693 sizeof(USB_EXTHUB_INFORMATION_0
),
697 PUSBHUB_FDO_EXTENSION
699 USBH_GetRootHubExtension(IN PUSBHUB_FDO_EXTENSION HubExtension
)
701 PDEVICE_OBJECT Device
;
702 PUSBHUB_FDO_EXTENSION RootHubExtension
;
704 DPRINT("USBH_GetRootHubExtension: HubExtension - %p\n", HubExtension
);
706 RootHubExtension
= HubExtension
;
708 if (HubExtension
->LowerPDO
!= HubExtension
->RootHubPdo
)
710 Device
= HubExtension
->RootHubPdo
;
714 Device
= Device
->AttachedDevice
;
716 while (Device
->DriverObject
!= HubExtension
->Common
.SelfDevice
->DriverObject
);
718 RootHubExtension
= Device
->DeviceExtension
;
721 DPRINT("USBH_GetRootHubExtension: RootHubExtension - %p\n", RootHubExtension
);
723 return RootHubExtension
;
728 USBH_SyncGetRootHubPdo(IN PDEVICE_OBJECT DeviceObject
,
729 IN OUT PDEVICE_OBJECT
* OutPdo1
,
730 IN OUT PDEVICE_OBJECT
* OutPdo2
)
733 IO_STATUS_BLOCK IoStatusBlock
;
735 PIO_STACK_LOCATION IoStack
;
738 DPRINT("USBH_SyncGetRootHubPdo: ... \n");
740 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
742 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
,
754 return STATUS_INSUFFICIENT_RESOURCES
;
757 IoStack
= IoGetNextIrpStackLocation(Irp
);
758 IoStack
->Parameters
.Others
.Argument1
= OutPdo1
;
759 IoStack
->Parameters
.Others
.Argument2
= OutPdo2
;
761 Status
= IoCallDriver(DeviceObject
, Irp
);
763 if (Status
== STATUS_PENDING
)
765 KeWaitForSingleObject(&Event
,
773 IoStatusBlock
.Status
= Status
;
776 return IoStatusBlock
.Status
;
781 USBH_SyncGetHubCount(IN PDEVICE_OBJECT DeviceObject
,
782 IN OUT PULONG OutHubCount
)
785 IO_STATUS_BLOCK IoStatusBlock
;
787 PIO_STACK_LOCATION IoStack
;
790 DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount
);
792 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
794 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_HUB_COUNT
,
806 return STATUS_INSUFFICIENT_RESOURCES
;
809 IoStack
= IoGetNextIrpStackLocation(Irp
);
810 IoStack
->Parameters
.Others
.Argument1
= OutHubCount
;
812 Status
= IoCallDriver(DeviceObject
, Irp
);
814 if (Status
== STATUS_PENDING
)
816 KeWaitForSingleObject(&Event
,
824 IoStatusBlock
.Status
= Status
;
827 return IoStatusBlock
.Status
;
832 USBH_SyncGetDeviceHandle(IN PDEVICE_OBJECT DeviceObject
)
836 IO_STATUS_BLOCK IoStatusBlock
;
837 PUSB_DEVICE_HANDLE DeviceHandle
= NULL
;
838 PIO_STACK_LOCATION IoStack
;
840 DPRINT("USBH_SyncGetDeviceHandle: ... \n");
842 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
844 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
,
856 DPRINT1("USBH_SyncGetDeviceHandle: Irp - NULL!\n");
860 IoStack
= IoGetNextIrpStackLocation(Irp
);
861 IoStack
->Parameters
.Others
.Argument1
= &DeviceHandle
;
863 if (IoCallDriver(DeviceObject
, Irp
) == STATUS_PENDING
)
865 KeWaitForSingleObject(&Event
,
877 USBH_GetDeviceDescriptor(IN PDEVICE_OBJECT DeviceObject
,
878 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor
)
880 struct _URB_CONTROL_DESCRIPTOR_REQUEST
* Urb
;
883 DPRINT("USBH_GetDeviceDescriptor: ... \n");
885 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
886 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
891 DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n");
892 return STATUS_INSUFFICIENT_RESOURCES
;
895 RtlZeroMemory(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
897 Urb
->Hdr
.Function
= URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
;
898 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
);
900 Urb
->TransferBufferLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
901 Urb
->TransferBuffer
= HubDeviceDescriptor
;
902 Urb
->DescriptorType
= USB_DEVICE_DESCRIPTOR_TYPE
;
904 Status
= USBH_FdoSyncSubmitUrb(DeviceObject
, (PURB
)Urb
);
906 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
913 USBH_SyncGetDeviceConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject
,
914 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
,
915 IN ULONG NumberOfBytes
,
918 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
919 struct _URB_CONTROL_DESCRIPTOR_REQUEST
* Urb
;
922 DPRINT("USBH_SyncGetDeviceConfigurationDescriptor: ... \n");
924 DeviceExtension
= DeviceObject
->DeviceExtension
;
931 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
932 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
937 return STATUS_INSUFFICIENT_RESOURCES
;
940 RtlZeroMemory(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
942 Urb
->Hdr
.Function
= URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
;
943 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
);
945 Urb
->TransferBufferLength
= NumberOfBytes
;
946 Urb
->TransferBuffer
= ConfigDescriptor
;
947 Urb
->DescriptorType
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
949 if (DeviceExtension
->ExtensionType
== USBH_EXTENSION_TYPE_HUB
||
950 DeviceExtension
->ExtensionType
== USBH_EXTENSION_TYPE_PARENT
)
952 Status
= USBH_FdoSyncSubmitUrb(DeviceObject
, (PURB
)Urb
);
956 Status
= USBH_SyncSubmitUrb(DeviceObject
, (PURB
)Urb
);
961 *OutLength
= Urb
->TransferBufferLength
;
966 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
974 USBH_GetConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject
,
975 IN PUSB_CONFIGURATION_DESCRIPTOR
* OutDescriptor
)
977 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
;
979 SIZE_T DescriptorLen
;
982 DPRINT("USBH_GetConfigurationDescriptor: ... \n");
984 DescriptorLen
= MAXUCHAR
;
988 ConfigDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
992 if (!ConfigDescriptor
)
994 Status
= STATUS_INSUFFICIENT_RESOURCES
;
998 Status
= USBH_SyncGetDeviceConfigurationDescriptor(DeviceObject
,
1003 if (ReturnedLen
< sizeof(USB_CONFIGURATION_DESCRIPTOR
))
1005 Status
= STATUS_DEVICE_DATA_ERROR
;
1008 if (!NT_SUCCESS(Status
))
1013 *OutDescriptor
= ConfigDescriptor
;
1015 if (ConfigDescriptor
->wTotalLength
<= DescriptorLen
)
1020 DescriptorLen
= ConfigDescriptor
->wTotalLength
;
1022 ExFreePool(ConfigDescriptor
);
1023 *OutDescriptor
= NULL
;
1026 if (NT_SUCCESS(Status
))
1028 if (ReturnedLen
< ConfigDescriptor
->wTotalLength
)
1030 Status
= STATUS_DEVICE_DATA_ERROR
;
1035 if (ConfigDescriptor
)
1037 ExFreePool(ConfigDescriptor
);
1040 *OutDescriptor
= NULL
;
1048 USBH_SyncGetHubDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension
)
1050 PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo
;
1052 PUSBHUB_PORT_DATA PortData
;
1053 USHORT RequestValue
;
1054 ULONG NumberOfBytes
;
1056 PUSB_HUB_DESCRIPTOR HubDescriptor
= NULL
;
1060 DPRINT("USBH_SyncGetHubDescriptor: ... \n");
1062 ExtendedHubInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1063 sizeof(USB_EXTHUB_INFORMATION_0
),
1066 if (!ExtendedHubInfo
)
1068 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1072 RtlZeroMemory(ExtendedHubInfo
, sizeof(USB_EXTHUB_INFORMATION_0
));
1074 Status
= USBHUB_GetExtendedHubInfo(HubExtension
, ExtendedHubInfo
);
1076 if (!NT_SUCCESS(Status
))
1078 ExFreePoolWithTag(ExtendedHubInfo
, USB_HUB_TAG
);
1079 ExtendedHubInfo
= NULL
;
1082 NumberOfBytes
= sizeof(USB_HUB_DESCRIPTOR
);
1084 HubDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
1090 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1094 RtlZeroMemory(HubDescriptor
, NumberOfBytes
);
1103 BM_REQUEST_TYPE RequestType
;
1106 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
1107 RequestType
.Type
= BMREQUEST_STANDARD
;
1108 RequestType
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1110 Status
= USBH_Transact(HubExtension
,
1113 BMREQUEST_DEVICE_TO_HOST
,
1114 URB_FUNCTION_CLASS_DEVICE
,
1116 USB_REQUEST_GET_DESCRIPTOR
,
1120 if (NT_SUCCESS(Status
))
1125 RequestValue
= 0x2900; // Hub DescriptorType - 0x29
1130 if (HubDescriptor
->bDescriptorLength
<= NumberOfBytes
)
1135 NumberOfBytes
= HubDescriptor
->bDescriptorLength
;
1136 ExFreePoolWithTag(HubDescriptor
, USB_HUB_TAG
);
1140 Status
= STATUS_DEVICE_DATA_ERROR
;
1141 HubDescriptor
= NULL
;
1145 HubDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
1151 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1155 RtlZeroMemory(HubDescriptor
, NumberOfBytes
);
1158 NumberPorts
= HubDescriptor
->bNumberOfPorts
;
1160 if (HubExtension
->PortData
)
1162 PortData
= HubExtension
->PortData
;
1164 for (ix
= 0; ix
< NumberPorts
; ix
++)
1166 PortData
[ix
].PortStatus
.AsUlong32
= 0;
1168 if (ExtendedHubInfo
)
1170 PortData
[ix
].PortAttributes
= ExtendedHubInfo
->Port
[ix
].PortAttributes
;
1174 PortData
[ix
].PortAttributes
= 0;
1177 PortData
[ix
].ConnectionStatus
= NoDeviceConnected
;
1179 if (PortData
[ix
].DeviceObject
!= NULL
)
1181 PortData
[ix
].ConnectionStatus
= DeviceConnected
;
1189 if (HubDescriptor
->bNumberOfPorts
)
1191 PortData
= ExAllocatePoolWithTag(NonPagedPool
,
1192 NumberPorts
* sizeof(USBHUB_PORT_DATA
),
1198 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1202 RtlZeroMemory(PortData
, NumberPorts
* sizeof(USBHUB_PORT_DATA
));
1204 for (ix
= 0; ix
< NumberPorts
; ix
++)
1206 PortData
[ix
].ConnectionStatus
= NoDeviceConnected
;
1208 if (ExtendedHubInfo
)
1210 PortData
[ix
].PortAttributes
= ExtendedHubInfo
->Port
[ix
].PortAttributes
;
1215 if (!NT_SUCCESS(Status
))
1220 HubExtension
->HubDescriptor
= HubDescriptor
;
1222 HubExtension
->PortData
= PortData
;
1224 if (ExtendedHubInfo
)
1226 ExFreePoolWithTag(ExtendedHubInfo
, USB_HUB_TAG
);
1235 ExFreePoolWithTag(HubDescriptor
, USB_HUB_TAG
);
1238 if (ExtendedHubInfo
)
1240 ExFreePoolWithTag(ExtendedHubInfo
, USB_HUB_TAG
);
1248 USBH_SyncGetStringDescriptor(IN PDEVICE_OBJECT DeviceObject
,
1250 IN USHORT LanguageId
,
1251 IN PUSB_STRING_DESCRIPTOR Descriptor
,
1252 IN ULONG NumberOfBytes
,
1253 IN PULONG OutLength
,
1254 IN BOOLEAN IsValidateLength
)
1256 struct _URB_CONTROL_DESCRIPTOR_REQUEST
* Urb
;
1257 ULONG TransferedLength
;
1260 DPRINT("USBH_SyncGetStringDescriptor: Index - %x, LanguageId - %x\n",
1264 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
1265 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
1270 return STATUS_INSUFFICIENT_RESOURCES
;
1273 RtlZeroMemory(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
1275 Urb
->Hdr
.Function
= URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
;
1276 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
);
1278 Urb
->TransferBuffer
= Descriptor
;
1279 Urb
->TransferBufferLength
= NumberOfBytes
;
1282 Urb
->DescriptorType
= USB_STRING_DESCRIPTOR_TYPE
;
1283 Urb
->LanguageId
= LanguageId
;
1285 Status
= USBH_SyncSubmitUrb(DeviceObject
, (PURB
)Urb
);
1287 if (!NT_SUCCESS(Status
))
1289 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
1293 TransferedLength
= Urb
->TransferBufferLength
;
1295 if (TransferedLength
> NumberOfBytes
)
1297 Status
= STATUS_DEVICE_DATA_ERROR
;
1300 if (!NT_SUCCESS(Status
))
1302 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
1308 *OutLength
= TransferedLength
;
1311 if (IsValidateLength
&& TransferedLength
!= Descriptor
->bLength
)
1313 Status
= STATUS_DEVICE_DATA_ERROR
;
1316 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
1323 USBH_SyncGetStatus(IN PDEVICE_OBJECT DeviceObject
,
1324 IN PUSHORT OutStatus
,
1326 IN USHORT RequestIndex
)
1328 struct _URB_CONTROL_GET_STATUS_REQUEST
* Urb
;
1332 DPRINT("USBH_SyncGetStatus: ... \n");
1334 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
1335 sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST
),
1340 return STATUS_INSUFFICIENT_RESOURCES
;
1343 RtlZeroMemory(Urb
, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST
));
1345 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST
);
1346 Urb
->Hdr
.Function
= Function
;
1348 Urb
->TransferBuffer
= &UsbStatus
;
1349 Urb
->TransferBufferLength
= sizeof(UsbStatus
);
1350 Urb
->Index
= RequestIndex
;
1352 NtStatus
= USBH_FdoSyncSubmitUrb(DeviceObject
, (PURB
)Urb
);
1354 *OutStatus
= UsbStatus
;
1356 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
1363 USBH_SyncGetHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1364 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus
,
1367 BM_REQUEST_TYPE RequestType
;
1369 DPRINT("USBH_SyncGetHubStatus\n");
1372 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
1373 RequestType
.Type
= BMREQUEST_CLASS
;
1374 RequestType
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1376 return USBH_Transact(HubExtension
,
1379 BMREQUEST_DEVICE_TO_HOST
,
1380 URB_FUNCTION_CLASS_DEVICE
,
1382 USB_REQUEST_GET_STATUS
,
1389 USBH_SyncClearHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1390 IN USHORT RequestValue
)
1392 BM_REQUEST_TYPE RequestType
;
1394 DPRINT("USBH_SyncClearHubStatus: RequestValue - %x\n", RequestValue
);
1397 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
1398 RequestType
.Type
= BMREQUEST_CLASS
;
1399 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
1401 return USBH_Transact(HubExtension
,
1404 BMREQUEST_HOST_TO_DEVICE
,
1405 URB_FUNCTION_CLASS_DEVICE
,
1407 USB_REQUEST_CLEAR_FEATURE
,
1414 USBH_SyncGetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1416 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus
,
1419 BM_REQUEST_TYPE RequestType
;
1421 DPRINT("USBH_SyncGetPortStatus: Port - %x\n", Port
);
1424 RequestType
.Recipient
= BMREQUEST_TO_OTHER
;
1425 RequestType
.Type
= BMREQUEST_CLASS
;
1426 RequestType
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1428 return USBH_Transact(HubExtension
,
1431 BMREQUEST_DEVICE_TO_HOST
,
1432 URB_FUNCTION_CLASS_OTHER
,
1434 USB_REQUEST_GET_STATUS
,
1442 USBH_SyncClearPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1444 IN USHORT RequestValue
)
1446 BM_REQUEST_TYPE RequestType
;
1448 DPRINT("USBH_SyncClearPortStatus: Port - %x, RequestValue - %x\n",
1453 RequestType
.Recipient
= BMREQUEST_TO_OTHER
;
1454 RequestType
.Type
= BMREQUEST_CLASS
;
1455 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
1457 return USBH_Transact(HubExtension
,
1460 BMREQUEST_HOST_TO_DEVICE
,
1461 URB_FUNCTION_CLASS_OTHER
,
1463 USB_REQUEST_CLEAR_FEATURE
,
1470 USBH_SyncPowerOnPort(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1474 PUSBHUB_PORT_DATA PortData
;
1475 PUSB_HUB_DESCRIPTOR HubDescriptor
;
1476 NTSTATUS Status
= STATUS_SUCCESS
;
1477 BM_REQUEST_TYPE RequestType
;
1478 PUSB_PORT_STATUS_AND_CHANGE PortStatus
;
1480 DPRINT("USBH_SyncPowerOnPort: Port - %x, IsWait - %x\n", Port
, IsWait
);
1483 PortData
= &HubExtension
->PortData
[Port
- 1];
1484 PortStatus
= &PortData
->PortStatus
;
1486 if (PortStatus
->PortStatus
.Usb20PortStatus
.CurrentConnectStatus
== 1)
1492 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
1493 RequestType
.Type
= BMREQUEST_CLASS
;
1494 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
1496 Status
= USBH_Transact(HubExtension
,
1499 BMREQUEST_HOST_TO_DEVICE
,
1500 URB_FUNCTION_CLASS_OTHER
,
1502 USB_REQUEST_SET_FEATURE
,
1503 USBHUB_FEATURE_PORT_POWER
,
1506 if (NT_SUCCESS(Status
))
1510 HubDescriptor
= HubExtension
->HubDescriptor
;
1511 USBH_Wait(2 * HubDescriptor
->bPowerOnToPowerGood
);
1514 PortStatus
->PortStatus
.Usb20PortStatus
.CurrentConnectStatus
= 1;
1522 USBH_SyncPowerOnPorts(IN PUSBHUB_FDO_EXTENSION HubExtension
)
1524 PUSB_HUB_DESCRIPTOR HubDescriptor
;
1525 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1527 UCHAR NumberOfPorts
;
1529 DPRINT("USBH_SyncPowerOnPorts: ... \n");
1531 HubDescriptor
= HubExtension
->HubDescriptor
;
1532 NumberOfPorts
= HubDescriptor
->bNumberOfPorts
;
1534 for (Port
= 1; Port
<= NumberOfPorts
; ++Port
)
1536 Status
= USBH_SyncPowerOnPort(HubExtension
, Port
, 0);
1538 if (!NT_SUCCESS(Status
))
1540 DPRINT1("USBH_SyncPowerOnPorts: USBH_SyncPowerOnPort() failed - %lX\n",
1546 USBH_Wait(2 * HubDescriptor
->bPowerOnToPowerGood
);
1553 USBH_SyncDisablePort(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1556 PUSBHUB_PORT_DATA PortData
;
1558 BM_REQUEST_TYPE RequestType
;
1560 DPRINT("USBH_SyncDisablePort ... \n");
1562 PortData
= &HubExtension
->PortData
[Port
- 1];
1565 RequestType
.Recipient
= BMREQUEST_TO_DEVICE
;
1566 RequestType
.Type
= BMREQUEST_CLASS
;
1567 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
1569 Status
= USBH_Transact(HubExtension
,
1572 BMREQUEST_HOST_TO_DEVICE
,
1573 URB_FUNCTION_CLASS_OTHER
,
1575 USB_REQUEST_CLEAR_FEATURE
,
1576 USBHUB_FEATURE_PORT_ENABLE
,
1579 if (NT_SUCCESS(Status
))
1581 PortData
->PortStatus
.PortStatus
.Usb20PortStatus
.PortEnabledDisabled
= 0;
1589 USBH_HubIsBusPowered(IN PDEVICE_OBJECT DeviceObject
,
1590 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor
)
1596 DPRINT("USBH_HubIsBusPowered: ... \n");
1598 Status
= USBH_SyncGetStatus(DeviceObject
,
1600 URB_FUNCTION_GET_STATUS_FROM_DEVICE
,
1603 if (!NT_SUCCESS(Status
))
1605 Result
= (HubConfigDescriptor
->bmAttributes
& USB_CONFIG_POWERED_MASK
)
1606 == USB_CONFIG_BUS_POWERED
;
1610 Result
= (UsbStatus
& USB_GETSTATUS_SELF_POWERED
) == 0;
1618 USBH_ChangeIndicationAckChangeComplete(IN PDEVICE_OBJECT DeviceObject
,
1622 PUSBHUB_FDO_EXTENSION HubExtension
;
1626 HubExtension
= Context
;
1628 DPRINT_SCE("USBH_ChangeIndicationAckChangeComplete: ... \n");
1630 ASSERT(HubExtension
->Port
> 0);
1631 Port
= HubExtension
->Port
- 1;
1633 HubExtension
->PortData
[Port
].PortStatus
= HubExtension
->PortStatus
;
1635 Event
= InterlockedExchangePointer((PVOID
)&HubExtension
->pResetPortEvent
,
1640 KeSetEvent(Event
, EVENT_INCREMENT
, FALSE
);
1643 USBH_SubmitStatusChangeTransfer(HubExtension
);
1645 if (!InterlockedDecrement(&HubExtension
->ResetRequestCount
))
1647 KeSetEvent(&HubExtension
->ResetEvent
,
1652 return STATUS_MORE_PROCESSING_REQUIRED
;
1657 USBH_ChangeIndicationAckChange(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1659 IN
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
* Urb
,
1661 IN USHORT RequestValue
)
1663 PIO_STACK_LOCATION IoStack
;
1664 BM_REQUEST_TYPE RequestType
;
1666 DPRINT_SCE("USBH_ChangeIndicationAckChange: ... \n");
1668 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
1669 Urb
->Hdr
.Function
= URB_FUNCTION_CLASS_OTHER
;
1670 Urb
->Hdr
.UsbdDeviceHandle
= NULL
;
1672 Urb
->TransferFlags
= USBD_SHORT_TRANSFER_OK
;
1673 Urb
->TransferBufferLength
= 0;
1674 Urb
->TransferBuffer
= NULL
;
1675 Urb
->TransferBufferMDL
= NULL
;
1676 Urb
->UrbLink
= NULL
;
1679 RequestType
.Recipient
= BMREQUEST_TO_OTHER
;
1680 RequestType
.Type
= BMREQUEST_CLASS
;
1681 RequestType
.Dir
= BMREQUEST_HOST_TO_DEVICE
;
1683 Urb
->RequestTypeReservedBits
= RequestType
.B
;
1684 Urb
->Request
= USB_REQUEST_CLEAR_FEATURE
;
1686 Urb
->Value
= RequestValue
;
1688 IoInitializeIrp(Irp
,
1689 IoSizeOfIrp(HubExtension
->LowerDevice
->StackSize
),
1690 HubExtension
->LowerDevice
->StackSize
);
1692 IoStack
= IoGetNextIrpStackLocation(Irp
);
1694 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
1695 IoStack
->Parameters
.Others
.Argument1
= Urb
;
1696 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
1698 IoSetCompletionRoutine(Irp
,
1699 USBH_ChangeIndicationAckChangeComplete
,
1705 return IoCallDriver(HubExtension
->LowerDevice
, Irp
);
1710 USBH_ChangeIndicationProcessChange(IN PDEVICE_OBJECT DeviceObject
,
1714 PUSBHUB_FDO_EXTENSION HubExtension
;
1715 PUSBHUB_IO_WORK_ITEM WorkItem
;
1716 USHORT RequestValue
;
1718 HubExtension
= Context
;
1720 DPRINT_SCE("USBH_ChangeIndicationProcessChange: PortStatus - %lX\n",
1721 HubExtension
->PortStatus
.AsUlong32
);
1723 if ((NT_SUCCESS(Irp
->IoStatus
.Status
) ||
1724 USBD_SUCCESS(HubExtension
->SCEWorkerUrb
.Hdr
.Status
)) &&
1725 (HubExtension
->PortStatus
.PortChange
.Usb20PortChange
.ResetChange
||
1726 HubExtension
->PortStatus
.PortChange
.Usb20PortChange
.PortEnableDisableChange
))
1728 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
1730 KeSetEvent(&HubExtension
->PendingRequestEvent
,
1735 USBH_FreeWorkItem(HubExtension
->WorkItemToQueue
);
1737 HubExtension
->WorkItemToQueue
= NULL
;
1739 if (HubExtension
->PortStatus
.PortChange
.Usb20PortChange
.ResetChange
)
1741 RequestValue
= USBHUB_FEATURE_C_PORT_RESET
;
1745 RequestValue
= USBHUB_FEATURE_C_PORT_ENABLE
;
1748 USBH_ChangeIndicationAckChange(HubExtension
,
1749 HubExtension
->ResetPortIrp
,
1750 &HubExtension
->SCEWorkerUrb
,
1756 ASSERT(HubExtension
->WorkItemToQueue
!= NULL
);
1758 WorkItem
= HubExtension
->WorkItemToQueue
;
1759 HubExtension
->WorkItemToQueue
= NULL
;
1761 USBH_QueueWorkItem(HubExtension
, WorkItem
);
1764 return STATUS_MORE_PROCESSING_REQUIRED
;
1769 USBH_ChangeIndicationQueryChange(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1771 IN
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
* Urb
,
1774 PUSBHUB_IO_WORK_ITEM WorkItem
;
1776 PIO_STACK_LOCATION IoStack
;
1777 BM_REQUEST_TYPE RequestType
;
1779 DPRINT_SCE("USBH_ChangeIndicationQueryChange: Port - %x\n", Port
);
1781 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
1785 ASSERT(HubExtension
->WorkItemToQueue
!= NULL
);
1787 WorkItem
= HubExtension
->WorkItemToQueue
;
1788 HubExtension
->WorkItemToQueue
= NULL
;
1790 USBH_QueueWorkItem(HubExtension
, WorkItem
);
1792 return STATUS_SUCCESS
;
1795 Urb
->Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
1796 Urb
->Hdr
.UsbdDeviceHandle
= NULL
;
1797 Urb
->Hdr
.Function
= URB_FUNCTION_CLASS_OTHER
;
1799 Urb
->TransferFlags
= USBD_SHORT_TRANSFER_OK
| USBD_TRANSFER_DIRECTION_IN
;
1800 Urb
->TransferBuffer
= &HubExtension
->PortStatus
;
1801 Urb
->TransferBufferLength
= sizeof(HubExtension
->PortStatus
);
1802 Urb
->TransferBufferMDL
= NULL
;
1803 Urb
->UrbLink
= NULL
;
1806 RequestType
.Recipient
= BMREQUEST_TO_OTHER
;
1807 RequestType
.Type
= BMREQUEST_CLASS
;
1808 RequestType
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
1810 Urb
->RequestTypeReservedBits
= RequestType
.B
;
1811 Urb
->Request
= USB_REQUEST_GET_STATUS
;
1815 HubExtension
->Port
= Port
;
1817 IoInitializeIrp(Irp
,
1818 IoSizeOfIrp(HubExtension
->LowerDevice
->StackSize
),
1819 HubExtension
->LowerDevice
->StackSize
);
1821 IoStack
= IoGetNextIrpStackLocation(Irp
);
1823 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
1824 IoStack
->Parameters
.Others
.Argument1
= Urb
;
1825 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
1827 IoSetCompletionRoutine(Irp
,
1828 USBH_ChangeIndicationProcessChange
,
1834 Status
= IoCallDriver(HubExtension
->LowerDevice
, Irp
);
1841 USBH_ProcessHubStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1842 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus
)
1844 USB_HUB_CHANGE HubStatusChange
;
1846 DPRINT_SCE("USBH_ProcessHubStateChange: HubStatus - %lx\n", HubStatus
->AsUlong32
);
1848 HubStatusChange
= HubStatus
->HubChange
;
1850 if (HubStatusChange
.LocalPowerChange
)
1852 DPRINT1("USBH_ProcessHubStateChange: LocalPowerChange\n");
1853 USBH_SyncClearHubStatus(HubExtension
,
1854 USBHUB_FEATURE_C_HUB_LOCAL_POWER
);
1856 else if (HubStatusChange
.OverCurrentChange
)
1858 USBH_SyncClearHubStatus(HubExtension
,
1859 USBHUB_FEATURE_C_HUB_OVER_CURRENT
);
1860 if (HubStatus
->HubStatus
.OverCurrent
)
1862 DPRINT1("USBH_ProcessHubStateChange: OverCurrent UNIMPLEMENTED. FIXME\n");
1870 USBH_ProcessPortStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1872 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus
)
1874 PUSBHUB_PORT_DATA PortData
;
1875 USB_20_PORT_CHANGE PortStatusChange
;
1876 PDEVICE_OBJECT PortDevice
;
1877 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
1880 USHORT RequestValue
;
1883 DPRINT_SCE("USBH_ProcessPortStateChange ... \n");
1886 PortData
= &HubExtension
->PortData
[Port
- 1];
1888 PortStatusChange
= PortStatus
->PortChange
.Usb20PortChange
;
1890 if (PortStatusChange
.ConnectStatusChange
)
1892 PortData
->PortStatus
= *PortStatus
;
1894 USBH_SyncClearPortStatus(HubExtension
,
1896 USBHUB_FEATURE_C_PORT_CONNECTION
);
1898 PortData
= &HubExtension
->PortData
[Port
- 1];
1900 PortDevice
= PortData
->DeviceObject
;
1904 IoInvalidateDeviceRelations(HubExtension
->LowerPDO
, BusRelations
);
1908 PortExtension
= PortDevice
->DeviceExtension
;
1910 if (PortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_OVERCURRENT_PORT
)
1915 KeAcquireSpinLock(&HubExtension
->RelationsWorkerSpinLock
, &Irql
);
1917 if (PortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_POWER_D3
)
1919 KeReleaseSpinLock(&HubExtension
->RelationsWorkerSpinLock
, Irql
);
1920 IoInvalidateDeviceRelations(HubExtension
->LowerPDO
, BusRelations
);
1924 PortData
->DeviceObject
= NULL
;
1925 PortData
->ConnectionStatus
= NoDeviceConnected
;
1927 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_STATE_CHANGING
;
1929 InsertTailList(&HubExtension
->PdoList
, &PortExtension
->PortLink
);
1931 KeReleaseSpinLock(&HubExtension
->RelationsWorkerSpinLock
, Irql
);
1933 SerialNumber
= InterlockedExchangePointer((PVOID
)&PortExtension
->SerialNumber
,
1938 ExFreePoolWithTag(SerialNumber
, USB_HUB_TAG
);
1941 DeviceHandle
= InterlockedExchangePointer(&PortExtension
->DeviceHandle
,
1946 USBD_RemoveDeviceEx(HubExtension
, DeviceHandle
, 0);
1947 USBH_SyncDisablePort(HubExtension
, Port
);
1950 IoInvalidateDeviceRelations(HubExtension
->LowerPDO
, BusRelations
);
1952 else if (PortStatusChange
.PortEnableDisableChange
)
1954 RequestValue
= USBHUB_FEATURE_C_PORT_ENABLE
;
1955 PortData
->PortStatus
= *PortStatus
;
1956 USBH_SyncClearPortStatus(HubExtension
, Port
, RequestValue
);
1959 else if (PortStatusChange
.SuspendChange
)
1961 DPRINT1("USBH_ProcessPortStateChange: SuspendChange UNIMPLEMENTED. FIXME\n");
1964 else if (PortStatusChange
.OverCurrentIndicatorChange
)
1966 DPRINT1("USBH_ProcessPortStateChange: OverCurrentIndicatorChange UNIMPLEMENTED. FIXME\n");
1969 else if (PortStatusChange
.ResetChange
)
1971 RequestValue
= USBHUB_FEATURE_C_PORT_RESET
;
1972 PortData
->PortStatus
= *PortStatus
;
1973 USBH_SyncClearPortStatus(HubExtension
, Port
, RequestValue
);
1979 USBH_GetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension
,
1980 IN PULONG PortStatus
)
1983 PIO_STACK_LOCATION IoStack
;
1986 IO_STATUS_BLOCK IoStatusBlock
;
1988 DPRINT("USBH_GetPortStatus ... \n");
1992 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1994 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PORT_STATUS
,
1995 HubExtension
->LowerDevice
,
2006 return STATUS_INSUFFICIENT_RESOURCES
;
2009 IoStack
= IoGetNextIrpStackLocation(Irp
);
2010 IoStack
->Parameters
.Others
.Argument1
= PortStatus
;
2012 Status
= IoCallDriver(HubExtension
->LowerDevice
, Irp
);
2014 if (Status
== STATUS_PENDING
)
2016 KeWaitForSingleObject(&Event
,
2024 IoStatusBlock
.Status
= Status
;
2027 return IoStatusBlock
.Status
;
2032 USBH_EnableParentPort(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2037 IO_STATUS_BLOCK IoStatusBlock
;
2039 DPRINT("USBH_EnableParentPort ... \n");
2041 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2043 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_ENABLE_PORT
,
2044 HubExtension
->LowerDevice
,
2055 return STATUS_INSUFFICIENT_RESOURCES
;
2058 Status
= IoCallDriver(HubExtension
->LowerDevice
, Irp
);
2060 if (Status
== STATUS_PENDING
)
2062 KeWaitForSingleObject(&Event
,
2070 IoStatusBlock
.Status
= Status
;
2073 return IoStatusBlock
.Status
;
2078 USBH_ResetInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2080 struct _URB_PIPE_REQUEST
* Urb
;
2083 DPRINT("USBH_ResetInterruptPipe ... \n");
2085 Urb
= ExAllocatePoolWithTag(NonPagedPool
,
2086 sizeof(struct _URB_PIPE_REQUEST
),
2091 RtlZeroMemory(Urb
, sizeof(struct _URB_PIPE_REQUEST
));
2093 Urb
->Hdr
.Length
= sizeof(struct _URB_PIPE_REQUEST
);
2094 Urb
->Hdr
.Function
= URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
;
2095 Urb
->PipeHandle
= HubExtension
->PipeInfo
.PipeHandle
;
2097 Status
= USBH_FdoSyncSubmitUrb(HubExtension
->Common
.SelfDevice
,
2100 ExFreePoolWithTag(Urb
, USB_HUB_TAG
);
2104 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2107 if (NT_SUCCESS(Status
))
2109 HubExtension
->RequestErrors
= 0;
2117 USBH_ResetHub(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2120 ULONG PortStatusFlags
= 0;
2122 DPRINT("USBH_ResetHub: ... \n");
2124 Status
= USBH_GetPortStatus(HubExtension
, &PortStatusFlags
);
2126 if (!NT_SUCCESS(Status
))
2131 if (!(PortStatusFlags
& USBD_PORT_ENABLED
))
2133 if (PortStatusFlags
& USBD_PORT_CONNECTED
)
2135 USBH_EnableParentPort(HubExtension
);
2139 Status
= USBH_ResetInterruptPipe(HubExtension
);
2146 USBH_ChangeIndicationWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2149 PUSBHUB_FDO_EXTENSION LowerHubExtension
;
2150 PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension
;
2151 PUSBHUB_STATUS_CHANGE_CONTEXT WorkItem
;
2152 USB_PORT_STATUS_AND_CHANGE PortStatus
;
2153 USB_HUB_STATUS_AND_CHANGE HubStatus
;
2157 DPRINT_SCE("USBH_ChangeIndicationWorker ... \n");
2161 KeWaitForSingleObject(&HubExtension
->HubSemaphore
,
2167 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
)
2169 KeSetEvent(&HubExtension
->StatusChangeEvent
,
2176 if (!HubExtension
->RequestErrors
)
2181 DPRINT_SCE("USBH_ChangeIndicationWorker: RequestErrors - %x\n",
2182 HubExtension
->RequestErrors
);
2184 if (HubExtension
->LowerPDO
== HubExtension
->RootHubPdo
)
2189 LowerPortExtension
= HubExtension
->LowerPDO
->DeviceExtension
;
2191 if (LowerPortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_POWER_D1_OR_D2
)
2196 LowerHubExtension
= LowerPortExtension
->HubExtension
;
2198 if (!LowerHubExtension
)
2203 Status
= USBH_SyncGetPortStatus(LowerHubExtension
,
2204 LowerPortExtension
->PortNumber
,
2206 sizeof(USB_PORT_STATUS_AND_CHANGE
));
2208 if (!NT_SUCCESS(Status
) ||
2209 !PortStatus
.PortStatus
.Usb20PortStatus
.CurrentConnectStatus
)
2211 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DEVICE_REMOVED
;
2213 KeSetEvent(&HubExtension
->StatusChangeEvent
,
2220 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_ESD_RECOVERING
))
2222 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_ESD_RECOVERING
;
2224 DPRINT1("USBH_ChangeIndicationWorker: USBHUB_FDO_FLAG_ESD_RECOVERING FIXME\n");
2232 if (WorkItem
->IsRequestErrors
)
2234 USBH_ResetHub(HubExtension
);
2239 Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
;
2242 if (IsBitSet((PUCHAR
)(WorkItem
+ 1), Port
))
2250 Status
= USBH_SyncGetPortStatus(HubExtension
,
2253 sizeof(PortStatus
));
2257 Status
= USBH_SyncGetHubStatus(HubExtension
,
2262 if (NT_SUCCESS(Status
))
2266 USBH_ProcessPortStateChange(HubExtension
,
2272 USBH_ProcessHubStateChange(HubExtension
,
2278 HubExtension
->RequestErrors
++;
2280 if (HubExtension
->RequestErrors
> USBHUB_MAX_REQUEST_ERRORS
)
2282 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DEVICE_FAILED
;
2288 USBH_SubmitStatusChangeTransfer(HubExtension
);
2292 KeReleaseSemaphore(&HubExtension
->HubSemaphore
,
2293 LOW_REALTIME_PRIORITY
,
2297 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
2299 KeSetEvent(&HubExtension
->PendingRequestEvent
,
2304 if (!InterlockedDecrement((PLONG
)&HubExtension
->ResetRequestCount
))
2306 KeSetEvent(&HubExtension
->ResetEvent
,
2310 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEFER_CHECK_IDLE
)
2312 USBH_CheckHubIdle(HubExtension
);
2319 USBH_ChangeIndication(IN PDEVICE_OBJECT DeviceObject
,
2323 PUSBHUB_FDO_EXTENSION HubExtension
;
2324 USBD_STATUS UrbStatus
;
2325 BOOLEAN IsErrors
= FALSE
;
2326 PUSBHUB_IO_WORK_ITEM HubWorkItem
;
2327 PUSBHUB_STATUS_CHANGE_CONTEXT HubWorkItemBuffer
;
2334 HubExtension
= Context
;
2335 UrbStatus
= HubExtension
->SCEWorkerUrb
.Hdr
.Status
;
2337 DPRINT_SCE("USBH_ChangeIndication: IrpStatus - %x, UrbStatus - %x, HubFlags - %lX\n",
2338 Irp
->IoStatus
.Status
,
2340 HubExtension
->HubFlags
);
2342 if (NT_ERROR(Irp
->IoStatus
.Status
) || USBD_ERROR(UrbStatus
) ||
2343 (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_FAILED
) ||
2344 (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
))
2346 HubExtension
->RequestErrors
++;
2350 KeSetEvent(&HubExtension
->StatusChangeEvent
,
2354 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
||
2355 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_FAILED
||
2356 HubExtension
->RequestErrors
> USBHUB_MAX_REQUEST_ERRORS
||
2357 Irp
->IoStatus
.Status
== STATUS_DELETE_PENDING
)
2359 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2360 HubExtension
->RequestErrors
);
2362 return STATUS_MORE_PROCESSING_REQUIRED
;
2365 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2366 HubExtension
->RequestErrors
);
2370 HubExtension
->RequestErrors
= 0;
2373 BufferLength
= sizeof(USBHUB_STATUS_CHANGE_CONTEXT
) +
2374 HubExtension
->SCEBitmapLength
;
2376 Status
= USBH_AllocateWorkItem(HubExtension
,
2378 USBH_ChangeIndicationWorker
,
2380 (PVOID
*)&HubWorkItemBuffer
,
2383 if (!NT_SUCCESS(Status
))
2385 return STATUS_MORE_PROCESSING_REQUIRED
;
2388 RtlZeroMemory(HubWorkItemBuffer
, BufferLength
);
2390 HubWorkItemBuffer
->IsRequestErrors
= FALSE
;
2394 HubWorkItemBuffer
->IsRequestErrors
= TRUE
;
2397 if (InterlockedIncrement(&HubExtension
->ResetRequestCount
) == 1)
2399 KeClearEvent(&HubExtension
->ResetEvent
);
2402 HubWorkItemBuffer
->HubExtension
= HubExtension
;
2404 HubExtension
->WorkItemToQueue
= HubWorkItem
;
2406 Bitmap
= HubWorkItemBuffer
+ 1;
2408 RtlCopyMemory(Bitmap
,
2409 HubExtension
->SCEBitmap
,
2410 HubExtension
->SCEBitmapLength
);
2412 NumPorts
= HubExtension
->HubDescriptor
->bNumberOfPorts
;
2414 for (Port
= 0; Port
<= NumPorts
; ++Port
)
2416 if (IsBitSet(Bitmap
, Port
))
2422 if (Port
> NumPorts
)
2427 Status
= USBH_ChangeIndicationQueryChange(HubExtension
,
2428 HubExtension
->ResetPortIrp
,
2429 &HubExtension
->SCEWorkerUrb
,
2432 if (NT_ERROR(Status
))
2434 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DEVICE_FAILED
;
2437 return STATUS_MORE_PROCESSING_REQUIRED
;
2442 USBH_SubmitStatusChangeTransfer(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2446 struct _URB_BULK_OR_INTERRUPT_TRANSFER
* Urb
;
2447 PIO_STACK_LOCATION IoStack
;
2449 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubExtension - %p, SCEIrp - %p\n",
2451 HubExtension
->SCEIrp
);
2453 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_NOT_D0_STATE
)
2455 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: USBHUB_FDO_FLAG_NOT_D0_STATE\n");
2456 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubFlags - %lX\n",
2457 HubExtension
->HubFlags
);
2459 return STATUS_INVALID_DEVICE_STATE
;
2462 Irp
= HubExtension
->SCEIrp
;
2466 return STATUS_INVALID_DEVICE_STATE
;
2469 Urb
= (struct _URB_BULK_OR_INTERRUPT_TRANSFER
*)&HubExtension
->SCEWorkerUrb
;
2471 Urb
->Hdr
.Length
= sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
);
2472 Urb
->Hdr
.Function
= URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
;
2473 Urb
->Hdr
.UsbdDeviceHandle
= NULL
;
2475 Urb
->PipeHandle
= HubExtension
->PipeInfo
.PipeHandle
;
2476 Urb
->TransferFlags
= USBD_SHORT_TRANSFER_OK
;
2477 Urb
->TransferBuffer
= HubExtension
->SCEBitmap
;
2478 Urb
->TransferBufferLength
= HubExtension
->SCEBitmapLength
;
2479 Urb
->TransferBufferMDL
= NULL
;
2480 Urb
->UrbLink
= NULL
;
2482 IoInitializeIrp(Irp
,
2483 IoSizeOfIrp(HubExtension
->LowerDevice
->StackSize
),
2484 HubExtension
->LowerDevice
->StackSize
);
2486 IoStack
= IoGetNextIrpStackLocation(Irp
);
2488 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
2489 IoStack
->Parameters
.Others
.Argument1
= &HubExtension
->SCEWorkerUrb
;
2490 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
2492 IoSetCompletionRoutine(Irp
,
2493 USBH_ChangeIndication
,
2499 KeClearEvent(&HubExtension
->StatusChangeEvent
);
2501 Status
= IoCallDriver(HubExtension
->LowerDevice
, Irp
);
2508 USBD_CreateDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2509 IN PUSB_DEVICE_HANDLE
* OutDeviceHandle
,
2510 IN USB_PORT_STATUS UsbPortStatus
,
2513 PUSB_DEVICE_HANDLE HubDeviceHandle
;
2514 PUSB_BUSIFFN_CREATE_USB_DEVICE CreateUsbDevice
;
2516 DPRINT("USBD_CreateDeviceEx: Port - %x, UsbPortStatus - 0x%04X\n",
2518 UsbPortStatus
.AsUshort16
);
2520 CreateUsbDevice
= HubExtension
->BusInterface
.CreateUsbDevice
;
2522 if (!CreateUsbDevice
)
2524 return STATUS_NOT_IMPLEMENTED
;
2527 HubDeviceHandle
= USBH_SyncGetDeviceHandle(HubExtension
->LowerDevice
);
2529 return CreateUsbDevice(HubExtension
->BusInterface
.BusContext
,
2532 UsbPortStatus
.AsUshort16
,
2538 USBD_RemoveDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2539 IN PUSB_DEVICE_HANDLE DeviceHandle
,
2542 PUSB_BUSIFFN_REMOVE_USB_DEVICE RemoveUsbDevice
;
2544 DPRINT("USBD_RemoveDeviceEx: DeviceHandle - %p, Flags - %X\n",
2548 RemoveUsbDevice
= HubExtension
->BusInterface
.RemoveUsbDevice
;
2550 if (!RemoveUsbDevice
)
2552 return STATUS_NOT_IMPLEMENTED
;
2555 return RemoveUsbDevice(HubExtension
->BusInterface
.BusContext
,
2562 USBD_InitializeDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2563 IN PUSB_DEVICE_HANDLE DeviceHandle
,
2564 IN PUCHAR DeviceDescriptorBuffer
,
2565 IN ULONG DeviceDescriptorBufferLength
,
2566 IN PUCHAR ConfigDescriptorBuffer
,
2567 IN ULONG ConfigDescriptorBufferLength
)
2570 PUSB_BUSIFFN_INITIALIZE_USB_DEVICE InitializeUsbDevice
;
2571 PUSB_BUSIFFN_GET_USB_DESCRIPTORS GetUsbDescriptors
;
2573 DPRINT("USBD_InitializeDeviceEx: ... \n");
2575 InitializeUsbDevice
= HubExtension
->BusInterface
.InitializeUsbDevice
;
2576 GetUsbDescriptors
= HubExtension
->BusInterface
.GetUsbDescriptors
;
2578 if (!InitializeUsbDevice
|| !GetUsbDescriptors
)
2580 return STATUS_NOT_IMPLEMENTED
;
2583 Status
= InitializeUsbDevice(HubExtension
->BusInterface
.BusContext
,
2586 if (!NT_SUCCESS(Status
))
2591 return GetUsbDescriptors(HubExtension
->BusInterface
.BusContext
,
2593 DeviceDescriptorBuffer
,
2594 &DeviceDescriptorBufferLength
,
2595 ConfigDescriptorBuffer
,
2596 &ConfigDescriptorBufferLength
);
2601 USBHUB_SetDeviceHandleData(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2602 IN PDEVICE_OBJECT UsbDevicePdo
,
2603 IN PVOID DeviceHandle
)
2605 PUSB_BUSIFFN_SET_DEVHANDLE_DATA SetDeviceHandleData
;
2607 DPRINT("USBHUB_SetDeviceHandleData ... \n");
2609 SetDeviceHandleData
= HubExtension
->BusInterface
.SetDeviceHandleData
;
2611 if (!SetDeviceHandleData
)
2616 SetDeviceHandleData(HubExtension
->BusInterface
.BusContext
,
2623 USBHUB_FlushAllTransfers(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2625 PUSB_BUSIFFN_FLUSH_TRANSFERS FlushTransfers
;
2627 DPRINT("USBHUB_FlushAllTransfers ... \n");
2629 FlushTransfers
= HubExtension
->BusInterface
.FlushTransfers
;
2633 FlushTransfers(HubExtension
->BusInterface
.BusContext
, NULL
);
2639 USBD_GetDeviceInformationEx(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
2640 IN PUSBHUB_FDO_EXTENSION HubExtension
,
2641 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info
,
2643 IN PUSB_DEVICE_HANDLE DeviceHandle
)
2645 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation
;
2646 PUSB_DEVICE_INFORMATION_0 DeviceInfo
;
2647 SIZE_T DeviceInfoLength
;
2648 PUSB_NODE_CONNECTION_INFORMATION_EX NodeInfo
;
2649 SIZE_T NodeInfoLength
;
2654 DPRINT("USBD_GetDeviceInformationEx ... \n");
2656 QueryDeviceInformation
= HubExtension
->BusInterface
.QueryDeviceInformation
;
2658 if (!QueryDeviceInformation
)
2660 Status
= STATUS_NOT_IMPLEMENTED
;
2664 DeviceInfoLength
= sizeof(USB_DEVICE_INFORMATION_0
);
2668 DeviceInfo
= ExAllocatePoolWithTag(PagedPool
,
2674 return STATUS_INSUFFICIENT_RESOURCES
;
2677 RtlZeroMemory(DeviceInfo
, DeviceInfoLength
);
2679 DeviceInfo
->InformationLevel
= 0;
2681 Status
= QueryDeviceInformation(HubExtension
->BusInterface
.BusContext
,
2687 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
2692 DeviceInfoLength
= DeviceInfo
->ActualLength
;
2694 ExFreePoolWithTag(DeviceInfo
, USB_HUB_TAG
);
2700 if (NT_SUCCESS(Status
))
2702 NodeInfoLength
= (sizeof(USB_NODE_CONNECTION_INFORMATION_EX
) - sizeof(USB_PIPE_INFO
)) +
2703 DeviceInfo
->NumberOfOpenPipes
* sizeof(USB_PIPE_INFO
);
2705 NodeInfo
= ExAllocatePoolWithTag(PagedPool
, NodeInfoLength
, USB_HUB_TAG
);
2709 ExFreePoolWithTag(DeviceInfo
, USB_HUB_TAG
);
2710 return STATUS_INSUFFICIENT_RESOURCES
;
2713 RtlZeroMemory(NodeInfo
, NodeInfoLength
);
2715 NodeInfo
->ConnectionIndex
= Info
->ConnectionIndex
;
2717 RtlCopyMemory(&NodeInfo
->DeviceDescriptor
,
2718 &DeviceInfo
->DeviceDescriptor
,
2719 sizeof(USB_DEVICE_DESCRIPTOR
));
2721 NodeInfo
->CurrentConfigurationValue
= DeviceInfo
->CurrentConfigurationValue
;
2722 NodeInfo
->Speed
= DeviceInfo
->DeviceSpeed
;
2723 NodeInfo
->DeviceIsHub
= PortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_HUB_DEVICE
;
2724 NodeInfo
->DeviceAddress
= DeviceInfo
->DeviceAddress
;
2725 NodeInfo
->NumberOfOpenPipes
= DeviceInfo
->NumberOfOpenPipes
;
2726 NodeInfo
->ConnectionStatus
= Info
->ConnectionStatus
;
2728 for (PipeNumber
= 0;
2729 PipeNumber
< DeviceInfo
->NumberOfOpenPipes
;
2732 RtlCopyMemory(&NodeInfo
->PipeList
[PipeNumber
],
2733 &DeviceInfo
->PipeList
[PipeNumber
],
2734 sizeof(USB_PIPE_INFO
));
2738 ExFreePoolWithTag(DeviceInfo
, USB_HUB_TAG
);
2742 if (NodeInfoLength
<= Length
)
2744 Length
= NodeInfoLength
;
2748 Status
= STATUS_BUFFER_TOO_SMALL
;
2751 RtlCopyMemory(Info
, NodeInfo
, Length
);
2753 ExFreePoolWithTag(NodeInfo
, USB_HUB_TAG
);
2761 USBD_RestoreDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2762 IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle
,
2763 IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle
)
2765 PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice
;
2768 DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n",
2773 RestoreUsbDevice
= HubExtension
->BusInterface
.RestoreUsbDevice
;
2775 if (RestoreUsbDevice
)
2777 Status
= RestoreUsbDevice(HubExtension
->BusInterface
.BusContext
,
2783 Status
= STATUS_NOT_IMPLEMENTED
;
2791 USBH_AllocateWorkItem(PUSBHUB_FDO_EXTENSION HubExtension
,
2792 PUSBHUB_IO_WORK_ITEM
* OutHubIoWorkItem
,
2793 PUSBHUB_WORKER_ROUTINE WorkerRoutine
,
2794 SIZE_T BufferLength
,
2795 PVOID
* OutHubWorkItemBuffer
,
2796 WORK_QUEUE_TYPE Type
)
2798 PUSBHUB_IO_WORK_ITEM HubIoWorkItem
;
2799 PIO_WORKITEM WorkItem
;
2800 PVOID WorkItemBuffer
;
2802 DPRINT("USBH_AllocateWorkItem: ... \n");
2804 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WITEM_INIT
))
2806 return STATUS_INVALID_PARAMETER
;
2809 HubIoWorkItem
= ExAllocatePoolWithTag(NonPagedPool
,
2810 sizeof(USBHUB_IO_WORK_ITEM
),
2815 return STATUS_INSUFFICIENT_RESOURCES
;
2818 RtlZeroMemory(HubIoWorkItem
, sizeof(USBHUB_IO_WORK_ITEM
));
2820 WorkItem
= IoAllocateWorkItem(HubExtension
->Common
.SelfDevice
);
2822 HubIoWorkItem
->HubWorkItem
= WorkItem
;
2826 ExFreePoolWithTag(HubIoWorkItem
, USB_HUB_TAG
);
2827 return STATUS_INSUFFICIENT_RESOURCES
;
2830 if (BufferLength
&& OutHubWorkItemBuffer
)
2832 WorkItemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2836 HubIoWorkItem
->HubWorkItemBuffer
= WorkItemBuffer
;
2838 if (!WorkItemBuffer
)
2840 IoFreeWorkItem(HubIoWorkItem
->HubWorkItem
);
2841 ExFreePoolWithTag(HubIoWorkItem
, USB_HUB_TAG
);
2843 return STATUS_INSUFFICIENT_RESOURCES
;
2846 RtlZeroMemory(WorkItemBuffer
, BufferLength
);
2850 HubIoWorkItem
->HubWorkItemBuffer
= NULL
;
2853 HubIoWorkItem
->HubWorkItemType
= Type
;
2854 HubIoWorkItem
->HubExtension
= HubExtension
;
2855 HubIoWorkItem
->HubWorkerRoutine
= WorkerRoutine
;
2857 if (OutHubIoWorkItem
)
2859 *OutHubIoWorkItem
= HubIoWorkItem
;
2862 if (OutHubWorkItemBuffer
)
2864 *OutHubWorkItemBuffer
= HubIoWorkItem
->HubWorkItemBuffer
;
2867 return STATUS_SUCCESS
;
2872 USBH_Worker(IN PDEVICE_OBJECT DeviceObject
,
2875 PUSBHUB_IO_WORK_ITEM HubIoWorkItem
;
2876 PUSBHUB_FDO_EXTENSION HubExtension
;
2878 PIO_WORKITEM WorkItem
;
2880 DPRINT("USBH_Worker: HubIoWorkItem - %p\n", Context
);
2882 HubIoWorkItem
= Context
;
2884 InterlockedDecrement(&HubIoWorkItem
->HubWorkerQueued
);
2886 HubExtension
= HubIoWorkItem
->HubExtension
;
2887 WorkItem
= HubIoWorkItem
->HubWorkItem
;
2889 HubIoWorkItem
->HubWorkerRoutine(HubIoWorkItem
->HubExtension
,
2890 HubIoWorkItem
->HubWorkItemBuffer
);
2892 KeAcquireSpinLock(&HubExtension
->WorkItemSpinLock
, &OldIrql
);
2893 RemoveEntryList(&HubIoWorkItem
->HubWorkItemLink
);
2894 KeReleaseSpinLock(&HubExtension
->WorkItemSpinLock
, OldIrql
);
2896 if (HubIoWorkItem
->HubWorkItemBuffer
)
2898 ExFreePoolWithTag(HubIoWorkItem
->HubWorkItemBuffer
, USB_HUB_TAG
);
2901 ExFreePoolWithTag(HubIoWorkItem
, USB_HUB_TAG
);
2903 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
2905 KeSetEvent(&HubExtension
->PendingRequestEvent
,
2910 IoFreeWorkItem(WorkItem
);
2912 DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context
);
2917 USBH_QueueWorkItem(IN PUSBHUB_FDO_EXTENSION HubExtension
,
2918 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem
)
2920 DPRINT("USBH_QueueWorkItem: ... \n");
2922 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
2923 InterlockedIncrement(&HubIoWorkItem
->HubWorkerQueued
);
2925 ExInterlockedInsertTailList(&HubExtension
->WorkItemList
,
2926 &HubIoWorkItem
->HubWorkItemLink
,
2927 &HubExtension
->WorkItemSpinLock
);
2929 IoQueueWorkItem(HubIoWorkItem
->HubWorkItem
,
2931 HubIoWorkItem
->HubWorkItemType
,
2937 USBH_FreeWorkItem(IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem
)
2939 PIO_WORKITEM WorkItem
;
2941 DPRINT("USBH_FreeWorkItem: ... \n");
2943 WorkItem
= HubIoWorkItem
->HubWorkItem
;
2945 if (HubIoWorkItem
->HubWorkItemBuffer
)
2947 ExFreePoolWithTag(HubIoWorkItem
->HubWorkItemBuffer
, USB_HUB_TAG
);
2950 ExFreePoolWithTag(HubIoWorkItem
, USB_HUB_TAG
);
2952 IoFreeWorkItem(WorkItem
);
2957 USBHUB_RootHubCallBack(IN PVOID Context
)
2959 PUSBHUB_FDO_EXTENSION HubExtension
;
2961 DPRINT("USBHUB_RootHubCallBack: ... \n");
2963 HubExtension
= Context
;
2965 if (HubExtension
->SCEIrp
)
2967 HubExtension
->HubFlags
|= (USBHUB_FDO_FLAG_DO_ENUMERATION
|
2968 USBHUB_FDO_FLAG_NOT_ENUMERATED
);
2970 USBH_SubmitStatusChangeTransfer(HubExtension
);
2972 IoInvalidateDeviceRelations(HubExtension
->LowerPDO
, BusRelations
);
2976 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DO_ENUMERATION
;
2979 KeSetEvent(&HubExtension
->RootHubNotificationEvent
,
2986 USBD_RegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension
)
2988 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification
;
2990 DPRINT("USBD_RegisterRootHubCallBack: ... \n");
2992 RootHubInitNotification
= HubExtension
->BusInterface
.RootHubInitNotification
;
2994 if (!RootHubInitNotification
)
2996 return STATUS_NOT_IMPLEMENTED
;
2999 KeClearEvent(&HubExtension
->RootHubNotificationEvent
);
3001 return RootHubInitNotification(HubExtension
->BusInterface
.BusContext
,
3003 USBHUB_RootHubCallBack
);
3008 USBD_UnRegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3010 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification
;
3013 DPRINT("USBD_UnRegisterRootHubCallBack ... \n");
3015 RootHubInitNotification
= HubExtension
->BusInterface
.RootHubInitNotification
;
3017 if (!RootHubInitNotification
)
3019 return STATUS_NOT_IMPLEMENTED
;
3022 Status
= RootHubInitNotification(HubExtension
->BusInterface
.BusContext
,
3026 if (!NT_SUCCESS(Status
))
3028 KeWaitForSingleObject(&HubExtension
->RootHubNotificationEvent
,
3040 USBH_HubSetDWakeCompletion(IN PDEVICE_OBJECT DeviceObject
,
3041 IN UCHAR MinorFunction
,
3042 IN POWER_STATE PowerState
,
3044 IN PIO_STATUS_BLOCK IoStatus
)
3046 DPRINT("USBH_HubSetDWakeCompletion: ... \n");
3047 KeSetEvent((PRKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
3052 USBH_HubQueuePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3053 IN PLIST_ENTRY IdleList
)
3055 PDEVICE_OBJECT PortDevice
;
3056 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
3063 DPRINT("USBH_HubQueuePortIdleIrps ... \n");
3065 InitializeListHead(IdleList
);
3067 IoAcquireCancelSpinLock(&Irql
);
3069 NumPorts
= HubExtension
->HubDescriptor
->bNumberOfPorts
;
3071 for (Port
= 0; Port
< NumPorts
; ++Port
)
3073 PortDevice
= HubExtension
->PortData
[Port
].DeviceObject
;
3077 PortExtension
= PortDevice
->DeviceExtension
;
3079 IdleIrp
= PortExtension
->IdleNotificationIrp
;
3080 PortExtension
->IdleNotificationIrp
= NULL
;
3082 if (IdleIrp
&& IoSetCancelRoutine(IdleIrp
, NULL
))
3084 DPRINT1("USBH_HubQueuePortIdleIrps: IdleIrp != NULL. FIXME\n");
3090 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
)
3092 HubIdleIrp
= HubExtension
->PendingIdleIrp
;
3093 HubExtension
->PendingIdleIrp
= NULL
;
3100 IoReleaseCancelSpinLock(Irql
);
3104 USBH_HubCancelIdleIrp(HubExtension
, HubIdleIrp
);
3110 USBH_HubCompleteQueuedPortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3111 IN PLIST_ENTRY IdleList
,
3112 IN NTSTATUS NtStatus
)
3114 DPRINT("USBH_HubCompleteQueuedPortIdleIrps ... \n");
3116 while (!IsListEmpty(IdleList
))
3118 DPRINT1("USBH_HubCompleteQueuedPortIdleIrps: IdleList not Empty. FIXME\n");
3125 USBH_FlushPortPwrList(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3127 PDEVICE_OBJECT PortDevice
;
3128 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
3132 DPRINT("USBH_FlushPortPwrList ... \n");
3134 InterlockedIncrement((PLONG
)&HubExtension
->PendingRequestCount
);
3136 KeWaitForSingleObject(&HubExtension
->ResetDeviceSemaphore
,
3142 for (Port
= 0; Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
; ++Port
)
3144 PortDevice
= HubExtension
->PortData
[Port
].DeviceObject
;
3151 PortExtension
= PortDevice
->DeviceExtension
;
3153 InterlockedExchange((PLONG
)&PortExtension
->StateBehindD2
, 0);
3157 Entry
= ExInterlockedRemoveHeadList(&PortExtension
->PortPowerList
,
3158 &PortExtension
->PortPowerListSpinLock
);
3165 DPRINT1("USBH_FlushPortPwrList: PortPowerList FIXME\n");
3170 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
3171 LOW_REALTIME_PRIORITY
,
3175 if (!InterlockedDecrement((PLONG
)&HubExtension
->PendingRequestCount
))
3177 KeSetEvent(&HubExtension
->PendingRequestEvent
,
3185 USBH_HubCompletePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3186 IN NTSTATUS NtStatus
)
3188 LIST_ENTRY IdleList
;
3190 DPRINT("USBH_HubCompletePortIdleIrps ... \n");
3192 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
)
3194 USBH_HubQueuePortIdleIrps(HubExtension
, &IdleList
);
3196 USBH_HubCompleteQueuedPortIdleIrps(HubExtension
,
3200 USBH_FlushPortPwrList(HubExtension
);
3206 USBH_HubCancelIdleIrp(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3209 DPRINT("USBH_HubCancelIdleIrp ... \n");
3211 IoCancelIrp(IdleIrp
);
3213 if (InterlockedExchange(&HubExtension
->IdleRequestLock
, 1))
3221 USBH_CheckIdleAbort(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3223 IN BOOLEAN IsExtCheck
)
3225 PDEVICE_OBJECT PdoDevice
;
3226 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
3227 PUSBHUB_PORT_DATA PortData
;
3229 BOOLEAN Result
= FALSE
;
3231 DPRINT("USBH_CheckIdleAbort: ... \n");
3233 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
3237 KeWaitForSingleObject(&HubExtension
->ResetDeviceSemaphore
,
3244 PortData
= HubExtension
->PortData
;
3246 for (Port
= 0; Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
; Port
++)
3248 PdoDevice
= PortData
[Port
].DeviceObject
;
3252 PortExtension
= PdoDevice
->DeviceExtension
;
3254 if (PortExtension
->PoRequestCounter
)
3262 if (IsExtCheck
== TRUE
)
3264 PortData
= HubExtension
->PortData
;
3267 Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
;
3270 PdoDevice
= PortData
[Port
].DeviceObject
;
3274 PortExtension
= PdoDevice
->DeviceExtension
;
3275 InterlockedExchange(&PortExtension
->StateBehindD2
, 0);
3284 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
3285 LOW_REALTIME_PRIORITY
,
3290 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
3292 KeSetEvent(&HubExtension
->PendingRequestEvent
,
3302 USBH_FdoWaitWakeIrpCompletion(IN PDEVICE_OBJECT DeviceObject
,
3303 IN UCHAR MinorFunction
,
3304 IN POWER_STATE PowerState
,
3306 IN PIO_STATUS_BLOCK IoStatus
)
3308 DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n");
3313 USBH_FdoSubmitWaitWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3315 POWER_STATE PowerState
;
3320 DPRINT("USBH_FdoSubmitWaitWakeIrp: ... \n");
3322 PowerState
.SystemState
= HubExtension
->SystemWake
;
3323 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_PENDING_WAKE_IRP
;
3325 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
3326 InterlockedExchange(&HubExtension
->FdoWaitWakeLock
, 0);
3328 Status
= PoRequestPowerIrp(HubExtension
->LowerPDO
,
3331 USBH_FdoWaitWakeIrpCompletion
,
3335 IoAcquireCancelSpinLock(&Irql
);
3337 if (Status
== STATUS_PENDING
)
3339 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_PENDING_WAKE_IRP
)
3341 HubExtension
->PendingWakeIrp
= Irp
;
3342 DPRINT("USBH_FdoSubmitWaitWakeIrp: PendingWakeIrp - %p\n",
3343 HubExtension
->PendingWakeIrp
);
3348 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP
;
3350 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
3352 KeSetEvent(&HubExtension
->PendingRequestEvent
,
3358 IoReleaseCancelSpinLock(Irql
);
3365 USBH_FdoIdleNotificationCallback(IN PVOID Context
)
3367 PUSBHUB_FDO_EXTENSION HubExtension
;
3368 PUSBHUB_PORT_DATA PortData
;
3369 PDEVICE_OBJECT PortDevice
;
3370 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
3373 POWER_STATE PowerState
;
3376 PIO_STACK_LOCATION IoStack
;
3377 PUSB_IDLE_CALLBACK_INFO CallbackInfo
;
3382 HubExtension
= Context
;
3384 DPRINT("USBH_FdoIdleNotificationCallback: HubExtension - %p, HubFlags - %lX\n",
3386 HubExtension
->HubFlags
);
3388 if (HubExtension
->HubFlags
& (USBHUB_FDO_FLAG_ENUM_POST_RECOVER
|
3389 USBHUB_FDO_FLAG_WAKEUP_START
|
3390 USBHUB_FDO_FLAG_DEVICE_REMOVED
|
3391 USBHUB_FDO_FLAG_STATE_CHANGING
|
3392 USBHUB_FDO_FLAG_ESD_RECOVERING
|
3393 USBHUB_FDO_FLAG_DEVICE_FAILED
|
3394 USBHUB_FDO_FLAG_DEVICE_STOPPING
))
3400 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_GOING_IDLE
;
3402 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_PENDING_WAKE_IRP
))
3404 Status
= USBH_FdoSubmitWaitWakeIrp(HubExtension
);
3406 if (Status
!= STATUS_PENDING
)
3408 DPRINT("Status != STATUS_PENDING. DbgBreakPoint()\n");
3410 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_GOING_IDLE
;
3415 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
3417 KeWaitForSingleObject(&HubExtension
->ResetDeviceSemaphore
,
3423 PortData
= HubExtension
->PortData
;
3427 Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
;
3430 PortDevice
= PortData
[Port
].DeviceObject
;
3434 PortExtension
= PortDevice
->DeviceExtension
;
3436 IdleIrp
= PortExtension
->IdleNotificationIrp
;
3444 IoStack
= IoGetCurrentIrpStackLocation(IdleIrp
);
3446 CallbackInfo
= IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
3454 if (!CallbackInfo
->IdleCallback
)
3460 if (PortExtension
->PendingSystemPoRequest
)
3466 if (InterlockedCompareExchange(&PortExtension
->StateBehindD2
,
3474 DPRINT("USBH_FdoIdleNotificationCallback: IdleContext - %p\n",
3475 CallbackInfo
->IdleContext
);
3477 CallbackInfo
->IdleCallback(CallbackInfo
->IdleContext
);
3479 if (PortExtension
->CurrentPowerState
.DeviceState
== PowerDeviceD0
)
3487 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
) &&
3488 (USBH_CheckIdleAbort(HubExtension
, FALSE
, FALSE
) == TRUE
))
3495 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
3496 LOW_REALTIME_PRIORITY
,
3500 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
3502 KeSetEvent(&HubExtension
->PendingRequestEvent
,
3508 (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_SUSPENDED
))
3510 DPRINT1("USBH_FdoIdleNotificationCallback: HubFlags - %lX\n",
3511 HubExtension
->HubFlags
);
3513 HubExtension
->HubFlags
&= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED
|
3514 USBHUB_FDO_FLAG_GOING_IDLE
);
3516 /* Aborting Idle for Hub */
3517 IoAcquireCancelSpinLock(&OldIrql
);
3519 if (HubExtension
->PendingIdleIrp
)
3521 Irp
= HubExtension
->PendingIdleIrp
;
3522 HubExtension
->PendingIdleIrp
= NULL
;
3525 IoReleaseCancelSpinLock(OldIrql
);
3529 USBH_HubCancelIdleIrp(HubExtension
, Irp
);
3533 USBH_HubCompletePortIdleIrps(HubExtension
, STATUS_CANCELLED
);
3537 PowerState
.DeviceState
= HubExtension
->DeviceWake
;
3539 KeWaitForSingleObject(&HubExtension
->IdleSemaphore
,
3545 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_GOING_IDLE
;
3546 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DO_SUSPENSE
;
3548 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
3550 DPRINT("USBH_FdoIdleNotificationCallback: LowerPdo - %p\n",
3551 HubExtension
->LowerPDO
);
3553 DPRINT("USBH_FdoIdleNotificationCallback: PowerState.DeviceState - %x\n",
3554 PowerState
.DeviceState
);
3556 Status
= PoRequestPowerIrp(HubExtension
->LowerPDO
,
3559 USBH_HubSetDWakeCompletion
,
3563 if (Status
== STATUS_PENDING
)
3565 KeWaitForSingleObject(&Event
,
3576 USBH_CompletePortIdleIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3579 PUSBHUB_IDLE_PORT_CONTEXT IdlePortContext
;
3582 BOOLEAN IsFlush
= FALSE
;
3584 DPRINT("USBH_CompletePortIdleIrpsWorker ... \n");
3586 IdlePortContext
= Context
;
3587 NtStatus
= IdlePortContext
->Status
;
3589 USBH_HubCompleteQueuedPortIdleIrps(HubExtension
,
3590 &IdlePortContext
->PwrList
,
3593 DPRINT1("USBH_CompletePortIdleIrpsWorker: USBH_RegQueryFlushPortPowerIrpsFlag() UNIMPLEMENTED. FIXME\n");
3594 Status
= STATUS_NOT_IMPLEMENTED
;// USBH_RegQueryFlushPortPowerIrpsFlag(&IsFlush);
3596 if (NT_SUCCESS(Status
))
3600 USBH_FlushPortPwrList(HubExtension
);
3607 USBH_IdleCompletePowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3610 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer
;
3612 DPRINT("USBH_IdleCompletePowerHubWorker ... \n");
3615 HubExtension
->CurrentPowerState
.DeviceState
!= PowerDeviceD0
&&
3616 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
)
3618 USBH_HubSetD0(HubExtension
);
3621 HubWorkItemBuffer
= Context
;
3623 USBH_HubCompletePortIdleIrps(HubExtension
, HubWorkItemBuffer
->Status
);
3629 USBH_FdoIdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject
,
3633 PUSBHUB_FDO_EXTENSION HubExtension
;
3638 PUSBHUB_IO_WORK_ITEM HubIoWorkItem
;
3640 IoAcquireCancelSpinLock(&Irql
);
3642 HubExtension
= Context
;
3643 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
;
3645 IdleIrp
= InterlockedExchangePointer((PVOID
)&HubExtension
->PendingIdleIrp
,
3648 DPRINT("USBH_FdoIdleNotificationRequestComplete: IdleIrp - %p\n", IdleIrp
);
3650 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
3652 KeSetEvent(&HubExtension
->PendingRequestEvent
, EVENT_INCREMENT
, FALSE
);
3655 IoReleaseCancelSpinLock(Irql
);
3657 NtStatus
= Irp
->IoStatus
.Status
;
3659 DPRINT("USBH_FdoIdleNotificationRequestComplete: NtStatus - %lX\n",
3662 if (!NT_SUCCESS(NtStatus
) &&
3663 NtStatus
!= STATUS_POWER_STATE_INVALID
&&
3664 !(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_REMOVED
) &&
3665 !(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPED
))
3667 DPRINT("USBH_FdoIdleNotificationRequestComplete: DeviceState - %x\n",
3668 HubExtension
->CurrentPowerState
.DeviceState
);
3670 if (HubExtension
->CurrentPowerState
.DeviceState
== PowerDeviceD0
)
3672 PUSBHUB_IDLE_PORT_CONTEXT HubWorkItemBuffer
;
3674 Status
= USBH_AllocateWorkItem(HubExtension
,
3676 USBH_CompletePortIdleIrpsWorker
,
3677 sizeof(USBHUB_IDLE_PORT_CONTEXT
),
3678 (PVOID
*)&HubWorkItemBuffer
,
3681 if (NT_SUCCESS(Status
))
3683 HubWorkItemBuffer
->Status
= NtStatus
;
3685 USBH_HubQueuePortIdleIrps(HubExtension
,
3686 &HubWorkItemBuffer
->PwrList
);
3688 USBH_QueueWorkItem(HubExtension
, HubIoWorkItem
);
3693 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer
;
3695 Status
= USBH_AllocateWorkItem(HubExtension
,
3697 USBH_IdleCompletePowerHubWorker
,
3698 sizeof(USBHUB_IDLE_HUB_CONTEXT
),
3699 (PVOID
*)&HubWorkItemBuffer
,
3702 if (NT_SUCCESS(Status
))
3704 HubWorkItemBuffer
->Status
= NtStatus
;
3705 USBH_QueueWorkItem(HubExtension
, HubIoWorkItem
);
3711 InterlockedExchange((PLONG
)&HubExtension
->IdleRequestLock
, 1))
3713 DPRINT("USBH_FdoIdleNotificationRequestComplete: Irp - %p\n", Irp
);
3717 return STATUS_MORE_PROCESSING_REQUIRED
;
3722 USBH_FdoSubmitIdleRequestIrp(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3726 PDEVICE_OBJECT LowerPDO
;
3728 PIO_STACK_LOCATION IoStack
;
3731 DPRINT("USBH_FdoSubmitIdleRequestIrp: HubExtension - %p, PendingIdleIrp - %p\n",
3733 HubExtension
->PendingIdleIrp
);
3735 if (HubExtension
->PendingIdleIrp
)
3737 Status
= STATUS_DEVICE_BUSY
;
3738 KeSetEvent(&HubExtension
->IdleEvent
, EVENT_INCREMENT
, FALSE
);
3742 HubFlags
= HubExtension
->HubFlags
;
3744 if (HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
||
3745 HubFlags
& USBHUB_FDO_FLAG_DEVICE_REMOVED
)
3747 HubExtension
->HubFlags
= HubFlags
& ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
;
3748 KeSetEvent(&HubExtension
->IdleEvent
, EVENT_INCREMENT
, FALSE
);
3749 return STATUS_DEVICE_REMOVED
;
3752 LowerPDO
= HubExtension
->LowerPDO
;
3754 HubExtension
->IdleCallbackInfo
.IdleCallback
= USBH_FdoIdleNotificationCallback
;
3755 HubExtension
->IdleCallbackInfo
.IdleContext
= HubExtension
;
3757 Irp
= IoAllocateIrp(LowerPDO
->StackSize
, FALSE
);
3761 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
;
3762 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3764 KeSetEvent(&HubExtension
->IdleEvent
, EVENT_INCREMENT
, FALSE
);
3768 IoStack
= IoGetNextIrpStackLocation(Irp
);
3770 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
3772 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= sizeof(USB_IDLE_CALLBACK_INFO
);
3773 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
;
3774 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= &HubExtension
->IdleCallbackInfo
;
3776 IoSetCompletionRoutine(Irp
,
3777 USBH_FdoIdleNotificationRequestComplete
,
3783 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
3784 InterlockedExchange(&HubExtension
->IdleRequestLock
, 0);
3786 HubExtension
->HubFlags
&= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED
|
3787 USBHUB_FDO_FLAG_GOING_IDLE
);
3789 Status
= IoCallDriver(HubExtension
->LowerPDO
, Irp
);
3791 IoAcquireCancelSpinLock(&Irql
);
3793 if (Status
== STATUS_PENDING
&&
3794 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
)
3796 HubExtension
->PendingIdleIrp
= Irp
;
3799 IoReleaseCancelSpinLock(Irql
);
3801 KeSetEvent(&HubExtension
->IdleEvent
, EVENT_INCREMENT
, FALSE
);
3808 USBH_CheckHubIdle(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3810 PDEVICE_OBJECT PdoDevice
;
3811 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
3812 PUSBHUB_PORT_DATA PortData
;
3816 BOOLEAN IsHubIdle
= FALSE
;
3817 BOOLEAN IsAllPortsIdle
;
3818 BOOLEAN IsHubCheck
= TRUE
;
3820 DPRINT("USBH_CheckHubIdle: FIXME !!! HubExtension - %p\n", HubExtension
);
3822 return; //HACK: delete it line after fixing Power Manager!!!
3824 KeAcquireSpinLock(&HubExtension
->CheckIdleSpinLock
, &Irql
);
3826 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_CHECK_IDLE_LOCK
)
3828 KeReleaseSpinLock(&HubExtension
->CheckIdleSpinLock
, Irql
);
3832 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_CHECK_IDLE_LOCK
;
3833 KeReleaseSpinLock(&HubExtension
->CheckIdleSpinLock
, Irql
);
3835 if (USBH_GetRootHubExtension(HubExtension
)->SystemPowerState
.SystemState
!= PowerSystemWorking
)
3837 KeAcquireSpinLock(&HubExtension
->CheckIdleSpinLock
, &Irql
);
3838 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK
;
3839 KeReleaseSpinLock(&HubExtension
->CheckIdleSpinLock
, Irql
);
3843 HubFlags
= HubExtension
->HubFlags
;
3844 DPRINT("USBH_CheckHubIdle: HubFlags - %lX\n", HubFlags
);
3846 if (!(HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
) ||
3847 !(HubFlags
& USBHUB_FDO_FLAG_DO_ENUMERATION
))
3852 if (HubFlags
& USBHUB_FDO_FLAG_NOT_ENUMERATED
||
3853 HubFlags
& USBHUB_FDO_FLAG_ENUM_POST_RECOVER
||
3854 HubFlags
& USBHUB_FDO_FLAG_DEVICE_FAILED
||
3855 HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPING
||
3856 HubFlags
& USBHUB_FDO_FLAG_DEVICE_REMOVED
||
3857 HubFlags
& USBHUB_FDO_FLAG_STATE_CHANGING
||
3858 HubFlags
& USBHUB_FDO_FLAG_WAKEUP_START
||
3859 HubFlags
& USBHUB_FDO_FLAG_ESD_RECOVERING
)
3864 if (HubExtension
->ResetRequestCount
)
3866 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_DEFER_CHECK_IDLE
;
3870 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_DEFER_CHECK_IDLE
;
3872 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
3874 KeWaitForSingleObject(&HubExtension
->ResetDeviceSemaphore
,
3880 IoAcquireCancelSpinLock(&Irql
);
3882 IsAllPortsIdle
= TRUE
;
3884 PortData
= HubExtension
->PortData
;
3887 Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
;
3890 PdoDevice
= PortData
[Port
].DeviceObject
;
3894 PortExtension
= PdoDevice
->DeviceExtension
;
3896 if (!PortExtension
->IdleNotificationIrp
)
3898 DPRINT("USBH_CheckHubIdle: PortExtension - %p\n",
3901 IsAllPortsIdle
= FALSE
;
3910 !(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
))
3912 KeClearEvent(&HubExtension
->IdleEvent
);
3913 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
;
3917 IoReleaseCancelSpinLock(Irql
);
3919 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
3920 LOW_REALTIME_PRIORITY
,
3924 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
3926 KeSetEvent(&HubExtension
->PendingRequestEvent
,
3931 DPRINT("USBH_CheckHubIdle: IsAllPortsIdle - %x, IsHubIdle - %x\n",
3935 if (IsAllPortsIdle
&& IsHubIdle
)
3937 USBH_FdoSubmitIdleRequestIrp(HubExtension
);
3941 KeAcquireSpinLock(&HubExtension
->CheckIdleSpinLock
, &Irql
);
3942 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK
;
3943 KeReleaseSpinLock(&HubExtension
->CheckIdleSpinLock
, Irql
);
3948 USBH_CheckIdleWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
3951 DPRINT("USBH_CheckIdleWorker: ... \n");
3952 USBH_CheckHubIdle(HubExtension
);
3957 USBH_CheckIdleDeferred(IN PUSBHUB_FDO_EXTENSION HubExtension
)
3959 PUSBHUB_IO_WORK_ITEM HubIoWorkItem
;
3962 DPRINT("USBH_CheckIdleDeferred: HubExtension - %p\n", HubExtension
);
3964 Status
= USBH_AllocateWorkItem(HubExtension
,
3966 USBH_CheckIdleWorker
,
3971 DPRINT("USBH_CheckIdleDeferred: HubIoWorkItem - %p\n", HubIoWorkItem
);
3973 if (NT_SUCCESS(Status
))
3975 USBH_QueueWorkItem(HubExtension
, HubIoWorkItem
);
3981 USBH_PdoSetCapabilities(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
)
3983 PUSBHUB_FDO_EXTENSION HubExtension
;
3985 SYSTEM_POWER_STATE SystemPowerState
;
3986 PDEVICE_POWER_STATE pDeviceState
;
3988 DPRINT("USBH_PdoSetCapabilities ... \n");
3990 HubExtension
= PortExtension
->HubExtension
;
3992 PortExtension
->Capabilities
.Size
= 64;
3993 PortExtension
->Capabilities
.Version
= 1;
3995 PortExtension
->Capabilities
.Removable
= 1;
3996 PortExtension
->Capabilities
.Address
= PortExtension
->PortNumber
;
3998 if (PortExtension
->SerialNumber
)
4000 PortExtension
->Capabilities
.UniqueID
= 1;
4004 PortExtension
->Capabilities
.UniqueID
= 0;
4007 PortExtension
->Capabilities
.RawDeviceOK
= 0;
4009 RtlCopyMemory(PortExtension
->Capabilities
.DeviceState
,
4010 HubExtension
->DeviceState
,
4011 (PowerSystemMaximum
+ 2) * sizeof(POWER_STATE
));
4013 PortExtension
->Capabilities
.DeviceState
[1] = PowerDeviceD0
;
4015 if (PortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_REMOTE_WAKEUP
)
4017 PortExtension
->Capabilities
.DeviceWake
= PowerDeviceD2
;
4019 PortExtension
->Capabilities
.DeviceD1
= 1;
4020 PortExtension
->Capabilities
.DeviceD2
= 1;
4022 PortExtension
->Capabilities
.WakeFromD0
= 1;
4023 PortExtension
->Capabilities
.WakeFromD1
= 1;
4024 PortExtension
->Capabilities
.WakeFromD2
= 1;
4026 pDeviceState
= &PortExtension
->Capabilities
.DeviceState
[2];
4028 for (State
= 2; State
<= 5; State
++)
4030 SystemPowerState
= State
;
4032 if (PortExtension
->Capabilities
.SystemWake
< SystemPowerState
)
4034 *pDeviceState
= PowerDeviceD3
;
4038 *pDeviceState
= PowerDeviceD2
;
4046 PortExtension
->Capabilities
.DeviceWake
= PowerDeviceD0
;
4047 PortExtension
->Capabilities
.DeviceState
[2] = PowerDeviceD3
;
4048 PortExtension
->Capabilities
.DeviceState
[3] = PowerDeviceD3
;
4049 PortExtension
->Capabilities
.DeviceState
[4] = PowerDeviceD3
;
4050 PortExtension
->Capabilities
.DeviceState
[5] = PowerDeviceD3
;
4056 USBH_ProcessDeviceInformation(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
)
4058 PUSB_INTERFACE_DESCRIPTOR Pid
;
4059 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
;
4062 DPRINT("USBH_ProcessDeviceInformation ... \n");
4064 ConfigDescriptor
= NULL
;
4066 RtlZeroMemory(&PortExtension
->InterfaceDescriptor
,
4067 sizeof(PortExtension
->InterfaceDescriptor
));
4069 PortExtension
->PortPdoFlags
&= ~USBHUB_PDO_FLAG_HUB_DEVICE
;
4071 Status
= USBH_GetConfigurationDescriptor(PortExtension
->Common
.SelfDevice
,
4074 if (!NT_SUCCESS(Status
))
4076 if (ConfigDescriptor
)
4078 ExFreePool(ConfigDescriptor
);
4084 PortExtension
->PortPdoFlags
&= ~USBHUB_PDO_FLAG_REMOTE_WAKEUP
;
4086 if (ConfigDescriptor
->bmAttributes
& 0x20)
4088 /* device configuration supports remote wakeup */
4089 PortExtension
->PortPdoFlags
|= USBHUB_PDO_FLAG_REMOTE_WAKEUP
;
4092 USBHUB_DumpingDeviceDescriptor(&PortExtension
->DeviceDescriptor
);
4093 USBHUB_DumpingConfiguration(ConfigDescriptor
);
4095 DPRINT_PNP("USBH_ProcessDeviceInformation: Class - %x, SubClass - %x, Protocol - %x\n",
4096 PortExtension
->DeviceDescriptor
.bDeviceClass
,
4097 PortExtension
->DeviceDescriptor
.bDeviceSubClass
,
4098 PortExtension
->DeviceDescriptor
.bDeviceProtocol
);
4100 DPRINT_PNP("USBH_ProcessDeviceInformation: bNumConfigurations - %x, bNumInterfaces - %x\n",
4101 PortExtension
->DeviceDescriptor
.bNumConfigurations
,
4102 ConfigDescriptor
->bNumInterfaces
);
4105 /* Enumeration of USB Composite Devices (msdn):
4106 1) The device class field of the device descriptor (bDeviceClass) must contain a value of zero,
4107 or the class (bDeviceClass), subclass (bDeviceSubClass), and protocol (bDeviceProtocol)
4108 fields of the device descriptor must have the values 0xEF, 0x02 and 0x01 respectively,
4109 as explained in USB Interface Association Descriptor.
4110 2) The device must have multiple interfaces
4111 3) The device must have a single configuration.
4114 if (((PortExtension
->DeviceDescriptor
.bDeviceClass
== USB_DEVICE_CLASS_RESERVED
) ||
4115 (PortExtension
->DeviceDescriptor
.bDeviceClass
== USB_DEVICE_CLASS_MISCELLANEOUS
&&
4116 PortExtension
->DeviceDescriptor
.bDeviceSubClass
== 0x02 &&
4117 PortExtension
->DeviceDescriptor
.bDeviceProtocol
== 0x01)) &&
4118 (ConfigDescriptor
->bNumInterfaces
> 1) &&
4119 (PortExtension
->DeviceDescriptor
.bNumConfigurations
< 2))
4121 DPRINT("USBH_ProcessDeviceInformation: Multi-Interface configuration\n");
4123 PortExtension
->PortPdoFlags
|= USBHUB_PDO_FLAG_MULTI_INTERFACE
;
4125 if (ConfigDescriptor
)
4127 ExFreePool(ConfigDescriptor
);
4133 Pid
= USBD_ParseConfigurationDescriptorEx(ConfigDescriptor
,
4142 RtlCopyMemory(&PortExtension
->InterfaceDescriptor
,
4144 sizeof(PortExtension
->InterfaceDescriptor
));
4146 if (Pid
->bInterfaceClass
== USB_DEVICE_CLASS_HUB
)
4148 PortExtension
->PortPdoFlags
|= (USBHUB_PDO_FLAG_HUB_DEVICE
|
4149 USBHUB_PDO_FLAG_REMOTE_WAKEUP
);
4154 Status
= STATUS_UNSUCCESSFUL
;
4157 if (ConfigDescriptor
)
4159 ExFreePool(ConfigDescriptor
);
4167 USBH_CheckDeviceIDUnique(IN PUSBHUB_FDO_EXTENSION HubExtension
,
4169 IN USHORT idProduct
,
4170 IN PVOID SerialNumber
,
4171 IN USHORT SN_DescriptorLength
)
4173 PDEVICE_OBJECT PortDevice
;
4174 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
4178 DPRINT("USBH_CheckDeviceIDUnique: idVendor - 0x%04X, idProduct - 0x%04X\n",
4182 if (!HubExtension
->HubDescriptor
->bNumberOfPorts
)
4187 for (Port
= 0; Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
; Port
++)
4189 PortDevice
= HubExtension
->PortData
[Port
].DeviceObject
;
4193 PortExtension
= PortDevice
->DeviceExtension
;
4195 if (PortExtension
->DeviceDescriptor
.idVendor
== idVendor
&&
4196 PortExtension
->DeviceDescriptor
.idProduct
== idProduct
&&
4197 PortExtension
->SN_DescriptorLength
== SN_DescriptorLength
)
4199 if (PortExtension
->SerialNumber
)
4201 NumberBytes
= RtlCompareMemory(PortExtension
->SerialNumber
,
4203 SN_DescriptorLength
);
4205 if (NumberBytes
== SN_DescriptorLength
)
4219 USBH_ValidateSerialNumberString(IN PUSHORT SerialNumberString
)
4224 DPRINT("USBH_ValidateSerialNumberString: ... \n");
4226 for (ix
= 0; SerialNumberString
[ix
] != UNICODE_NULL
; ix
++)
4228 Symbol
= SerialNumberString
[ix
];
4230 if (Symbol
< 0x20 || Symbol
> 0x7F || Symbol
== 0x2C) // ','
4242 USBH_CheckDeviceLanguage(IN PDEVICE_OBJECT DeviceObject
,
4243 IN USHORT LanguageId
)
4245 PUSB_STRING_DESCRIPTOR Descriptor
;
4252 DPRINT("USBH_CheckDeviceLanguage: LanguageId - 0x%04X\n", LanguageId
);
4254 Descriptor
= ExAllocatePoolWithTag(NonPagedPool
,
4255 MAXIMUM_USB_STRING_LENGTH
,
4260 return STATUS_INSUFFICIENT_RESOURCES
;
4263 RtlZeroMemory(Descriptor
, MAXIMUM_USB_STRING_LENGTH
);
4265 Status
= USBH_SyncGetStringDescriptor(DeviceObject
,
4269 MAXIMUM_USB_STRING_LENGTH
,
4273 if (!NT_SUCCESS(Status
) ||
4274 Length
< sizeof(USB_COMMON_DESCRIPTOR
))
4279 NumSymbols
= (Length
-
4280 FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
)) / sizeof(WCHAR
);
4282 pSymbol
= Descriptor
->bString
;
4284 for (ix
= 1; ix
< NumSymbols
; ix
++)
4286 if (*pSymbol
== (WCHAR
)LanguageId
)
4288 Status
= STATUS_SUCCESS
;
4295 Status
= STATUS_NOT_SUPPORTED
;
4298 ExFreePoolWithTag(Descriptor
, USB_HUB_TAG
);
4304 USBH_GetSerialNumberString(IN PDEVICE_OBJECT DeviceObject
,
4305 IN LPWSTR
* OutSerialNumber
,
4306 IN PUSHORT OutDescriptorLength
,
4307 IN USHORT LanguageId
,
4310 PUSB_STRING_DESCRIPTOR Descriptor
;
4312 LPWSTR SerialNumberBuffer
= NULL
;
4316 DPRINT("USBH_GetSerialNumberString: ... \n");
4318 *OutSerialNumber
= NULL
;
4319 *OutDescriptorLength
= 0;
4321 Descriptor
= ExAllocatePoolWithTag(NonPagedPool
,
4322 MAXIMUM_USB_STRING_LENGTH
,
4327 return STATUS_INSUFFICIENT_RESOURCES
;
4330 RtlZeroMemory(Descriptor
, MAXIMUM_USB_STRING_LENGTH
);
4332 Status
= USBH_CheckDeviceLanguage(DeviceObject
, LanguageId
);
4334 if (!NT_SUCCESS(Status
))
4339 Status
= USBH_SyncGetStringDescriptor(DeviceObject
,
4343 MAXIMUM_USB_STRING_LENGTH
,
4347 if (!NT_SUCCESS(Status
) ||
4348 Descriptor
->bLength
<= sizeof(USB_COMMON_DESCRIPTOR
))
4350 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4354 StringLength
= Descriptor
->bLength
-
4355 FIELD_OFFSET(USB_STRING_DESCRIPTOR
, bString
);
4357 Length
= StringLength
+ sizeof(UNICODE_NULL
);
4359 SerialNumberBuffer
= ExAllocatePoolWithTag(PagedPool
, Length
, USB_HUB_TAG
);
4361 if (!SerialNumberBuffer
)
4366 RtlZeroMemory(SerialNumberBuffer
, Length
);
4367 RtlCopyMemory(SerialNumberBuffer
, Descriptor
->bString
, StringLength
);
4369 *OutSerialNumber
= SerialNumberBuffer
;
4370 *OutDescriptorLength
= Length
;
4373 ExFreePoolWithTag(Descriptor
, USB_HUB_TAG
);
4379 USBH_CreateDevice(IN PUSBHUB_FDO_EXTENSION HubExtension
,
4381 IN USB_PORT_STATUS UsbPortStatus
,
4384 ULONG PdoNumber
= 0;
4385 WCHAR CharDeviceName
[64];
4386 UNICODE_STRING DeviceName
;
4387 PDEVICE_OBJECT DeviceObject
= NULL
;
4388 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
4389 PUSB_DEVICE_HANDLE DeviceHandle
;
4390 LPWSTR SerialNumberBuffer
;
4393 BOOLEAN IgnoringHwSerial
= FALSE
;
4395 UNICODE_STRING DestinationString
;
4397 DPRINT("USBH_CreateDevice: Port - %x, UsbPortStatus - %lX\n",
4399 UsbPortStatus
.AsUshort16
);
4403 RtlStringCbPrintfW(CharDeviceName
,
4404 sizeof(CharDeviceName
),
4405 L
"\\Device\\USBPDO-%d",
4408 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
4410 Status
= IoCreateDevice(HubExtension
->Common
.SelfDevice
->DriverObject
,
4411 sizeof(USBHUB_PORT_PDO_EXTENSION
),
4420 while (Status
== STATUS_OBJECT_NAME_COLLISION
);
4422 if (!NT_SUCCESS(Status
))
4425 HubExtension
->PortData
[Port
-1].DeviceObject
= DeviceObject
;
4429 DeviceObject
->StackSize
= HubExtension
->RootHubPdo2
->StackSize
;
4431 PortExtension
= DeviceObject
->DeviceExtension
;
4433 DPRINT("USBH_CreateDevice: PortDevice - %p, <%wZ>\n", DeviceObject
, &DeviceName
);
4434 DPRINT("USBH_CreateDevice: PortExtension - %p\n", PortExtension
);
4436 RtlZeroMemory(PortExtension
, sizeof(USBHUB_PORT_PDO_EXTENSION
));
4438 PortExtension
->Common
.ExtensionType
= USBH_EXTENSION_TYPE_PORT
;
4439 PortExtension
->Common
.SelfDevice
= DeviceObject
;
4441 PortExtension
->HubExtension
= HubExtension
;
4442 PortExtension
->RootHubExtension
= HubExtension
;
4444 PortExtension
->PortNumber
= Port
;
4445 PortExtension
->CurrentPowerState
.DeviceState
= PowerDeviceD0
;
4446 PortExtension
->IgnoringHwSerial
= FALSE
;
4448 KeInitializeSpinLock(&PortExtension
->PortTimeoutSpinLock
);
4450 InitializeListHead(&PortExtension
->PortPowerList
);
4451 KeInitializeSpinLock(&PortExtension
->PortPowerListSpinLock
);
4453 PortExtension
->PoRequestCounter
= 0;
4454 PortExtension
->PendingSystemPoRequest
= 0;
4455 PortExtension
->PendingDevicePoRequest
= 0;
4456 PortExtension
->StateBehindD2
= 0;
4458 SerialNumberBuffer
= NULL
;
4460 IsHsDevice
= UsbPortStatus
.Usb20PortStatus
.HighSpeedDeviceAttached
;
4461 IsLsDevice
= UsbPortStatus
.Usb20PortStatus
.LowSpeedDeviceAttached
;
4463 if (IsLsDevice
== 0)
4467 PortExtension
->PortPdoFlags
= USBHUB_PDO_FLAG_PORT_HIGH_SPEED
;
4472 PortExtension
->PortPdoFlags
= USBHUB_PDO_FLAG_PORT_LOW_SPEED
;
4475 /* Initialize PortExtension->InstanceID */
4476 RtlInitUnicodeString(&DestinationString
, (PCWSTR
)&PortExtension
->InstanceID
);
4477 DestinationString
.MaximumLength
= 4 * sizeof(WCHAR
);
4478 Status
= RtlIntegerToUnicodeString(Port
, 10, &DestinationString
);
4480 DeviceObject
->Flags
|= DO_POWER_PAGABLE
;
4481 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
4483 if (!NT_SUCCESS(Status
))
4485 DPRINT1("USBH_CreateDevice: IoCreateDevice() failed - %lX\n", Status
);
4489 Status
= USBD_CreateDeviceEx(HubExtension
,
4490 &PortExtension
->DeviceHandle
,
4494 if (!NT_SUCCESS(Status
))
4496 DPRINT1("USBH_CreateDevice: USBD_CreateDeviceEx() failed - %lX\n", Status
);
4500 Status
= USBH_SyncResetPort(HubExtension
, Port
);
4502 if (!NT_SUCCESS(Status
))
4504 DPRINT1("USBH_CreateDevice: USBH_SyncResetPort() failed - %lX\n", Status
);
4513 Status
= USBD_InitializeDeviceEx(HubExtension
,
4514 PortExtension
->DeviceHandle
,
4515 (PUCHAR
)&PortExtension
->DeviceDescriptor
,
4516 sizeof(USB_DEVICE_DESCRIPTOR
),
4517 (PUCHAR
)&PortExtension
->ConfigDescriptor
,
4518 sizeof(USB_CONFIGURATION_DESCRIPTOR
));
4520 if (!NT_SUCCESS(Status
))
4522 DPRINT1("USBH_CreateDevice: USBD_InitializeDeviceEx() failed - %lX\n", Status
);
4523 PortExtension
->DeviceHandle
= NULL
;
4527 DPRINT1("USBH_RegQueryDeviceIgnoreHWSerNumFlag UNIMPLEMENTED. FIXME\n");
4528 //Status = USBH_RegQueryDeviceIgnoreHWSerNumFlag(PortExtension->DeviceDescriptor.idVendor,
4529 // PortExtension->DeviceDescriptor.idProduct,
4530 // &IgnoringHwSerial);
4532 if (TRUE
)//Status == STATUS_OBJECT_NAME_NOT_FOUND)
4534 IgnoringHwSerial
= FALSE
;
4537 if (IgnoringHwSerial
)
4539 PortExtension
->IgnoringHwSerial
= TRUE
;
4542 if (PortExtension
->DeviceDescriptor
.iSerialNumber
&&
4543 !PortExtension
->IgnoringHwSerial
)
4545 InterlockedExchangePointer((PVOID
)&PortExtension
->SerialNumber
, NULL
);
4547 USBH_GetSerialNumberString(PortExtension
->Common
.SelfDevice
,
4548 &SerialNumberBuffer
,
4549 &PortExtension
->SN_DescriptorLength
,
4550 MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
),
4551 PortExtension
->DeviceDescriptor
.iSerialNumber
);
4553 if (SerialNumberBuffer
)
4555 if (!USBH_ValidateSerialNumberString((PUSHORT
)SerialNumberBuffer
))
4557 ExFreePoolWithTag(SerialNumberBuffer
, USB_HUB_TAG
);
4558 SerialNumberBuffer
= NULL
;
4561 if (SerialNumberBuffer
&&
4562 !USBH_CheckDeviceIDUnique(HubExtension
,
4563 PortExtension
->DeviceDescriptor
.idVendor
,
4564 PortExtension
->DeviceDescriptor
.idProduct
,
4566 PortExtension
->SN_DescriptorLength
))
4568 ExFreePoolWithTag(SerialNumberBuffer
, USB_HUB_TAG
);
4569 SerialNumberBuffer
= NULL
;
4573 InterlockedExchangePointer((PVOID
)&PortExtension
->SerialNumber
,
4574 SerialNumberBuffer
);
4577 Status
= USBH_ProcessDeviceInformation(PortExtension
);
4579 USBH_PdoSetCapabilities(PortExtension
);
4581 if (NT_SUCCESS(Status
))
4588 PortExtension
->PortPdoFlags
|= USBHUB_PDO_FLAG_INIT_PORT_FAILED
;
4590 DeviceHandle
= InterlockedExchangePointer(&PortExtension
->DeviceHandle
,
4595 USBD_RemoveDeviceEx(HubExtension
, DeviceHandle
, 0);
4598 SerialNumberBuffer
= InterlockedExchangePointer((PVOID
)&PortExtension
->SerialNumber
,
4601 if (SerialNumberBuffer
)
4603 ExFreePoolWithTag(SerialNumberBuffer
, USB_HUB_TAG
);
4609 HubExtension
->PortData
[Port
-1].DeviceObject
= DeviceObject
;
4615 USBH_ResetDevice(IN PUSBHUB_FDO_EXTENSION HubExtension
,
4617 IN BOOLEAN IsKeepDeviceData
,
4621 PUSBHUB_PORT_DATA PortData
;
4622 PDEVICE_OBJECT PortDevice
;
4623 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
4624 PVOID NewDeviceHandle
;
4626 PVOID OldDeviceHandle
;
4627 PUSB_DEVICE_HANDLE
* DeviceHandle
;
4628 USB_PORT_STATUS_AND_CHANGE PortStatus
;
4630 DPRINT("USBH_ResetDevice: HubExtension - %p, Port - %x, IsKeepDeviceData - %x, IsWait - %x\n",
4636 Status
= USBH_SyncGetPortStatus(HubExtension
,
4639 sizeof(USB_PORT_STATUS_AND_CHANGE
));
4641 if (!NT_SUCCESS(Status
) ||
4642 !(PortStatus
.PortStatus
.Usb20PortStatus
.CurrentConnectStatus
))
4644 return STATUS_UNSUCCESSFUL
;
4647 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
4649 KeWaitForSingleObject(&HubExtension
->ResetDeviceSemaphore
,
4656 PortData
= &HubExtension
->PortData
[Port
-1];
4658 PortDevice
= PortData
->DeviceObject
;
4662 Status
= STATUS_INVALID_PARAMETER
;
4664 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
4665 LOW_REALTIME_PRIORITY
,
4669 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
4671 KeSetEvent(&HubExtension
->PendingRequestEvent
,
4679 PortExtension
= PortDevice
->DeviceExtension
;
4680 DeviceHandle
= &PortExtension
->DeviceHandle
;
4682 OldDeviceHandle
= InterlockedExchangePointer(&PortExtension
->DeviceHandle
,
4685 if (OldDeviceHandle
)
4687 if (!(PortExtension
->PortPdoFlags
& USBHUB_PDO_FLAG_REMOVING_PORT_PDO
))
4689 Status
= USBD_RemoveDeviceEx(HubExtension
,
4693 PortExtension
->PortPdoFlags
|= USBHUB_PDO_FLAG_REMOVING_PORT_PDO
;
4698 OldDeviceHandle
= NULL
;
4701 if (!NT_SUCCESS(Status
))
4706 Status
= USBH_SyncResetPort(HubExtension
, Port
);
4708 if (!NT_SUCCESS(Status
))
4713 Status
= USBH_SyncGetPortStatus(HubExtension
,
4716 sizeof(USB_PORT_STATUS_AND_CHANGE
));
4718 if (!NT_SUCCESS(Status
))
4723 Status
= USBD_CreateDeviceEx(HubExtension
,
4725 PortStatus
.PortStatus
,
4728 if (!NT_SUCCESS(Status
))
4733 Status
= USBH_SyncResetPort(HubExtension
, Port
);
4740 if (!NT_SUCCESS(Status
))
4745 Status
= USBD_InitializeDeviceEx(HubExtension
,
4747 &PortExtension
->DeviceDescriptor
.bLength
,
4748 sizeof(PortExtension
->DeviceDescriptor
),
4749 &PortExtension
->ConfigDescriptor
.bLength
,
4750 sizeof(PortExtension
->ConfigDescriptor
));
4752 if (NT_SUCCESS(Status
))
4754 if (IsKeepDeviceData
)
4756 Status
= USBD_RestoreDeviceEx(HubExtension
,
4760 if (!NT_SUCCESS(Status
))
4762 Handle
= InterlockedExchangePointer(DeviceHandle
, NULL
);
4764 USBD_RemoveDeviceEx(HubExtension
, Handle
, 0);
4765 USBH_SyncDisablePort(HubExtension
, Port
);
4767 Status
= STATUS_NO_SUCH_DEVICE
;
4772 PortExtension
->PortPdoFlags
&= ~USBHUB_PDO_FLAG_REMOVING_PORT_PDO
;
4778 *DeviceHandle
= NULL
;
4782 NewDeviceHandle
= InterlockedExchangePointer(DeviceHandle
,
4785 if (NewDeviceHandle
)
4787 Status
= USBD_RemoveDeviceEx(HubExtension
, NewDeviceHandle
, 0);
4792 KeReleaseSemaphore(&HubExtension
->ResetDeviceSemaphore
,
4793 LOW_REALTIME_PRIORITY
,
4797 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
4799 KeSetEvent(&HubExtension
->PendingRequestEvent
,
4809 USBH_PdoDispatch(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
4812 PIO_STACK_LOCATION IoStack
;
4813 UCHAR MajorFunction
;
4814 BOOLEAN ShouldCompleteIrp
;
4818 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
4819 MajorFunction
= IoStack
->MajorFunction
;
4821 switch (MajorFunction
)
4825 DPRINT("USBH_PdoDispatch: IRP_MJ_CREATE / IRP_MJ_CLOSE (%d)\n",
4827 Status
= STATUS_SUCCESS
;
4828 USBH_CompleteIrp(Irp
, Status
);
4831 case IRP_MJ_DEVICE_CONTROL
:
4832 ControlCode
= IoStack
->Parameters
.DeviceIoControl
.IoControlCode
;
4833 DPRINT("USBH_PdoDispatch: IRP_MJ_DEVICE_CONTROL ControlCode - %x\n",
4836 if (ControlCode
== IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER
)
4838 Status
= STATUS_NOT_SUPPORTED
;
4839 USBH_CompleteIrp(Irp
, Status
);