From 4dd29952c86bd0b764b1170cf688034f949de0a2 Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Fri, 14 Feb 2025 19:38:02 +1300 Subject: [PATCH] Fix the handling of of the kernel change from "quiet" to "low-power" A coming kernel change will convert "quiet" to "low-power" due to how platform_profile can now have multiple registered handlers. (kernel 6.14 est) Fixes #609 --- asusctl/src/main.rs | 6 +- asusd/src/ctrl_fancurves.rs | 2 +- asusd/src/ctrl_platform.rs | 34 +++++- rog-control-center/src/main.rs | 4 +- rog-control-center/src/types/fan_types.rs | 2 + .../translations/en/rog-control-center.po | 7 +- rog-control-center/ui/types/fan_types.slint | 1 + rog-dbus/src/zbus_platform.rs | 4 + rog-platform/src/cpu.rs | 1 + rog-platform/src/lib.rs | 13 +++ rog-platform/src/macros.rs | 21 ++++ rog-platform/src/platform.rs | 108 +++++++++--------- rog-profiles/src/lib.rs | 14 +-- 13 files changed, 146 insertions(+), 71 deletions(-) diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 11f13bbe..c03f2b44 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -927,16 +927,16 @@ fn handle_throttle_profile( let proxy = PlatformProxyBlocking::new(conn)?; let current = proxy.platform_profile()?; + let choices = proxy.platform_profile_choices()?; if cmd.next { - proxy.set_platform_profile(current.next())?; + proxy.set_platform_profile(PlatformProfile::next(current, &choices))?; } else if let Some(profile) = cmd.profile_set { proxy.set_platform_profile(profile)?; } if cmd.list { - let res = PlatformProfile::list(); - for p in &res { + for p in &choices { println!("{:?}", p); } } diff --git a/asusd/src/ctrl_fancurves.rs b/asusd/src/ctrl_fancurves.rs index d4cbb1c5..d30afd5c 100644 --- a/asusd/src/ctrl_fancurves.rs +++ b/asusd/src/ctrl_fancurves.rs @@ -216,7 +216,7 @@ impl CtrlFanCurveZbus { .lock() .await .profiles - .set_active_curve_to_defaults((&active).into(), &mut find_fan_curve_node()?)?; + .set_active_curve_to_defaults(active.as_str().into(), &mut find_fan_curve_node()?)?; self.platform.set_platform_profile(active.as_str())?; self.config.lock().await.write(); diff --git a/asusd/src/ctrl_platform.rs b/asusd/src/ctrl_platform.rs index f6b89d24..a1af1f11 100644 --- a/asusd/src/ctrl_platform.rs +++ b/asusd/src/ctrl_platform.rs @@ -211,6 +211,7 @@ impl CtrlPlatform { PlatformProfile::Balanced => self.config.lock().await.profile_balanced_epp, PlatformProfile::Performance => self.config.lock().await.profile_performance_epp, PlatformProfile::Quiet => self.config.lock().await.profile_quiet_epp, + PlatformProfile::LowPower => self.config.lock().await.profile_quiet_epp, } } @@ -323,7 +324,9 @@ impl CtrlPlatform { ) -> Result<(), FdoErr> { let policy: PlatformProfile = platform_get_value!(self, platform_profile, "platform_profile").map(|n| n.into())?; - let policy = PlatformProfile::next(policy); + let choices = + platform_get_value!(self, platform_profile_choices, "platform_profile_choices")?; + let policy = PlatformProfile::next(policy, &choices); if self.platform.has_platform_profile() { let change_epp = self.config.lock().await.platform_profile_linked_epp; @@ -344,9 +347,24 @@ impl CtrlPlatform { } } + #[zbus(property)] + fn platform_profile_choices(&self) -> Result, FdoErr> { + platform_get_value!(self, platform_profile_choices, "platform_profile_choices") + } + #[zbus(property)] fn platform_profile(&self) -> Result { - platform_get_value!(self, platform_profile, "platform_profile").map(|n| n.into()) + let choices = self.platform.get_platform_profile_choices()?; + let policy: PlatformProfile = self.platform.get_platform_profile()?.as_str().into(); + let policy = if policy == PlatformProfile::LowPower + && choices.contains(&PlatformProfile::LowPower) + { + PlatformProfile::Quiet + } else { + policy + }; + + Ok(policy) } #[zbus(property)] @@ -362,7 +380,16 @@ impl CtrlPlatform { self.check_and_set_epp(epp, change_epp); self.config.lock().await.write(); - // TODO: Need to get supported profiles here and ensure we translate to one + + let choices = self.platform.get_platform_profile_choices()?; + let policy = if policy == PlatformProfile::Quiet + && choices.contains(&PlatformProfile::LowPower) + { + PlatformProfile::LowPower + } else { + policy + }; + self.platform .set_platform_profile(policy.into()) .map_err(|err| { @@ -623,6 +650,7 @@ impl ReloadAndNotify for CtrlPlatform { PlatformProfile::Balanced => data.profile_balanced_epp, PlatformProfile::Performance => data.profile_performance_epp, PlatformProfile::Quiet => data.profile_quiet_epp, + PlatformProfile::LowPower => data.profile_quiet_epp, }; warn!("setting epp to {epp:?}"); self.check_and_set_epp(epp, true); diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 1cdca14f..5ea5d7e6 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -35,7 +35,9 @@ async fn main() -> Result<()> { // If we're running under gamescope we have to set WAYLAND_DISPLAY for winit to // use if let Ok(gamescope) = env::var("GAMESCOPE_WAYLAND_DISPLAY") { - env::set_var("WAYLAND_DISPLAY", gamescope); + if !gamescope.is_empty() { + env::set_var("WAYLAND_DISPLAY", gamescope); + } } // Try to open a proxy and check for app state first diff --git a/rog-control-center/src/types/fan_types.rs b/rog-control-center/src/types/fan_types.rs index 5897f257..0ec9630e 100644 --- a/rog-control-center/src/types/fan_types.rs +++ b/rog-control-center/src/types/fan_types.rs @@ -9,6 +9,7 @@ impl From for PlatformProfile { Profile::Balanced => PlatformProfile::Balanced, Profile::Performance => PlatformProfile::Performance, Profile::Quiet => PlatformProfile::Quiet, + Profile::LowPower => PlatformProfile::LowPower, } } } @@ -19,6 +20,7 @@ impl From for Profile { PlatformProfile::Balanced => Profile::Balanced, PlatformProfile::Performance => Profile::Performance, PlatformProfile::Quiet => Profile::Quiet, + PlatformProfile::LowPower => Profile::LowPower, } } } diff --git a/rog-control-center/translations/en/rog-control-center.po b/rog-control-center/translations/en/rog-control-center.po index e5f28620..ed720d3f 100644 --- a/rog-control-center/translations/en/rog-control-center.po +++ b/rog-control-center/translations/en/rog-control-center.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2025-02-14 03:05+0000\n" +"POT-Creation-Date: 2025-02-14 06:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,6 +27,11 @@ msgctxt "SystemPageData" msgid "Quiet" msgstr "" +#: rog-control-center/ui/pages/system.slint:20 +msgctxt "SystemPageData" +msgid "LowPower" +msgstr "" + #: rog-control-center/ui/pages/system.slint:23 msgctxt "SystemPageData" msgid "Default" diff --git a/rog-control-center/ui/types/fan_types.slint b/rog-control-center/ui/types/fan_types.slint index fe2be1aa..a224e1af 100644 --- a/rog-control-center/ui/types/fan_types.slint +++ b/rog-control-center/ui/types/fan_types.slint @@ -4,6 +4,7 @@ export enum Profile { Balanced, Performance, Quiet, + LowPower, } export enum FanType { diff --git a/rog-dbus/src/zbus_platform.rs b/rog-dbus/src/zbus_platform.rs index da198ca2..f26d6229 100644 --- a/rog-dbus/src/zbus_platform.rs +++ b/rog-dbus/src/zbus_platform.rs @@ -99,6 +99,10 @@ pub trait Platform { #[zbus(property)] fn set_profile_quiet_epp(&self, epp: CPUEPP) -> zbus::Result<()>; + /// PlatformProfileChoices property + #[zbus(property)] + fn platform_profile_choices(&self) -> zbus::Result>; + /// ThrottlePolicy property #[zbus(property)] fn platform_profile(&self) -> zbus::Result; diff --git a/rog-platform/src/cpu.rs b/rog-platform/src/cpu.rs index b97149f1..46432458 100644 --- a/rog-platform/src/cpu.rs +++ b/rog-platform/src/cpu.rs @@ -207,6 +207,7 @@ impl From for CPUEPP { PlatformProfile::Balanced => CPUEPP::BalancePerformance, PlatformProfile::Performance => CPUEPP::Performance, PlatformProfile::Quiet => CPUEPP::Power, + PlatformProfile::LowPower => CPUEPP::Power, } } } diff --git a/rog-platform/src/lib.rs b/rog-platform/src/lib.rs index 3d81b488..deb4fd12 100644 --- a/rog-platform/src/lib.rs +++ b/rog-platform/src/lib.rs @@ -15,6 +15,7 @@ use std::path::Path; use error::{PlatformError, Result}; use log::warn; +use platform::PlatformProfile; use udev::Device; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -107,6 +108,18 @@ pub fn write_attr_string(device: &mut Device, attr: &str, value: &str) -> Result .map_err(|e| PlatformError::IoPath(attr.into(), e)) } +pub fn read_attr_string_array(device: &Device, attr_name: &str) -> Result> { + if let Some(value) = device.attribute_value(attr_name) { + let tmp: Vec = value + .to_string_lossy() + .split(' ') + .map(PlatformProfile::from) + .collect(); + return Ok(tmp); + } + Err(PlatformError::AttrNotFound(attr_name.to_owned())) +} + #[cfg(test)] mod tests { #[test] diff --git a/rog-platform/src/macros.rs b/rog-platform/src/macros.rs index 5198e865..1cbb65c3 100644 --- a/rog-platform/src/macros.rs +++ b/rog-platform/src/macros.rs @@ -154,6 +154,18 @@ macro_rules! get_attr_string { }; } +#[macro_export] +macro_rules! get_attr_string_array { + ($(#[$attr:meta])* $attr_name:literal $item:ident) => { + concat_idents::concat_idents!(fn_name = get_, $attr_name { + $(#[$attr])* + pub fn fn_name(&self) -> Result> { + $crate::read_attr_string_array(&to_device(&self.$item)?, $attr_name) + } + }); + }; +} + #[macro_export] macro_rules! set_attr_string { ($(#[$attr:meta])* $attr_name:literal $item:ident) => { @@ -175,3 +187,12 @@ macro_rules! attr_string { $crate::watch_attr!($attr_name $item); }; } + +#[macro_export] +macro_rules! attr_string_array { + ($(#[$attr:meta])* $attr_name:literal, $item:ident) => { + $crate::has_attr!($attr_name $item); + $crate::get_attr_string_array!($attr_name $item); + $crate::watch_attr!($attr_name $item); + }; +} diff --git a/rog-platform/src/platform.rs b/rog-platform/src/platform.rs index 7b51fcac..616191a7 100644 --- a/rog-platform/src/platform.rs +++ b/rog-platform/src/platform.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use zbus::zvariant::{OwnedValue, Type, Value}; use crate::error::{PlatformError, Result}; -use crate::{attr_string, to_device}; +use crate::{attr_string, attr_string_array, to_device}; /// The "platform" device provides access to things like: /// - `dgpu_disable` @@ -30,6 +30,12 @@ impl RogPlatform { pp_path ); + attr_string_array!( + /// The acpi platform_profile support + "platform_profile_choices", + pp_path + ); + pub fn new() -> Result { let mut enumerator = udev::Enumerator::new().map_err(|err| { warn!("{}", err); @@ -169,7 +175,7 @@ impl Display for GpuMode { } } -#[repr(u32)] +#[repr(i32)] #[derive( Deserialize, Serialize, @@ -185,39 +191,40 @@ impl Display for GpuMode { Clone, Copy, )] -#[zvariant(signature = "u")] +#[zvariant(signature = "i")] /// `platform_profile` in asus_wmi pub enum PlatformProfile { #[default] Balanced = 0, Performance = 1, Quiet = 2, + LowPower = 3, } impl PlatformProfile { - pub const fn next(self) -> Self { - match self { + pub fn next(current: Self, choices: &[Self]) -> Self { + match current { Self::Balanced => Self::Performance, - Self::Performance => Self::Quiet, + Self::Performance => { + if choices.contains(&Self::LowPower) { + Self::LowPower + } else { + Self::Quiet + } + } Self::Quiet => Self::Balanced, + Self::LowPower => Self::Balanced, } } - - pub const fn list() -> [Self; 3] { - [ - Self::Balanced, - Self::Performance, - Self::Quiet, - ] - } } -impl From for PlatformProfile { - fn from(num: u8) -> Self { +impl From for PlatformProfile { + fn from(num: i32) -> Self { match num { 0 => Self::Balanced, 1 => Self::Performance, 2 => Self::Quiet, + 3 => Self::LowPower, _ => { warn!("Unknown number for PlatformProfile: {}", num); Self::Balanced @@ -226,56 +233,38 @@ impl From for PlatformProfile { } } -impl From for PlatformProfile { - fn from(num: i32) -> Self { - (num as u8).into() - } -} - -impl From for u8 { - fn from(p: PlatformProfile) -> Self { - match p { - PlatformProfile::Balanced => 0, - PlatformProfile::Performance => 1, - PlatformProfile::Quiet => 2, - } - } -} - impl From for i32 { fn from(p: PlatformProfile) -> Self { - ::from(p) as i32 + p as i32 + } +} + +impl From<&PlatformProfile> for &str { + fn from(profile: &PlatformProfile) -> &'static str { + match profile { + PlatformProfile::Balanced => "balanced", + PlatformProfile::Performance => "performance", + PlatformProfile::Quiet => "quiet", + PlatformProfile::LowPower => "low-power", + } } } impl From for &str { fn from(profile: PlatformProfile) -> &'static str { - match profile { - PlatformProfile::Balanced => "balanced", - PlatformProfile::Performance => "performance", - PlatformProfile::Quiet => "quiet", - } + <&str>::from(&profile) } } impl From for PlatformProfile { fn from(profile: String) -> Self { - Self::from(&profile) + Self::from(profile.as_str()) } } -impl From<&String> for PlatformProfile { - fn from(profile: &String) -> Self { - match profile.to_ascii_lowercase().trim() { - "balanced" => PlatformProfile::Balanced, - "performance" => PlatformProfile::Performance, - "quiet" => PlatformProfile::Quiet, - "low-power" => PlatformProfile::Quiet, - _ => { - warn!("{profile} is unknown, using ThrottlePolicy::Balanced"); - PlatformProfile::Balanced - } - } +impl Display for PlatformProfile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "({})", <&str>::from(self)) } } @@ -287,15 +276,24 @@ impl std::str::FromStr for PlatformProfile { "balanced" => Ok(PlatformProfile::Balanced), "performance" => Ok(PlatformProfile::Performance), "quiet" => Ok(PlatformProfile::Quiet), - "low-power" => Ok(PlatformProfile::Quiet), + "low-power" => Ok(PlatformProfile::LowPower), _ => Err(PlatformError::NotSupported), } } } -impl Display for PlatformProfile { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) +impl From<&str> for PlatformProfile { + fn from(profile: &str) -> Self { + match profile.to_ascii_lowercase().trim() { + "balanced" => PlatformProfile::Balanced, + "performance" => PlatformProfile::Performance, + "quiet" => PlatformProfile::Quiet, + "low-power" => PlatformProfile::LowPower, + _ => { + warn!("{profile} is unknown, using ThrottlePolicy::Balanced"); + PlatformProfile::Balanced + } + } } } diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index f2697a95..6be5d32c 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -145,7 +145,7 @@ impl FanCurveProfiles { match profile { PlatformProfile::Balanced => self.balanced = curves, PlatformProfile::Performance => self.performance = curves, - PlatformProfile::Quiet => self.quiet = curves, + PlatformProfile::Quiet | PlatformProfile::LowPower => self.quiet = curves, } Ok(()) } @@ -181,7 +181,7 @@ impl FanCurveProfiles { let fans = match profile { PlatformProfile::Balanced => &mut self.balanced, PlatformProfile::Performance => &mut self.performance, - PlatformProfile::Quiet => &mut self.quiet, + PlatformProfile::Quiet | PlatformProfile::LowPower => &mut self.quiet, }; for fan in fans.iter().filter(|f| !f.enabled) { debug!("write_profile_curve_to_platform: writing profile:{profile}, {fan:?}"); @@ -208,7 +208,7 @@ impl FanCurveProfiles { curve.enabled = enabled; } } - PlatformProfile::Quiet => { + PlatformProfile::Quiet | PlatformProfile::LowPower => { for curve in self.quiet.iter_mut() { curve.enabled = enabled; } @@ -239,7 +239,7 @@ impl FanCurveProfiles { } } } - PlatformProfile::Quiet => { + PlatformProfile::Quiet | PlatformProfile::LowPower => { for curve in self.quiet.iter_mut() { if curve.fan == fan { curve.enabled = enabled; @@ -254,7 +254,7 @@ impl FanCurveProfiles { match name { PlatformProfile::Balanced => &self.balanced, PlatformProfile::Performance => &self.performance, - PlatformProfile::Quiet => &self.quiet, + PlatformProfile::Quiet | PlatformProfile::LowPower => &self.quiet, } } @@ -274,7 +274,7 @@ impl FanCurveProfiles { } } } - PlatformProfile::Quiet => { + PlatformProfile::Quiet | PlatformProfile::LowPower => { for this_curve in self.quiet.iter() { if this_curve.fan == pu { return Some(this_curve); @@ -307,7 +307,7 @@ impl FanCurveProfiles { } } } - PlatformProfile::Quiet => { + PlatformProfile::Quiet | PlatformProfile::LowPower => { for this_curve in self.quiet.iter_mut() { if this_curve.fan == curve.fan { *this_curve = curve;