diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 7f406071..fdc745c4 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -746,7 +746,8 @@ fn handle_fan_curve( } if cmd.default { - dbus.proxies().fan_curves().set_active_curve_to_defaults()?; + let active = dbus.proxies().platform().throttle_thermal_policy()?; + dbus.proxies().fan_curves().set_curves_to_defaults(active)?; } if let Some(profile) = cmd.mod_profile { diff --git a/asusd/src/ctrl_fancurves.rs b/asusd/src/ctrl_fancurves.rs index dbf0da75..437709b6 100644 --- a/asusd/src/ctrl_fancurves.rs +++ b/asusd/src/ctrl_fancurves.rs @@ -182,18 +182,20 @@ impl CtrlFanCurveZbus { Ok(()) } - /// Reset the stored (self) and device curve to the defaults of the + /// Reset the stored (self) and device curves to the defaults of the /// platform. /// - /// Each platform_profile has a different default and the defualt can be + /// Each platform_profile has a different default and the default can be /// read only for the currently active profile. - async fn set_active_curve_to_defaults(&mut self) -> zbus::fdo::Result<()> { + async fn set_curves_to_defaults(&mut self, profile: ThrottlePolicy) -> zbus::fdo::Result<()> { let active = self.platform.get_throttle_thermal_policy()?; + self.platform.set_throttle_thermal_policy(profile.into())?; self.config .lock() .await .profiles - .set_active_curve_to_defaults(active.into(), &mut find_fan_curve_node()?)?; + .set_active_curve_to_defaults(profile.into(), &mut find_fan_curve_node()?)?; + self.platform.set_throttle_thermal_policy(active.into())?; self.config.lock().await.write(); Ok(()) } diff --git a/rog-control-center/Cargo.toml b/rog-control-center/Cargo.toml index 5022b9c6..c3fe4f90 100644 --- a/rog-control-center/Cargo.toml +++ b/rog-control-center/Cargo.toml @@ -11,7 +11,9 @@ edition = "2021" [dependencies] -betrayer = { git = "https://github.com/flukejones/betrayer.git", features = ["winit"] } +betrayer = { git = "https://github.com/flukejones/betrayer.git", features = [ + "winit", +] } asusd = { path = "../asusd" } config-traits = { path = "../config-traits" } @@ -52,11 +54,18 @@ winit = "*" git = "https://github.com/flukejones/sixtyfps.git" branch = "asusctl" default-features = false -features = ["std", "gettext", "compat-1-0", "backend-winit-wayland", "backend-linuxkms", "renderer-femtovg"] +features = [ + "std", + "gettext", + "compat-1-0", + "backend-winit-wayland", + "backend-linuxkms", + "renderer-femtovg", +] [build-dependencies.slint-build] git = "https://github.com/flukejones/sixtyfps.git" branch = "asusctl" [dev-dependencies] -cargo-husky.workspace = true \ No newline at end of file +cargo-husky.workspace = true diff --git a/rog-control-center/src/ui_setup.rs b/rog-control-center/src/ui_setup.rs index ec960f50..1347a6dc 100644 --- a/rog-control-center/src/ui_setup.rs +++ b/rog-control-center/src/ui_setup.rs @@ -8,13 +8,15 @@ use rog_dbus::zbus_aura::AuraProxy; use rog_dbus::zbus_fan_curves::FanCurvesProxy; use rog_dbus::zbus_platform::{PlatformProxy, PlatformProxyBlocking}; use rog_platform::platform::{Properties, ThrottlePolicy}; +use rog_profiles::fan_curve_set::CurveData; +use rog_profiles::FanCurvePU; use slint::{ComponentHandle, Model, PhysicalSize, RgbaColor, SharedString, Weak}; use zbus::proxy::CacheProperties; use crate::config::Config; use crate::{ AnimePageData, AppSettingsPageData, AuraPageData, AvailableSystemProperties, FanPageData, - MainWindow, Node, PowerZones as SlintPowerZones, SystemPageData, + FanType, MainWindow, Node, PowerZones as SlintPowerZones, Profile, SystemPageData, }; // This macro expects are consistent naming between proxy calls and slint @@ -122,6 +124,122 @@ pub fn setup_window(config: Arc>) -> MainWindow { ui } +pub fn update_fan_data( + handle: Weak, + bal: Vec, + perf: Vec, + quiet: Vec, +) { + handle + .upgrade_in_event_loop(move |handle| { + let global = handle.global::(); + let collect = |temp: &[u8], pwm: &[u8]| -> slint::ModelRc { + let tmp: Vec = temp + .iter() + .zip(pwm.iter()) + .map(|(x, y)| Node { + x: *x as f32, + y: *y as f32, + }) + .collect(); + tmp.as_slice().into() + }; + + for fan in bal { + global.set_balanced_available(true); + match fan.fan { + rog_profiles::FanCurvePU::CPU => { + global.set_cpu_fan_available(true); + global.set_balanced_cpu_enabled(fan.enabled); + global.set_balanced_cpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::GPU => { + global.set_gpu_fan_available(true); + global.set_balanced_gpu_enabled(fan.enabled); + global.set_balanced_gpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::MID => { + global.set_mid_fan_available(true); + global.set_balanced_mid_enabled(fan.enabled); + global.set_balanced_mid(collect(&fan.temp, &fan.pwm)) + } + } + } + for fan in perf { + global.set_performance_available(true); + match fan.fan { + rog_profiles::FanCurvePU::CPU => { + global.set_performance_cpu_enabled(fan.enabled); + global.set_performance_cpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::GPU => { + global.set_performance_gpu_enabled(fan.enabled); + global.set_performance_gpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::MID => { + global.set_performance_mid_enabled(fan.enabled); + global.set_performance_mid(collect(&fan.temp, &fan.pwm)) + } + } + } + for fan in quiet { + global.set_quiet_available(true); + match fan.fan { + rog_profiles::FanCurvePU::CPU => { + global.set_quiet_cpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::GPU => { + global.set_quiet_gpu(collect(&fan.temp, &fan.pwm)) + } + rog_profiles::FanCurvePU::MID => { + global.set_quiet_mid(collect(&fan.temp, &fan.pwm)) + } + } + } + }) + .unwrap(); +} + +impl From for ThrottlePolicy { + fn from(value: Profile) -> Self { + match value { + Profile::Balanced => ThrottlePolicy::Balanced, + Profile::Performance => ThrottlePolicy::Performance, + Profile::Quiet => ThrottlePolicy::Quiet, + } + } +} + +impl From for Profile { + fn from(value: ThrottlePolicy) -> Self { + match value { + ThrottlePolicy::Balanced => Profile::Balanced, + ThrottlePolicy::Performance => Profile::Performance, + ThrottlePolicy::Quiet => Profile::Quiet, + } + } +} + +impl From for FanCurvePU { + fn from(value: FanType) -> Self { + match value { + FanType::CPU => FanCurvePU::CPU, + FanType::Middle => FanCurvePU::MID, + FanType::GPU => FanCurvePU::GPU, + } + } +} + +impl From for FanType { + fn from(value: FanCurvePU) -> Self { + match value { + FanCurvePU::CPU => FanType::CPU, + FanCurvePU::GPU => FanType::GPU, + FanCurvePU::MID => FanType::Middle, + } + } +} + pub fn setup_fan_curve_page(ui: &MainWindow, _config: Arc>) { let handle = ui.as_weak(); @@ -130,6 +248,7 @@ pub fn setup_fan_curve_page(ui: &MainWindow, _config: Arc>) { let conn = zbus::Connection::system().await.unwrap(); let fans = FanCurvesProxy::new(&conn).await.unwrap(); + let handle_copy = handle.clone(); // Do initial setup let balanced = fans.fan_curve_data(ThrottlePolicy::Balanced).await.unwrap(); let perf = fans @@ -137,75 +256,60 @@ pub fn setup_fan_curve_page(ui: &MainWindow, _config: Arc>) { .await .unwrap(); let quiet = fans.fan_curve_data(ThrottlePolicy::Quiet).await.unwrap(); + update_fan_data(handle, balanced, perf, quiet); - handle + let handle_next1 = handle_copy.clone(); + handle_copy .upgrade_in_event_loop(move |handle| { let global = handle.global::(); - let collect = |temp: &[u8], pwm: &[u8]| -> slint::ModelRc { - let tmp: Vec = temp - .iter() - .zip(pwm.iter()) - .map(|(x, y)| Node { - x: *x as f32, - y: *y as f32, - }) - .collect(); - tmp.as_slice().into() - }; + let fans1 = fans.clone(); + global.on_set_profile_default(move |profile| { + let fans = fans1.clone(); + let handle_next = handle_next1.clone(); + tokio::spawn(async move { + fans.set_curves_to_defaults(profile.into()).await.unwrap(); - for fan in balanced { - match fan.fan { - rog_profiles::FanCurvePU::CPU => { - global.set_balanced_cpu_available(true); - global.set_balanced_cpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::GPU => { - global.set_balanced_gpu_available(true); - global.set_balanced_gpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::MID => { - global.set_balanced_mid_available(true); - global.set_balanced_mid(collect(&fan.temp, &fan.pwm)) - } - } - } - for fan in perf { - match fan.fan { - rog_profiles::FanCurvePU::CPU => { - global.set_performance_cpu_available(true); - global.set_performance_cpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::GPU => { - global.set_performance_gpu_available(true); - global.set_performance_gpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::MID => { - global.set_performance_mid_available(true); - global.set_performance_mid(collect(&fan.temp, &fan.pwm)) - } - } - } - for fan in quiet { - match fan.fan { - rog_profiles::FanCurvePU::CPU => { - global.set_quiet_cpu_available(true); - global.set_quiet_cpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::GPU => { - global.set_quiet_gpu_available(true); - global.set_quiet_gpu(collect(&fan.temp, &fan.pwm)) - } - rog_profiles::FanCurvePU::MID => { - global.set_quiet_mid_available(true); - global.set_quiet_mid(collect(&fan.temp, &fan.pwm)) - } - } - } + let balanced = fans.fan_curve_data(ThrottlePolicy::Balanced).await.unwrap(); + let perf = fans + .fan_curve_data(ThrottlePolicy::Performance) + .await + .unwrap(); + let quiet = fans.fan_curve_data(ThrottlePolicy::Quiet).await.unwrap(); + update_fan_data(handle_next, balanced, perf, quiet); + }); + }); + global.on_set_fan_data(move |fan, profile, enabled, data| { + let fans = fans.clone(); + let data: Vec = data.iter().collect(); + let data = fan_data_for(fan, enabled, data); + tokio::spawn(async move { + fans.set_fan_curve(profile.into(), data).await.unwrap(); + }); + }); }) .unwrap(); }); } +fn fan_data_for(fan: FanType, enabled: bool, data: Vec) -> CurveData { + let mut temp = [0u8; 8]; + let mut pwm = [0u8; 8]; + for (i, n) in data.iter().enumerate() { + if i == 8 { + break; + } + temp[i] = n.x as u8; + pwm[i] = n.y as u8; + } + + CurveData { + fan: fan.into(), + pwm, + temp, + enabled, + } +} + pub fn setup_app_settings_page(ui: &MainWindow, config: Arc>) { let config_copy = config.clone(); let global = ui.global::(); diff --git a/rog-control-center/ui/pages/fans.slint b/rog-control-center/ui/pages/fans.slint index 0640ab0a..fc3f703c 100644 --- a/rog-control-center/ui/pages/fans.slint +++ b/rog-control-center/ui/pages/fans.slint @@ -5,7 +5,7 @@ import { Profile, FanType, FanPageData } from "../types/fan_types.slint"; component FanTab inherits Rectangle { in-out property enabled: false; - in-out property tab_enabled: false; + in-out property tab_enabled: true; in property profile; in property fan_type; callback apply(); @@ -15,22 +15,17 @@ component FanTab inherits Rectangle { in property title; in-out property <[Node]> nodes; - if !root.tab_enabled: VerticalLayout { - alignment: center; - HorizontalLayout { - alignment: center; - Text { - font-size: 24px; - text: "WIP: Not enabled yet"; - } - } - } - VerticalLayout { HorizontalLayout { - Graph { + if root.tab_enabled: Graph { nodes <=> root.nodes; } + if !root.tab_enabled: Rectangle { + Text { + font-size: 24px; + text: @tr("This fan is not avilable on this machine"); + } + } } HorizontalLayout { @@ -61,7 +56,7 @@ component FanTab inherits Rectangle { } Button { - text: @tr("Factory Default"); + text: @tr("Factory Default (all fans)"); enabled <=> root.tab_enabled; clicked => { root.default(); @@ -79,21 +74,54 @@ export component PageFans inherits VerticalLayout { Tab { title: @tr("CPU"); FanTab { + tab_enabled <=> FanPageData.cpu_fan_available; + enabled <=> FanPageData.balanced_cpu_enabled; nodes <=> FanPageData.balanced_cpu; + apply => { + FanPageData.set_fan_data(FanType.CPU, Profile.Balanced, self.enabled, FanPageData.balanced_cpu); + } + toggled => { + FanPageData.set_fan_data(FanType.CPU, Profile.Balanced, self.enabled, FanPageData.balanced_cpu); + } + default => { + FanPageData.set_profile_default(Profile.Balanced); + } } } Tab { title: @tr("Mid"); FanTab { + tab_enabled <=> FanPageData.mid_fan_available; + enabled <=> FanPageData.balanced_mid_enabled; nodes <=> FanPageData.balanced_mid; + apply => { + FanPageData.set_fan_data(FanType.Middle, Profile.Balanced, self.enabled, FanPageData.balanced_mid); + } + toggled => { + FanPageData.set_fan_data(FanType.Middle, Profile.Balanced, self.enabled, FanPageData.balanced_mid); + } + default => { + FanPageData.set_profile_default(Profile.Balanced); + } } } Tab { title: @tr("GPU"); FanTab { + tab_enabled <=> FanPageData.gpu_fan_available; + enabled <=> FanPageData.balanced_gpu_enabled; nodes <=> FanPageData.balanced_gpu; + apply => { + FanPageData.set_fan_data(FanType.GPU, Profile.Balanced, self.enabled, FanPageData.balanced_gpu); + } + toggled => { + FanPageData.set_fan_data(FanType.GPU, Profile.Balanced, self.enabled, FanPageData.balanced_gpu); + } + default => { + FanPageData.set_profile_default(Profile.Balanced); + } } } } @@ -105,21 +133,54 @@ export component PageFans inherits VerticalLayout { Tab { title: @tr("CPU"); FanTab { + tab_enabled <=> FanPageData.cpu_fan_available; + enabled <=> FanPageData.performance_cpu_enabled; nodes <=> FanPageData.performance_cpu; + apply => { + FanPageData.set_fan_data(FanType.CPU, Profile.Performance, self.enabled, FanPageData.performance_cpu); + } + toggled => { + FanPageData.set_fan_data(FanType.CPU, Profile.Performance, self.enabled, FanPageData.performance_cpu); + } + default => { + FanPageData.set_profile_default(Profile.Performance); + } } } Tab { title: @tr("Mid"); FanTab { + tab_enabled <=> FanPageData.mid_fan_available; + enabled <=> FanPageData.performance_mid_enabled; nodes <=> FanPageData.performance_mid; + apply => { + FanPageData.set_fan_data(FanType.Middle, Profile.Performance, self.enabled, FanPageData.performance_mid); + } + toggled => { + FanPageData.set_fan_data(FanType.Middle, Profile.Performance, self.enabled, FanPageData.performance_mid); + } + default => { + FanPageData.set_profile_default(Profile.Performance); + } } } Tab { title: @tr("GPU"); FanTab { + tab_enabled <=> FanPageData.gpu_fan_available; + enabled <=> FanPageData.performance_gpu_enabled; nodes <=> FanPageData.performance_gpu; + apply => { + FanPageData.set_fan_data(FanType.GPU, Profile.Performance, self.enabled, FanPageData.performance_gpu); + } + toggled => { + FanPageData.set_fan_data(FanType.GPU, Profile.Performance, self.enabled, FanPageData.performance_gpu); + } + default => { + FanPageData.set_profile_default(Profile.Performance); + } } } } @@ -131,21 +192,54 @@ export component PageFans inherits VerticalLayout { Tab { title: @tr("CPU"); FanTab { + tab_enabled <=> FanPageData.cpu_fan_available; + enabled <=> FanPageData.quiet_cpu_enabled; nodes <=> FanPageData.quiet_cpu; + apply => { + FanPageData.set_fan_data(FanType.CPU, Profile.Quiet, self.enabled, FanPageData.quiet_cpu); + } + toggled => { + FanPageData.set_fan_data(FanType.CPU, Profile.Quiet, self.enabled, FanPageData.quiet_cpu); + } + default => { + FanPageData.set_profile_default(Profile.Quiet); + } } } Tab { title: @tr("Mid"); FanTab { + tab_enabled <=> FanPageData.mid_fan_available; + enabled <=> FanPageData.quiet_mid_enabled; nodes <=> FanPageData.quiet_mid; + apply => { + FanPageData.set_fan_data(FanType.Middle, Profile.Quiet, self.enabled, FanPageData.quiet_mid); + } + toggled => { + FanPageData.set_fan_data(FanType.Middle, Profile.Quiet, self.enabled, FanPageData.quiet_mid); + } + default => { + FanPageData.set_profile_default(Profile.Quiet); + } } } Tab { title: @tr("GPU"); FanTab { + tab_enabled <=> FanPageData.gpu_fan_available; + enabled <=> FanPageData.quiet_gpu_enabled; nodes <=> FanPageData.quiet_gpu; + apply => { + FanPageData.set_fan_data(FanType.GPU, Profile.Quiet, self.enabled, FanPageData.quiet_gpu); + } + toggled => { + FanPageData.set_fan_data(FanType.GPU, Profile.Quiet, self.enabled, FanPageData.quiet_gpu); + } + default => { + FanPageData.set_profile_default(Profile.Quiet); + } } } } diff --git a/rog-control-center/ui/types/fan_types.slint b/rog-control-center/ui/types/fan_types.slint index 4b1888b6..fe2be1aa 100644 --- a/rog-control-center/ui/types/fan_types.slint +++ b/rog-control-center/ui/types/fan_types.slint @@ -16,15 +16,25 @@ export global FanPageData { in-out property <[Profile]> available_profiles: [Profile.Balanced, Profile.Performance, Profile.Quiet]; in-out property <[FanType]> available_fans: [FanType.CPU, FanType.Middle, FanType.GPU]; - in-out property balanced_cpu_available: true; - in-out property balanced_gpu_available: true; - in-out property balanced_mid_available: false; - in-out property performance_cpu_available: true; - in-out property performance_gpu_available: true; - in-out property performance_mid_available: false; - in-out property quiet_cpu_available: true; - in-out property quiet_gpu_available: true; - in-out property quiet_mid_available: false; + in-out property cpu_fan_available: true; + in-out property gpu_fan_available: true; + in-out property mid_fan_available: false; + in-out property balanced_available: true; + in-out property performance_available: true; + in-out property quiet_available: false; + + in-out property balanced_cpu_enabled: true; + in-out property balanced_gpu_enabled: true; + in-out property balanced_mid_enabled: false; + in-out property performance_cpu_enabled: true; + in-out property performance_gpu_enabled: true; + in-out property performance_mid_enabled: false; + in-out property quiet_cpu_enabled: true; + in-out property quiet_gpu_enabled: true; + in-out property quiet_mid_enabled: false; + + callback set_fan_data(FanType, Profile, bool, [Node]); + callback set_profile_default(Profile); in-out property <[Node]> balanced_cpu: [ { diff --git a/rog-dbus/src/zbus_fan_curves.rs b/rog-dbus/src/zbus_fan_curves.rs index d6837e8a..e8cf4d12 100644 --- a/rog-dbus/src/zbus_fan_curves.rs +++ b/rog-dbus/src/zbus_fan_curves.rs @@ -42,7 +42,7 @@ trait FanCurves { fn reset_profile_curves(&self, profile: ThrottlePolicy) -> zbus::Result<()>; /// SetActiveCurveToDefaults method - fn set_active_curve_to_defaults(&self) -> zbus::Result<()>; + fn set_curves_to_defaults(&self, profile: ThrottlePolicy) -> zbus::Result<()>; /// Set the fan curve for the specified profile, or the profile the user is /// currently in if profile == None. Will also activate the fan curve. diff --git a/rog-profiles/src/fan_curve_set.rs b/rog-profiles/src/fan_curve_set.rs index 41cbdd23..9a32681d 100644 --- a/rog-profiles/src/fan_curve_set.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -1,3 +1,6 @@ +use std::fs::OpenOptions; +use std::io::Write; + use log::trace; use serde_derive::{Deserialize, Serialize}; use typeshare::typeshare; @@ -168,7 +171,7 @@ impl CurveData { /// Write this curve to the device fan specified by `self.fan` pub fn write_to_device(&self, device: &mut Device) -> std::io::Result<()> { let pwm_num: char = self.fan.into(); - let enable = if self.enabled { "1" } else { "2" }; + let enable = if self.enabled { '1' } else { '2' }; for (index, out) in self.pwm.iter().enumerate() { let pwm = pwm_str(pwm_num, index); @@ -182,8 +185,16 @@ impl CurveData { device.set_attribute_value(&temp, &out.to_string())?; } - // Enable must be done *after* all points are written - device.set_attribute_value(format!("pwm{pwm_num}_enable"), enable) + // Enable must be done *after* all points are written pwm3_enable + // device.syspath() + let mut path = device.syspath().to_path_buf(); + path.push(format!("pwm{pwm_num}_enable")); + let mut f = OpenOptions::new().write(true).open(path).unwrap(); + f.write_all(&[enable as u8]).unwrap(); + // device + // .set_attribute_value(format!("pwm{pwm_num}_enable"), enable.to_string()) + // .unwrap(); + Ok(()) } }