From bfaa478a4a13cb44af5f4f013e6990e71a692b18 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Tue, 7 Sep 2021 20:20:37 +1200 Subject: [PATCH 1/3] 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); } } From 0a565a7a5c18a27c836a02d487c44b0191ffda9b Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Wed, 8 Sep 2021 23:33:42 +1200 Subject: [PATCH 2/3] Fleshing out functions and zbus controls --- daemon/src/ctrl_profiles/config.rs | 6 +-- daemon/src/ctrl_profiles/controller.rs | 10 ++--- daemon/src/ctrl_profiles/zbus.rs | 28 ++++++++++--- rog-profiles/src/fan_curves.rs | 42 +++++-------------- rog-profiles/src/lib.rs | 57 ++++++++++++++++++++++++-- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index 71fbfc08..552e7a71 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -10,7 +10,7 @@ pub struct ProfileConfig { #[serde(skip)] config_path: String, /// For restore on boot - pub active: Profile, + pub active_profile: Profile, /// States to restore pub fan_curves: Option, } @@ -19,13 +19,13 @@ impl ProfileConfig { fn new(config_path: String) -> Self { let mut platform = ProfileConfig { config_path, - active: Profile::Balanced, + active_profile: Profile::Balanced, fan_curves: None, }; if let Ok(res) = FanCurveSet::is_supported() { if res { - let mut curves = FanCurves::default(); + let curves = FanCurves::default(); platform.fan_curves = Some(curves); } } diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 61a23637..98434323 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -57,7 +57,7 @@ impl crate::Reloadable for CtrlPlatformProfile { fn reload(&mut self) -> Result<(), RogError> { 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); + curves.write_to_platform(self.config.active_profile, &mut device); } } Ok(()) @@ -86,18 +86,18 @@ impl CtrlPlatformProfile { // Read first just incase the user has modified the config before calling this self.config.read(); - match self.config.active { + match self.config.active_profile { Profile::Balanced => { Profile::set_profile(Profile::Performance)?; - self.config.active = Profile::Performance; + self.config.active_profile = Profile::Performance; } Profile::Performance => { Profile::set_profile(Profile::Quiet)?; - self.config.active = Profile::Quiet; + self.config.active_profile = Profile::Quiet; } Profile::Quiet => { Profile::set_profile(Profile::Balanced)?; - self.config.active = Profile::Balanced; + self.config.active_profile = Profile::Balanced; } } diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index 275089e3..478a7192 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -1,4 +1,5 @@ use log::warn; +use rog_profiles::fan_curves::CurveData; use rog_profiles::fan_curves::FanCurveSet; use rog_profiles::Profile; @@ -47,7 +48,7 @@ impl ProfileZbus { fn active_profile(&mut self) -> zbus::fdo::Result { if let Ok(mut ctrl) = self.inner.try_lock() { ctrl.config.read(); - return Ok(ctrl.config.active); + return Ok(ctrl.config.active_profile); } Err(Error::Failed( "Failed to get active profile name".to_string(), @@ -62,7 +63,7 @@ impl ProfileZbus { Profile::set_profile(profile) .map_err(|e| warn!("Profile::set_profile, {}", e)) .ok(); - ctrl.config.active = profile; + ctrl.config.active_profile = profile; ctrl.save_config(); } @@ -74,7 +75,21 @@ impl ProfileZbus { 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 Ok(curves.get_enabled_curve_profiles().to_vec()); + } + return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); + } + Err(Error::Failed( + "Failed to get enabled fan curve names".to_string(), + )) + } + + /// Get a list of profiles that have fan-curves enabled. + fn set_enabled_fan_profiles(&mut self, profiles: Vec) -> zbus::fdo::Result<()> { + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.config.read(); + if let Some(curves) = &mut ctrl.config.fan_curves { + curves.set_enabled_curve_profiles(profiles); } return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); } @@ -108,12 +123,13 @@ impl ProfileZbus { } /// Set this fan-curve data - fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::fdo::Result<()> { + fn set_fan_curve(&self, curve: CurveData) -> zbus::fdo::Result<()> { if let Ok(mut ctrl) = self.inner.try_lock() { ctrl.config.read(); + let profile = ctrl.config.active_profile; if let Some(mut device) = ctrl.get_device() { if let Some(curves) = &mut ctrl.config.fan_curves { - curves.set_fan_curve(curve, &mut device); + curves.write_and_set_fan_curve(curve, profile, &mut device); } } else { return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); @@ -132,7 +148,7 @@ impl ProfileZbus { impl ProfileZbus { fn do_notification(&self) { if let Ok(ctrl) = self.inner.try_lock() { - self.notify_profile(&ctrl.config.active) + self.notify_profile(&ctrl.config.active_profile) .unwrap_or_else(|err| warn!("{}", err)); } } diff --git a/rog-profiles/src/fan_curves.rs b/rog-profiles/src/fan_curves.rs index 1813032c..dd8d0854 100644 --- a/rog-profiles/src/fan_curves.rs +++ b/rog-profiles/src/fan_curves.rs @@ -4,7 +4,7 @@ use udev::Device; #[cfg(feature = "dbus")] use zvariant_derive::Type; -use crate::error::ProfileError; +use crate::{FanCurvePU, error::ProfileError, write_to_fan}; pub fn pwm_str(fan: char, index: char) -> String { let mut buf = "pwm1_auto_point1_pwm".to_string(); @@ -29,6 +29,7 @@ pub fn temp_str(fan: char, index: char) -> String { #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Deserialize, Serialize, Default, Debug, Clone)] pub struct CurveData { + pub fan: FanCurvePU, pub pwm: [u8; 8], pub temp: [u8; 8], } @@ -63,7 +64,12 @@ impl FanCurveSet { cpu: CurveData::default(), gpu: CurveData::default(), }; + + fans.cpu.fan = FanCurvePU::CPU; + fans.cpu.fan = FanCurvePU::GPU; + fans.init_from_device(&device); + return Ok((fans, device)); } @@ -109,39 +115,11 @@ impl FanCurveSet { } } - 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); + write_to_fan(&self.cpu, '1', device); } pub fn write_gpu_fan(&self, device: &mut Device) { - Self::write_to_fan(&self.gpu, '2', device); + write_to_fan(&self.gpu, '2', device); } -} +} \ No newline at end of file diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 0cf88fb9..3bee4ae7 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -165,10 +165,14 @@ impl FanCurves { fans.write_gpu_fan(device); } - pub fn get_enabled_curve_names(&self) -> &[Profile] { + pub fn get_enabled_curve_profiles(&self) -> &[Profile] { &self.enabled } + pub fn set_enabled_curve_profiles(&mut self, profiles: Vec) { + self.enabled = profiles + } + pub fn get_all_fan_curves(&self) -> Vec { vec![ self.balanced.clone(), @@ -210,8 +214,53 @@ impl FanCurves { } } - pub fn set_fan_curve(&self, curve: FanCurveSet, device: &mut Device) { - curve.write_cpu_fan(device); - curve.write_gpu_fan(device); + pub fn write_and_set_fan_curve(&mut self, curve: CurveData, profile: Profile, device: &mut Device) { + match curve.fan { + FanCurvePU::CPU => write_to_fan(&curve, '1', device), + FanCurvePU::GPU => write_to_fan(&curve, '2', device), + } + match profile { + Profile::Balanced => match curve.fan { + FanCurvePU::CPU => self.balanced.cpu = curve, + FanCurvePU::GPU => self.balanced.gpu = curve, + }, + Profile::Performance => match curve.fan { + FanCurvePU::CPU => self.performance.cpu = curve, + FanCurvePU::GPU => self.performance.gpu = curve, + }, + Profile::Quiet => match curve.fan { + FanCurvePU::CPU => self.quiet.cpu = curve, + FanCurvePU::GPU => self.quiet.gpu = curve, + }, + } } } + + +pub 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(); + } +} \ No newline at end of file From b939a9d33105bc591ad410764faf2f3bfacd20c7 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 9 Sep 2021 23:45:18 +1200 Subject: [PATCH 3/3] Fetch and store fan curve correctly --- CHANGELOG.md | 2 + asusctl/src/main.rs | 12 +++-- asusctl/src/profiles_cli.rs | 6 --- daemon/Cargo.toml | 2 +- daemon/src/ctrl_profiles/config.rs | 18 +++---- daemon/src/ctrl_profiles/controller.rs | 26 +++++++--- daemon/src/ctrl_profiles/zbus.rs | 4 +- daemon/src/daemon.rs | 2 +- data/asusd-ledmodes.toml | 7 +++ rog-dbus/src/zbus_profile.rs | 24 +++++----- .../src/{fan_curves.rs => fan_curve_set.rs} | 48 ++++++++++++------- rog-profiles/src/lib.rs | 36 ++++++++------ 12 files changed, 114 insertions(+), 73 deletions(-) rename rog-profiles/src/{fan_curves.rs => fan_curve_set.rs} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2319347..df3d0882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 + `BREAKING:` plain `Image` with time period is changed and old anime configs break as a result (sorry) - LED: + By popular request LED prev/next cycle is added + + Add led modes for GX551Q ### BREAKING CHANGES - Graphics control: + graphics control is pulled out of asusd and moved to new package; https://gitlab.com/asus-linux/supergfxctl @@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 + profiles now depend on power-profile-daemon plus kernel patches for support of platform_profile - if your system supports fan-curves you will also require upcoming kernel patches for this + profiles are now moved to a new file + + fan-curves are only partially completed due to this release needing to be done sooner # [3.7.2] - 2021-08-02 ### Added diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index c8dc6b68..820fe039 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -375,7 +375,9 @@ fn handle_profile( supported: &PlatformProfileFunctions, cmd: &ProfileCommand, ) -> Result<(), Box> { - if !cmd.next && !cmd.list && !cmd.active_name && !cmd.active_data && !cmd.profiles_data { + println!("Warning: Profiles should work fine but now depend on power-profiles-daemon v0.9+"); + println!("Warning: Fan-curve support is coming in a 4.1.x release"); + if !cmd.next && !cmd.list { if !cmd.help { println!("Missing arg or command\n"); } @@ -394,14 +396,18 @@ fn handle_profile( println!("\n{}", lst); } - println!("Note: turbo, frequency, fan preset and fan curve options will apply to"); - println!(" to the currently active profile unless a profile name is specified"); + // println!("Note: turbo, frequency, fan preset and fan curve options will apply to"); + // println!(" to the currently active profile unless a profile name is specified"); std::process::exit(1); } if cmd.next { dbus.proxies().profile().next_profile()?; } + if cmd.list { + let res = dbus.proxies().profile().profiles()?; + res.iter().for_each(|p| println!("{:?}", p)); + } Ok(()) } diff --git a/asusctl/src/profiles_cli.rs b/asusctl/src/profiles_cli.rs index 921ba7a2..09550a42 100644 --- a/asusctl/src/profiles_cli.rs +++ b/asusctl/src/profiles_cli.rs @@ -8,10 +8,4 @@ pub struct ProfileCommand { pub next: bool, #[options(help = "list available profiles")] pub list: bool, - #[options(help = "get active profile name")] - pub active_name: bool, - #[options(help = "get active profile data")] - pub active_data: bool, - #[options(help = "get all profile data")] - pub profiles_data: bool, } diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index cb54d5d8..8f3a1e35 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -39,7 +39,7 @@ logind-zbus = "^0.7.1" serde = "^1.0" serde_derive = "^1.0" serde_json = "^1.0" -toml = "^0.5" +toml = "^0.5.8" # Device control sysfs-class = "^0.1.2" # used for backlight control and baord ID diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index 552e7a71..176d9158 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -1,6 +1,6 @@ use log::{error, warn}; -use rog_profiles::fan_curves::FanCurveSet; -use rog_profiles::{FanCurves, Profile}; +use rog_profiles::fan_curve_set::FanCurveSet; +use rog_profiles::{FanCurveProfiles, Profile}; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; @@ -12,20 +12,20 @@ pub struct ProfileConfig { /// For restore on boot pub active_profile: Profile, /// States to restore - pub fan_curves: Option, + pub fan_curves: Option, } impl ProfileConfig { fn new(config_path: String) -> Self { let mut platform = ProfileConfig { config_path, - active_profile: Profile::Balanced, + active_profile: Profile::get_active_profile().unwrap_or(Profile::Balanced), fan_curves: None, }; if let Ok(res) = FanCurveSet::is_supported() { if res { - let curves = FanCurves::default(); + let curves = FanCurveProfiles::default(); platform.fan_curves = Some(curves); } } @@ -45,7 +45,7 @@ impl ProfileConfig { if let Ok(read_len) = file.read_to_string(&mut buf) { if read_len == 0 { config = Self::new(config_path); - } else if let Ok(data) = serde_json::from_str(&buf) { + } else if let Ok(data) = toml::from_str(&buf) { config = data; config.config_path = config_path; } else { @@ -70,7 +70,7 @@ impl ProfileConfig { if l == 0 { warn!("File is empty {}", self.config_path); } else { - let mut data: ProfileConfig = serde_json::from_str(&buf) + let mut data: ProfileConfig = toml::from_str(&buf) .unwrap_or_else(|_| panic!("Could not deserialise {}", self.config_path)); // copy over serde skipped values data.config_path = self.config_path.clone(); @@ -81,8 +81,8 @@ impl ProfileConfig { pub fn write(&self) { let mut file = File::create(&self.config_path).expect("Couldn't overwrite config"); - let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed"); - file.write_all(json.as_bytes()) + let data = toml::to_string(self).expect("Parse config to toml failed"); + file.write_all(data.as_bytes()) .unwrap_or_else(|err| error!("Could not write config: {}", err)); } } diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 98434323..4f55d52a 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -2,8 +2,8 @@ use crate::error::RogError; use crate::GetSupported; use log::{info, warn}; use rog_profiles::error::ProfileError; -use rog_profiles::fan_curves::FanCurveSet; -use rog_profiles::{Profile}; +use rog_profiles::fan_curve_set::FanCurveSet; +use rog_profiles::Profile; use rog_supported::PlatformProfileFunctions; use udev::Device; @@ -55,21 +55,33 @@ 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 Some(curves) = &self.config.fan_curves { - if let Ok(mut device) = FanCurveSet::get_device() { - curves.write_to_platform(self.config.active_profile, &mut device); - } + if let Some(curves) = &self.config.fan_curves { + if let Ok(mut device) = FanCurveSet::get_device() { + curves.write_to_platform(self.config.active_profile, &mut device); } + } Ok(()) } } impl CtrlPlatformProfile { - pub fn new(config: ProfileConfig, fan_device: Option) -> Result { + pub fn new(mut config: ProfileConfig, fan_device: Option) -> Result { if Profile::is_platform_profile_supported() { info!("Device has profile control available"); + + if let Some(ref device) = fan_device { + let profile = config.active_profile; + config + .fan_curves + .as_mut() + .unwrap() + .read_from_dev_profile(profile, device); + } + config.write(); + return Ok(CtrlPlatformProfile { config, fan_device }); } + Err(ProfileError::NotSupported.into()) } diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index 478a7192..c0f1e61c 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -1,6 +1,6 @@ use log::warn; -use rog_profiles::fan_curves::CurveData; -use rog_profiles::fan_curves::FanCurveSet; +use rog_profiles::fan_curve_set::CurveData; +use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::Profile; use std::sync::Arc; diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index bc4ce3d1..46df535b 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -20,7 +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 rog_profiles::fan_curve_set::FanCurveSet; use std::env; use std::error::Error; use std::io::Write; diff --git a/data/asusd-ledmodes.toml b/data/asusd-ledmodes.toml index b5f4ae39..660ae22d 100644 --- a/data/asusd-ledmodes.toml +++ b/data/asusd-ledmodes.toml @@ -109,3 +109,10 @@ board_names = ["GX550L"] standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] multizone = false per_key = true + +[[led_data]] +prod_family = "ROG Zephyrus Duo 15 SE" +board_name = ["GX551Q"] +standard ["Static", "Breathe", "Pulse", "Rainbow", "Strobe"] +multizone = false +per_key = true \ No newline at end of file diff --git a/rog-dbus/src/zbus_profile.rs b/rog-dbus/src/zbus_profile.rs index 229881a0..954d63ea 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::{Profile, fan_curves::FanCurveSet}; +use rog_profiles::{fan_curve_set::FanCurveSet, Profile}; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -29,27 +29,27 @@ use zbus::{dbus_proxy, Connection, Result}; default_path = "/org/asuslinux/Profile" )] trait Daemon { - /// Profiles method - fn profiles(&self) -> zbus::Result>; - - /// NextProfile method - fn next_profile(&self) -> zbus::Result<()>; + /// Get the active `Profile` data + fn active_fan_curve_data(&self) -> zbus::Result; /// Profile, get the active profile fn active_profile(&self) -> zbus::Result; - /// Set the specific profile as active - fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>; - /// Get enabled fan curves fn enabled_fan_profiles(&self) -> zbus::Result>; - /// Get the active `Profile` data - fn active_fan_data(&self) -> zbus::Result; - /// Get all fan curve data fn fan_curves(&self) -> zbus::Result>; + /// NextProfile method + fn next_profile(&self) -> zbus::Result<()>; + + /// Profiles method + fn profiles(&self) -> zbus::Result>; + + /// Set the specific profile as active + fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>; + /// Set a fan curve. If a field is empty then the exisiting saved curve is used fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::Result<()>; diff --git a/rog-profiles/src/fan_curves.rs b/rog-profiles/src/fan_curve_set.rs similarity index 84% rename from rog-profiles/src/fan_curves.rs rename to rog-profiles/src/fan_curve_set.rs index dd8d0854..1ebd93e8 100644 --- a/rog-profiles/src/fan_curves.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -4,7 +4,7 @@ use udev::Device; #[cfg(feature = "dbus")] use zvariant_derive::Type; -use crate::{FanCurvePU, error::ProfileError, write_to_fan}; +use crate::{error::ProfileError, write_to_fan, FanCurvePU}; pub fn pwm_str(fan: char, index: char) -> String { let mut buf = "pwm1_auto_point1_pwm".to_string(); @@ -34,13 +34,31 @@ pub struct CurveData { pub temp: [u8; 8], } +/// A `FanCurveSet` contains both CPU and GPU fan curve data #[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Deserialize, Serialize, Default, Debug, Clone)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct FanCurveSet { pub cpu: CurveData, pub gpu: CurveData, } +impl Default for FanCurveSet { + fn default() -> Self { + Self { + cpu: CurveData { + fan: FanCurvePU::CPU, + pwm: [0u8; 8], + temp: [0u8; 8], + }, + gpu: CurveData { + fan: FanCurvePU::GPU, + pwm: [0u8; 8], + temp: [0u8; 8], + }, + } + } +} + impl FanCurveSet { pub fn get_device() -> Result { let mut enumerator = udev::Enumerator::new()?; @@ -58,6 +76,14 @@ impl FanCurveSet { Err(ProfileError::NotSupported) } + pub fn is_supported() -> Result { + if Self::get_device().is_ok() { + return Ok(true); + } + + Ok(false) + } + pub fn new() -> Result<(Self, Device), ProfileError> { if let Ok(device) = Self::get_device() { let mut fans = Self { @@ -68,7 +94,7 @@ impl FanCurveSet { fans.cpu.fan = FanCurvePU::CPU; fans.cpu.fan = FanCurvePU::GPU; - fans.init_from_device(&device); + fans.read_from_device(&device); return Ok((fans, device)); } @@ -76,18 +102,6 @@ impl FanCurveSet { 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; @@ -97,7 +111,7 @@ impl FanCurveSet { } } - pub fn init_from_device(&mut self, device: &Device) { + pub fn read_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") { @@ -122,4 +136,4 @@ impl FanCurveSet { pub fn write_gpu_fan(&self, device: &mut Device) { write_to_fan(&self.gpu, '2', device); } -} \ No newline at end of file +} diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 3bee4ae7..35a4b96a 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -1,14 +1,14 @@ pub mod error; -pub mod fan_curves; +pub mod fan_curve_set; use std::{ fs::OpenOptions, io::{Read, Write}, - path::{Path}, + path::Path, }; use error::ProfileError; -use fan_curves::{CurveData, FanCurveSet}; +use fan_curve_set::{CurveData, FanCurveSet}; use serde_derive::{Deserialize, Serialize}; use udev::Device; @@ -135,19 +135,18 @@ impl Default for FanCurvePU { /// Main purpose of `FanCurves` is to enable retoring state on system boot #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Deserialize, Serialize, Debug, Default)] -pub struct FanCurves { +pub struct FanCurveProfiles { enabled: Vec, balanced: FanCurveSet, performance: FanCurveSet, quiet: FanCurveSet, } - -impl FanCurves { +impl FanCurveProfiles { /// - pub fn init_from_platform(&mut self, profile: Profile, device: &Device) { + pub fn read_from_dev_profile(&mut self, profile: Profile, device: &Device) { let mut tmp = FanCurveSet::default(); - tmp.init_from_device(device); + tmp.read_from_device(device); match profile { Profile::Balanced => self.balanced = tmp, Profile::Performance => self.performance = tmp, @@ -214,7 +213,12 @@ impl FanCurves { } } - pub fn write_and_set_fan_curve(&mut self, curve: CurveData, profile: Profile, device: &mut Device) { + pub fn write_and_set_fan_curve( + &mut self, + curve: CurveData, + profile: Profile, + device: &mut Device, + ) { match curve.fan { FanCurvePU::CPU => write_to_fan(&curve, '1', device), FanCurvePU::GPU => write_to_fan(&curve, '2', device), @@ -236,31 +240,33 @@ impl FanCurves { } } - pub 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() { + dbg!(&device); + 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; + buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8; } let out = out.to_string(); + dbg!(&pwm); + dbg!(&out); device.set_attribute_value(&pwm, &out).unwrap(); } let mut pwm = "pwmN_auto_pointN_temp".to_string(); - for (index,out) in curve.temp.iter().enumerate() { + 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; + buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8; } let out = out.to_string(); device.set_attribute_value(&pwm, &out).unwrap(); } -} \ No newline at end of file +}