15#define UCX_SIZE_ADDRESS0 sizeof(ADDRESS0_OWNERSHIP_ACQUIRE)
16#define UCX_SIZE_ENABLE sizeof(USBDEVICE_ENABLE)
17#define UCX_SIZE_RESET sizeof(USBDEVICE_RESET)
18#define UCX_SIZE_ADDRESS sizeof(USBDEVICE_ADDRESS)
19#define UCX_SIZE_UPDATE sizeof(USBDEVICE_UPDATE)
20#define UCX_SIZE_DISABLE sizeof(USBDEVICE_DISABLE)
21#define UCX_SIZE_PURGE sizeof(USBDEVICE_PURGEIO)
22#define UCX_SIZE_START sizeof(USBDEVICE_STARTIO)
23#define UCX_SIZE_ABORT sizeof(USBDEVICE_ABORTIO)
24#define UCX_SIZE_CONFIGURE sizeof(ENDPOINTS_CONFIGURE)
25#define UCX_SIZE_EP0_UPDATE sizeof(DEFAULT_ENDPOINT_UPDATE)
26#define UCX_SIZE_EP_RESET sizeof(ENDPOINT_RESET)
34#define EP0_PACKET_SUPER 512
35#define EP0_PACKET_HIGH_FULL 64
36#define EP0_PACKET_LOW 8
39#define BANDWIDTH_RETRY_DELAY_MS 1000
42#define HUB_MSG_SET_ADDRESS_FAILED 0x40010001
45#define HUB_ROOT_RESUME_SIGNAL_MS 20
48#define LPM20_DEFAULT_BESL 4
78 return Child->m_UcxPayload;
96 WdfTimerStop(
Child->m_BandwidthRetryTimer,
FALSE);
107 Child->m_LastNtStatus = NtStatus;
124 if (
Child->m_UnchangedCount >=
Child->m_EndpointArrayCapacity)
127 Child->m_EndpointsUnchanged[
Child->m_UnchangedCount++] = Endpoints[
Index];
178 WDFIOTARGET
Target =
Child->m_Hub->m_RootHubTarget;
191 Status = WdfIoTargetFormatRequestForInternalIoctlOthers(
Target,
194 Child->m_UcxPayloadMemory,
225 if (
Enable->FailureFlags.InsufficientHardwareResourcesForDefaultEndpoint ||
226 Enable->FailureFlags.InsufficientHardwareResourcesForDevice)
228 DPRINT(
"Device %p enable ran out of controller resources\n",
Child);
266 if (
Configure->FailureFlags.MaxExitLatencyTooLarge)
268 DPRINT1(
"Device %p exit latency delta %lu rejected, effective latency %u\n",
270 Child->m_MaxExitLatencyFromEld = 0;
274 Child->m_MaxExitLatencyFromEld =
Child->m_EffectiveExitLatency +
Configure->ExitLatencyDelta;
275 DPRINT(
"Device %p max exit latency from delta is %lu\n",
Child,
Child->m_MaxExitLatencyFromEld);
279 Child->m_MaxExitLatencyFromEld = 0;
284 Configure->FailureFlags.InsufficientHardwareResourcesForEndpoints ||
285 Configure->FailureFlags.MaxExitLatencyTooLarge;
289 DPRINT(
"Device %p endpoint configure ran out of bandwidth or resources\n",
Child);
294 if (
Child->m_EffectiveExitLatency != 0)
296 DPRINT1(
"Device %p endpoint configure failed at exit latency %u, retrying without U1 and U2\n",
299 Child->m_DisableCount = 0;
313 DPRINT1(
"Device %p select failed by the alternate setting filter\n",
Child);
331 Child->m_DisableCount = 0;
332 Child->m_EnableCount = 0;
333 Child->m_UnchangedCount = 0;
353 DPRINT1(
"Device %p SET_ADDRESS works again after an earlier failure\n",
Child);
365 DPRINT1(
"Device %p SET_ADDRESS failed, SuperSpeed connects now get extra debounce time\n",
Child);
380 if (!
Update->Flags.UpdateTunnelState)
386 DPRINT1(
"Device %p controller gave no USB4 tunnel state\n",
Child);
409 switch (
Child->m_UcxIoctl)
432 Child->m_EffectiveExitLatency =
Child->m_TargetExitLatency;
435 else if (
Child->m_UcxPayload->Update.FailureFlags.MaxExitLatencyTooLarge)
437 DPRINT1(
"Device %p exit latency %u too large for the controller 0x%lx\n",
454 if (
Child->m_LastUsbdStatus == 0)
496 Info->Size =
sizeof(*Info);
519 Info->PortNumber =
Child->m_Port->Number();
520 Info->HubDeviceContext = (UCXHUB_DEVICE_CONTEXT)
Child;
525 DPRINT1(
"Port %u controller device create failed 0x%lx\n",
Child->m_Port->Number(),
Status);
544 Child->m_MaxPacketSize0,
671 if (
Extension->bmAttributes.BESLAndAlternateHIRDSupported)
674 if (
Extension->bmAttributes.BaselineBESLValid && Baseline != 0)
677 Lpm->Baseline = Baseline;
681 if (
Extension->bmAttributes.DeepBESLValid && Deep != 0 &&
682 !(
Extension->bmAttributes.BaselineBESLValid && Deep <= Baseline))
711 else if (!
Lpm.Capable)
722 Update->Flags.Update20HardwareLpmParameters = 1;
723 Update->Usb20HardwareLpmParameters.HardwareLpmEnable = 1;
725 Update->Usb20HardwareLpmParameters.RemoteWakeEnable =
728 Update->Usb20HardwareLpmParameters.BestEffortServiceLatencyDeep = 0;
729 Update->Usb20HardwareLpmParameters.HostInitiatedResumeDurationMode = 0;
733 if (
Lpm.BaselineValid)
734 Update->Usb20HardwareLpmParameters.BestEffortServiceLatency =
Lpm.Baseline;
738 Update->Usb20HardwareLpmParameters.BestEffortServiceLatencyDeep =
Lpm.Deep;
739 Update->Usb20HardwareLpmParameters.HostInitiatedResumeDurationMode = 1;
762 if (
Child->m_Port->HasFlag(PortFlag::Usb4Host))
765 Update->Flags.UpdateTunnelState = 1;
768 Update->Flags.UpdateDeviceDescriptor = 1;
769 Update->Flags.UpdateBosDescriptor = 1;
770 Update->Flags.UpdateMaxExitLatency = 1;
771 Update->Flags.UpdateIsHub = 1;
772 if (
Child->HasHack(ChildHack::TolerateStalePipes))
773 Update->Flags.UpdateAllowIoOnInvalidPipeHandles = 1;
775 Update->DeviceDescriptor = &
Child->m_DeviceDescriptor;
783 if (
Child->m_HasResumeRecoveryTime &&
784 Child->HasProperty(ChildProperty::NotRemovable) &&
786 Child->m_Port->m_Info.Protocol == 0x200)
788 Update->Flags.UpdateRootPortResumeTime = 1;
789 Update->RootPortResumeTime =
Child->m_Hub->IsRootHub() ?
Child->m_ResumeSignalingTime
817 if (
Child->m_MaxExitLatencyFromEld != 0 &&
818 Child->m_TargetExitLatency >
Child->m_MaxExitLatencyFromEld)
820 DPRINT1(
"Device %p exit latency %u is above the controller limit %lu\n",
822 Child->Post(DsmEvent::ControllerExitLatencyTooLarge);
841 UCXENDPOINT* Endpoints =
NULL;
851 Endpoints =
Child->m_EndpointsToDisable;
864 if (Endpoints ==
NULL)
878 DPRINT1(
"Device %p reset has enabled endpoints but no disable list 0x%lx\n",
Child,
Status);
880 Child->Post(DsmEvent::ControllerIoctlFailed);
889 Payload->
Reset.EndpointsToDisable = Endpoints;
953 DPRINT1(
"Device %p endpoint reset without a target pipe\n",
Child);
986 if (
Child->m_DisableCount == 0 &&
Child->m_EnableCount == 0)
988 DPRINT(
"Device %p has no endpoints to program\n",
Child);
990 Child->Post(DsmEvent::ControllerIoctlDone);
995 if (
Child->m_DisableCount == 0 && FailAlternate)
997 DPRINT1(
"Device %p select failed by the alternate setting filter\n",
Child);
1000 Child->Post(DsmEvent::ControllerIoctlFailed);
1014 Configure->EndpointsEnabledAndUnchangedCount =
Child->m_UnchangedCount;
1015 Configure->EndpointsEnabledAndUnchanged =
Child->m_EndpointsUnchanged;
1018 Configure->ConfigurationValue =
Child->m_CurrentConfig->Descriptor.bConfigurationValue;
1023 Configure->InterfaceNumber =
Child->m_NewInterface->Descriptor->bInterfaceNumber;
1024 Configure->AlternateSetting =
Child->m_NewInterface->Descriptor->bAlternateSetting;
1039 DPRINT(
"Device %p has no endpoints to disable\n",
Child);
1040 Child->Post(DsmEvent::ControllerIoctlDone);
1044 Child->m_EnableCount = 0;
1045 Child->m_DisableCount = 0;
1046 Child->m_UnchangedCount = 0;
1051 if (
Child->m_DisableCount == 0)
1053 Child->Post(DsmEvent::ControllerIoctlDone);
1067 Child->
Post(DsmEvent::ControllerIoctlDone);
1071 Child->m_EnableCount = 0;
1072 Child->m_DisableCount = 0;
1073 Child->m_UnchangedCount = 0;
1077 if (
Child->m_DisableCount == 0)
1079 Child->Post(DsmEvent::ControllerIoctlDone);
1093 if (
Child->m_DisableCount == 0)
1095 Child->Post(DsmEvent::ControllerIoctlDone);
1099 Child->m_EnableCount = 0;
1125 Child->m_EnableCount = 0;
1128 return Child->m_DisableCount != 0;
1149 DPRINT(
"Device %p has no endpoints to create\n",
Child);
1162 if (
Pipe->State != PipeState::NotCreated)
1165 Pipe->State = PipeState::PendingCreate;
1174 DPRINT1(
"Device %p endpoint 0x%x create failed 0x%lx\n",
1176 Pipe->State = PipeState::NotCreated;
1180 if (
Pipe->ZeroBandwidth)
1182 Pipe->State = PipeState::Disabled;
1183 Child->m_EndpointsUnchanged[
Child->m_UnchangedCount++] =
Pipe->Endpoint;
1187 Child->m_EndpointsToEnable[
Child->m_EnableCount++] =
Pipe->Endpoint;
1199 if (
Pipe->State != PipeState::PendingCreate)
1204 Pipe->State = PipeState::PendingEnable;
1208 Pipe->State = PipeState::NotCreated;
1217 Child->m_EnableCount = 0;
1218 Child->m_UnchangedCount = 0;
1231HubChildDeleteInterface(
1257HubChildDeleteConfiguration(
1357 WdfRequestFormatRequestUsingCurrentType(
Request);
1362 DPRINT1(
"Device %p client request not sent 0x%lx\n",
Child, WdfRequestGetStatus(
Request));
1393HubQueryBusInformation(
1408 DPRINT1(
"Hub %p no memory for bus information\n",
Hub);
1421 DPRINT1(
"Hub %p no memory for %lu bytes of bus information\n",
Hub,
Length);
1443HubQueryControllerName(
1458 DPRINT1(
"Hub %p controller name buffer of %lu bytes is too small\n",
Hub,
Length);
1463 Name->ActualLength =
Info->ControllerNameLength;
1476HubQueryDeviceBusInfo(
#define InterlockedIncrement
#define InterlockedDecrement
USBD_STATUS NTAPI HubNtStatusToUsbd(_In_ NTSTATUS Status)
VOID ReleaseAddressZero()
BOOLEAN CreateDeviceInController()
VOID UpdateDeviceInController()
VOID DeleteDefaultEndpoint()
VOID DisablePendingEndpoints()
VOID ResetEndpointAndTransfers()
VOID DisableDeviceInController()
BOOLEAN EndpointsNeedDisableOnFailure()
VOID DeleteDeviceInController()
VOID UpdateDefaultEndpoint()
VOID MarkPendingEndpointsDisabled()
VOID DisableNewInterfaceEndpoints()
VOID DeleteOldInterfaceEndpoints()
BOOLEAN CreateDefaultEndpoint()
VOID CancelControllerIoctl()
BOOLEAN EndpointsNeedProgramming()
VOID DisableAllEndpoints()
VOID DeleteOldConfigEndpoints()
VOID DeleteConfigEndpoints()
VOID EnableDeviceInController()
VOID DeleteNewInterfaceEndpoints()
VOID ForwardToController()
BOOLEAN CreateEndpoints()
HubInterface * m_OldInterface
VOID Post(_In_ DsmEvent Event)
HubConfiguration * m_OldConfig
HubConfiguration * m_CurrentConfig
BOOLEAN HasState(_In_ ChildState Flag) const
UCXENDPOINT m_DefaultEndpoint
USB_BUS_INTERFACE_USBDI_V3 m_Usbdi
UCXHUB_STACK_INTERFACE m_Stack
UCXUSBDEVICE UsbDevice() const
_In_ ULONG _Out_opt_ HubBosInfo _Out_opt_ PUSHORT _Out_opt_ PUSHORT _Inout_opt_ PBOOLEAN _Inout_opt_ HubLpmInfo * Lpm
VOID NTAPI HubChildCollectForDisable(_In_ HubChild *Child, _In_ HubInterface *Interface)
static VOID NTAPI HubChildAddressDone(_In_ HubChild *Child, _In_ NTSTATUS Status)
#define LPM20_DEFAULT_BESL
static VOID NTAPI HubChildReadUsb20Lpm(_In_ HubChild *Child, _Out_ HubUsb20Lpm *Lpm)
static VOID NTAPI HubChildResetTargetEndpoint(_In_ HubChild *Child, _In_ ULONG Flags)
WdfObjectDelete(Interface->Memory)
_Inout_ HubConfiguration ** Slot
NTSTATUS NTAPI HubChildSubmitUcxIoctl(_In_ HubChild *Child, _In_ ULONG IoControlCode)
static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubChildUcxIoctlComplete
#define UCX_SIZE_EP0_UPDATE
#define HUB_ROOT_RESUME_SIGNAL_MS
_In_ PVOID _Outptr_result_maybenull_ PUSB_BUS_INFORMATION_LEVEL_1 * Result
#define HUB_MSG_SET_ADDRESS_FAILED
static BOOLEAN NTAPI HubChildComputeLpm20(_In_ HubChild *Child, _Inout_ PUSBDEVICE_UPDATE Update)
static VOID NTAPI HubChildKeepUnchanged(_In_ HubChild *Child, _In_reads_(Count) UCXENDPOINT *Endpoints, _In_ ULONG Count)
static VOID NTAPI HubInterfaceSetPipes(_In_ HubInterface *Interface, _In_ PipeState To)
VOID NTAPI HubChildForwardToController(_In_ HubChild *Child)
static NTSTATUS NTAPI HubChildEnableDone(_In_ HubChild *Child, _In_ NTSTATUS Status)
#define UCX_SIZE_EP_RESET
static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubChildClientRequestComplete
static VOID NTAPI HubChildSetPayloadHeader(_In_ HubChild *Child, _In_ ULONG Size)
static VOID NTAPI HubChildFailStatus(_In_ HubChild *Child, _In_ NTSTATUS NtStatus, _In_ USBD_STATUS UsbdStatus)
static VOID NTAPI HubChildStopBandwidthTimer(_In_ HubChild *Child)
VOID NTAPI HubConfigMovePipes(_In_opt_ HubConfiguration *Config, _In_ PipeState From, _In_ PipeState To)
#define EP0_PACKET_HIGH_FULL
if(Length< FIELD_OFFSET(USB_HUB_NAME, HubName))
static VOID NTAPI HubChildStartBandwidthTimer(_In_ HubChild *Child)
#define BANDWIDTH_RETRY_DELAY_MS
static HubUcxPayload *NTAPI HubChildNewPayload(_In_ HubChild *Child, _In_ ULONG Size)
_In_ HubInterface * Interface
static VOID NTAPI HubChildTakeTunnelState(_In_ HubChild *Child)
static BOOLEAN NTAPI HubChildConfigureDone(_In_ HubChild *Child, _Inout_ NTSTATUS *Status)
#define UCX_SIZE_CONFIGURE
#define UCX_SIZE_ADDRESS0
BOOLEAN NTAPI HubChildU2ForEnumerated(_In_ HubChild *Child)
#define DSM_KIND_SUPER_SPEED
@ ControllerExitLatencyTooLarge
#define DSM_KIND_LOW_SPEED
#define DSM_KIND_HIGH_SPEED
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
#define NT_SUCCESS(StatCode)
#define _IRQL_requires_(irql)
#define RemoveEntryList(Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
#define IsListEmpty(ListHead)
#define KeReleaseSpinLock(sl, irql)
#define KeAcquireSpinLock(sl, irql)
#define RemoveHeadList(ListHead)
_Inout_opt_ PUNICODE_STRING Extension
return pRequest Reuse(ReuseParams)
_In_ UCXUSBDEVICE UsbDevice
#define HUB_TUNNEL_STATE_UNKNOWN
#define HUB_TUNNEL_STATE_NONE
@ DisableRemoteWakeForUsb20Lpm
#define HUB_TUNNEL_STATE_NOT_USB4
#define IOCTL_UCXHUB_DEVICE_ENABLE
#define IOCTL_UCXHUB_DEVICE_ADDRESS
#define IOCTL_UCXHUB_ADDRESS0_OWNERSHIP_ACQUIRE
#define IOCTL_UCXHUB_DEVICE_TREE_PURGE_IO
#define IOCTL_UCXHUB_DEVICE_START_IO
#define IOCTL_UCXHUB_ENDPOINT_RESET
#define IOCTL_UCXHUB_DEVICE_UPDATE
#define IOCTL_UCXHUB_DEVICE_DISABLE
#define IOCTL_UCXHUB_DEVICE_RESET
_In_ UCXHUB_DEVICE_CONTEXT _In_ UCXENDPOINT Endpoint
#define IOCTL_UCXHUB_DEFAULT_ENDPOINT_UPDATE
#define IOCTL_UCXHUB_ENDPOINTS_CONFIGURE
FORCEINLINE PUCXHUB_UPDATE_TUNNEL_ANSWER NTAPI UcxHubUpdateTunnelAnswer(_In_ PUSBDEVICE_UPDATE Update)
#define IOCTL_UCXHUB_DEVICE_PURGE_IO
#define IOCTL_UCXHUB_DEVICE_ABORT_IO
_In_ UCXUSBDEVICE _In_ PDEVICE_OBJECT Pdo
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
#define ExFreePoolWithTag(_P, _T)
static LRESULT Configure(const CodecInfo *pi, HWND hWnd)
#define _Outptr_result_maybenull_
#define _Out_writes_bytes_(s)
#define UNREFERENCED_PARAMETER(P)
_In_ ULONG _In_ ULONG _In_ ULONG Length
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
#define STATUS_BUFFER_TOO_SMALL
volatile LONG SuperSpeedDebounceVotes
BOOLEAN HasFlag(_In_ HubGlobal Flag) const
UCXENDPOINT DefaultEndpoint
ENDPOINT_RESET_FLAGS Flags
struct _LIST_ENTRY * Flink
PFN_UCXHUB_DEVICE_CREATE DeviceCreate
PFN_UCXHUB_ENDPOINT_CREATE EndpointCreate
PFN_UCXHUB_DEFAULT_ENDPOINT_CREATE CreateControlEndpoint
PFN_UCXHUB_ENDPOINT_DELETE EndpointDelete
PFN_UCXHUB_ADDRESS0_RELEASE Address0Release
PFN_UCXHUB_DEVICE_SET_PDO DeviceSetPdo
PFN_UCXHUB_DEVICE_DELETE DeviceDelete
UCXENDPOINT DefaultEndpoint
UCXENDPOINT DefaultEndpoint
ULONG EndpointsToDisableCount
UCXENDPOINT DefaultEndpoint
ULONG UpdateMaxExitLatency
USBDEVICE_UPDATE_FLAGS Flags
PUSB_BUSIFFN_QUERY_BUS_INFORMATION QueryBusInformation
#define FIELD_OFFSET(t, f)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
@ FlagEndpointResetPreserveTransferState
WDF_EXTERN_C_START enum _ENDPOINT_RESET_FLAGS ENDPOINT_RESET_FLAGS
_In_ UCXUSBDEVICE _In_ ULONG Interface
#define STATUS_INVALID_PARAMETER
#define STATUS_UNSUCCESSFUL
#define STATUS_INSUFFICIENT_RESOURCES
ENDPOINT_RESET EndpointReset
USBDEVICE_ADDRESS Address
USBDEVICE_DISABLE Disable
ENDPOINTS_CONFIGURE Configure
DEFAULT_ENDPOINT_UPDATE DefaultEndpoint
struct _USB_COMMON_DESCRIPTOR * PUSB_COMMON_DESCRIPTOR
struct _USB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR * PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR
#define USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE
#define USB_DEVICE_CAPABILITY_USB20_EXTENSION
#define USBD_STATUS_INVALID_PIPE_HANDLE
#define USBD_STATUS_NO_BANDWIDTH
#define USBD_STATUS_INSUFFICIENT_RESOURCES
struct _USB_BUS_INFORMATION_LEVEL_1 * PUSB_BUS_INFORMATION_LEVEL_1
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, ActualLength)
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PWDFDEVICE_INIT _In_ PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification
FORCEINLINE LONGLONG WDF_REL_TIMEOUT_IN_MS(_In_ ULONGLONG Time)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
_Must_inspect_result_ FORCEINLINE BOOLEAN WdfRequestSend(_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_opt_ PWDF_REQUEST_SEND_OPTIONS Options)
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
@ WDF_REQUEST_REUSE_NO_FLAGS
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
#define WDF_NO_SEND_OPTIONS
_In_ NTSTATUS _In_ USBD_STATUS UsbdStatus