From f8ea999604e0829b9f16bd59287de1a71a799e29 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Thu, 25 May 2023 21:03:13 -0400 Subject: [PATCH] Refactor steam_deck to modularize system interactions --- backend/Cargo.lock | 2 +- backend/Cargo.toml | 2 +- backend/limits_core/Cargo.lock | 2 +- backend/limits_core/Cargo.toml | 2 +- backend/limits_core/src/json/base.rs | 48 +++--- backend/limits_core/src/json/range.rs | 4 +- backend/limits_srv/Cargo.toml | 4 +- backend/src/api/api_types.rs | 12 +- backend/src/api/cpu.rs | 8 +- backend/src/api/gpu.rs | 8 +- backend/src/api/handler.rs | 4 +- backend/src/api/utility.rs | 12 +- backend/src/persist/general.rs | 4 +- backend/src/settings/generic/cpu.rs | 13 +- backend/src/settings/generic/gpu.rs | 51 +++++- backend/src/settings/generic_amd/gpu.rs | 68 ++++---- backend/src/settings/min_max.rs | 8 +- backend/src/settings/steam_deck/battery.rs | 49 +++--- backend/src/settings/steam_deck/cpu.rs | 154 +++++++++++-------- backend/src/settings/steam_deck/gpu.rs | 152 ++++++++---------- backend/src/settings/steam_deck/oc_limits.rs | 2 +- 21 files changed, 329 insertions(+), 280 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 82681fb..3c098c3 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -799,7 +799,7 @@ dependencies = [ [[package]] name = "limits_core" -version = "1.0.0" +version = "2.0.0" dependencies = [ "serde", "serde_json", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index c441c74..b6d2e47 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -25,7 +25,7 @@ log = "0.4" simplelog = "0.12" # limits & driver functionality -limits_core = { version = "1.0.0", path = "./limits_core" } +limits_core = { version = "2", path = "./limits_core" } regex = "1" libryzenadj = { version = "0.12" } # ureq's tls feature does not like musl targets diff --git a/backend/limits_core/Cargo.lock b/backend/limits_core/Cargo.lock index 1914c35..ac3e0ed 100644 --- a/backend/limits_core/Cargo.lock +++ b/backend/limits_core/Cargo.lock @@ -10,7 +10,7 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "limits_core" -version = "1.0.0" +version = "2.0.0" dependencies = [ "serde", "serde_json", diff --git a/backend/limits_core/Cargo.toml b/backend/limits_core/Cargo.toml index 2bb9e77..7dd5c63 100644 --- a/backend/limits_core/Cargo.toml +++ b/backend/limits_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limits_core" -version = "1.0.0" +version = "2.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/backend/limits_core/src/json/base.rs b/backend/limits_core/src/json/base.rs index d6e013c..41e9801 100644 --- a/backend/limits_core/src/json/base.rs +++ b/backend/limits_core/src/json/base.rs @@ -57,16 +57,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 3700 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 3700 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(3700) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(3700) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 1100 }), - clock_max: Some(super::RangeLimit { min: 400, max: 1100 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(1100) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(1100) }), clock_step: Some(100), ..Default::default() })), @@ -84,16 +84,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4000 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4000 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4000) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4000) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 1600 }), - clock_max: Some(super::RangeLimit { min: 400, max: 1600 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(1600) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(1600) }), clock_step: Some(100), ..Default::default() })), @@ -111,16 +111,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4500 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4500 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4500) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4500) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 2000 }), - clock_max: Some(super::RangeLimit { min: 400, max: 2000 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(2000) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(2000) }), clock_step: Some(100), ..Default::default() })), @@ -138,16 +138,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::Generic(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4700 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4700 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4700) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4700) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::Generic(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 28_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 28_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(28_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(28_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 2200 }), - clock_max: Some(super::RangeLimit { min: 400, max: 2200 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(2200) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(2200) }), clock_step: Some(100), ..Default::default() })), diff --git a/backend/limits_core/src/json/range.rs b/backend/limits_core/src/json/range.rs index 2ea3718..49135eb 100644 --- a/backend/limits_core/src/json/range.rs +++ b/backend/limits_core/src/json/range.rs @@ -3,6 +3,6 @@ use serde::{Deserialize, Serialize}; /// Base JSON limits information #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RangeLimit { - pub min: T, - pub max: T, + pub min: Option, + pub max: Option, } diff --git a/backend/limits_srv/Cargo.toml b/backend/limits_srv/Cargo.toml index 67305c8..11cd344 100644 --- a/backend/limits_srv/Cargo.toml +++ b/backend/limits_srv/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "limits_srv" -version = "1.0.0" +version = "2.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -limits_core = { version = "1.0.0", path = "../limits_core" } +limits_core = { version = "2.0.0", path = "../limits_core" } chrono = { version = "0.4" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index aa904b5..8d72107 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -1,18 +1,14 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct RangeLimit { pub min: T, pub max: T, } -impl From> for RangeLimit { - #[inline] - fn from(other: limits_core::json::RangeLimit) -> Self { - RangeLimit { - min: other.min, - max: other.max, - } +impl RangeLimit { + pub fn new(min: T, max: T) -> Self { + Self { min, max } } } diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index c737aac..bd19eab 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -6,6 +6,7 @@ use usdpl_back::AsyncCallable; use crate::settings::{MinMax, SettingError, SettingVariant}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, CpuMessage}; +use super::utility::map_optional; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { @@ -205,8 +206,8 @@ pub fn set_clock_limits( setter( index as usize, MinMax { - min: safe_min as u64, - max: safe_max as u64, + min: Some(safe_min as u64), + max: Some(safe_max as u64), }, ); vec![safe_min.into(), safe_max.into()] @@ -220,6 +221,7 @@ pub fn set_clock_limits( vec!["set_clock_limits missing parameter 0".into()] } } + // TODO allow param 0 and/or 1 to be Primitive::Empty } pub fn get_clock_limits( @@ -245,7 +247,7 @@ pub fn get_clock_limits( move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(min_max) = getter(index as usize) { - vec![min_max.min.into(), min_max.max.into()] + vec![map_optional(min_max.min), map_optional(min_max.max)] } else { vec![Primitive::Empty, Primitive::Empty] } diff --git a/backend/src/api/gpu.rs b/backend/src/api/gpu.rs index 3829d30..320a331 100644 --- a/backend/src/api/gpu.rs +++ b/backend/src/api/gpu.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; +use super::utility::map_optional; use crate::settings::MinMax; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, GpuMessage}; @@ -94,8 +95,8 @@ pub fn set_clock_limits( let safe_max = if max < min { min } else { max }; let safe_min = if min > max { max } else { min }; setter(MinMax { - min: safe_min as _, - max: safe_max as _, + min: Some(safe_min as _), + max: Some(safe_max as _), }); vec![(safe_min as u64).into(), (safe_max as u64).into()] } else { @@ -105,6 +106,7 @@ pub fn set_clock_limits( vec!["set_clock_limits missing parameter 0".into()] } } + // TODO allow param 0 and/or 1 to be Primitive::Empty } pub fn get_clock_limits(sender: Sender) -> impl AsyncCallable { @@ -131,7 +133,7 @@ pub fn get_clock_limits(sender: Sender) -> impl AsyncCallable { set_get: getter, trans_getter: |clocks: Option>| { clocks - .map(|x| vec![x.min.into(), x.max.into()]) + .map(|x| vec![map_optional(x.min), map_optional(x.max)]) .unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty]) }, } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 57f57f5..2ff576a 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -268,7 +268,9 @@ impl ApiMessageHandler { while let Ok(msg) = self.intake.try_recv() { dirty |= self.process(settings, msg); } - if dirty /*|| dirty_echo */ { + if dirty + /*|| dirty_echo */ + { //dirty_echo = dirty; // echo only once // run on_set diff --git a/backend/src/api/utility.rs b/backend/src/api/utility.rs index 7cec146..fda4404 100644 --- a/backend/src/api/utility.rs +++ b/backend/src/api/utility.rs @@ -19,10 +19,7 @@ pub fn map_optional_result>( result: Result, SettingError>, ) -> super::ApiParameterType { match result { - Ok(val) => match val { - Some(val) => vec![val.into()], - None => vec![Primitive::Empty], - }, + Ok(val) => vec![map_optional(val)], Err(e) => { log::debug!("Mapping error to primitive: {}", e); vec![e.msg.into()] @@ -30,6 +27,13 @@ pub fn map_optional_result>( } } +pub fn map_optional>(option: Option) -> Primitive { + match option { + Some(val) => val.into(), + None => Primitive::Empty, + } +} + /*#[inline] pub fn map_empty_result>( result: Result<(), SettingError>, diff --git a/backend/src/persist/general.rs b/backend/src/persist/general.rs index d012743..9148675 100644 --- a/backend/src/persist/general.rs +++ b/backend/src/persist/general.rs @@ -58,6 +58,6 @@ impl SettingsJson { #[derive(Serialize, Deserialize, Clone)] pub struct MinMaxJson { - pub max: T, - pub min: T, + pub max: Option, + pub min: Option, } diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 3e838ce..b821053 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -3,6 +3,7 @@ use std::convert::{AsMut, AsRef, Into}; use limits_core::json::GenericCpuLimit; use super::FromGenericCpuInfo; +use crate::api::RangeLimit; use crate::persist::CpuJson; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; @@ -330,8 +331,16 @@ impl Cpu { fn limits(&self) -> crate::api::CpuLimits { crate::api::CpuLimits { - clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), - clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_min_limits: self + .limits + .clock_min + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(5_000))), + clock_max_limits: self + .limits + .clock_max + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(5_000))), clock_step: self.limits.clock_step, governors: self.governors(), } diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index f8d1a5c..b388df1 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -2,6 +2,7 @@ use std::convert::Into; use limits_core::json::GenericGpuLimit; +use crate::api::RangeLimit; use crate::persist::GpuJson; use crate::settings::TGpu; use crate::settings::{min_max_from_json, MinMax}; @@ -97,14 +98,38 @@ impl crate::settings::OnPowerEvent for Gpu {} impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { crate::api::GpuLimits { - fast_ppt_limits: self.limits.fast_ppt.clone().map(|x| x.into()), - slow_ppt_limits: self.limits.slow_ppt.clone().map(|x| x.into()), + fast_ppt_limits: self + .limits + .fast_ppt + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), + slow_ppt_limits: self + .limits + .slow_ppt + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), ppt_step: self.limits.ppt_step.unwrap_or(1_000_000), - tdp_limits: self.limits.tdp.clone().map(|x| x.into()), - tdp_boost_limits: self.limits.tdp_boost.clone().map(|x| x.into()), + tdp_limits: self + .limits + .tdp + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), + tdp_boost_limits: self + .limits + .tdp_boost + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), tdp_step: self.limits.tdp_step.unwrap_or(42), - clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), - clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_min_limits: self + .limits + .clock_min + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(3_000))), + clock_max_limits: self + .limits + .clock_max + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(3_000))), clock_step: self.limits.clock_step.unwrap_or(100), memory_control_capable: false, } @@ -116,10 +141,20 @@ impl TGpu for Gpu { fn ppt(&mut self, fast: Option, slow: Option) { if let Some(fast_lims) = &self.limits.fast_ppt { - self.fast_ppt = fast.map(|x| x.clamp(fast_lims.min, fast_lims.max)); + self.fast_ppt = fast.map(|x| { + x.clamp( + fast_lims.min.unwrap_or(0), + fast_lims.max.unwrap_or(u64::MAX), + ) + }); } if let Some(slow_lims) = &self.limits.slow_ppt { - self.slow_ppt = slow.map(|x| x.clamp(slow_lims.min, slow_lims.max)); + self.slow_ppt = slow.map(|x| { + x.clamp( + slow_lims.min.unwrap_or(0), + slow_lims.max.unwrap_or(u64::MAX), + ) + }); } } diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 841393b..9af3bc2 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -128,24 +128,22 @@ impl Gpu { } if let Some(clock_limits) = &self.generic.clock_limits { self.state.clock_limits_set = true; - lock.set_max_gfxclk_freq(clock_limits.max as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_max_gfxclk_freq({}) err: {}", - clock_limits.max, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - lock.set_min_gfxclk_freq(clock_limits.min as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_min_gfxclk_freq({}) err: {}", - clock_limits.min, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + lock.set_max_gfxclk_freq(max as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } + if let Some(min) = clock_limits.min { + lock.set_min_gfxclk_freq(min as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } } else if self.state.clock_limits_set { self.state.clock_limits_set = false; let limits = self.generic.limits(); @@ -218,24 +216,22 @@ impl Gpu { .unwrap_or_else(|e| errors.push(e)); } if let Some(clock_limits) = &self.generic.clock_limits { - lock.set_max_gfxclk_freq(clock_limits.max as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_max_gfxclk_freq({}) err: {}", - clock_limits.max, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - lock.set_min_gfxclk_freq(clock_limits.min as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_min_gfxclk_freq({}) err: {}", - clock_limits.min, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + lock.set_max_gfxclk_freq(max as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } + if let Some(min) = clock_limits.min { + lock.set_min_gfxclk_freq(min as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } } Ok(()) } diff --git a/backend/src/settings/min_max.rs b/backend/src/settings/min_max.rs index c1c9563..e307268 100644 --- a/backend/src/settings/min_max.rs +++ b/backend/src/settings/min_max.rs @@ -8,8 +8,8 @@ pub type MinMax = RangeLimit; pub fn min_max_from_json>(other: MinMaxJson, _version: u64) -> MinMax { MinMax { - max: other.max.into(), - min: other.min.into(), + max: other.max.map(|x| x.into()), + min: other.min.map(|x| x.into()), } } @@ -17,8 +17,8 @@ impl, Y> Into> for RangeLimit { #[inline] fn into(self) -> MinMaxJson { MinMaxJson { - max: self.max.into(), - min: self.min.into(), + max: self.max.map(|x| x.into()), + min: self.min.map(|x| x.into()), } } } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 4a5305c..9ea5372 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -99,12 +99,12 @@ impl EventInstruction { .trim_start_matches('>') .parse::() .ok() - .map(|x| EventTrigger::BatteryAbove(x/100.0)), + .map(|x| EventTrigger::BatteryAbove(x / 100.0)), s if s.starts_with('<') => s .trim_start_matches('<') .parse::() .ok() - .map(|x| EventTrigger::BatteryBelow(x/100.0)), + .map(|x| EventTrigger::BatteryBelow(x / 100.0)), _ => None, } } @@ -244,6 +244,30 @@ impl Battery { } } + fn set_charge_rate(&mut self) -> Result<(), SettingError> { + if let Some(charge_rate) = self.charge_rate { + self.state.charge_rate_set = true; + usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( + |e| SettingError { + msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }, + ) + } else if self.state.charge_rate_set { + self.state.charge_rate_set = false; + usdpl_back::api::files::write_single( + BATTERY_CHARGE_RATE_PATH, + self.limits.charge_rate.max, + ) + .map_err(|e| SettingError { + msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }) + } else { + Ok(()) + } + } + fn set_charge_mode(&mut self) -> Result<(), SettingError> { if let Some(charge_mode) = self.charge_mode { self.state.charge_mode_set = true; @@ -268,26 +292,7 @@ impl Battery { fn set_all(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); - if let Some(charge_rate) = self.charge_rate { - self.state.charge_rate_set = true; - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }) - .unwrap_or_else(|e| errors.push(e)); - } else if self.state.charge_rate_set { - self.state.charge_rate_set = false; - usdpl_back::api::files::write_single( - BATTERY_CHARGE_RATE_PATH, - self.limits.charge_rate.max, - ) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }) - .unwrap_or_else(|e| errors.push(e)); - } + self.set_charge_rate().unwrap_or_else(|e| errors.push(e)); self.set_charge_mode().unwrap_or_else(|e| errors.push(e)); if errors.is_empty() { Ok(()) diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 91ec128..58c315e 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -234,6 +234,11 @@ pub struct Cpu { const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +enum ClockType { + Min = 0, + Max = 1, +} + impl Cpu { #[inline] fn from_json(other: CpuJson, version: u64, i: usize, oc_limits: CpuLimits) -> Self { @@ -257,86 +262,91 @@ impl Cpu { } } - fn set_force_performance_related(&mut self) -> Result<(), Vec> { - let mut errors = Vec::new(); + fn set_clock_limit(index: usize, speed: u64, mode: ClockType) -> Result<(), SettingError> { + let payload = format!("p {} {} {}\n", index / 2, mode as u8, speed); + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload, CPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + }) + } - // set clock limits - //log::debug!("Setting {} to manual", CPU_FORCE_LIMITS_PATH); - //let mode: String = usdpl_back::api::files::read_single(CPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); + fn set_clock_limits(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); if let Some(clock_limits) = &self.clock_limits { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; log::debug!( - "Setting CPU {} (min, max) clockspeed to ({}, {})", + "Setting CPU {} (min, max) clockspeed to ({:?}, {:?})", self.index, clock_limits.min, clock_limits.max ); self.state.clock_limits_set = true; // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + Self::set_clock_limit(self.index, max, ClockType::Max) + .unwrap_or_else(|e| errors.push(e)); + } // min clock - let valid_min = if clock_limits.min < self.limits.clock_min.min { - self.limits.clock_min.min + if let Some(min) = clock_limits.min { + let valid_min = if min < self.limits.clock_min.min { + self.limits.clock_min.min + } else { + min + }; + Self::set_clock_limit(self.index, valid_min, ClockType::Min) + .unwrap_or_else(|e| errors.push(e)); + } + + if errors.is_empty() { + Ok(()) } else { - clock_limits.min - }; - let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); + Err(errors) + } } else if self.state.clock_limits_set || (self.state.is_resuming && !self.limits.skip_resume_reclock) || POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { + let mut errors = Vec::new(); self.state.clock_limits_set = false; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; // disable manual clock limits log::debug!("Setting CPU {} to default clockspeed", self.index); // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, self.limits.clock_max.max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) + Self::set_clock_limit(self.index, self.limits.clock_max.max, ClockType::Max) .unwrap_or_else(|e| errors.push(e)); // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, self.limits.clock_min.min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) + Self::set_clock_limit(self.index, self.limits.clock_min.min, ClockType::Min) .unwrap_or_else(|e| errors.push(e)); } - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT .enforce_level() .unwrap_or_else(|mut e| errors.append(&mut e)); + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } else { + Ok(()) } + } + + fn set_force_performance_related(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); + + // set clock limits + //log::debug!("Setting {} to manual", CPU_FORCE_LIMITS_PATH); + //let mode: String = usdpl_back::api::files::read_single(CPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); + self.set_clock_limits() + .unwrap_or_else(|mut e| errors.append(&mut e)); // commit changes (if no errors have already occured) if errors.is_empty() { if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { @@ -354,6 +364,23 @@ impl Cpu { } } + fn set_governor(&self) -> Result<(), SettingError> { + if self.index == 0 || self.online { + let governor_path = cpu_governor_path(self.index); + usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &self.governor, &governor_path, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + }) + } else { + Ok(()) + } + } + fn set_all(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); // set cpu online/offline @@ -371,19 +398,8 @@ impl Cpu { self.set_force_performance_related() .unwrap_or_else(|mut e| errors.append(&mut e)); - // set governor - if self.index == 0 || self.online { - let governor_path = cpu_governor_path(self.index); - usdpl_back::api::files::write_single(&governor_path, &self.governor) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &self.governor, &governor_path, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - } + self.set_governor().unwrap_or_else(|e| errors.push(e)); + if errors.is_empty() { Ok(()) } else { @@ -393,12 +409,14 @@ impl Cpu { fn clamp_all(&mut self) { if let Some(clock_limits) = &mut self.clock_limits { - clock_limits.min = clock_limits - .min - .clamp(self.limits.clock_min.min, self.limits.clock_min.max); - clock_limits.max = clock_limits - .max - .clamp(self.limits.clock_max.min, self.limits.clock_max.max); + if let Some(min) = clock_limits.min { + clock_limits.min = + Some(min.clamp(self.limits.clock_min.min, self.limits.clock_min.max)); + } + if let Some(max) = clock_limits.max { + clock_limits.max = + Some(max.clamp(self.limits.clock_max.min, self.limits.clock_max.max)); + } } } diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 83bf2bd..c44f3af 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -26,6 +26,11 @@ pub struct Gpu { const GPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk"; +enum ClockType { + Min = 0, + Max = 1, +} + impl Gpu { #[inline] pub fn from_json(other: GpuJson, version: u64) -> Self { @@ -57,6 +62,28 @@ impl Gpu { } } + fn set_clock_limit(speed: u64, mode: ClockType) -> Result<(), SettingError> { + let payload = format!("s {} {}\n", mode as u8, speed); + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload, GPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } + + fn set_confirm() -> Result<(), SettingError> { + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { + SettingError { + msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } + fn set_clocks(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); if let Some(clock_limits) = &self.clock_limits { @@ -65,81 +92,37 @@ impl Gpu { // set clock limits self.state.clock_limits_set = true; // max clock - let payload_max = format!("s 1 {}\n", clock_limits.max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + Self::set_clock_limit(max, ClockType::Max).unwrap_or_else(|e| errors.push(e)); + } // min clock - let payload_min = format!("s 0 {}\n", clock_limits.min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else( - |e| { - errors.push(SettingError { - msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }) - }, - ); + if let Some(min) = clock_limits.min { + Self::set_clock_limit(min, ClockType::Min).unwrap_or_else(|e| errors.push(e)); + } + + Self::set_confirm().unwrap_or_else(|e| errors.push(e)); } else if self.state.clock_limits_set || (self.state.is_resuming && !self.limits.skip_resume_reclock) || POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { self.state.clock_limits_set = false; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory); if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; // disable manual clock limits // max clock - let payload_max = format!("s 1 {}\n", self.limits.clock_max.max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) + Self::set_clock_limit(self.limits.clock_max.max, ClockType::Max) .unwrap_or_else(|e| errors.push(e)); // min clock - let payload_min = format!("s 0 {}\n", self.limits.clock_min.min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) + Self::set_clock_limit(self.limits.clock_min.min, ClockType::Min) .unwrap_or_else(|e| errors.push(e)); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else( - |e| { - errors.push(SettingError { - msg: format!( - "Failed to write `c` to `{}`: {}", - GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - }, - ); + + Self::set_confirm().unwrap_or_else(|e| errors.push(e)); + } else { + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT + .enforce_level() + .unwrap_or_else(|mut e| errors.append(&mut e)); } - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level() - .unwrap_or_else(|mut e| errors.append(&mut e)); } if errors.is_empty() { Ok(()) @@ -148,6 +131,15 @@ impl Gpu { } } + fn set_slow_memory(slow: bool) -> Result<(), SettingError> { + usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, slow as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } + fn set_force_performance_related(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); // enable/disable downclock of GPU memory (to 400Mhz?) @@ -156,21 +148,9 @@ impl Gpu { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT .enforce_level() .unwrap_or_else(|mut e| errors.append(&mut e)); - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .unwrap_or_else(|e| { - errors.push(SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }); - }); + Self::set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e)); } else if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .unwrap_or_else(|e| { - errors.push(SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }); - }); + Self::set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.clock_limits.is_some()); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT .enforce_level() @@ -181,11 +161,9 @@ impl Gpu { // commit changes (if no errors have already occured) if errors.is_empty() { if self.slow_memory || self.clock_limits.is_some() { - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - vec![SettingError { - msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }] + Self::set_confirm().map_err(|e| { + errors.push(e); + errors }) } else { Ok(()) @@ -276,12 +254,14 @@ impl Gpu { *slow_ppt = (*slow_ppt).clamp(self.limits.slow_ppt.min, self.limits.slow_ppt.max); } if let Some(clock_limits) = &mut self.clock_limits { - clock_limits.min = clock_limits - .min - .clamp(self.limits.clock_min.min, self.limits.clock_min.max); - clock_limits.max = clock_limits - .max - .clamp(self.limits.clock_max.min, self.limits.clock_max.max); + if let Some(min) = clock_limits.min { + clock_limits.min = + Some(min.clamp(self.limits.clock_min.min, self.limits.clock_min.max)); + } + if let Some(max) = clock_limits.max { + clock_limits.max = + Some(max.clamp(self.limits.clock_max.min, self.limits.clock_max.max)); + } } } diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index 69aa364..74c2bf2 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -1,4 +1,4 @@ -use crate::settings::MinMax; +use crate::api::RangeLimit as MinMax; use serde::{Deserialize, Serialize}; const OC_LIMITS_FILEPATH: &str = "pt_oc.json";