From d93b8707265bd3daeebcf619227757f6a5deac1f Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Fri, 6 Jan 2023 16:52:04 +1300 Subject: [PATCH] Split fan-curve config to own file --- CHANGELOG.md | 1 + daemon/src/config.rs | 2 +- daemon/src/config_traits.rs | 77 +++++++++++++------------ daemon/src/ctrl_anime/config.rs | 14 ++--- daemon/src/ctrl_aura/config.rs | 14 ++--- daemon/src/ctrl_profiles/config.rs | 5 +- daemon/src/ctrl_profiles/controller.rs | 31 +++++++--- daemon/src/ctrl_profiles/trait_impls.rs | 10 ++-- daemon/src/error.rs | 8 +++ 9 files changed, 88 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af9794a..8eca4a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Better handling of non-existant config files - Move all config handling to generic traits for better consistency - Re-parse all configs to RON format +- Move fan-curve config to own config file - Added option to set `disable_nvidia_powerd_on_battery` - Add short log entry to throttle_thermal_policy change detection - ROGCC: Don't notify user if changing to same mux mode diff --git a/daemon/src/config.rs b/daemon/src/config.rs index 05851c2f..70c02bd3 100644 --- a/daemon/src/config.rs +++ b/daemon/src/config.rs @@ -2,7 +2,7 @@ use serde_derive::{Deserialize, Serialize}; use crate::config_traits::{StdConfig, StdConfigLoad3}; -pub static CONFIG_FILE: &str = "asusd.conf"; +const CONFIG_FILE: &str = "asusd.conf"; #[derive(Deserialize, Serialize, Default)] pub struct Config { diff --git a/daemon/src/config_traits.rs b/daemon/src/config_traits.rs index eba44422..fad109d7 100644 --- a/daemon/src/config_traits.rs +++ b/daemon/src/config_traits.rs @@ -7,30 +7,10 @@ use ron::ser::PrettyConfig; use serde::de::DeserializeOwned; use serde::Serialize; -static CONFIG_PATH_BASE: &str = "/etc/asusd/"; - -/// Create a `PathBuf` for `file`. If the base config dir `CONFIG_PATH_BASE` -/// does not exist it is created. -fn config_file(file: &str) -> PathBuf { - let mut config = PathBuf::from(CONFIG_PATH_BASE); - if !config.exists() { - create_dir(config.as_path()).unwrap_or_else(|_| panic!("Could not create {config:?}")); - } - config.push(file); - config -} - -/// Open a config file as read/write. If the file or dir does not exist then -/// both are created. -fn config_file_open(file: PathBuf) -> File { - OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(file.clone()) - .unwrap_or_else(|_| panic!("The file {file:?} or directory {CONFIG_PATH_BASE} is missing")) -} +const CONFIG_PATH_BASE: &str = "/etc/asusd/"; +/// Config file helper traits. Only `new()` and `file_name()` are required to be +/// implemented, the rest are intended to be free methods. pub trait StdConfig where Self: Serialize + DeserializeOwned, @@ -40,18 +20,32 @@ where fn file_name() -> &'static str; fn file_path() -> PathBuf { - config_file(Self::file_name()) + let mut config = PathBuf::from(CONFIG_PATH_BASE); + if !config.exists() { + create_dir(config.as_path()) + .unwrap_or_else(|e| panic!("Could not create {CONFIG_PATH_BASE} {e}")); + } + config.push(Self::file_name()); + config } fn file_open() -> File { - config_file_open(Self::file_path()) + OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(Self::file_path()) + .unwrap_or_else(|e| panic!("Could not open {:?} {e}", Self::file_path())) } fn read(&mut self) { - let mut file = OpenOptions::new() - .read(true) - .open(Self::file_path()) - .unwrap_or_else(|err| panic!("Error reading {:?}: {}", Self::file_path(), err)); + let mut file = match OpenOptions::new().read(true).open(Self::file_path()) { + Ok(data) => data, + Err(err) => { + error!("Error reading {:?}: {}", Self::file_path(), err); + return; + } + }; let mut buf = String::new(); if let Ok(l) = file.read_to_string(&mut buf) { if l == 0 { @@ -67,12 +61,23 @@ where } fn write(&self) { - let mut file = File::create(Self::file_path()).expect(&format!( - "Couldn't overwrite config {:?}", - Self::file_path() - )); - let ron = ron::ser::to_string_pretty(&self, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); + let mut file = match File::create(Self::file_path()) { + Ok(data) => data, + Err(e) => { + error!( + "Couldn't overwrite config {:?}, error: {e}", + Self::file_path() + ); + return; + } + }; + let ron = match ron::ser::to_string_pretty(&self, PrettyConfig::new().depth_limit(4)) { + Ok(data) => data, + Err(e) => { + error!("Parse {:?} to RON failed, error: {e}", Self::file_path()); + return; + } + }; file.write_all(ron.as_bytes()) .unwrap_or_else(|err| error!("Could not write config: {}", err)); } @@ -86,7 +91,7 @@ where ); let cfg_old = Self::file_path().to_string_lossy().to_string() + "-old"; std::fs::rename(Self::file_path(), cfg_old).unwrap_or_else(|err| { - panic!( + error!( "Could not rename. Please remove {} then restart service: Error {}", Self::file_name(), err diff --git a/daemon/src/ctrl_anime/config.rs b/daemon/src/ctrl_anime/config.rs index f4c1ae8f..3d03fdd3 100644 --- a/daemon/src/ctrl_anime/config.rs +++ b/daemon/src/ctrl_anime/config.rs @@ -1,5 +1,3 @@ -use std::fs::File; -use std::io::Write; use std::time::Duration; use rog_anime::error::AnimeError; @@ -8,8 +6,7 @@ use serde_derive::{Deserialize, Serialize}; use crate::config_traits::{StdConfig, StdConfigLoad3}; -pub static CONFIG_FILE: &str = "anime.conf"; -pub static ANIME_CACHE_PATH: &str = "/etc/asusd/anime-cache.conf"; +const CONFIG_FILE: &str = "anime.conf"; #[derive(Deserialize, Serialize)] pub struct AnimeConfigV341 { @@ -141,7 +138,7 @@ impl Default for AnimeConfig { impl StdConfig for AnimeConfig { fn new() -> Self { - Self::create_default(&mut Self::file_open()) + Self::create_default() } fn file_name() -> &'static str { @@ -162,7 +159,7 @@ impl AnimeConfig { // } // } - fn create_default(file: &mut File) -> Self { + fn create_default() -> Self { // create a default config here let config = AnimeConfig { system: vec![], @@ -202,10 +199,7 @@ impl AnimeConfig { awake_enabled: true, boot_anim_enabled: true, }; - // Should be okay to unwrap this as is since it is a Default - let json = serde_json::to_string_pretty(&config).unwrap(); - file.write_all(json.as_bytes()) - .unwrap_or_else(|_| panic!("Could not write {}", CONFIG_FILE)); + config.write(); config } } diff --git a/daemon/src/ctrl_aura/config.rs b/daemon/src/ctrl_aura/config.rs index 36932171..453317ea 100644 --- a/daemon/src/ctrl_aura/config.rs +++ b/daemon/src/ctrl_aura/config.rs @@ -1,6 +1,4 @@ use std::collections::{BTreeMap, HashSet}; -use std::fs::File; -use std::io::Write; use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; @@ -11,7 +9,7 @@ use serde_derive::{Deserialize, Serialize}; use crate::config_traits::{StdConfig, StdConfigLoad1}; -static CONFIG_FILE: &str = "aura.conf"; +const CONFIG_FILE: &str = "aura.conf"; /// Enable/disable LED control in various states such as /// when the device is awake, suspended, shutting down or @@ -190,7 +188,7 @@ impl Default for AuraConfig { impl StdConfig for AuraConfig { fn new() -> Self { - Self::create_default(&mut Self::file_open(), &LaptopLedData::get_data()) + Self::create_default(&LaptopLedData::get_data()) } fn file_name() -> &'static str { @@ -201,7 +199,7 @@ impl StdConfig for AuraConfig { impl StdConfigLoad1 for AuraConfig {} impl AuraConfig { - fn create_default(file: &mut File, support_data: &LaptopLedData) -> Self { + fn create_default(support_data: &LaptopLedData) -> Self { // create a default config here let mut config = AuraConfig::default(); @@ -231,11 +229,7 @@ impl AuraConfig { } } } - - // Should be okay to unwrap this as is since it is a Default - let json = serde_json::to_string(&config).unwrap(); - file.write_all(json.as_bytes()) - .unwrap_or_else(|_| panic!("Could not write {}", CONFIG_FILE)); + config.write(); config } diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index 3a59afb2..0bb1e25c 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -10,15 +10,12 @@ const CONFIG_FAN_FILE: &str = "fan_curves.conf"; pub struct ProfileConfig { /// For restore on boot pub active_profile: Profile, - /// States to restore - pub fan_curves: Option, } impl StdConfig for ProfileConfig { fn new() -> Self { Self { active_profile: Profile::Balanced, - fan_curves: None, } } @@ -39,4 +36,4 @@ impl StdConfig for FanCurveProfiles { } } -impl StdConfigLoad1 for FanCurveProfiles {} \ No newline at end of file +impl StdConfigLoad1 for FanCurveProfiles {} diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 51471370..3a8f0af9 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -11,6 +11,7 @@ use crate::GetSupported; pub struct CtrlPlatformProfile { pub profile_config: ProfileConfig, + pub fan_config: Option, pub platform: AsusPlatform, } @@ -51,21 +52,26 @@ impl CtrlPlatformProfile { if platform.has_platform_profile() || platform.has_throttle_thermal_policy() { info!("Device has profile control available"); - let mut controller = CtrlPlatformProfile { profile_config: config, platform }; + let mut controller = CtrlPlatformProfile { + profile_config: config, + fan_config: None, + platform, + }; if FanCurveProfiles::get_device().is_ok() { info!("Device has fan curves available"); - if controller.profile_config.fan_curves.is_none() { - controller.profile_config.fan_curves = Some(Default::default()); + if controller.fan_config.is_none() { + controller.fan_config = Some(Default::default()); for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] { controller.set_next_profile()?; controller.set_active_curve_to_defaults()?; let active = Profile::get_active_profile().unwrap_or(Profile::Balanced); - if let Some(curves) = controller.profile_config.fan_curves.as_ref() { + if let Some(curves) = controller.fan_config.as_ref() { info!( "{active:?}: {}", String::from(curves.get_fan_curves_for(active)) ); + curves.write(); } } } @@ -79,6 +85,9 @@ impl CtrlPlatformProfile { pub fn save_config(&self) { self.profile_config.write(); + if let Some(fans) = self.fan_config.as_ref() { + fans.write(); + } } /// Toggle to next profile in list. This will first read the config, switch, @@ -105,18 +114,24 @@ impl CtrlPlatformProfile { /// Set the curve for the active profile active pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> { - if let Some(curves) = &mut self.profile_config.fan_curves { + if let Some(curves) = &mut self.fan_config { if let Ok(mut device) = FanCurveProfiles::get_device() { - curves.write_profile_curve_to_platform(self.profile_config.active_profile, &mut device)?; + curves.write_profile_curve_to_platform( + self.profile_config.active_profile, + &mut device, + )?; } } Ok(()) } pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> { - if let Some(curves) = self.profile_config.fan_curves.as_mut() { + if let Some(curves) = self.fan_config.as_mut() { if let Ok(mut device) = FanCurveProfiles::get_device() { - curves.set_active_curve_to_defaults(self.profile_config.active_profile, &mut device)?; + curves.set_active_curve_to_defaults( + self.profile_config.active_profile, + &mut device, + )?; } } Ok(()) diff --git a/daemon/src/ctrl_profiles/trait_impls.rs b/daemon/src/ctrl_profiles/trait_impls.rs index 7c9658de..18685458 100644 --- a/daemon/src/ctrl_profiles/trait_impls.rs +++ b/daemon/src/ctrl_profiles/trait_impls.rs @@ -81,7 +81,7 @@ impl ProfileZbus { async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result> { let mut ctrl = self.0.lock().await; ctrl.profile_config.read(); - if let Some(curves) = &ctrl.profile_config.fan_curves { + if let Some(curves) = &ctrl.fan_config { return Ok(curves.get_enabled_curve_profiles()); } Err(Error::Failed(UNSUPPORTED_MSG.to_owned())) @@ -96,7 +96,7 @@ impl ProfileZbus { ) -> zbus::fdo::Result<()> { let mut ctrl = self.0.lock().await; ctrl.profile_config.read(); - if let Some(curves) = &mut ctrl.profile_config.fan_curves { + if let Some(curves) = &mut ctrl.fan_config { curves.set_profile_curve_enabled(profile, enabled); ctrl.write_profile_curve_to_platform() @@ -114,7 +114,7 @@ impl ProfileZbus { async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result { let mut ctrl = self.0.lock().await; ctrl.profile_config.read(); - if let Some(curves) = &ctrl.profile_config.fan_curves { + if let Some(curves) = &ctrl.fan_config { let curve = curves.get_fan_curves_for(profile); return Ok(curve.clone()); } @@ -126,7 +126,7 @@ impl ProfileZbus { async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> { let mut ctrl = self.0.lock().await; ctrl.profile_config.read(); - if let Some(curves) = &mut ctrl.profile_config.fan_curves { + if let Some(curves) = &mut ctrl.fan_config { curves .save_fan_curve(curve, profile) .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; @@ -240,7 +240,7 @@ impl crate::Reloadable for ProfileZbus { async fn reload(&mut self) -> Result<(), RogError> { let mut ctrl = self.0.lock().await; let active = ctrl.profile_config.active_profile; - if let Some(curves) = &mut ctrl.profile_config.fan_curves { + if let Some(curves) = &mut ctrl.fan_config { if let Ok(mut device) = FanCurveProfiles::get_device() { // There is a possibility that the curve was default zeroed, so this call // initialises the data from system read and we need to save it diff --git a/daemon/src/error.rs b/daemon/src/error.rs index a70450e3..068a792d 100644 --- a/daemon/src/error.rs +++ b/daemon/src/error.rs @@ -34,6 +34,7 @@ pub enum RogError { SystemdUnitAction(String), SystemdUnitWaitTimeout(String), Command(String, std::io::Error), + ParseRon(ron::Error), } impl fmt::Display for RogError { @@ -82,6 +83,7 @@ impl fmt::Display for RogError { ) } RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error), + RogError::ParseRon(error) => write!(f, "Parse config error: {}", error), } } } @@ -118,6 +120,12 @@ impl From for RogError { } } +impl From for RogError { + fn from(err: ron::Error) -> Self { + RogError::ParseRon(err) + } +} + impl From for zbus::fdo::Error { #[inline] fn from(err: RogError) -> Self {