From bfaa478a4a13cb44af5f4f013e6990e71a692b18 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Tue, 7 Sep 2021 20:20:37 +1200 Subject: [PATCH] Begin syncing changes with patch series --- Cargo.lock | 1 + daemon/src/ctrl_profiles/config.rs | 10 +- daemon/src/ctrl_profiles/controller.rs | 98 +++++++-------- daemon/src/ctrl_profiles/zbus.rs | 87 ++++++------- daemon/src/daemon.rs | 13 +- rog-dbus/src/zbus_profile.rs | 8 +- rog-profiles/Cargo.toml | 1 + rog-profiles/src/fan_curves.rs | 147 ++++++++++++++++++++++ rog-profiles/src/lib.rs | 166 ++++++++----------------- 9 files changed, 298 insertions(+), 233 deletions(-) create mode 100644 rog-profiles/src/fan_curves.rs diff --git a/Cargo.lock b/Cargo.lock index 987a33a6..9f381c75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -938,6 +938,7 @@ version = "1.0.0" dependencies = [ "serde", "serde_derive", + "udev", "zvariant", "zvariant_derive", ] diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index 71aa4a69..71fbfc08 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -1,4 +1,5 @@ use log::{error, warn}; +use rog_profiles::fan_curves::FanCurveSet; use rog_profiles::{FanCurves, Profile}; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; @@ -22,10 +23,11 @@ impl ProfileConfig { fan_curves: None, }; - if FanCurves::is_fan_curves_supported() { - let mut curves = FanCurves::default(); - curves.update_from_platform(); - platform.fan_curves = Some(curves); + if let Ok(res) = FanCurveSet::is_supported() { + if res { + let mut curves = FanCurves::default(); + platform.fan_curves = Some(curves); + } } platform diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 3b292e63..61a23637 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -2,37 +2,16 @@ use crate::error::RogError; use crate::GetSupported; use log::{info, warn}; use rog_profiles::error::ProfileError; -use rog_profiles::{FanCurves, Profile}; +use rog_profiles::fan_curves::FanCurveSet; +use rog_profiles::{Profile}; use rog_supported::PlatformProfileFunctions; -use std::sync::Arc; -use std::sync::Mutex; +use udev::Device; use super::config::ProfileConfig; -pub struct CtrlPlatformTask { - config: Arc>, -} - -impl CtrlPlatformTask { - pub fn new(config: Arc>) -> Self { - Self { config } - } -} - -impl crate::CtrlTask for CtrlPlatformTask { - fn do_task(&self) -> Result<(), RogError> { - if let Ok(mut lock) = self.config.try_lock() { - // Refresh the config in-case the user has edited it - if let Some(curves) = &mut lock.fan_curves { - curves.update_from_platform(); - } - } - Ok(()) - } -} - pub struct CtrlPlatformProfile { - pub config: Arc>, + pub config: ProfileConfig, + pub fan_device: Option, } impl GetSupported for CtrlPlatformProfile { @@ -48,7 +27,14 @@ https://lkml.org/lkml/2021/8/18/1022 "# ); } - if !FanCurves::is_fan_curves_supported() { + + let res = FanCurveSet::is_supported(); + let mut fan_curve_supported = res.is_err(); + if let Ok(r) = res { + fan_curve_supported = r; + }; + + if fan_curve_supported { info!( r#" fan curves kernel interface not found, your laptop does not support this, or the interface is missing. @@ -58,9 +44,10 @@ Please note that as of 24/08/2021 this is not final. "# ); } + PlatformProfileFunctions { platform_profile: Profile::is_platform_profile_supported(), - fan_curves: FanCurves::is_fan_curves_supported(), + fan_curves: fan_curve_supported, } } } @@ -68,53 +55,54 @@ Please note that as of 24/08/2021 this is not final. impl crate::Reloadable for CtrlPlatformProfile { /// Fetch the active profile and use that to set all related components up fn reload(&mut self) -> Result<(), RogError> { - if let Ok(cfg) = self.config.clone().try_lock() { - if let Some(curves) = &cfg.fan_curves { - curves.update_platform(); + if let Some(curves) = &self.config.fan_curves { + if let Ok(mut device) = FanCurveSet::get_device() { + curves.write_to_platform(self.config.active, &mut device); + } } - } Ok(()) } } impl CtrlPlatformProfile { - pub fn new(config: Arc>) -> Result { + pub fn new(config: ProfileConfig, fan_device: Option) -> Result { if Profile::is_platform_profile_supported() { info!("Device has profile control available"); - return Ok(CtrlPlatformProfile { config }); + return Ok(CtrlPlatformProfile { config, fan_device }); } Err(ProfileError::NotSupported.into()) } + pub fn get_device(&self) -> Option { + self.fan_device.clone() + } + pub fn save_config(&self) { - if let Ok(lock) = self.config.lock() { - lock.write(); - } + self.config.write(); } /// Toggle to next profile in list. This will first read the config, switch, then write out pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> { - if let Ok(mut config) = self.config.clone().try_lock() { - // Read first just incase the user has modified the config before calling this - config.read(); + // Read first just incase the user has modified the config before calling this + self.config.read(); - match config.active { - Profile::Balanced => { - Profile::set_profile(Profile::Performance)?; - config.active = Profile::Performance; - } - Profile::Performance => { - Profile::set_profile(Profile::Quiet)?; - config.active = Profile::Quiet; - } - Profile::Quiet => { - Profile::set_profile(Profile::Balanced)?; - config.active = Profile::Balanced; - } + match self.config.active { + Profile::Balanced => { + Profile::set_profile(Profile::Performance)?; + self.config.active = Profile::Performance; + } + Profile::Performance => { + Profile::set_profile(Profile::Quiet)?; + self.config.active = Profile::Quiet; + } + Profile::Quiet => { + Profile::set_profile(Profile::Balanced)?; + self.config.active = Profile::Balanced; } - - config.write(); } + + self.config.write(); + Ok(()) } } diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index 572dca34..275089e3 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -1,5 +1,5 @@ use log::warn; -use rog_profiles::FanCurve; +use rog_profiles::fan_curves::FanCurveSet; use rog_profiles::Profile; use std::sync::Arc; @@ -45,11 +45,9 @@ impl ProfileZbus { /// Fetch the active profile name fn active_profile(&mut self) -> zbus::fdo::Result { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - cfg.read(); - return Ok(cfg.active); - } + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + return Ok(ctrl.config.active); } Err(Error::Failed( "Failed to get active profile name".to_string(), @@ -58,15 +56,14 @@ impl ProfileZbus { /// Set this platform_profile name as active fn set_active_profile(&self, profile: Profile) { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - // Read first just incase the user has modified the config before calling this - cfg.read(); - Profile::set_profile(profile) - .map_err(|e| warn!("Profile::set_profile, {}", e)) - .ok(); - cfg.active = profile; - } + if let Ok(mut ctrl) = self.inner.try_lock() { + // Read first just incase the user has modified the config before calling this + ctrl.config.read(); + Profile::set_profile(profile) + .map_err(|e| warn!("Profile::set_profile, {}", e)) + .ok(); + ctrl.config.active = profile; + ctrl.save_config(); } self.do_notification(); @@ -74,14 +71,12 @@ impl ProfileZbus { /// Get a list of profiles that have fan-curves enabled. fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result> { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - cfg.read(); - if let Some(curves) = &cfg.fan_curves { - return Ok(curves.get_enabled_curve_names().to_vec()); - } - return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + if let Some(curves) = &ctrl.config.fan_curves { + return Ok(curves.get_enabled_curve_names().to_vec()); } + return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); } Err(Error::Failed( "Failed to get enabled fan curve names".to_string(), @@ -89,43 +84,41 @@ impl ProfileZbus { } /// Get the fan-curve data for the currently active Profile - fn active_fan_curve_data(&mut self) -> zbus::fdo::Result { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - cfg.read(); - if let Some(curves) = &cfg.fan_curves { - return Ok((*curves.get_active_fan_curves()).clone()); - } - return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); + fn active_fan_curve_data(&mut self) -> zbus::fdo::Result { + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + if let Some(curves) = &ctrl.config.fan_curves { + return Ok((*curves.get_active_fan_curves()).clone()); } + return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); } Err(Error::Failed("Failed to get fan curve data".to_string())) } /// Get fan-curve data for each Profile as an array of objects - fn fan_curves(&self) -> zbus::fdo::Result> { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - cfg.read(); - if let Some(curves) = &cfg.fan_curves { - return Ok(curves.get_all_fan_curves()); - } - return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); + fn fan_curves(&self) -> zbus::fdo::Result> { + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + if let Some(curves) = &ctrl.config.fan_curves { + return Ok(curves.get_all_fan_curves()); } + return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); } Err(Error::Failed("Failed to get all fan curves".to_string())) } /// Set this fan-curve data - fn set_fan_curve(&self, curve: FanCurve) -> zbus::fdo::Result<()> { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.try_lock() { - cfg.read(); - if let Some(curves) = &mut cfg.fan_curves { - curves.set_fan_curve(curve); + fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::fdo::Result<()> { + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + if let Some(mut device) = ctrl.get_device() { + if let Some(curves) = &mut ctrl.config.fan_curves { + curves.set_fan_curve(curve, &mut device); } + } else { return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); } + ctrl.save_config(); } @@ -139,10 +132,8 @@ impl ProfileZbus { impl ProfileZbus { fn do_notification(&self) { if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(cfg) = ctrl.config.clone().try_lock() { - self.notify_profile(&cfg.active) - .unwrap_or_else(|err| warn!("{}", err)); - } + self.notify_profile(&ctrl.config.active) + .unwrap_or_else(|err| warn!("{}", err)); } } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 61797021..bc4ce3d1 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -7,7 +7,6 @@ use daemon::ctrl_aura::controller::{ }; use daemon::ctrl_charge::CtrlCharge; use daemon::ctrl_profiles::config::ProfileConfig; -use daemon::ctrl_profiles::controller::CtrlPlatformTask; use daemon::{ config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, }; @@ -21,6 +20,7 @@ use daemon::{CtrlTask, Reloadable, ZbusAdd}; use log::LevelFilter; use log::{error, info, warn}; use rog_dbus::DBUS_NAME; +use rog_profiles::fan_curves::FanCurveSet; use std::env; use std::error::Error; use std::io::Write; @@ -108,16 +108,19 @@ fn start_daemon() -> Result<(), Box> { } } - let profile_config = Arc::new(Mutex::new(ProfileConfig::load(PROFILE_CONFIG_PATH.into()))); - match CtrlPlatformProfile::new(profile_config.clone()) { + let fan_device = if let Ok(res) = FanCurveSet::get_device() { + Some(res) + } else { + None + }; + let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into()); + match CtrlPlatformProfile::new(profile_config, fan_device) { Ok(mut ctrl) => { ctrl.reload() .unwrap_or_else(|err| warn!("Profile control: {}", err)); let tmp = Arc::new(Mutex::new(ctrl)); ProfileZbus::new(tmp).add_to_server(&mut object_server); - - tasks.push(Box::new(CtrlPlatformTask::new(profile_config))); } Err(err) => { error!("Profile control: {}", err); diff --git a/rog-dbus/src/zbus_profile.rs b/rog-dbus/src/zbus_profile.rs index 7e5247ac..229881a0 100644 --- a/rog-dbus/src/zbus_profile.rs +++ b/rog-dbus/src/zbus_profile.rs @@ -21,7 +21,7 @@ use std::sync::mpsc::Sender; -use rog_profiles::{FanCurve, Profile}; +use rog_profiles::{Profile, fan_curves::FanCurveSet}; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -45,13 +45,13 @@ trait Daemon { fn enabled_fan_profiles(&self) -> zbus::Result>; /// Get the active `Profile` data - fn active_fan_data(&self) -> zbus::Result; + fn active_fan_data(&self) -> zbus::Result; /// Get all fan curve data - fn fan_curves(&self) -> zbus::Result>; + fn fan_curves(&self) -> zbus::Result>; /// Set a fan curve. If a field is empty then the exisiting saved curve is used - fn set_fan_curve(&self, curve: FanCurve) -> zbus::Result<()>; + fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::Result<()>; /// NotifyProfile signal #[dbus_proxy(signal)] diff --git a/rog-profiles/Cargo.toml b/rog-profiles/Cargo.toml index dec19f61..e58e1c73 100644 --- a/rog-profiles/Cargo.toml +++ b/rog-profiles/Cargo.toml @@ -9,6 +9,7 @@ default = ["dbus"] dbus = ["zvariant", "zvariant_derive"] [dependencies] +udev = "^0.6" serde = "^1.0" serde_derive = "^1.0" diff --git a/rog-profiles/src/fan_curves.rs b/rog-profiles/src/fan_curves.rs new file mode 100644 index 00000000..1813032c --- /dev/null +++ b/rog-profiles/src/fan_curves.rs @@ -0,0 +1,147 @@ +use serde_derive::{Deserialize, Serialize}; + +use udev::Device; +#[cfg(feature = "dbus")] +use zvariant_derive::Type; + +use crate::error::ProfileError; + +pub fn pwm_str(fan: char, index: char) -> String { + let mut buf = "pwm1_auto_point1_pwm".to_string(); + unsafe { + let tmp = buf.as_bytes_mut(); + tmp[3] = fan as u8; + tmp[15] = index as u8; + } + buf +} + +pub fn temp_str(fan: char, index: char) -> String { + let mut buf = "pwm1_auto_point1_temp".to_string(); + unsafe { + let tmp = buf.as_bytes_mut(); + tmp[3] = fan as u8; + tmp[15] = index as u8; + } + buf +} + +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Deserialize, Serialize, Default, Debug, Clone)] +pub struct CurveData { + pub pwm: [u8; 8], + pub temp: [u8; 8], +} + +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Deserialize, Serialize, Default, Debug, Clone)] +pub struct FanCurveSet { + pub cpu: CurveData, + pub gpu: CurveData, +} + +impl FanCurveSet { + pub fn get_device() -> Result { + let mut enumerator = udev::Enumerator::new()?; + enumerator.match_subsystem("hwmon")?; + + for device in enumerator.scan_devices().unwrap() { + if device.parent_with_subsystem("platform").unwrap().is_some() { + if let Some(name) = device.attribute_value("name") { + if name == "asus_custom_fan_curve" { + return Ok(device); + } + } + } + } + Err(ProfileError::NotSupported) + } + + pub fn new() -> Result<(Self, Device), ProfileError> { + if let Ok(device) = Self::get_device() { + let mut fans = Self { + cpu: CurveData::default(), + gpu: CurveData::default(), + }; + fans.init_from_device(&device); + return Ok((fans, device)); + } + + Err(ProfileError::NotSupported) + } + + pub fn is_supported() -> Result { + if Self::get_device().is_ok() { + return Ok(true); + } + + Ok(false) + } + + pub fn update_from_device(&mut self, device: &Device) { + self.init_from_device(device); + } + + fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) { + if let Some(n) = tmp.chars().nth(15) { + let i = n.to_digit(10).unwrap() as usize; + let d = device.attribute_value(tmp).unwrap(); + let d: u8 = d.to_string_lossy().parse().unwrap(); + buf[i - 1] = d; + } + } + + pub fn init_from_device(&mut self, device: &Device) { + for attr in device.attributes() { + let tmp = attr.name().to_string_lossy(); + if tmp.starts_with("pwm1") && tmp.ends_with("_temp") { + Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.temp) + } + if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") { + Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.pwm) + } + if tmp.starts_with("pwm2") && tmp.ends_with("_temp") { + Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.temp) + } + if tmp.starts_with("pwm2") && tmp.ends_with("_pwm") { + Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.pwm) + } + } + } + + fn write_to_fan(curve: &CurveData, pwm_num: char, device: &mut Device) { + let mut pwm = "pwmN_auto_pointN_pwm".to_string(); + + for (index,out) in curve.pwm.iter().enumerate() { + unsafe { + let buf = pwm.as_bytes_mut(); + buf[3] = pwm_num as u8; + // Should be quite safe to unwrap as we're not going over 8 + buf[15] = char::from_digit(index as u32, 10).unwrap() as u8; + } + let out = out.to_string(); + device.set_attribute_value(&pwm, &out).unwrap(); + } + + let mut pwm = "pwmN_auto_pointN_temp".to_string(); + + for (index,out) in curve.temp.iter().enumerate() { + unsafe { + let buf = pwm.as_bytes_mut(); + buf[3] = pwm_num as u8; + // Should be quite safe to unwrap as we're not going over 8 + buf[15] = char::from_digit(index as u32, 10).unwrap() as u8; + } + let out = out.to_string(); + device.set_attribute_value(&pwm, &out).unwrap(); + } + } + + pub fn write_cpu_fan(&self, device: &mut Device) { + Self::write_to_fan(&self.cpu, '1', device); + } + + pub fn write_gpu_fan(&self, device: &mut Device) { + Self::write_to_fan(&self.gpu, '2', device); + } +} diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 23f18a83..0cf88fb9 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -1,26 +1,42 @@ pub mod error; +pub mod fan_curves; use std::{ fs::OpenOptions, io::{Read, Write}, - path::{Path, PathBuf}, + path::{Path}, }; use error::ProfileError; +use fan_curves::{CurveData, FanCurveSet}; use serde_derive::{Deserialize, Serialize}; +use udev::Device; #[cfg(feature = "dbus")] use zvariant_derive::Type; pub static PLATFORM_PROFILE: &str = "/sys/firmware/acpi/platform_profile"; pub static PLATFORM_PROFILES: &str = "/sys/firmware/acpi/platform_profile_choices"; -pub static FAN_CURVE_BASE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/"; -pub static FAN_CURVE_ACTIVE_FILE: &str = "enabled_fan_curve_profiles"; -pub static FAN_CURVE_FILENAME_PART: &str = "_fan_curve_"; - pub static VERSION: &str = env!("CARGO_PKG_VERSION"); +pub fn find_fan_curve_node() -> Result, ProfileError> { + let mut enumerator = udev::Enumerator::new()?; + enumerator.match_subsystem("hwmon")?; + + for device in enumerator.scan_devices()? { + if device.parent_with_subsystem("platform")?.is_some() { + if let Some(name) = device.attribute_value("name") { + if name == "asus_custom_fan_curve" { + return Ok(Some(device)); + } + } + } + } + + Err(ProfileError::NotSupported) +} + #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Deserialize, Serialize, Debug, Clone, Copy)] pub enum Profile { @@ -116,82 +132,44 @@ impl Default for FanCurvePU { } } -#[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Deserialize, Serialize, Default, Debug, Clone)] -pub struct FanCurve { - pub profile: Profile, - pub cpu: String, - pub gpu: String, -} - /// Main purpose of `FanCurves` is to enable retoring state on system boot #[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Default)] pub struct FanCurves { enabled: Vec, - balanced: FanCurve, - performance: FanCurve, - quiet: FanCurve, + balanced: FanCurveSet, + performance: FanCurveSet, + quiet: FanCurveSet, } -impl Default for FanCurves { - fn default() -> Self { - let mut curves = Self { - enabled: Default::default(), - balanced: Default::default(), - performance: Default::default(), - quiet: Default::default(), - }; - curves.balanced.profile = Profile::Balanced; - curves.performance.profile = Profile::Performance; - curves.quiet.profile = Profile::Quiet; - curves - } -} impl FanCurves { - pub fn is_fan_curves_supported() -> bool { - let mut path = PathBuf::new(); - path.push(FAN_CURVE_BASE_PATH); - path.push(FAN_CURVE_ACTIVE_FILE); - path.exists() + /// + pub fn init_from_platform(&mut self, profile: Profile, device: &Device) { + let mut tmp = FanCurveSet::default(); + tmp.init_from_device(device); + match profile { + Profile::Balanced => self.balanced = tmp, + Profile::Performance => self.performance = tmp, + Profile::Quiet => self.quiet = tmp, + } } - pub fn update_from_platform(&mut self) { - self.balanced.cpu = Self::get_fan_curve_from_file(Profile::Balanced, FanCurvePU::CPU); - self.balanced.gpu = Self::get_fan_curve_from_file(Profile::Balanced, FanCurvePU::GPU); - - self.performance.cpu = Self::get_fan_curve_from_file(Profile::Performance, FanCurvePU::CPU); - self.performance.gpu = Self::get_fan_curve_from_file(Profile::Performance, FanCurvePU::GPU); - - self.quiet.cpu = Self::get_fan_curve_from_file(Profile::Quiet, FanCurvePU::CPU); - self.quiet.gpu = Self::get_fan_curve_from_file(Profile::Quiet, FanCurvePU::GPU); - } - - pub fn update_platform(&self) { - Self::set_fan_curve_for_platform(Profile::Balanced, FanCurvePU::CPU, &self.balanced.cpu); - Self::set_fan_curve_for_platform(Profile::Balanced, FanCurvePU::GPU, &self.balanced.gpu); - - Self::set_fan_curve_for_platform( - Profile::Performance, - FanCurvePU::CPU, - &self.performance.cpu, - ); - Self::set_fan_curve_for_platform( - Profile::Performance, - FanCurvePU::GPU, - &self.performance.gpu, - ); - - Self::set_fan_curve_for_platform(Profile::Quiet, FanCurvePU::CPU, &self.quiet.cpu); - Self::set_fan_curve_for_platform(Profile::Quiet, FanCurvePU::GPU, &self.quiet.gpu); + pub fn write_to_platform(&self, profile: Profile, device: &mut Device) { + let fans = match profile { + Profile::Balanced => &self.balanced, + Profile::Performance => &self.performance, + Profile::Quiet => &self.quiet, + }; + fans.write_cpu_fan(device); + fans.write_gpu_fan(device); } pub fn get_enabled_curve_names(&self) -> &[Profile] { &self.enabled } - pub fn get_all_fan_curves(&self) -> Vec { + pub fn get_all_fan_curves(&self) -> Vec { vec![ self.balanced.clone(), self.performance.clone(), @@ -199,7 +177,7 @@ impl FanCurves { ] } - pub fn get_active_fan_curves(&self) -> &FanCurve { + pub fn get_active_fan_curves(&self) -> &FanCurveSet { match Profile::get_active_profile().unwrap() { Profile::Balanced => &self.balanced, Profile::Performance => &self.performance, @@ -207,7 +185,7 @@ impl FanCurves { } } - pub fn get_fan_curves_for(&self, name: Profile) -> &FanCurve { + pub fn get_fan_curves_for(&self, name: Profile) -> &FanCurveSet { match name { Profile::Balanced => &self.balanced, Profile::Performance => &self.performance, @@ -215,23 +193,7 @@ impl FanCurves { } } - fn get_fan_curve_from_file(name: Profile, pu: FanCurvePU) -> String { - let mut file: String = FAN_CURVE_BASE_PATH.into(); - file.push_str(pu.into()); - file.push_str(FAN_CURVE_FILENAME_PART); - file.push_str(name.into()); - - let mut file = OpenOptions::new() - .read(true) - .open(&file) - .unwrap_or_else(|_| panic!("{} not found", &file)); - - let mut buf = String::new(); - file.read_to_string(&mut buf).unwrap(); - buf.trim().to_string() - } - - pub fn get_fan_curve_for(&self, name: &Profile, pu: &FanCurvePU) -> &str { + pub fn get_fan_curve_for(&self, name: &Profile, pu: &FanCurvePU) -> &CurveData { match name { Profile::Balanced => match pu { FanCurvePU::CPU => &self.balanced.cpu, @@ -248,38 +210,8 @@ impl FanCurves { } } - fn set_fan_curve_for_platform(name: Profile, pu: FanCurvePU, curve: &str) { - let mut file: String = FAN_CURVE_BASE_PATH.into(); - file.push_str(pu.into()); - file.push_str(FAN_CURVE_FILENAME_PART); - file.push_str(name.into()); - - let mut file = OpenOptions::new() - .write(true) - .open(&file) - .unwrap_or_else(|_| panic!("{} not found", &file)); - - file.write_all(curve.as_bytes()).unwrap(); - } - - pub fn set_fan_curve(&mut self, curve: FanCurve) { - // First, set the profiles. - Self::set_fan_curve_for_platform(curve.profile, FanCurvePU::CPU, &curve.cpu); - match curve.profile { - Profile::Balanced => self.balanced.cpu = curve.cpu, - Profile::Performance => self.performance.cpu = curve.cpu, - Profile::Quiet => self.quiet.cpu = curve.cpu, - }; - - Self::set_fan_curve_for_platform(curve.profile, FanCurvePU::GPU, &curve.gpu); - match curve.profile { - Profile::Balanced => self.balanced.gpu = curve.gpu, - Profile::Performance => self.performance.gpu = curve.gpu, - Profile::Quiet => self.quiet.cpu = curve.gpu, - }; - - // Any curve that was blank will have been reset, so repopulate the settings - // Note: successfully set curves will just be re-read in. - self.update_from_platform(); + pub fn set_fan_curve(&self, curve: FanCurveSet, device: &mut Device) { + curve.write_cpu_fan(device); + curve.write_gpu_fan(device); } }