diff --git a/CHANGELOG.md b/CHANGELOG.md index cdb85c98..7ea0c49a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ## [v6.1.0-rc2] +### Changed +- Bug fixes +- Partial support for per-profile CPU tunings (WIP) + +## [v6.1.0-rc2] + ### Added - asus-armoury driver support. WIP, will be adjusted/changed further - More "Slash" display controls diff --git a/Cargo.toml b/Cargo.toml index b079a4c4..2c64311d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "6.1.0-rc2" +version = "6.1.0-rc3" rust-version = "1.82" license = "MPL-2.0" readme = "README.md" diff --git a/asusd/src/asus_armoury.rs b/asusd/src/asus_armoury.rs index f2b0daed..87850dc4 100644 --- a/asusd/src/asus_armoury.rs +++ b/asusd/src/asus_armoury.rs @@ -1,11 +1,18 @@ +use std::str::FromStr; +use std::sync::Arc; + +use ::zbus::export::futures_util::lock::Mutex; +use config_traits::StdConfig; use log::error; use rog_platform::firmware_attributes::{ AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes }; +use rog_platform::platform::{RogPlatform, ThrottlePolicy}; use serde::{Deserialize, Serialize}; use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value}; use zbus::{fdo, interface, Connection}; +use crate::config::Config; use crate::error::RogError; use crate::ASUS_ZBUS_PATH; @@ -21,18 +28,27 @@ fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath { ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into() } -pub struct AsusArmouryAttribute(Attribute); +pub struct AsusArmouryAttribute { + attr: Attribute, + config: Arc>, + /// platform control required here for access to PPD or Throttle profile + platform: RogPlatform +} impl AsusArmouryAttribute { - pub fn new(attr: Attribute) -> Self { - Self(attr) + pub fn new(attr: Attribute, platform: RogPlatform, config: Arc>) -> Self { + Self { + attr, + config, + platform + } } pub async fn start_tasks(self, connection: &Connection) -> Result<(), RogError> { // self.reload() // .await // .unwrap_or_else(|err| warn!("Controller error: {}", err)); - let path = dbus_path_for_attr(self.0.name()); + let path = dbus_path_for_attr(self.attr.name()); connection .object_server() .at(path.clone(), self) @@ -48,30 +64,30 @@ impl AsusArmouryAttribute { #[interface(name = "xyz.ljones.AsusArmoury")] impl AsusArmouryAttribute { #[zbus(property)] - async fn name(&self) -> FirmwareAttribute { - self.0.name().into() + fn name(&self) -> FirmwareAttribute { + self.attr.name().into() } #[zbus(property)] async fn available_attrs(&self) -> Vec { let mut attrs = Vec::new(); - if !matches!(self.0.default_value(), AttrValue::None) { + if !matches!(self.attr.default_value(), AttrValue::None) { attrs.push("default_value".to_string()); } - if !matches!(self.0.min_value(), AttrValue::None) { + if !matches!(self.attr.min_value(), AttrValue::None) { attrs.push("min_value".to_string()); } - if !matches!(self.0.max_value(), AttrValue::None) { + if !matches!(self.attr.max_value(), AttrValue::None) { attrs.push("max_value".to_string()); } - if !matches!(self.0.scalar_increment(), AttrValue::None) { + if !matches!(self.attr.scalar_increment(), AttrValue::None) { attrs.push("scalar_increment".to_string()); } - if !matches!(self.0.possible_values(), AttrValue::None) { + if !matches!(self.attr.possible_values(), AttrValue::None) { attrs.push("possible_values".to_string()); } // TODO: Don't unwrap, use error - if let Ok(value) = self.0.current_value().map_err(|e| { + if let Ok(value) = self.attr.current_value().map_err(|e| { error!("Failed to read: {e:?}"); e }) { @@ -85,7 +101,7 @@ impl AsusArmouryAttribute { /// If return is `-1` then there is no default value #[zbus(property)] async fn default_value(&self) -> i32 { - match self.0.default_value() { + match self.attr.default_value() { AttrValue::Integer(i) => *i, _ => -1 } @@ -93,7 +109,7 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn min_value(&self) -> i32 { - match self.0.min_value() { + match self.attr.min_value() { AttrValue::Integer(i) => *i, _ => -1 } @@ -101,7 +117,7 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn max_value(&self) -> i32 { - match self.0.max_value() { + match self.attr.max_value() { AttrValue::Integer(i) => *i, _ => -1 } @@ -109,7 +125,7 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn scalar_increment(&self) -> i32 { - match self.0.scalar_increment() { + match self.attr.scalar_increment() { AttrValue::Integer(i) => *i, _ => -1 } @@ -117,7 +133,7 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn possible_values(&self) -> Vec { - match self.0.possible_values() { + match self.attr.possible_values() { AttrValue::EnumInt(i) => i.clone(), _ => Vec::default() } @@ -125,7 +141,7 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn current_value(&self) -> fdo::Result { - if let Ok(AttrValue::Integer(i)) = self.0.current_value() { + if let Ok(AttrValue::Integer(i)) = self.attr.current_value() { return Ok(i); } Err(fdo::Error::Failed( @@ -135,19 +151,31 @@ impl AsusArmouryAttribute { #[zbus(property)] async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> { - Ok(self - .0 + self.attr .set_current_value(AttrValue::Integer(value)) .map_err(|e| { error!("Could not set value: {e:?}"); e - })?) + })?; + let profile: ThrottlePolicy = + ThrottlePolicy::from_str(self.platform.get_platform_profile()?.as_str())?; + if let Some(tunings) = self.config.lock().await.tunings.get_mut(&profile) { + if let Some(tune) = tunings.get_mut(&self.name()) { + *tune = value; + } + } + self.config.lock().await.write(); + Ok(()) } } -pub async fn start_attributes_zbus(server: &Connection) -> Result<(), RogError> { +pub async fn start_attributes_zbus( + server: &Connection, + platform: RogPlatform, + config: Arc> +) -> Result<(), RogError> { for attr in FirmwareAttributes::new().attributes() { - AsusArmouryAttribute::new(attr.clone()) + AsusArmouryAttribute::new(attr.clone(), platform.clone(), config.clone()) .start_tasks(server) .await?; } diff --git a/asusd/src/config.rs b/asusd/src/config.rs index c4489e5c..8814d9f0 100644 --- a/asusd/src/config.rs +++ b/asusd/src/config.rs @@ -1,11 +1,14 @@ +use std::collections::HashMap; + use config_traits::{StdConfig, StdConfigLoad1}; use rog_platform::cpu::CPUEPP; +use rog_platform::firmware_attributes::FirmwareAttribute; use rog_platform::platform::ThrottlePolicy; use serde::{Deserialize, Serialize}; const CONFIG_FILE: &str = "asusd.ron"; -#[derive(Deserialize, Serialize, Debug, PartialEq, PartialOrd)] +#[derive(Deserialize, Serialize)] pub struct Config { // The current charge limit applied pub charge_control_end_threshold: u8, @@ -37,27 +40,7 @@ pub struct Config { pub throttle_balanced_epp: CPUEPP, /// The energy_performance_preference for this throttle/platform profile pub throttle_performance_epp: CPUEPP, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub ppt_pl1_spl: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub ppt_pl2_sppt: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub ppt_fppt: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub ppt_apu_sppt: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub ppt_platform_sppt: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub nv_dynamic_boost: Option, - /// Defaults to `None` if not supported - #[serde(skip_serializing_if = "Option::is_none", default)] - pub nv_temp_target: Option, + pub tunings: HashMap>, /// Temporary state for AC/Batt #[serde(skip)] pub last_power_plugged: u8 @@ -82,13 +65,7 @@ impl Default for Config { throttle_quiet_epp: CPUEPP::Power, throttle_balanced_epp: CPUEPP::BalancePower, throttle_performance_epp: CPUEPP::Performance, - ppt_pl1_spl: Default::default(), - ppt_pl2_sppt: Default::default(), - ppt_fppt: Default::default(), - ppt_apu_sppt: Default::default(), - ppt_platform_sppt: Default::default(), - nv_dynamic_boost: Default::default(), - nv_temp_target: Default::default(), + tunings: HashMap::default(), last_power_plugged: Default::default() } } @@ -116,58 +93,69 @@ impl StdConfig for Config { } } -impl StdConfigLoad1 for Config {} +impl StdConfigLoad1 for Config {} #[derive(Deserialize, Serialize)] -pub struct Config507 { - // The current charge limit applied +pub struct Config601 { pub charge_control_end_threshold: u8, + #[serde(skip)] + pub base_charge_control_end_threshold: u8, pub panel_od: bool, + pub boot_sound: bool, pub mini_led_mode: bool, pub disable_nvidia_powerd_on_battery: bool, pub ac_command: String, pub bat_command: String, - pub platform_policy_linked_epp: bool, - pub platform_policy_on_battery: ThrottlePolicy, - pub platform_policy_on_ac: ThrottlePolicy, - // + pub throttle_policy_linked_epp: bool, + pub throttle_policy_on_battery: ThrottlePolicy, + pub change_throttle_policy_on_battery: bool, + pub throttle_policy_on_ac: ThrottlePolicy, + pub change_throttle_policy_on_ac: bool, + pub throttle_quiet_epp: CPUEPP, + pub throttle_balanced_epp: CPUEPP, + pub throttle_performance_epp: CPUEPP, + #[serde(skip_serializing_if = "Option::is_none", default)] pub ppt_pl1_spl: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] pub ppt_pl2_sppt: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] + pub ppt_pl3_fppt: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] pub ppt_fppt: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] pub ppt_apu_sppt: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] pub ppt_platform_sppt: Option, + #[serde(skip_serializing_if = "Option::is_none", default)] pub nv_dynamic_boost: Option, - pub nv_temp_target: Option + #[serde(skip_serializing_if = "Option::is_none", default)] + pub nv_temp_target: Option, + #[serde(skip)] + pub last_power_plugged: u8 } -impl From for Config { - fn from(c: Config507) -> Self { +impl From for Config { + fn from(c: Config601) -> Self { Self { // Restore the base charge limit charge_control_end_threshold: c.charge_control_end_threshold, base_charge_control_end_threshold: c.charge_control_end_threshold, panel_od: c.panel_od, - boot_sound: false, + boot_sound: c.boot_sound, disable_nvidia_powerd_on_battery: c.disable_nvidia_powerd_on_battery, ac_command: c.ac_command, bat_command: c.bat_command, mini_led_mode: c.mini_led_mode, - throttle_policy_linked_epp: true, - throttle_policy_on_battery: c.platform_policy_on_battery, - change_throttle_policy_on_battery: true, - throttle_policy_on_ac: c.platform_policy_on_ac, - change_throttle_policy_on_ac: true, - throttle_quiet_epp: CPUEPP::Power, - throttle_balanced_epp: CPUEPP::BalancePower, - throttle_performance_epp: CPUEPP::Performance, - ppt_pl1_spl: c.ppt_pl1_spl, - ppt_pl2_sppt: c.ppt_pl2_sppt, - ppt_fppt: c.ppt_fppt, - ppt_apu_sppt: c.ppt_apu_sppt, - ppt_platform_sppt: c.ppt_platform_sppt, - nv_dynamic_boost: c.nv_dynamic_boost, - nv_temp_target: c.nv_temp_target, - last_power_plugged: 0 + throttle_policy_linked_epp: c.throttle_policy_linked_epp, + throttle_policy_on_battery: c.throttle_policy_on_battery, + change_throttle_policy_on_battery: c.change_throttle_policy_on_battery, + throttle_policy_on_ac: c.throttle_policy_on_ac, + change_throttle_policy_on_ac: c.change_throttle_policy_on_ac, + throttle_quiet_epp: c.throttle_quiet_epp, + throttle_balanced_epp: c.throttle_balanced_epp, + throttle_performance_epp: c.throttle_performance_epp, + last_power_plugged: c.last_power_plugged, + tunings: HashMap::default() } } } diff --git a/asusd/src/ctrl_platform.rs b/asusd/src/ctrl_platform.rs index 8050c829..6aaac7e7 100644 --- a/asusd/src/ctrl_platform.rs +++ b/asusd/src/ctrl_platform.rs @@ -619,29 +619,28 @@ impl ReloadAndNotify for CtrlPlatform { data: Self::Data ) -> Result<(), RogError> { let mut config = self.config.lock().await; - if *config != data { - info!("asusd.ron updated externally, reloading and updating internal copy"); + info!("asusd.ron updated externally, reloading and updating internal copy"); - let mut base_charge_control_end_threshold = None; + let mut base_charge_control_end_threshold = None; - if self.power.has_charge_control_end_threshold() { - let limit = data.charge_control_end_threshold; - warn!("setting charge_control_end_threshold to {limit}"); - self.power.set_charge_control_end_threshold(limit)?; - self.charge_control_end_threshold_changed(signal_context) - .await?; - base_charge_control_end_threshold = (config.base_charge_control_end_threshold > 0) - .then_some(config.base_charge_control_end_threshold) - .or(Some(limit)); - } + if self.power.has_charge_control_end_threshold() { + let limit = data.charge_control_end_threshold; + warn!("setting charge_control_end_threshold to {limit}"); + self.power.set_charge_control_end_threshold(limit)?; + self.charge_control_end_threshold_changed(signal_context) + .await?; + base_charge_control_end_threshold = (config.base_charge_control_end_threshold > 0) + .then_some(config.base_charge_control_end_threshold) + .or(Some(limit)); + } - if self.platform.has_throttle_thermal_policy() - && config.throttle_policy_linked_epp != data.throttle_policy_linked_epp - { - // TODO: extra stuff - } + if self.platform.has_throttle_thermal_policy() + && config.throttle_policy_linked_epp != data.throttle_policy_linked_epp + { + // TODO: extra stuff + } - macro_rules! reload_and_notify { + macro_rules! reload_and_notify { ($property:tt, $prop_name:literal) => { concat_idents::concat_idents!(has = has_, $property { if self.platform.has() && config.$property != data.$property { @@ -654,15 +653,14 @@ impl ReloadAndNotify for CtrlPlatform { }) } } - reload_and_notify!(mini_led_mode, "mini_led_mode"); - reload_and_notify!(panel_od, "panel_od"); - reload_and_notify!(boot_sound, "boot_sound"); - // reload_and_notify!(throttle_thermal_policy, "throttle_thermal_policy"); + reload_and_notify!(mini_led_mode, "mini_led_mode"); + reload_and_notify!(panel_od, "panel_od"); + reload_and_notify!(boot_sound, "boot_sound"); + // reload_and_notify!(throttle_thermal_policy, "throttle_thermal_policy"); - *config = data; - config.base_charge_control_end_threshold = - base_charge_control_end_threshold.unwrap_or_default(); - } + *config = data; + config.base_charge_control_end_threshold = + base_charge_control_end_threshold.unwrap_or_default(); Ok(()) } diff --git a/asusd/src/daemon.rs b/asusd/src/daemon.rs index 55600e54..742e6e88 100644 --- a/asusd/src/daemon.rs +++ b/asusd/src/daemon.rs @@ -12,6 +12,7 @@ use asusd::ctrl_platform::CtrlPlatform; use asusd::{print_board_info, start_tasks, CtrlTask, DBUS_NAME}; use config_traits::{StdConfig, StdConfigLoad1}; use log::{error, info}; +use rog_platform::platform::RogPlatform; use zbus::fdo::ObjectManager; #[tokio::main] @@ -65,7 +66,8 @@ async fn start_daemon() -> Result<(), Box> { let config = Arc::new(Mutex::new(config)); // supported.add_to_server(&mut connection).await; - start_attributes_zbus(&server).await?; + let platform = RogPlatform::new()?; // TODO: maybe needs async mutex? + start_attributes_zbus(&server, platform, config.clone()).await?; match CtrlFanCurveZbus::new() { Ok(ctrl) => { diff --git a/config-traits/src/lib.rs b/config-traits/src/lib.rs index f9b61113..4557be57 100644 --- a/config-traits/src/lib.rs +++ b/config-traits/src/lib.rs @@ -203,7 +203,7 @@ macro_rules! std_config_load { /// new one created pub trait $trait_name<$($generic),*> where - Self: $crate::StdConfig +std::fmt::Debug + DeserializeOwned + Serialize, + Self: $crate::StdConfig + DeserializeOwned + Serialize, $($generic: DeserializeOwned + Into),* { fn load(mut self) -> Self { diff --git a/rog-platform/src/firmware_attributes.rs b/rog-platform/src/firmware_attributes.rs index b58e3a9f..27d619cf 100644 --- a/rog-platform/src/firmware_attributes.rs +++ b/rog-platform/src/firmware_attributes.rs @@ -230,7 +230,20 @@ define_attribute_getters!( /// CamelCase names of the properties. Intended for use with DBUS #[repr(u8)] -#[derive(Clone, Copy, Serialize, Deserialize, Type, Value, OwnedValue, PartialEq, PartialOrd)] +#[derive( + Clone, + Copy, + Serialize, + Deserialize, + Type, + Value, + OwnedValue, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, +)] #[zvariant(signature = "s")] pub enum FirmwareAttribute { ApuMem = 0, diff --git a/rog-platform/src/platform.rs b/rog-platform/src/platform.rs index 5081c85d..7a63dcb7 100644 --- a/rog-platform/src/platform.rs +++ b/rog-platform/src/platform.rs @@ -204,7 +204,6 @@ impl Display for GpuMode { PartialEq, Eq, PartialOrd, - Ord, Hash, Clone, Copy,