From 20a6ea980bab20da0e6b75036e8ec3f32826e6ef Mon Sep 17 00:00:00 2001 From: chehan Date: Thu, 21 May 2026 14:28:11 -0700 Subject: [PATCH 1/2] Remove unreferenced functions and variables Signed-off-by: chehan --- src/windows/wdfserial/QCMAIN.h | 1 - src/windows/wdfserial/QCPNP.c | 75 +--------------------------------- src/windows/wdfserial/QCPNP.h | 11 ----- 3 files changed, 2 insertions(+), 85 deletions(-) diff --git a/src/windows/wdfserial/QCMAIN.h b/src/windows/wdfserial/QCMAIN.h index 7dafa03..2182863 100644 --- a/src/windows/wdfserial/QCMAIN.h +++ b/src/windows/wdfserial/QCMAIN.h @@ -258,7 +258,6 @@ typedef struct _DEVICE_CONTEXT #endif // QCUSB_MUX_PROTOCOL //QCPNP_RetrieveServiceConfig - BOOLEAN InServiceSelectiveSuspension; ULONG SelectiveSuspendIdleTime; BOOLEAN SelectiveSuspendInMiliSeconds; WDF_POWER_POLICY_S0_IDLE_CAPABILITIES AssignedIdleCaps; diff --git a/src/windows/wdfserial/QCPNP.c b/src/windows/wdfserial/QCPNP.c index b1fa541..3b9bebb 100644 --- a/src/windows/wdfserial/QCPNP.c +++ b/src/windows/wdfserial/QCPNP.c @@ -3849,15 +3849,6 @@ VOID QCPNP_RetrieveServiceConfig(PDEVICE_CONTEXT pDevContext) if (status == STATUS_SUCCESS) { - if (QCUTIL_IsHighSpeedDevice(pDevContext) == TRUE) - { - pDevContext->InServiceSelectiveSuspension = TRUE; - } - else - { - pDevContext->InServiceSelectiveSuspension = ((selectiveSuspendIdleTime >> 31) != 0); - } - selectiveSuspendInMili = selectiveSuspendIdleTime & 0x40000000; selectiveSuspendIdleTime &= 0x00FFFFFF; @@ -3895,13 +3886,10 @@ VOID QCPNP_RetrieveServiceConfig(PDEVICE_CONTEXT pDevContext) ( QCSER_DBG_MASK_READ, QCSER_DBG_LEVEL_ERROR, - ("<%ws> QCPNP_RetrieveServiceConfig: new selective suspend idle time=%us(%u)\n", - pDevContext->PortName, selectiveSuspendIdleTime, - pDevContext->InServiceSelectiveSuspension) + ("<%ws> QCPNP_RetrieveServiceConfig: new selective suspend idle time=%us\n", + pDevContext->PortName, selectiveSuspendIdleTime) ); pDevContext->SelectiveSuspendIdleTime = selectiveSuspendIdleTime; - QCPWR_SyncUpWaitWake(pDevContext); - QCPWR_SetIdleTimer(pDevContext, 0, FALSE, 8); } } else @@ -3936,65 +3924,6 @@ VOID QCPNP_RetrieveServiceConfig(PDEVICE_CONTEXT pDevContext) return; } // QCPNP_RetrieveServiceConfig -/**************************************************************************** - * - * function: QCUTIL_IsHighSpeedDevice - * - * purpose: Stub function. Returns FALSE to indicate the device is not a - * high-speed USB device in this implementation. - * - * arguments:pDevContext = pointer to the device context. - * - * returns: BOOLEAN (always FALSE) - * - ****************************************************************************/ -//Empty Functions to support QCPNP_RetrieveServiceConfig -BOOLEAN QCUTIL_IsHighSpeedDevice(PDEVICE_CONTEXT pDevContext) -{ - UNREFERENCED_PARAMETER(pDevContext); - return 0; -} // QCUTIL_IsHighSpeedDevice - -/**************************************************************************** - * - * function: QCPWR_SyncUpWaitWake - * - * purpose: Stub function. Placeholder for synchronizing wait/wake power - * management state. - * - * arguments:pDevContext = pointer to the device context. - * - * returns: VOID - * - ****************************************************************************/ -VOID QCPWR_SyncUpWaitWake(PDEVICE_CONTEXT pDevContext) -{ - UNREFERENCED_PARAMETER(pDevContext); -} - -/**************************************************************************** - * - * function: QCPWR_SetIdleTimer - * - * purpose: Stub function. Placeholder for setting the selective suspend - * idle timer. - * - * arguments:pDevContext = pointer to the device context. - * BusyMask = bitmask indicating busy state sources. - * NoReset = if TRUE, do not reset the timer. - * Cookie = caller identifier for debug purposes. - * - * returns: VOID - * - ****************************************************************************/ -VOID QCPWR_SetIdleTimer(PDEVICE_CONTEXT pDevContext, UCHAR BusyMask, BOOLEAN NoReset, UCHAR Cookie) -{ - UNREFERENCED_PARAMETER(pDevContext); - UNREFERENCED_PARAMETER(BusyMask); - UNREFERENCED_PARAMETER(NoReset); - UNREFERENCED_PARAMETER(Cookie); -} - /**************************************************************************** * * function: QCPNP_GetCID diff --git a/src/windows/wdfserial/QCPNP.h b/src/windows/wdfserial/QCPNP.h index 863638d..724776b 100644 --- a/src/windows/wdfserial/QCPNP.h +++ b/src/windows/wdfserial/QCPNP.h @@ -166,17 +166,6 @@ NTSTATUS QCPNP_PostVendorRegistryProcess PDEVICE_CONTEXT pDevContext ); -BOOLEAN QCUTIL_IsHighSpeedDevice -( - PDEVICE_CONTEXT pDevContext -); - -//Empty Functions to support QCPNP_RetrieveServiceConfig -BOOLEAN QCUTIL_IsHighSpeedDevice -( - PDEVICE_CONTEXT pDevContext -); - VOID QCPWR_SyncUpWaitWake ( PDEVICE_CONTEXT pDevContext From 23797073fe1d5442b3355ed7a239beff310b7836 Mon Sep 17 00:00:00 2001 From: chehan Date: Thu, 21 May 2026 15:23:29 -0700 Subject: [PATCH 2/2] Disable selective suspend by default on sahara and firehorse devices Signed-off-by: chehan --- src/windows/wdfserial/QCMAIN.h | 15 ++++++ src/windows/wdfserial/QCPNP.c | 90 +++++++++++++++++----------------- 2 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/windows/wdfserial/QCMAIN.h b/src/windows/wdfserial/QCMAIN.h index 2182863..e9851bf 100644 --- a/src/windows/wdfserial/QCMAIN.h +++ b/src/windows/wdfserial/QCMAIN.h @@ -237,6 +237,7 @@ typedef struct _DEVICE_CONTEXT ULONG DebugLevel; UCHAR UsbDeviceType; USHORT InterfaceIndex; + UCHAR InterfaceProtocol; DEVICE_TYPE FdoDeviceType; KEVENT TimeoutEvent; @@ -360,6 +361,20 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, QCReqGetContext) #define QCUSB_DEV_FUNC_VI 0x04 #define QCUSB_DEV_FUNC_UNDEF 0xFFFFFFFF +// USB interface bInterfaceProtocol values used by Qualcomm devices. +#define DEV_PROTOCOL_UNKNOWN 0x00 +#define DEV_PROTOCOL_SAHARA 0x10 +#define DEV_PROTOCOL_FIREHOSE 0x20 +#define DEV_PROTOCOL_DIAG 0x30 +#define DEV_PROTOCOL_DUN 0x40 + +// Helpers that classify a bInterfaceProtocol value by its high-nibble protocol family. +#define DEV_PROTOCOL_GROUP(p) ((UCHAR)((p) & 0xF0)) +#define IS_DEV_PROTOCOL_SAHARA(p) (DEV_PROTOCOL_GROUP(p) == DEV_PROTOCOL_SAHARA) +#define IS_DEV_PROTOCOL_FIREHOSE(p) (DEV_PROTOCOL_GROUP(p) == DEV_PROTOCOL_FIREHOSE) +#define IS_DEV_PROTOCOL_DIAG(p) (DEV_PROTOCOL_GROUP(p) == DEV_PROTOCOL_DIAG) +#define IS_DEV_PROTOCOL_DUN(p) (DEV_PROTOCOL_GROUP(p) == DEV_PROTOCOL_DUN) + // Debug levels #define QCSER_DBG_LEVEL_FORCE 0x0 #define QCSER_DBG_LEVEL_CRITICAL 0x1 diff --git a/src/windows/wdfserial/QCPNP.c b/src/windows/wdfserial/QCPNP.c index 3b9bebb..907c6ae 100644 --- a/src/windows/wdfserial/QCPNP.c +++ b/src/windows/wdfserial/QCPNP.c @@ -1603,7 +1603,8 @@ NTSTATUS QCPNP_EvtDevicePrepareHardware usbInterfaceDesc.bInterfaceClass << 8 | usbInterfaceDesc.bAlternateSetting << 16 | usbInterfaceDesc.bInterfaceNumber << 24; - pDevContext->InterfaceIndex = usbInterfaceDesc.bInterfaceNumber; + pDevContext->InterfaceIndex = usbInterfaceDesc.bInterfaceNumber; + pDevContext->InterfaceProtocol = usbInterfaceDesc.bInterfaceProtocol; status = QCMAIN_SetDriverRegistryDword(VEN_DEV_PROTOC, ifProtocol, pDevContext); QCPNP_SetFunctionProtocol(pDevContext, ifProtocol); @@ -1612,7 +1613,7 @@ NTSTATUS QCPNP_EvtDevicePrepareHardware ( QCSER_DBG_MASK_READ, QCSER_DBG_LEVEL_DETAIL, - ("<%ws> QCPNP_EvtDevicePrepareHardware set interface protocol: %lu, status: 0x%x\n", pDevContext->PortName, ifProtocol, status) + ("<%ws> QCPNP_EvtDevicePrepareHardware set interface protocol: 0x%x, status: 0x%x\n", pDevContext->PortName, usbInterfaceDesc.bInterfaceProtocol, status) ); } // End update registry settings @@ -1673,6 +1674,21 @@ NTSTATUS QCPNP_EvtDevicePrepareHardware goto exit; } + // For SAHARA or FIREHOSE devices, selective suspend is disabled by default + if (IS_DEV_PROTOCOL_SAHARA(pDevContext->InterfaceProtocol) || + IS_DEV_PROTOCOL_FIREHOSE(pDevContext->InterfaceProtocol) || + (pDevContext->DeviceFunction == QCUSB_DEV_FUNC_LPC)) + { + QCSER_DbgPrint + ( + QCSER_DBG_MASK_POWER, + QCSER_DBG_LEVEL_TRACE, + ("<%ws> QCPNP_EvtDevicePrepareHardware selective suspend disabled for SAHARA/FIREHOSE and LPC devices\n", + pDevContext->PortName) + ); + pDevContext->PowerManagementEnabled = FALSE; + } + // Setup usb selective suspend status = QCPNP_EnableSelectiveSuspend(Device); if (!NT_SUCCESS(status)) @@ -2071,64 +2087,46 @@ NTSTATUS QCPNP_EnableSelectiveSuspend ("<%ws> QCPNP_EnableSelectiveSuspend\n", pDevContext->PortName) ); -#ifdef QCUSB_MUX_PROTOCOL - if (pDevContext->DeviceFunction == QCUSB_DEV_FUNC_LPC) + idleSettings.IdleTimeout = pDevContext->SelectiveSuspendIdleTime; +#ifdef POFX_SUPPORT + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; +#endif + if (idleSettings.IdleTimeout == 0) { - QCSER_DbgPrint - ( - QCSER_DBG_MASK_POWER, - QCSER_DBG_LEVEL_TRACE, - ("<%ws> QCPNP_EnableSelectiveSuspend LPC deivce found, selective suspend disabled\n", pDevContext->PortName) - ); - - // prevent sending further control packets + // registry not set, ss is disabled idleSettings.Enabled = WdfFalse; idleSettings.IdleCaps = IdleCannotWakeFromS0; + idleSettings.UserControlOfIdleSettings = IdleDoNotAllowUserControl; status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); } else -#endif { idleSettings.UserControlOfIdleSettings = IdleAllowUserControl; - idleSettings.IdleTimeout = pDevContext->SelectiveSuspendIdleTime; -#ifdef POFX_SUPPORT - idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; -#endif - if (idleSettings.IdleTimeout == 0) + if (pDevContext->SelectiveSuspendInMiliSeconds == FALSE) { - // registry not set, ss is disabled - idleSettings.Enabled = WdfFalse; - idleSettings.IdleCaps = IdleCannotWakeFromS0; - status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + idleSettings.IdleTimeout *= 1000; } - else + idleSettings.Enabled = pDevContext->PowerManagementEnabled ? WdfTrue : WdfFalse; + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + if (status == STATUS_POWER_STATE_INVALID) { - if (pDevContext->SelectiveSuspendInMiliSeconds == FALSE) - { - idleSettings.IdleTimeout *= 1000; - } - idleSettings.Enabled = WdfTrue; // explicitly enable SS (overrides any user/registry disable) + // bus driver reports the device cannot wakeup itself + QCSER_DbgPrint + ( + QCSER_DBG_MASK_POWER, + QCSER_DBG_LEVEL_TRACE, + ("<%ws> QCPNP_EnableSelectiveSuspend device reported cannot wake from idle\n", pDevContext->PortName) + ); + idleSettings.IdleCaps = IdleCannotWakeFromS0; status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); - if (status == STATUS_POWER_STATE_INVALID) - { - // bus driver reports the device cannot wakeup itself - QCSER_DbgPrint - ( - QCSER_DBG_MASK_POWER, - QCSER_DBG_LEVEL_TRACE, - ("<%ws> QCPNP_EnableSelectiveSuspend device reported cannot wake from idle\n", pDevContext->PortName) - ); - idleSettings.IdleCaps = IdleCannotWakeFromS0; - status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); - } } - QCSER_DbgPrint - ( - QCSER_DBG_MASK_POWER, - QCSER_DBG_LEVEL_DETAIL, - ("<%ws> QCPNP_EnableSelectiveSuspend timeout: %lu, status: 0x%x\n", pDevContext->PortName, idleSettings.IdleTimeout, status) - ); } + QCSER_DbgPrint + ( + QCSER_DBG_MASK_POWER, + QCSER_DBG_LEVEL_DETAIL, + ("<%ws> QCPNP_EnableSelectiveSuspend timeout: %lu, status: 0x%x\n", pDevContext->PortName, idleSettings.IdleTimeout, status) + ); pDevContext->AssignedIdleCaps = idleSettings.IdleCaps;