diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 1fc9ddb..682bc22 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "powertools-rs" -version = "1.2.0-beta1" +version = "1.2.0-beta2" dependencies = [ "async-trait", "limits_core", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index b2c5933..e9ed6f1 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "powertools-rs" -version = "1.2.0-beta1" +version = "1.2.0-beta2" edition = "2021" authors = ["NGnius (Graham) "] description = "Backend (superuser) functionality for PowerTools" diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 1a59250..7d3e7f9 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -1,4 +1,5 @@ use std::sync::mpsc::{self, Receiver, Sender}; +use std::fmt::Write; use crate::settings::{Settings, TCpus, TGpu, TBattery, TGeneral, OnSet, OnResume, MinMax}; use crate::persist::SettingsJson; @@ -216,6 +217,12 @@ pub struct ApiMessageHandler { on_empty: Vec>, } +fn print_errors(call_name: &str, errors: Vec) { + let mut err_list = String::new(); + errors.iter().for_each(|e| write!(err_list, "\t{},\n", e).unwrap_or(())); + log::error!("Settings {}() err:\n{}", call_name, err_list); +} + impl ApiMessageHandler { pub fn process_forever(&mut self, settings: &mut Settings) { let mut dirty_echo = true; // set everything twice, to make sure PowerTools wins on race conditions @@ -228,7 +235,7 @@ impl ApiMessageHandler { dirty_echo = dirty; // echo only once // run on_set if let Err(e) = settings.on_set() { - log::error!("Settings on_set() err: {}", e); + print_errors("on_set", e); } // do callbacks for func in self.on_empty.drain(..) { @@ -272,7 +279,7 @@ impl ApiMessageHandler { ApiMessage::General(x) => x.process(settings.general.as_mut()), ApiMessage::OnResume => { if let Err(e) = settings.on_resume() { - log::error!("Settings on_resume() err: {}", e); + print_errors("on_resume", e); } false } diff --git a/backend/src/main.rs b/backend/src/main.rs index 6d6bac6..ab70cbc 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -224,7 +224,7 @@ fn main() -> Result<(), ()> { .register("GENERAL_idk", api::general::gunter); if let Err(e) = loaded_settings.on_set() { - log::error!("Startup Settings.on_set() error: {}", e); + e.iter().for_each(|e| log::error!("Startup Settings.on_set() error: {}", e)); } else { log::info!("Startup Settings.on_set() success"); } diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index 2279f4f..f88a05d 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -37,13 +37,13 @@ pub struct General { } impl OnSet for General { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { Ok(()) } } impl OnResume for General { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { Ok(()) } } @@ -91,7 +91,7 @@ pub struct Settings { } impl OnSet for Settings { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.battery.on_set()?; self.cpus.on_set()?; self.gpu.on_set()?; @@ -224,7 +224,7 @@ impl Settings { } impl OnResume for Settings { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { log::debug!("Applying settings for on_resume"); self.battery.on_resume()?; log::debug!("Resumed battery"); diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index 1555f4a..f2551a0 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -52,13 +52,15 @@ impl Battery { } impl OnSet for Battery { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { + // TODO Ok(()) } } impl OnResume for Battery { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { + // TODO Ok(()) } } diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 2ae1f5c..873a98d 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -19,7 +19,8 @@ pub struct Cpus + AsRef + TCpu> { } impl + AsRef + TCpu + OnSet> OnSet for Cpus { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); if self.smt_capable { // toggle SMT if self.smt { @@ -31,7 +32,7 @@ impl + AsRef + TCpu + OnSet> OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } else { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { SettingError { @@ -41,23 +42,32 @@ impl + AsRef + TCpu + OnSet> OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { cpu.as_mut().state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; - cpu.on_set()?; + cpu.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } impl + AsRef + TCpu + OnResume> OnResume for Cpus { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { + let mut errors = Vec::new(); for cpu in &self.cpus { - cpu.on_resume()?; + cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } @@ -232,7 +242,8 @@ impl FromGenericCpuInfo for Cpu { } impl Cpu { - fn set_all(&mut self) -> Result<(), SettingError> { + fn set_all(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); // set cpu online/offline if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled let online_path = cpu_online_path(self.index); @@ -241,7 +252,7 @@ impl Cpu { msg: format!("Failed to write to `{}`: {}", &online_path, e), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } // set governor @@ -255,9 +266,13 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } /*fn from_sys(cpu_index: usize) -> Self { @@ -304,14 +319,14 @@ impl Into for Cpu { } impl OnSet for Cpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { //self.clamp_all(); self.set_all() } } impl OnResume for Cpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { let mut copy = self.clone(); copy.state.is_resuming = true; copy.set_all() diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 7e658a4..064e87a 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -69,13 +69,13 @@ impl Into for Gpu { } impl OnSet for Gpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { Ok(()) } } impl OnResume for Gpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { Ok(()) } } diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs index 74f5c5b..8285fd0 100644 --- a/backend/src/settings/generic_amd/cpu.rs +++ b/backend/src/settings/generic_amd/cpu.rs @@ -24,14 +24,14 @@ impl Cpus { } impl OnResume for Cpus { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { self.generic.on_resume() // TODO } } impl OnSet for Cpus { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.generic.on_set() // TODO } @@ -97,14 +97,14 @@ impl AsMut for Cpu { } impl OnResume for Cpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { self.generic.on_resume() // TODO } } impl OnSet for Cpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.generic.on_set() // TODO } diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index ca4dffe..6d35bb1 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -41,25 +41,26 @@ impl Gpu { } } - fn set_all(&mut self) -> Result<(), SettingError> { + fn set_all(&mut self) -> Result<(), Vec> { let mutex = match &self.implementor { Some(x) => x, None => { - return Err(SettingError { + return Err(vec![SettingError { msg: "RyzenAdj unavailable".to_owned(), setting: SettingVariant::Gpu, - }); + }]); } }; let lock = match mutex.lock() { Ok(x) => x, Err(e) => { - return Err(SettingError { + return Err(vec![SettingError { msg: format!("RyzenAdj lock acquire failed: {}", e), setting: SettingVariant::Gpu, - }); + }]); } }; + let mut errors = Vec::new(); if let Some(fast_ppt) = &self.generic.fast_ppt { if self.state.old_fast_ppt.is_none() { self.state.old_fast_ppt = Some(lock.get_fast_value() as _); @@ -67,12 +68,12 @@ impl Gpu { lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); } else if let Some(fast_ppt) = &self.state.old_fast_ppt { lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); self.state.old_fast_ppt = None; } if let Some(slow_ppt) = &self.generic.slow_ppt { @@ -82,12 +83,12 @@ impl Gpu { lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); } else if let Some(slow_ppt) = &self.state.old_slow_ppt { lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); self.state.old_slow_ppt = None; } if let Some(clock_limits) = &self.generic.clock_limits { @@ -95,11 +96,11 @@ impl Gpu { 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)); } else if self.state.clock_limits_set { self.state.clock_limits_set = false; let limits = self.generic.limits(); @@ -108,73 +109,78 @@ impl Gpu { lock.set_max_gfxclk_freq(max_limits.max as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max_limits.max, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); lock.set_min_gfxclk_freq(min_limits.min as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min_limits.min, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); } } } - Ok(()) + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } } - fn resume_all(&self) -> Result<(), SettingError> { + fn resume_all(&self) -> Result<(), Vec> { // like set_all() but without updating state // -- assumption: state is already up to date let mutex = match &self.implementor { Some(x) => x, None => { - return Err(SettingError { + return Err(vec![SettingError { msg: "RyzenAdj unavailable".to_owned(), setting: SettingVariant::Gpu, - }); + }]); } }; let lock = match mutex.lock() { Ok(x) => x, Err(e) => { - return Err(SettingError { + return Err(vec![SettingError { msg: format!("RyzenAdj lock acquire failed: {}", e), setting: SettingVariant::Gpu, - }); + }]); } }; + let mut errors = Vec::new(); if let Some(fast_ppt) = &self.generic.fast_ppt { lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), setting: SettingVariant::Gpu, - })?; + }).unwrap_or_else(|e| errors.push(e)); } if let Some(slow_ppt) = &self.generic.slow_ppt { lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), setting: SettingVariant::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)); } Ok(()) } } impl OnResume for Gpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { self.generic.on_resume()?; self.resume_all() } } impl OnSet for Gpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.generic.on_set()?; self.set_all() } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 5a7f745..e4c9574 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -67,7 +67,8 @@ impl Battery { } } - fn set_all(&mut self) -> Result<(), SettingError> { + 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( @@ -75,7 +76,7 @@ impl Battery { 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( @@ -83,7 +84,7 @@ impl Battery { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), setting: crate::settings::SettingVariant::Battery, }, - )?; + ).unwrap_or_else(|e| errors.push(e)); } if let Some(charge_mode) = self.charge_mode { self.state.charge_mode_set = true; @@ -92,7 +93,7 @@ impl Battery { msg: format!("Failed to set charge mode: {}", e), setting: crate::settings::SettingVariant::Battery, }, - )?; + ).unwrap_or_else(|e| {errors.push(e); 0}); } else if self.state.charge_mode_set { self.state.charge_mode_set = false; super::util::set(super::util::Setting::ChargeMode, ChargeMode::Normal as _).map_err( @@ -100,9 +101,13 @@ impl Battery { msg: format!("Failed to set charge mode: {}", e), setting: crate::settings::SettingVariant::Battery, }, - )?; + ).unwrap_or_else(|e| {errors.push(e); 0}); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } fn clamp_all(&mut self) { @@ -181,14 +186,14 @@ impl Into for Battery { } impl OnSet for Battery { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.clamp_all(); self.set_all() } } impl OnResume for Battery { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { self.clone().set_all() } } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 426497d..97adea7 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -20,7 +20,8 @@ pub struct Cpus { } impl OnSet for Cpus { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); if self.smt_capable { // toggle SMT if self.smt { @@ -32,7 +33,7 @@ impl OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } else { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { SettingError { @@ -42,23 +43,32 @@ impl OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { cpu.state.do_set_online = self.smt || i % 2 == 0; - cpu.on_set()?; + cpu.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } impl OnResume for Cpus { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { + let mut errors = Vec::new(); for cpu in &self.cpus { - cpu.on_resume()?; + cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } @@ -221,30 +231,22 @@ impl Cpu { } } - fn set_all(&mut self) -> Result<(), SettingError> { - // set cpu online/offline - if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled - let online_path = cpu_online_path(self.index); - usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { - SettingError { - msg: format!("Failed to write to `{}`: {}", &online_path, e), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } + 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(); if mode != "manual" { // set manual control usdpl_back::api::files::write_single(CPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { - SettingError { + vec![SettingError { msg: format!( "Failed to write `manual` to `{}`: {}", CPU_FORCE_LIMITS_PATH, e ), setting: crate::settings::SettingVariant::Cpu, - } + }] })?; } if let Some(clock_limits) = &self.clock_limits { @@ -260,7 +262,7 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, }, - )?; + ).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} else {clock_limits.min}; let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min); @@ -272,7 +274,7 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, }, - )?; + ).unwrap_or_else(|e| errors.push(e)); } else if self.state.clock_limits_set || (self.state.is_resuming && !self.limits.skip_resume_reclock) { self.state.clock_limits_set = false; // disable manual clock limits @@ -287,7 +289,7 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, }, - )?; + ).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( @@ -298,15 +300,39 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, }, - )?; + ).unwrap_or_else(|e| errors.push(e)); } // commit changes - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - SettingError { - msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Cpu, - } - })?; + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n") + .unwrap_or_else(|e| { + errors.push(SettingError { + msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), + setting: crate::settings::SettingVariant::Cpu, + }); + }); + + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } + + fn set_all(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); + // set cpu online/offline + if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled + let online_path = cpu_online_path(self.index); + usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", &online_path, e), + setting: crate::settings::SettingVariant::Cpu, + } + }).unwrap_or_else(|e| errors.push(e)); + } + + self.set_force_performance_related() + .unwrap_or_else(|mut e| errors.append(&mut e)); // set governor if self.index == 0 || self.online { @@ -319,9 +345,13 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } fn clamp_all(&mut self) { @@ -394,14 +424,14 @@ impl Into for Cpu { } impl OnSet for Cpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.clamp_all(); self.set_all() } } impl OnResume for Cpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { let mut copy = self.clone(); copy.state.is_resuming = true; copy.set_all() diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index cf5e788..fef4498 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -53,53 +53,8 @@ impl Gpu { } } - fn set_all(&mut self) -> Result<(), SettingError> { - // set fast PPT - if let Some(fast_ppt) = &self.fast_ppt { - let fast_ppt_path = gpu_power_path(FAST_PPT); - usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt).map_err(|e| { - SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - fast_ppt, &fast_ppt_path, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // set slow PPT - if let Some(slow_ppt) = &self.slow_ppt { - let slow_ppt_path = gpu_power_path(SLOW_PPT); - usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt).map_err(|e| { - SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - slow_ppt, &slow_ppt_path, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // settings using force_performance_level - let mode: String = usdpl_back::api::files::read_single(GPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); - if mode != "manual" { - // set manual control - usdpl_back::api::files::write_single(GPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { - SettingError { - msg: format!( - "Failed to write `manual` to `{}`: {}", - GPU_FORCE_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // enable/disable downclock of GPU memory (to 400Mhz?) - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_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 { // set clock limits self.state.clock_limits_set = true; @@ -113,7 +68,7 @@ impl Gpu { ), setting: crate::settings::SettingVariant::Gpu, }, - )?; + ).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( @@ -124,7 +79,7 @@ impl Gpu { ), setting: crate::settings::SettingVariant::Gpu, }, - )?; + ).unwrap_or_else(|e| errors.push(e)); } else if self.state.clock_limits_set || (self.state.is_resuming && !self.limits.skip_resume_reclock) { self.state.clock_limits_set = false; // disable manual clock limits @@ -138,7 +93,7 @@ impl Gpu { ), setting: crate::settings::SettingVariant::Gpu, }, - )?; + ).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( @@ -149,17 +104,90 @@ impl Gpu { ), setting: crate::settings::SettingVariant::Gpu, }, - )?; + ).unwrap_or_else(|e| errors.push(e)); } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } + + fn set_force_performance_related(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); + // settings using force_performance_level + let mode: String = usdpl_back::api::files::read_single(GPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); + if mode != "manual" { + // set manual control + usdpl_back::api::files::write_single(GPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { + vec![SettingError { + msg: format!( + "Failed to write `manual` to `{}`: {}", + GPU_FORCE_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + }] + })?; + } + // enable/disable downclock of GPU memory (to 400Mhz?) + 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_clocks() + .unwrap_or_else(|mut e| errors.append(&mut e)); // commit changes 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, } - })?; + }).unwrap_or_else(|e| errors.push(e)); + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } - Ok(()) + fn set_all(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); + // set fast PPT + if let Some(fast_ppt) = &self.fast_ppt { + let fast_ppt_path = gpu_power_path(FAST_PPT); + usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + fast_ppt, &fast_ppt_path, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + }).unwrap_or_else(|e| {errors.push(e);}); + } + // set slow PPT + if let Some(slow_ppt) = &self.slow_ppt { + let slow_ppt_path = gpu_power_path(SLOW_PPT); + usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + slow_ppt, &slow_ppt_path, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + }).unwrap_or_else(|e| {errors.push(e);}); + } + self.set_force_performance_related() + .unwrap_or_else(|mut e| errors.append(&mut e)); + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } } fn clamp_all(&mut self) { @@ -208,14 +236,14 @@ impl Into for Gpu { } impl OnSet for Gpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { self.clamp_all(); self.set_all() } } impl OnResume for Gpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { let mut copy = self.clone(); copy.state.is_resuming = true; copy.set_all() diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index c2f70bf..304bb4c 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -3,11 +3,11 @@ use super::SettingError; use super::MinMax; pub trait OnSet { - fn on_set(&mut self) -> Result<(), SettingError>; + fn on_set(&mut self) -> Result<(), Vec>; } pub trait OnResume { - fn on_resume(&self) -> Result<(), SettingError>; + fn on_resume(&self) -> Result<(), Vec>; } pub trait SettingsRange { diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index dfc57ce..21554f3 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -18,13 +18,13 @@ impl Into for Battery { } impl OnSet for Battery { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { Ok(()) } } impl OnResume for Battery { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { Ok(()) } } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 16e5ba4..36c800f 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -16,7 +16,8 @@ pub struct Cpus { } impl OnSet for Cpus { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); if self.smt_capable { // toggle SMT if self.smt { @@ -28,7 +29,7 @@ impl OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| {errors.push(e);}); } else { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { SettingError { @@ -38,23 +39,32 @@ impl OnSet for Cpus { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| {errors.push(e);}); } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { - cpu.state.do_set_online = self.smt || i % 2 == 0; - cpu.on_set()?; + cpu.state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; + cpu.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } impl OnResume for Cpus { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { + let mut errors = Vec::new(); for cpu in &self.cpus { - cpu.on_resume()?; + cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } } @@ -191,7 +201,8 @@ impl Cpu { } } - fn set_all(&mut self) -> Result<(), SettingError> { + fn set_all(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); // set cpu online/offline if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled let online_path = cpu_online_path(self.index); @@ -200,7 +211,7 @@ impl Cpu { msg: format!("Failed to write to `{}`: {}", &online_path, e), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); } // set governor @@ -214,9 +225,13 @@ impl Cpu { ), setting: crate::settings::SettingVariant::Cpu, } - })?; + }).unwrap_or_else(|e| errors.push(e)); + } + if errors.is_empty() { + Ok(()) + } else { + Err(errors) } - Ok(()) } fn from_sys(cpu_index: usize) -> Self { @@ -251,14 +266,14 @@ impl Into for Cpu { } impl OnSet for Cpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { //self.clamp_all(); self.set_all() } } impl OnResume for Cpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { let mut copy = self.clone(); copy.state.is_resuming = true; copy.set_all() diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs index fecc4ed..4cec037 100644 --- a/backend/src/settings/unknown/gpu.rs +++ b/backend/src/settings/unknown/gpu.rs @@ -38,13 +38,13 @@ impl Into for Gpu { } impl OnSet for Gpu { - fn on_set(&mut self) -> Result<(), SettingError> { + fn on_set(&mut self) -> Result<(), Vec> { Ok(()) } } impl OnResume for Gpu { - fn on_resume(&self) -> Result<(), SettingError> { + fn on_resume(&self) -> Result<(), Vec> { Ok(()) } } diff --git a/backend/src/utility.rs b/backend/src/utility.rs index 7469ba9..cd1c452 100644 --- a/backend/src/utility.rs +++ b/backend/src/utility.rs @@ -44,10 +44,10 @@ pub fn chown_settings_dir() -> std::io::Result<()> { .output()?; let uid: u32 = String::from_utf8_lossy(&output.stdout).parse().unwrap_or(1000); log::info!("chmod/chown ~/.config/powertools for user `{}` ({})", deck_user, uid); - let permissions = PermissionsExt::from_mode(0o655); + let permissions = PermissionsExt::from_mode(0o755); std::fs::set_permissions(&dir, permissions)?; // FIXME once merged into stable https://github.com/rust-lang/rust/issues/88989 - //std::os::unix::fs::chown(&dir, Some(uid), None) + //std::os::unix::fs::chown(&dir, Some(uid), Some(uid)) std::process::Command::new("chown") .args(["-R", &format!("{}:{}", deck_user, deck_user), &dir.to_str().unwrap_or(".")]) .output()?; diff --git a/package.json b/package.json index d4171f4..8a73eba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.2.0-beta1", + "version": "1.2.0-beta2", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", @@ -39,7 +39,7 @@ "typescript": "^4.9.5" }, "dependencies": { - "decky-frontend-lib": "~3.18.11", + "decky-frontend-lib": "~3.19.1", "react-icons": "^4.7.1", "usdpl-front": "file:src/usdpl_front" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59345b9..c3a416b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ specifiers: '@rollup/plugin-typescript': ^8.5.0 '@types/react': 16.14.0 '@types/webpack': ^5.28.0 - decky-frontend-lib: ~3.18.11 + decky-frontend-lib: ~3.19.1 react-icons: ^4.7.1 rollup: ^2.79.1 rollup-plugin-import-assets: ^1.1.1 @@ -18,7 +18,7 @@ specifiers: usdpl-front: file:src/usdpl_front dependencies: - decky-frontend-lib: 3.18.11 + decky-frontend-lib: 3.19.1 react-icons: 4.7.1 usdpl-front: file:src/usdpl_front @@ -185,8 +185,8 @@ packages: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true - /@types/node/18.14.0: - resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==} + /@types/node/18.14.1: + resolution: {integrity: sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==} dev: true /@types/prop-types/15.7.5: @@ -203,13 +203,13 @@ packages: /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 18.14.0 + '@types/node': 18.14.1 dev: true /@types/webpack/5.28.0: resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==} dependencies: - '@types/node': 18.14.0 + '@types/node': 18.14.1 tapable: 2.2.1 webpack: 5.75.0 transitivePeerDependencies: @@ -381,7 +381,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001457 - electron-to-chromium: 1.4.305 + electron-to-chromium: 1.4.309 node-releases: 2.0.10 update-browserslist-db: 1.0.10_browserslist@4.21.5 dev: true @@ -420,8 +420,8 @@ packages: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true - /decky-frontend-lib/3.18.11: - resolution: {integrity: sha512-SLb3qWJc6CLNRqcbNyJsA8D6sXf7aix8/h6VqQTWjVmel6c3SkOR6b9KMvgFRzXumfRt7XGasBnZJmyCwH4BCQ==} + /decky-frontend-lib/3.19.1: + resolution: {integrity: sha512-hU4+EFs74MGzUCv8l1AO2+EBj9RRbnpU19Crm4u+3lbLu6d63U2GsUeQ9ssmNRcOMY1OuVZkRoZBE58soOBJ3A==} dev: false /deepmerge/4.3.0: @@ -429,8 +429,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /electron-to-chromium/1.4.305: - resolution: {integrity: sha512-WETy6tG0CT5gm1O+xCbyapWNsCcmIvrn4NHViIGYo2AT8FV2qUCXdaB+WqYxSv/vS5mFqhBYnfZAAkVArjBmUg==} + /electron-to-chromium/1.4.309: + resolution: {integrity: sha512-U7DTiKe4h+irqBG6h4EZ0XXaZuJj4md3xIXXaGSYhwiumPZ4BSc6rgf9UD0hVUMaeP/jB0q5pKWCPxvhO8fvZA==} dev: true /enhanced-resolve/5.12.0: @@ -590,7 +590,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.14.0 + '@types/node': 18.14.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -821,12 +821,12 @@ packages: jest-worker: 27.5.1 schema-utils: 3.1.1 serialize-javascript: 6.0.1 - terser: 5.16.4 + terser: 5.16.5 webpack: 5.75.0 dev: true - /terser/5.16.4: - resolution: {integrity: sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug==} + /terser/5.16.5: + resolution: {integrity: sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==} engines: {node: '>=10'} hasBin: true dependencies: diff --git a/src/backend.ts b/src/backend.ts index f8674f9..0d7da44 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -29,7 +29,7 @@ export async function initBackend() { // init usdpl await init_embedded(); init_usdpl(USDPL_PORT); - console.log("USDPL started for framework: " + target_usdpl()); + console.log("POWERTOOLS: USDPL started for framework: " + target_usdpl()); const user_locale = navigator.languages && navigator.languages.length ? navigator.languages[0] diff --git a/src/components/debug.tsx b/src/components/debug.tsx index f76a7e4..dd6aa32 100644 --- a/src/components/debug.tsx +++ b/src/components/debug.tsx @@ -35,7 +35,7 @@ function buildDebug() { if (eggCount % 10 == 9) { // you know you're bored and/or conceited when you spend time adding an easter egg // that just sends people to your own project's repo - Router.NavigateToExternalWeb("https://github.com/NGnius/PowerTools"); + Router.NavigateToExternalWeb("https://github.com/NGnius/PowerTools/releases"); } eggCount++; }}>