From be3dae29f1712ca1e0034e5944744a8d40d22f1c Mon Sep 17 00:00:00 2001 From: Cristian Manca Date: Mon, 27 Apr 2026 12:13:18 +0200 Subject: [PATCH 1/2] Improve power management idle policy handling - Remove unnecessary IdleCaps assignment when SS is disabled (registry not set) - Explicitly enable selective suspend in high timeout case to override user/registry settings - Use IdleUsbSelectiveSuspend instead of IdleCannotWakeFromS0 when disabling SS - Add UserControlOfIdleSettings to restore user control when disabling selective suspend Ensures proper power policy state transitions and respects user preferences. Signed-off-by: Cristian Manca --- src/windows/wdfserial/QCPNP.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/windows/wdfserial/QCPNP.c b/src/windows/wdfserial/QCPNP.c index 99fa4a4..a8936e3 100644 --- a/src/windows/wdfserial/QCPNP.c +++ b/src/windows/wdfserial/QCPNP.c @@ -2098,7 +2098,6 @@ NTSTATUS QCPNP_EnableSelectiveSuspend { // registry not set, ss is disabled idleSettings.Enabled = WdfFalse; - idleSettings.IdleCaps = IdleCannotWakeFromS0; status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); } else @@ -2107,6 +2106,7 @@ NTSTATUS QCPNP_EnableSelectiveSuspend { idleSettings.IdleTimeout *= 1000; } + idleSettings.Enabled = WdfTrue; // explicitly enable SS (overrides any user/registry disable) status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); if (status == STATUS_POWER_STATE_INVALID) { @@ -2159,8 +2159,9 @@ NTSTATUS QCPNP_DisableSelectiveSuspend ("<%ws> QCPNP_DisableSelectiveSuspend\n", pDevContext->PortName) ); - WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend); idleSettings.Enabled = WdfFalse; + idleSettings.UserControlOfIdleSettings = IdleAllowUserControl; return WdfDeviceAssignS0IdleSettings(Device, &idleSettings); } From 19079005ed387f3897b9b0b429f70beb48acdf98 Mon Sep 17 00:00:00 2001 From: Cristian Manca Date: Mon, 27 Apr 2026 12:15:24 +0200 Subject: [PATCH 2/2] Track and restore idle capabilities in power management Store assigned idle capabilities in device context to maintain power policy consistency when toggling selective suspend enable/disable. - Add AssignedIdleCaps field to device context to track idle capabilities - Store assigned idle caps once at function end - Restore stored idle caps or fallback to IdleCannotWakeFromS0 when disabling selective suspend - Ensures power policy state consistency across enable/disable cycles Signed-off-by: Cristian Manca --- src/windows/wdfserial/QCMAIN.h | 1 + src/windows/wdfserial/QCPNP.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/windows/wdfserial/QCMAIN.h b/src/windows/wdfserial/QCMAIN.h index c1c7337..7dafa03 100644 --- a/src/windows/wdfserial/QCMAIN.h +++ b/src/windows/wdfserial/QCMAIN.h @@ -261,6 +261,7 @@ typedef struct _DEVICE_CONTEXT BOOLEAN InServiceSelectiveSuspension; ULONG SelectiveSuspendIdleTime; BOOLEAN SelectiveSuspendInMiliSeconds; + WDF_POWER_POLICY_S0_IDLE_CAPABILITIES AssignedIdleCaps; WMILIB_CONTEXT WmiLibInfo; // to query system power management tab CHAR DevSerialNumber[256]; // to hold USB_STRING_DESCRIPTOR of the serial number diff --git a/src/windows/wdfserial/QCPNP.c b/src/windows/wdfserial/QCPNP.c index a8936e3..ab0da7b 100644 --- a/src/windows/wdfserial/QCPNP.c +++ b/src/windows/wdfserial/QCPNP.c @@ -2098,6 +2098,7 @@ NTSTATUS QCPNP_EnableSelectiveSuspend { // registry not set, ss is disabled idleSettings.Enabled = WdfFalse; + idleSettings.IdleCaps = IdleCannotWakeFromS0; status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); } else @@ -2129,6 +2130,8 @@ NTSTATUS QCPNP_EnableSelectiveSuspend ); } + pDevContext->AssignedIdleCaps = idleSettings.IdleCaps; + return status; } @@ -2159,7 +2162,12 @@ NTSTATUS QCPNP_DisableSelectiveSuspend ("<%ws> QCPNP_DisableSelectiveSuspend\n", pDevContext->PortName) ); - WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT( + &idleSettings, + (pDevContext->AssignedIdleCaps != IdleCapsInvalid) + ? pDevContext->AssignedIdleCaps + : IdleCannotWakeFromS0 + ); idleSettings.Enabled = WdfFalse; idleSettings.UserControlOfIdleSettings = IdleAllowUserControl; return WdfDeviceAssignS0IdleSettings(Device, &idleSettings);