diff --git a/.gitignore b/.gitignore index 99a7d022..8d235fc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ /target -vendor.tar.xz \ No newline at end of file +vendor.tar.xz +cargo-config +.idea +vendor-* +vendor_* diff --git a/CHANGELOG.md b/CHANGELOG.md index 9683a38c..b09239f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Add GX550L led modes - Don't save compute/vfio modes. Option in config for this is removed. +- Store a temporary non-serialised option in config for if compute/vfio is active + for informational purposes only (will not apply on boot) +- Save state for LEDs enabled + sleep animation enabled +- Save state for AnimMe enabled + boot animation enabled # [3.5.2] - 2021-05-15 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 50a8c5bf..ba9dddba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,7 @@ dependencies = [ "daemon", "notify-rust", "rog_dbus", + "rog_profiles", "rog_types", "serde_json", ] @@ -44,15 +45,15 @@ dependencies = [ name = "asusctl" version = "3.5.0" dependencies = [ - "daemon", "gif", "glam", "gumdrop", "rog_anime", "rog_aura", "rog_dbus", + "rog_fan_curve", + "rog_profiles", "rog_types", - "serde_json", "tinybmp", "yansi-term", ] @@ -206,16 +207,16 @@ dependencies = [ [[package]] name = "daemon" -version = "3.5.2" +version = "3.6.0" dependencies = [ "env_logger", - "intel-pstate", "log", "logind-zbus", "rog_anime", "rog_aura", "rog_dbus", "rog_fan_curve", + "rog_profiles", "rog_types", "rusb", "serde", @@ -226,6 +227,7 @@ dependencies = [ "udev", "zbus", "zvariant", + "zvariant_derive", ] [[package]] @@ -320,20 +322,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "err-derive" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote 1.0.9", - "rustversion", - "syn 1.0.69", - "synstructure", -] - [[package]] name = "fastrand" version = "1.4.0" @@ -526,12 +514,12 @@ dependencies = [ [[package]] name = "intel-pstate" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e7f68d8a6d149a5b2195ab645923c63ee35928fff58895b3c1d21541afe90c" +checksum = "0dbd48c2f4886e44c137f4acb6ba3cf8df15154a2c996a65ee5e57c54a04c01f" dependencies = [ - "err-derive", "smart-default", + "thiserror", ] [[package]] @@ -803,30 +791,6 @@ dependencies = [ "toml", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote 1.0.9", - "syn 1.0.69", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote 1.0.9", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -907,31 +871,28 @@ dependencies = [ "png_pong", "serde", "serde_derive", - "zbus", "zvariant", "zvariant_derive", ] [[package]] name = "rog_aura" -version = "1.0.1" +version = "1.1.0" dependencies = [ "serde", "serde_derive", - "zbus", "zvariant", "zvariant_derive", ] [[package]] name = "rog_dbus" -version = "3.2.0" +version = "3.4.0" dependencies = [ "rog_anime", "rog_aura", - "rog_fan_curve", + "rog_profiles", "rog_types", - "serde_json", "zbus", "zbus_macros", "zvariant", @@ -946,13 +907,23 @@ dependencies = [ "serde", ] +[[package]] +name = "rog_profiles" +version = "0.1.0" +dependencies = [ + "intel-pstate", + "rog_fan_curve", + "serde", + "serde_derive", + "zvariant", + "zvariant_derive", +] + [[package]] name = "rog_types" version = "3.2.0" dependencies = [ - "gumdrop", "rog_aura", - "rog_fan_curve", "serde", "serde_derive", "zvariant", @@ -981,12 +952,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rustversion" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" - [[package]] name = "ryu" version = "1.0.5" @@ -1115,18 +1080,6 @@ dependencies = [ "unicode-xid 0.0.4", ] -[[package]] -name = "synstructure" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" -dependencies = [ - "proc-macro2", - "quote 1.0.9", - "syn 1.0.69", - "unicode-xid 0.2.1", -] - [[package]] name = "sysfs-class" version = "0.1.3" @@ -1145,6 +1098,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" +dependencies = [ + "proc-macro2", + "quote 1.0.9", + "syn 1.0.69", +] + [[package]] name = "time" version = "0.1.44" diff --git a/Cargo.toml b/Cargo.toml index c80df6f7..774d9f13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-types", "rog-dbus", "rog-anime"] +members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-types", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles"] [profile.release] lto = true diff --git a/asus-notify/Cargo.toml b/asus-notify/Cargo.toml index 38bf2ad1..e361dfa8 100644 --- a/asus-notify/Cargo.toml +++ b/asus-notify/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" # serialisation serde_json = "^1.0" rog_dbus = { path = "../rog-dbus" } +rog_profiles = { path = "../rog-profiles" } rog_types = { path = "../rog-types" } daemon = { path = "../daemon" } diff --git a/asus-notify/src/main.rs b/asus-notify/src/main.rs index 974131b5..574ce467 100644 --- a/asus-notify/src/main.rs +++ b/asus-notify/src/main.rs @@ -1,6 +1,6 @@ use notify_rust::{Hint, Notification, NotificationHandle}; use rog_dbus::{DbusProxies, Signals}; -use rog_types::profile::Profile; +use rog_profiles::profiles::{FanLevel, Profile}; use std::error::Error; use std::thread::sleep; use std::time::Duration; @@ -36,73 +36,59 @@ fn main() -> Result<(), Box> { } err_count = 0; - if let Ok(mut lock) = signals.gfx_vendor.lock() { - if let Some(vendor) = lock.take() { - if let Some(notif) = last_gfx_notif.take() { - notif.close(); - } - let x = do_notif(&format!( - "Graphics mode changed to {}", - <&str>::from(vendor) - ))?; - last_gfx_notif = Some(x); + if let Ok(vendor) = signals.gfx_vendor.try_recv() { + if let Some(notif) = last_gfx_notif.take() { + notif.close(); } + let x = do_notif(&format!( + "Graphics mode changed to {}", + <&str>::from(vendor) + ))?; + last_gfx_notif = Some(x); } - if let Ok(mut lock) = signals.charge.lock() { - if let Some(limit) = lock.take() { - if let Some(notif) = last_chrg_notif.take() { - notif.close(); - } - let x = do_notif(&format!("Battery charge limit changed to {}", limit))?; - last_chrg_notif = Some(x); + if let Ok(limit) = signals.charge.try_recv() { + if let Some(notif) = last_chrg_notif.take() { + notif.close(); } + let x = do_notif(&format!("Battery charge limit changed to {}", limit))?; + last_chrg_notif = Some(x); } - if let Ok(mut lock) = signals.profile.lock() { - if let Some(profile) = lock.take() { - if let Some(notif) = last_profile_notif.take() { - notif.close(); - } - if let Ok(profile) = serde_json::from_str(&profile) { - let profile: Profile = profile; - if let Ok(name) = proxies.profile().active_profile_name() { - let x = do_thermal_notif(&profile, &name)?; - last_profile_notif = Some(x); - } - } + if let Ok(profile) = signals.profile.try_recv() { + if let Some(notif) = last_profile_notif.take() { + notif.close(); } + let x = do_thermal_notif(&profile)?; + last_profile_notif = Some(x); } - if let Ok(mut lock) = signals.led_mode.lock() { - if let Some(ledmode) = lock.take() { - if let Some(notif) = last_led_notif.take() { - notif.close(); - } - let x = do_notif(&format!( - "Keyboard LED mode changed to {}", - ledmode.mode_name() - ))?; - last_led_notif = Some(x); + if let Ok(ledmode) = signals.led_mode.try_recv() { + if let Some(notif) = last_led_notif.take() { + notif.close(); } + let x = do_notif(&format!( + "Keyboard LED mode changed to {}", + ledmode.mode_name() + ))?; + last_led_notif = Some(x); } } } -fn do_thermal_notif(profile: &Profile, label: &str) -> Result> { +fn do_thermal_notif(profile: &Profile) -> Result> { let fan = profile.fan_preset; let turbo = if profile.turbo { "enabled" } else { "disabled" }; let icon = match fan { - 0 => "asus_notif_yellow", - 1 => "asus_notif_red", - 2 => "asus_notif_green", - _ => "asus_notif_red", + FanLevel::Normal => "asus_notif_yellow", + FanLevel::Boost => "asus_notif_red", + FanLevel::Silent => "asus_notif_green", }; let x = Notification::new() .summary("ASUS ROG") .body(&format!( "Thermal profile changed to {}, turbo {}", - label.to_uppercase(), + profile.name.to_uppercase(), turbo )) .hint(Hint::Resident(true)) diff --git a/asusctl/Cargo.toml b/asusctl/Cargo.toml index ce2431d8..eba82003 100644 --- a/asusctl/Cargo.toml +++ b/asusctl/Cargo.toml @@ -7,13 +7,12 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -# serialisation -serde_json = "^1.0" rog_anime = { path = "../rog-anime" } rog_aura = { path = "../rog-aura" } rog_dbus = { path = "../rog-dbus" } +rog_profiles = { path = "../rog-profiles" } rog_types = { path = "../rog-types" } -daemon = { path = "../daemon" } +rog_fan_curve = { version = "^0.1", features = ["serde"] } gumdrop = "^0.8" yansi-term = "^0.1" diff --git a/asusctl/examples/anime-diag-png.rs b/asusctl/examples/anime-diag-png.rs index f38fc2c7..091e6064 100644 --- a/asusctl/examples/anime-diag-png.rs +++ b/asusctl/examples/anime-diag-png.rs @@ -1,10 +1,10 @@ use std::{env, error::Error, path::Path, process::exit}; use rog_anime::{AnimeDataBuffer, AnimeDiagonal}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let args: Vec = env::args().into_iter().collect(); if args.len() != 3 { diff --git a/asusctl/examples/anime-diag.rs b/asusctl/examples/anime-diag.rs index 8d323ee4..01a9f498 100644 --- a/asusctl/examples/anime-diag.rs +++ b/asusctl/examples/anime-diag.rs @@ -1,7 +1,7 @@ use std::{thread::sleep, time::Duration}; use rog_anime::{AnimeDataBuffer, AnimeDiagonal}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; // In usable data: // Top row start at 1, ends at 32 @@ -9,7 +9,7 @@ use rog_dbus::AuraDbusClient; // 74w x 36h diagonal used by the windows app fn main() { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); for step in (2..50).rev() { let mut matrix = AnimeDiagonal::new(None); diff --git a/asusctl/examples/anime-gif.rs b/asusctl/examples/anime-gif.rs index 1e6ef6a5..0370ac60 100644 --- a/asusctl/examples/anime-gif.rs +++ b/asusctl/examples/anime-gif.rs @@ -1,10 +1,10 @@ use std::{env, path::Path, thread::sleep}; use rog_anime::{ActionData, AnimeAction, Sequences}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let args: Vec = env::args().into_iter().collect(); if args.len() != 3 { diff --git a/asusctl/examples/anime-grid.rs b/asusctl/examples/anime-grid.rs index 28196c46..09bb6dad 100644 --- a/asusctl/examples/anime-grid.rs +++ b/asusctl/examples/anime-grid.rs @@ -1,5 +1,5 @@ use rog_anime::{AnimeDataBuffer, AnimeGrid}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; // In usable data: // Top row start at 1, ends at 32 @@ -7,7 +7,7 @@ use rog_dbus::AuraDbusClient; // 74w x 36h diagonal used by the windows app fn main() { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let mut matrix = AnimeGrid::new(None); let tmp = matrix.get_mut(); diff --git a/asusctl/examples/anime-outline.rs b/asusctl/examples/anime-outline.rs index d0f956b8..f59f2f88 100644 --- a/asusctl/examples/anime-outline.rs +++ b/asusctl/examples/anime-outline.rs @@ -1,11 +1,11 @@ use rog_anime::AnimeDataBuffer; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; // In usable data: // Top row start at 1, ends at 32 fn main() { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let mut matrix = AnimeDataBuffer::new(); matrix.get_mut()[1] = 100; // start = 1 for n in matrix.get_mut()[2..32].iter_mut() { diff --git a/asusctl/examples/anime-png.rs b/asusctl/examples/anime-png.rs index e54e28fc..126ee978 100644 --- a/asusctl/examples/anime-png.rs +++ b/asusctl/examples/anime-png.rs @@ -3,10 +3,10 @@ use std::{env, error::Error, path::Path, process::exit}; use rog_anime::{ AnimeDataBuffer, {AnimeImage, Vec2}, }; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let args: Vec = env::args().into_iter().collect(); if args.len() != 7 { diff --git a/asusctl/examples/anime-spinning.rs b/asusctl/examples/anime-spinning.rs index aa59fadf..8bc2c965 100644 --- a/asusctl/examples/anime-spinning.rs +++ b/asusctl/examples/anime-spinning.rs @@ -5,10 +5,10 @@ use std::{ use rog_anime::{ AnimeDataBuffer, {AnimeImage, Vec2}, }; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let args: Vec = env::args().into_iter().collect(); if args.len() != 7 { diff --git a/asusctl/examples/aura-rgb-ball.rs b/asusctl/examples/aura-rgb-ball.rs index 22dbd604..d7c21235 100644 --- a/asusctl/examples/aura-rgb-ball.rs +++ b/asusctl/examples/aura-rgb-ball.rs @@ -1,5 +1,5 @@ use rog_aura::{GX502Layout, Key, KeyColourArray, KeyLayout}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; use std::collections::LinkedList; #[derive(Debug, Clone)] @@ -52,7 +52,7 @@ impl Ball { } fn main() -> Result<(), Box> { - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; let mut colours = KeyColourArray::new(); diff --git a/asusctl/examples/aura-rgb-comet.rs b/asusctl/examples/aura-rgb-comet.rs index 72b109bb..e6444ab2 100644 --- a/asusctl/examples/aura-rgb-comet.rs +++ b/asusctl/examples/aura-rgb-comet.rs @@ -1,8 +1,8 @@ use rog_aura::{GX502Layout, KeyColourArray, KeyLayout}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; let layout = GX502Layout::default(); diff --git a/asusctl/examples/aura-rgb-iterate-keys.rs b/asusctl/examples/aura-rgb-iterate-keys.rs index 7ab9376f..8bf3b929 100644 --- a/asusctl/examples/aura-rgb-iterate-keys.rs +++ b/asusctl/examples/aura-rgb-iterate-keys.rs @@ -1,8 +1,8 @@ use rog_aura::{GX502Layout, Key, KeyColourArray, KeyLayout}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; let mut key_colours = KeyColourArray::new(); let layout = GX502Layout::default(); diff --git a/asusctl/examples/aura-rgb-per-key-effect-2.rs b/asusctl/examples/aura-rgb-per-key-effect-2.rs index bbbb1e3f..38957237 100644 --- a/asusctl/examples/aura-rgb-per-key-effect-2.rs +++ b/asusctl/examples/aura-rgb-per-key-effect-2.rs @@ -1,8 +1,8 @@ use rog_aura::{Key, KeyColourArray}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; let mut key_colours = KeyColourArray::new(); diff --git a/asusctl/examples/aura-rgb-pulser.rs b/asusctl/examples/aura-rgb-pulser.rs index 354864c7..d68faf9e 100644 --- a/asusctl/examples/aura-rgb-pulser.rs +++ b/asusctl/examples/aura-rgb-pulser.rs @@ -1,8 +1,8 @@ use rog_aura::{GX502Layout, KeyColourArray, KeyLayout}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; fn main() -> Result<(), Box> { - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; let mut key_colours = KeyColourArray::new(); let layout = GX502Layout::default(); diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 0b236492..c97f7d58 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -1,15 +1,17 @@ mod anime_cli; mod aura_cli; +mod profiles_cli; use crate::aura_cli::{LedBrightness, SetAuraBuiltin}; use anime_cli::{AnimeActions, AnimeCommand}; use gumdrop::{Opt, Options}; +use profiles_cli::ProfileCommand; use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN}; use rog_aura::{self, AuraEffect}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; +use rog_profiles::profiles::Profile; use rog_types::{ gfx_vendors::GfxVendors, - profile::{FanLevel, ProfileCommand, ProfileEvent}, supported::{ FanCpuSupportedFunctions, LedSupportedFunctions, RogBiosSupportedFunctions, SupportedFunctions, @@ -29,11 +31,6 @@ struct CliStart { show_supported: bool, #[options(meta = "", help = "")] kbd_bright: Option, - #[options( - meta = "", - help = ", set fan mode independent of profile" - )] - fan_mode: Option, #[options(meta = "", help = "<20-100>")] chg_limit: Option, #[options(command)] @@ -132,10 +129,9 @@ fn main() -> Result<(), Box> { } } - let (dbus, _) = AuraDbusClient::new()?; + let (dbus, _) = RogDbusClient::new()?; - let supported_tmp = dbus.proxies().supported().get_supported_functions()?; - let supported = serde_json::from_str::(&supported_tmp)?; + let supported = dbus.proxies().supported().get_supported_functions()?; if parsed.help { print_supported_help(&supported, &parsed); @@ -147,7 +143,6 @@ fn main() -> Result<(), Box> { println!(" asusctl v{}", env!("CARGO_PKG_VERSION")); println!(" rog-dbus v{}", rog_dbus::VERSION); println!("rog-types v{}", rog_types::VERSION); - println!(" daemon v{}", daemon::VERSION); return Ok(()); } @@ -203,10 +198,7 @@ fn main() -> Result<(), Box> { } Some(CliCommand::Bios(cmd)) => handle_bios_option(&dbus, &supported.rog_bios_ctrl, &cmd)?, None => { - if (!parsed.show_supported - && parsed.kbd_bright.is_none() - && parsed.fan_mode.is_none() - && parsed.chg_limit.is_none()) + if (!parsed.show_supported && parsed.kbd_bright.is_none() && parsed.chg_limit.is_none()) || parsed.help { println!("{}", CliStart::usage()); @@ -231,15 +223,13 @@ fn main() -> Result<(), Box> { if parsed.show_supported { let dat = dbus.proxies().supported().get_supported_functions()?; - println!("Supported laptop functions:\n{}", dat); + println!("Supported laptop functions:\n{:?}", dat); } - if let Some(fan_level) = parsed.fan_mode { - dbus.proxies().profile().write_fan_mode(fan_level.into())?; - } if let Some(chg_limit) = parsed.chg_limit { dbus.proxies().charge().write_limit(chg_limit)?; } + Ok(()) } @@ -269,7 +259,7 @@ fn print_supported_help(supported: &SupportedFunctions, parsed: &CliStart) { { return false; } - if line.contains("led-mode") && supported.keyboard_led.stock_led_modes.is_none() { + if line.contains("led-mode") && !supported.keyboard_led.stock_led_modes.is_empty() { return false; } if line.contains("bios") @@ -295,7 +285,7 @@ fn print_supported_help(supported: &SupportedFunctions, parsed: &CliStart) { } fn do_gfx( - dbus: &AuraDbusClient, + dbus: &RogDbusClient, supported: &RogBiosSupportedFunctions, command: GraphicsCommand, ) -> Result<(), Box> { @@ -341,7 +331,7 @@ fn do_gfx( } fn handle_led_mode( - dbus: &AuraDbusClient, + dbus: &RogDbusClient, supported: &LedSupportedFunctions, mode: &LedModeCommand, ) -> Result<(), Box> { @@ -363,11 +353,9 @@ fn handle_led_mode( .map(|s| s.to_string()) .collect(); for command in commands.iter().filter(|command| { - if let Some(modes) = supported.stock_led_modes.as_ref() { - for mode in modes { - if command.contains(&(<&str>::from(mode)).to_lowercase()) { - return true; - } + for mode in &supported.stock_led_modes { + if command.contains(<&str>::from(mode)) { + return true; } } if supported.multizone_led_mode { @@ -421,7 +409,7 @@ fn handle_led_mode( } fn handle_profile( - dbus: &AuraDbusClient, + dbus: &RogDbusClient, supported: &FanCpuSupportedFunctions, cmd: &ProfileCommand, ) -> Result<(), Box> { @@ -476,14 +464,12 @@ fn handle_profile( if cmd.active_name { println!( "Active profile: {:?}", - dbus.proxies().profile().active_profile_name()? + dbus.proxies().profile().active_name()? ); } if cmd.active_data { println!("Active profile:"); - for s in dbus.proxies().profile().active_profile_data()?.lines() { - println!("{}", s); - } + println!("{:?}", dbus.proxies().profile().active_data()?); } if cmd.profiles_data { println!("Profiles:"); @@ -492,41 +478,48 @@ fn handle_profile( } } - // This must come before the next block of actions so that changing a specific - // profile can be done - if cmd.profile.is_some() { - dbus.proxies() - .profile() - .write_command(&ProfileEvent::Cli(cmd.clone()))?; - return Ok(()); + let mut set_profile = false; + let mut profile; + if cmd.create { + profile = Profile::default(); + set_profile = true; + } else { + profile = dbus.proxies().profile().active_data()?; } if let Some(turbo) = cmd.turbo { - dbus.proxies().profile().set_turbo(turbo)?; + set_profile = true; + profile.turbo = turbo; } - if let Some(min) = cmd.min_percentage { - dbus.proxies().profile().set_min_frequency(min)?; + set_profile = true; + profile.min_percentage = min; } - if let Some(max) = cmd.max_percentage { - dbus.proxies().profile().set_max_frequency(max)?; + set_profile = true; + profile.max_percentage = max; } - - if let Some(ref preset) = cmd.fan_preset { - dbus.proxies().profile().set_fan_preset(preset.into())?; + if let Some(preset) = cmd.fan_preset { + set_profile = true; + profile.fan_preset = preset; } - if let Some(ref curve) = cmd.curve { - let s = curve.as_config_string(); - dbus.proxies().profile().set_fan_curve(&s)?; + set_profile = true; + profile.fan_curve = curve.as_config_string(); + } + if let Some(ref name) = cmd.profile { + set_profile = true; + profile.name = name.clone(); + } + if set_profile { + dbus.proxies().profile().new_or_modify(&profile)?; } Ok(()) } fn handle_bios_option( - dbus: &AuraDbusClient, + dbus: &RogDbusClient, supported: &RogBiosSupportedFunctions, cmd: &BiosCommand, ) -> Result<(), Box> { @@ -545,8 +538,8 @@ fn handle_bios_option( .collect(); for line in usage.iter().filter(|line| { - !(line.contains("sound") && !supported.post_sound_toggle) - || !(line.contains("GPU") && !supported.dedicated_gfx_toggle) + !line.contains("sound") && !supported.post_sound_toggle + || !line.contains("GPU") && !supported.dedicated_gfx_toggle }) { println!("{}", line); } diff --git a/asusctl/src/profiles_cli.rs b/asusctl/src/profiles_cli.rs new file mode 100644 index 00000000..ada243f1 --- /dev/null +++ b/asusctl/src/profiles_cli.rs @@ -0,0 +1,53 @@ +use gumdrop::Options; +use rog_fan_curve::{Curve, Fan}; +use rog_profiles::profiles::FanLevel; + +#[derive(Debug, Clone, Options)] +pub struct ProfileCommand { + #[options(help = "print help message")] + pub help: bool, + #[options(help = "toggle to next profile in list")] + pub next: bool, + #[options(help = "create the profile if it doesn't exist")] + pub create: bool, + #[options(meta = "", help = "remove a profile by name")] + pub remove: Option, + #[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, + + // Options for profile + #[options(meta = "", help = "enable or disable cpu turbo")] + pub turbo: Option, + #[options(meta = "", help = "set min cpu scaling (intel)")] + pub min_percentage: Option, + #[options(meta = "", help = "set max cpu scaling (intel)")] + pub max_percentage: Option, + + #[options(meta = "", help = "")] + pub fan_preset: Option, + #[options( + meta = "", + parse(try_from_str = "parse_fan_curve"), + help = "set fan curve" + )] + pub curve: Option, + #[options(free)] + pub profile: Option, +} + +fn parse_fan_curve(data: &str) -> Result { + let curve = Curve::from_config_str(data)?; + if let Err(err) = curve.check_safety(Fan::Cpu) { + return Err(format!("Unsafe curve {:?}", err)); + } + if let Err(err) = curve.check_safety(Fan::Gpu) { + return Err(format!("Unsafe curve {:?}", err)); + } + Ok(curve) +} diff --git a/daemon-user/src/ctrl_anime.rs b/daemon-user/src/ctrl_anime.rs index 36699cca..283ea5a7 100644 --- a/daemon-user/src/ctrl_anime.rs +++ b/daemon-user/src/ctrl_anime.rs @@ -1,5 +1,5 @@ use rog_anime::{ActionData, AnimTime, AnimeAction, Sequences, Vec2}; -use rog_dbus::AuraDbusClient; +use rog_dbus::RogDbusClient; //use crate::dbus::DbusEvents; use serde_derive::{Deserialize, Serialize}; use std::time::Duration; @@ -28,14 +28,14 @@ pub enum TimeType { /// and a zbus server behind `Arc>` pub struct CtrlAnimeInner<'a> { sequences: Sequences, - client: AuraDbusClient<'a>, + client: RogDbusClient<'a>, do_early_return: &'a AtomicBool, } impl<'a> CtrlAnimeInner<'static> { pub fn new( sequences: Sequences, - client: AuraDbusClient<'static>, + client: RogDbusClient<'static>, do_early_return: &'static AtomicBool, ) -> Result { Ok(Self { @@ -112,7 +112,7 @@ impl<'a> CtrlAnimeInner<'static> { pub struct CtrlAnime<'a> { config: Arc>, - client: AuraDbusClient<'a>, + client: RogDbusClient<'a>, inner: Arc>>, /// Must be the same Atomic as in CtrlAnimeInner inner_early_return: &'a AtomicBool, @@ -122,13 +122,13 @@ impl<'a> CtrlAnime<'static> { pub fn new( config: Arc>, inner: Arc>>, - client: AuraDbusClient<'static>, + client: RogDbusClient<'static>, inner_early_return: &'static AtomicBool, ) -> Result { Ok(CtrlAnime { config, - inner, client, + inner, inner_early_return, }) } @@ -180,7 +180,10 @@ impl CtrlAnime<'static> { self.inner_early_return.store(true, Ordering::SeqCst); if let Ok(mut controller) = self.inner.lock() { - controller.sequences.insert(index as usize, &action)?; + controller + .sequences + .insert(index as usize, &action) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; } config.anime.push(action); config.write()?; @@ -227,7 +230,10 @@ impl CtrlAnime<'static> { self.inner_early_return.store(true, Ordering::SeqCst); if let Ok(mut controller) = self.inner.lock() { - controller.sequences.insert(index as usize, &action)?; + controller + .sequences + .insert(index as usize, &action) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; } config.anime.push(action); config.write()?; @@ -265,7 +271,10 @@ impl CtrlAnime<'static> { self.inner_early_return.store(true, Ordering::SeqCst); if let Ok(mut controller) = self.inner.lock() { - controller.sequences.insert(index as usize, &action)?; + controller + .sequences + .insert(index as usize, &action) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; } config.anime.push(action); config.write()?; @@ -287,7 +296,10 @@ impl CtrlAnime<'static> { self.inner_early_return.store(true, Ordering::SeqCst); if let Ok(mut controller) = self.inner.lock() { - controller.sequences.insert(index as usize, &action)?; + controller + .sequences + .insert(index as usize, &action) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; } config.anime.push(action); config.write()?; diff --git a/daemon-user/src/daemon.rs b/daemon-user/src/daemon.rs index bb792a5d..9ee58a12 100644 --- a/daemon-user/src/daemon.rs +++ b/daemon-user/src/daemon.rs @@ -1,5 +1,4 @@ -use rog_dbus::AuraDbusClient; -use rog_types::supported::SupportedFunctions; +use rog_dbus::RogDbusClient; use rog_user::{ ctrl_anime::{CtrlAnime, CtrlAnimeInner}, user_config::*, @@ -16,13 +15,13 @@ use std::sync::atomic::AtomicBool; static ANIME_INNER_EARLY_RETURN: AtomicBool = AtomicBool::new(false); fn main() -> Result<(), Box> { - println!("user daemon v{}", rog_user::VERSION); - println!(" rog-anime v{}", rog_anime::VERSION); - println!(" rog-dbus v{}", rog_dbus::VERSION); + println!(" user daemon v{}", rog_user::VERSION); + println!(" rog-anime v{}", rog_anime::VERSION); + println!(" rog-dbus v{}", rog_dbus::VERSION); + println!(" rog-types v{}", rog_types::VERSION); - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let supported = client.proxies().supported().get_supported_functions()?; - let supported = serde_json::from_str::(&&supported).unwrap(); let mut config = UserConfig::new(); config.load_config()?; @@ -47,7 +46,7 @@ fn main() -> Result<(), Box> { &ANIME_INNER_EARLY_RETURN, )?)); // Need new client object for dbus control part - let (client, _) = AuraDbusClient::new().unwrap(); + let (client, _) = RogDbusClient::new().unwrap(); let anime_control = CtrlAnime::new( anime_config, inner.clone(), diff --git a/daemon-user/src/lib.rs b/daemon-user/src/lib.rs index eeb96c2a..1a3d3d24 100644 --- a/daemon-user/src/lib.rs +++ b/daemon-user/src/lib.rs @@ -8,4 +8,4 @@ pub mod zbus_anime; pub static DBUS_NAME: &str = "org.asuslinux.Daemon"; -pub static VERSION: &str = env!("CARGO_PKG_VERSION"); \ No newline at end of file +pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/daemon-user/src/user_config.rs b/daemon-user/src/user_config.rs index 4bb08e71..b2cce2cd 100644 --- a/daemon-user/src/user_config.rs +++ b/daemon-user/src/user_config.rs @@ -75,7 +75,10 @@ impl UserAnimeConfig { if let Ok(read_len) = file.read_to_string(&mut buf) { if read_len == 0 { - let default = UserAnimeConfig { name, ..Default::default() }; + let default = UserAnimeConfig { + name, + ..Default::default() + }; let json = serde_json::to_string_pretty(&default).unwrap(); file.write_all(json.as_bytes())?; return Ok(default); diff --git a/daemon-user/src/zbus_anime.rs b/daemon-user/src/zbus_anime.rs index ec497f79..6a22aa9c 100644 --- a/daemon-user/src/zbus_anime.rs +++ b/daemon-user/src/zbus_anime.rs @@ -18,6 +18,7 @@ //! * [`zbus::fdo::PropertiesProxy`] //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. +#![allow(clippy::too_many_arguments)] use zbus::dbus_proxy; diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index 7759537d..d8bab45d 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "daemon" -version = "3.5.2" +version = "3.6.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] @@ -21,6 +21,7 @@ path = "src/daemon.rs" rog_anime = { path = "../rog-anime" } rog_aura = { path = "../rog-aura" } rog_types = { path = "../rog-types" } +rog_profiles = { path = "../rog-profiles" } rog_dbus = { path = "../rog-dbus" } rusb = "^0.8" udev = "^0.6" @@ -31,6 +32,7 @@ env_logger = "^0.8" zbus = "^1.9.1" zvariant = "^2.6" +zvariant_derive = { version = "^2.6" } logind-zbus = "^0.7.1" # serialisation @@ -42,5 +44,3 @@ toml = "^0.5" # Device control sysfs-class = "^0.1.2" # used for backlight control and baord ID rog_fan_curve = { version = "0.1", features = ["serde"] } -# cpu power management -intel-pstate = "^0.2" \ No newline at end of file diff --git a/daemon/src/config.rs b/daemon/src/config.rs index 93e98e25..a1792353 100644 --- a/daemon/src/config.rs +++ b/daemon/src/config.rs @@ -1,5 +1,6 @@ use log::{error, info, warn}; -use rog_types::{gfx_vendors::GfxVendors, profile::Profile}; +use rog_profiles::profiles::{FanLevel, Profile}; +use rog_types::gfx_vendors::GfxVendors; use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fs::{File, OpenOptions}; @@ -30,9 +31,39 @@ pub struct Config { impl Default for Config { fn default() -> Self { let mut pwr = BTreeMap::new(); - pwr.insert("normal".into(), Profile::new(0, 100, true, 0, None)); - pwr.insert("boost".into(), Profile::new(0, 100, true, 1, None)); - pwr.insert("silent".into(), Profile::new(0, 100, true, 2, None)); + pwr.insert( + "normal".into(), + Profile::new( + "normal".into(), + 0, + 100, + true, + FanLevel::Normal, + "".to_string(), + ), + ); + pwr.insert( + "boost".into(), + Profile::new( + "boost".into(), + 0, + 100, + true, + FanLevel::Boost, + "".to_string(), + ), + ); + pwr.insert( + "silent".into(), + Profile::new( + "silent".into(), + 0, + 100, + true, + FanLevel::Silent, + "".to_string(), + ), + ); Config { gfx_mode: GfxVendors::Hybrid, diff --git a/daemon/src/config_anime.rs b/daemon/src/config_anime.rs index 176d8fc8..487827ab 100644 --- a/daemon/src/config_anime.rs +++ b/daemon/src/config_anime.rs @@ -41,6 +41,31 @@ impl AnimeConfigV341 { vec![] }, brightness: 1.0, + awake_enabled: true, + boot_anim_enabled: true, + } + } +} + +#[derive(Deserialize, Serialize)] +pub struct AnimeConfigV352 { + pub system: Vec, + pub boot: Vec, + pub wake: Vec, + pub shutdown: Vec, + pub brightness: f32, +} + +impl AnimeConfigV352 { + pub(crate) fn into_current(self) -> AnimeConfig { + AnimeConfig { + system: self.system, + boot: self.boot, + wake: self.wake, + shutdown: self.shutdown, + brightness: 1.0, + awake_enabled: true, + boot_anim_enabled: true, } } } @@ -90,6 +115,8 @@ pub struct AnimeConfig { pub wake: Vec, pub shutdown: Vec, pub brightness: f32, + pub awake_enabled: bool, + pub boot_anim_enabled: bool, } impl Default for AnimeConfig { @@ -100,6 +127,8 @@ impl Default for AnimeConfig { wake: Vec::new(), shutdown: Vec::new(), brightness: 1.0, + awake_enabled: true, + boot_anim_enabled: true, } } } @@ -130,6 +159,11 @@ impl AnimeConfig { config.write(); info!("Updated config version to: {}", VERSION); return config; + } else if let Ok(data) = serde_json::from_str::(&buf) { + let config = data.into_current(); + config.write(); + info!("Updated config version to: {}", VERSION); + return config; } warn!("Could not deserialise {}", ANIME_CONFIG_PATH); panic!("Please remove {} then restart asusd", ANIME_CONFIG_PATH); @@ -167,6 +201,8 @@ impl AnimeConfig { time: AnimTime::Infinite, }], brightness: 1.0, + awake_enabled: true, + boot_anim_enabled: true, }; // Should be okay to unwrap this as is since it is a Default let json = serde_json::to_string_pretty(&config).unwrap(); diff --git a/daemon/src/config_aura.rs b/daemon/src/config_aura.rs index 46920465..d60b2809 100644 --- a/daemon/src/config_aura.rs +++ b/daemon/src/config_aura.rs @@ -23,6 +23,29 @@ impl AuraConfigV320 { current_mode: self.current_mode, builtins: self.builtins, multizone: self.multizone, + awake_enabled: true, + sleep_anim_enabled: true, + } + } +} + +#[derive(Deserialize, Serialize)] +pub struct AuraConfigV352 { + pub brightness: LedBrightness, + pub current_mode: AuraModeNum, + pub builtins: BTreeMap, + pub multizone: Option, +} + +impl AuraConfigV352 { + pub(crate) fn into_current(self) -> AuraConfig { + AuraConfig { + brightness: self.brightness, + current_mode: self.current_mode, + builtins: self.builtins, + multizone: self.multizone, + awake_enabled: true, + sleep_anim_enabled: true, } } } @@ -33,6 +56,8 @@ pub struct AuraConfig { pub current_mode: AuraModeNum, pub builtins: BTreeMap, pub multizone: Option, + pub awake_enabled: bool, + pub sleep_anim_enabled: bool, } impl Default for AuraConfig { @@ -42,6 +67,8 @@ impl Default for AuraConfig { current_mode: AuraModeNum::Static, builtins: BTreeMap::new(), multizone: None, + awake_enabled: true, + sleep_anim_enabled: true, } } } @@ -72,6 +99,11 @@ impl AuraConfig { config.write(); info!("Updated AuraConfig version"); return config; + } else if let Ok(data) = serde_json::from_str::(&buf) { + let config = data.into_current(); + config.write(); + info!("Updated AuraConfig version"); + return config; } warn!("Could not deserialise {}", AURA_CONFIG_PATH); panic!("Please remove {} then restart asusd", AURA_CONFIG_PATH); diff --git a/daemon/src/config_old.rs b/daemon/src/config_old.rs index 4ea03830..0fdcbe1e 100644 --- a/daemon/src/config_old.rs +++ b/daemon/src/config_old.rs @@ -1,11 +1,13 @@ -use rog_types::{gfx_vendors::GfxVendors, profile::Profile}; +use rog_fan_curve::Curve; +use rog_profiles::profiles::Profile; +use rog_types::gfx_vendors::GfxVendors; use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeMap; use crate::config::Config; /// for parsing old v3.1.7 config -#[derive(Deserialize, Serialize)] +#[derive(Deserialize)] pub(crate) struct ConfigV317 { pub gfx_mode: GfxVendors, pub gfx_managed: bool, @@ -18,7 +20,7 @@ pub(crate) struct ConfigV317 { pub kbd_backlight_mode: u8, #[serde(skip)] pub kbd_backlight_modes: Option, - pub power_profiles: BTreeMap, + pub power_profiles: BTreeMap, } impl ConfigV317 { @@ -32,7 +34,7 @@ impl ConfigV317 { toggle_profiles: self.toggle_profiles, curr_fan_mode: self.curr_fan_mode, bat_charge_limit: self.bat_charge_limit, - power_profiles: self.power_profiles, + power_profiles: ProfileV317::transform_map(self.power_profiles), } } } @@ -46,7 +48,7 @@ pub struct ConfigV324 { #[serde(skip)] pub curr_fan_mode: u8, pub bat_charge_limit: u8, - pub power_profiles: BTreeMap, + pub power_profiles: BTreeMap, } impl ConfigV324 { @@ -60,7 +62,7 @@ impl ConfigV324 { toggle_profiles: self.toggle_profiles, curr_fan_mode: self.curr_fan_mode, bat_charge_limit: self.bat_charge_limit, - power_profiles: self.power_profiles, + power_profiles: ProfileV317::transform_map(self.power_profiles), } } } @@ -75,7 +77,7 @@ pub struct ConfigV341 { #[serde(skip)] pub curr_fan_mode: u8, pub bat_charge_limit: u8, - pub power_profiles: BTreeMap, + pub power_profiles: BTreeMap, } impl ConfigV341 { @@ -89,12 +91,11 @@ impl ConfigV341 { toggle_profiles: self.toggle_profiles, curr_fan_mode: self.curr_fan_mode, bat_charge_limit: self.bat_charge_limit, - power_profiles: self.power_profiles, + power_profiles: ProfileV317::transform_map(self.power_profiles), } } } - #[derive(Deserialize, Serialize)] pub struct ConfigV352 { pub gfx_mode: GfxVendors, @@ -107,7 +108,7 @@ pub struct ConfigV352 { #[serde(skip)] pub curr_fan_mode: u8, pub bat_charge_limit: u8, - pub power_profiles: BTreeMap, + pub power_profiles: BTreeMap, } impl ConfigV352 { @@ -121,7 +122,39 @@ impl ConfigV352 { toggle_profiles: self.toggle_profiles, curr_fan_mode: self.curr_fan_mode, bat_charge_limit: self.bat_charge_limit, - power_profiles: self.power_profiles, + power_profiles: ProfileV317::transform_map(self.power_profiles), } } -} \ No newline at end of file +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct ProfileV317 { + pub min_percentage: u8, + pub max_percentage: u8, + pub turbo: bool, + pub fan_preset: u8, + pub fan_curve: Option, +} + +impl ProfileV317 { + fn into_current(self, name: String) -> Profile { + Profile { + name, + min_percentage: self.min_percentage, + max_percentage: self.max_percentage, + turbo: self.turbo, + fan_preset: self.fan_preset.into(), + fan_curve: self + .fan_curve + .map_or_else(|| "".to_string(), |c| c.as_config_string()), + } + } + + fn transform_map(map: BTreeMap) -> BTreeMap { + let mut new_map = BTreeMap::new(); + map.iter().for_each(|(k, v)| { + new_map.insert(k.to_string(), v.clone().into_current(k.to_string())); + }); + new_map + } +} diff --git a/daemon/src/ctrl_anime.rs b/daemon/src/ctrl_anime.rs index 58904394..40bee1f5 100644 --- a/daemon/src/ctrl_anime.rs +++ b/daemon/src/ctrl_anime.rs @@ -5,7 +5,7 @@ use rog_anime::{ pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID, VENDOR_ID, }, - ActionData, AnimTime, AnimeDataBuffer, AnimePacketType, ANIME_DATA_LEN, + ActionData, AnimTime, AnimeDataBuffer, AnimePacketType, AnimePowerStates, ANIME_DATA_LEN, }; use rog_types::supported::AnimeSupportedFunctions; use rusb::{Device, DeviceHandle}; @@ -333,6 +333,11 @@ pub struct CtrlAnimeReloader(pub Arc>); impl crate::Reloadable for CtrlAnimeReloader { fn reload(&mut self) -> Result<(), RogError> { if let Ok(lock) = self.0.try_lock() { + lock.write_bytes(&pkt_for_set_on(lock.config.awake_enabled)); + lock.write_bytes(&pkt_for_apply()); + lock.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled)); + lock.write_bytes(&pkt_for_apply()); + let action = lock.cache.boot.clone(); CtrlAnime::run_thread(self.0.clone(), action, true); } @@ -392,8 +397,17 @@ impl CtrlAnimeZbus { fn set_on_off(&self, status: bool) { 'outer: loop { - if let Ok(lock) = self.0.try_lock() { + if let Ok(mut lock) = self.0.try_lock() { lock.write_bytes(&pkt_for_set_on(status)); + lock.config.awake_enabled = status; + lock.config.write(); + + let states = AnimePowerStates { + enabled: lock.config.awake_enabled, + boot_anim_enabled: lock.config.boot_anim_enabled, + }; + self.notify_power_states(&states) + .unwrap_or_else(|err| warn!("{}", err)); break 'outer; } } @@ -401,9 +415,18 @@ impl CtrlAnimeZbus { fn set_boot_on_off(&self, on: bool) { 'outer: loop { - if let Ok(lock) = self.0.try_lock() { + if let Ok(mut lock) = self.0.try_lock() { lock.write_bytes(&pkt_for_set_boot(on)); lock.write_bytes(&pkt_for_apply()); + lock.config.boot_anim_enabled = on; + lock.config.write(); + + let states = AnimePowerStates { + enabled: lock.config.awake_enabled, + boot_anim_enabled: lock.config.boot_anim_enabled, + }; + self.notify_power_states(&states) + .unwrap_or_else(|err| warn!("{}", err)); break 'outer; } } @@ -422,4 +445,23 @@ impl CtrlAnimeZbus { } } } + + #[dbus_interface(property)] + fn awake_enabled(&self) -> bool { + if let Ok(ctrl) = self.0.try_lock() { + return ctrl.config.awake_enabled; + } + true + } + + #[dbus_interface(property)] + fn boot_enabled(&self) -> bool { + if let Ok(ctrl) = self.0.try_lock() { + return ctrl.config.boot_anim_enabled; + } + true + } + + #[dbus_interface(signal)] + fn notify_power_states(&self, data: &AnimePowerStates) -> zbus::Result<()>; } diff --git a/daemon/src/ctrl_gfx/controller.rs b/daemon/src/ctrl_gfx/controller.rs index b7263f9b..b24504df 100644 --- a/daemon/src/ctrl_gfx/controller.rs +++ b/daemon/src/ctrl_gfx/controller.rs @@ -120,7 +120,7 @@ impl CtrlGraphics { pub fn get_gfx_mode(&self) -> Result { if let Ok(config) = self.config.lock() { if let Some(mode) = config.gfx_tmp_mode { - return Ok(mode); + return Ok(mode); } return Ok(config.gfx_mode); } diff --git a/daemon/src/ctrl_gfx/zbus_gfx.rs b/daemon/src/ctrl_gfx/zbus_gfx.rs index 94391cbd..53dd403b 100644 --- a/daemon/src/ctrl_gfx/zbus_gfx.rs +++ b/daemon/src/ctrl_gfx/zbus_gfx.rs @@ -1,7 +1,7 @@ +use ::zbus::dbus_interface; +use log::{error, info, warn}; use rog_types::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; -use ::zbus::{dbus_interface}; use zvariant::ObjectPath; -use log::{error, warn, info}; use crate::ZbusAdd; @@ -53,4 +53,4 @@ impl ZbusAdd for CtrlGraphics { }) .ok(); } -} \ No newline at end of file +} diff --git a/daemon/src/ctrl_leds.rs b/daemon/src/ctrl_leds/controller.rs similarity index 63% rename from daemon/src/ctrl_leds.rs rename to daemon/src/ctrl_leds/controller.rs index 0f780d49..13bb23d6 100644 --- a/daemon/src/ctrl_leds.rs +++ b/daemon/src/ctrl_leds/controller.rs @@ -6,9 +6,12 @@ use crate::{ error::RogError, laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES}, }; -use log::{error, info, warn}; +use log::{info, warn}; use rog_aura::{ - usb::{LED_APPLY, LED_AWAKE_OFF, LED_AWAKE_ON, LED_SET, LED_SLEEP_OFF, LED_SLEEP_ON}, + usb::{ + LED_APPLY, LED_AWAKE_OFF_SLEEP_OFF, LED_AWAKE_OFF_SLEEP_ON, LED_AWAKE_ON_SLEEP_OFF, + LED_AWAKE_ON_SLEEP_ON, LED_SET, + }, AuraEffect, LedBrightness, LED_MSG_LEN, }; use rog_types::supported::LedSupportedFunctions; @@ -17,8 +20,6 @@ use std::io::{Read, Write}; use std::path::Path; use std::sync::Arc; use std::sync::Mutex; -use zbus::dbus_interface; -use zvariant::ObjectPath; use crate::GetSupported; @@ -30,11 +31,7 @@ impl GetSupported for CtrlKbdLed { let multizone_led_mode = false; let per_key_led_mode = false; let laptop = LaptopLedData::get_data(); - let stock_led_modes = if laptop.standard.is_empty() { - None - } else { - Some(laptop.standard) - }; + let stock_led_modes = laptop.standard; LedSupportedFunctions { brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(), @@ -46,11 +43,11 @@ impl GetSupported for CtrlKbdLed { } pub struct CtrlKbdLed { - led_node: Option, + pub led_node: Option, pub bright_node: String, - supported_modes: LaptopLedData, - flip_effect_write: bool, - config: AuraConfig, + pub supported_modes: LaptopLedData, + pub flip_effect_write: bool, + pub config: AuraConfig, } pub struct CtrlKbdLedTask(pub Arc>); @@ -88,151 +85,28 @@ pub struct CtrlKbdLedReloader(pub Arc>); impl crate::Reloadable for CtrlKbdLedReloader { fn reload(&mut self) -> Result<(), RogError> { - if let Ok(mut lock) = self.0.try_lock() { - let current = lock.config.current_mode; - if let Some(mode) = lock.config.builtins.get(¤t).cloned() { - lock.do_command(mode).ok(); + if let Ok(mut ctrl) = self.0.try_lock() { + let current = ctrl.config.current_mode; + if let Some(mode) = ctrl.config.builtins.get(¤t).cloned() { + ctrl.do_command(mode).ok(); } + + ctrl.set_states_enabled(ctrl.config.awake_enabled, ctrl.config.sleep_anim_enabled) + .map_err(|err| warn!("{}", err)) + .ok(); } Ok(()) } } -pub struct CtrlKbdLedZbus { - inner: Arc>, -} +pub struct CtrlKbdLedZbus(pub Arc>); impl CtrlKbdLedZbus { pub fn new(inner: Arc>) -> Self { - Self { inner } + Self(inner) } } -impl crate::ZbusAdd for CtrlKbdLedZbus { - fn add_to_server(self, server: &mut zbus::ObjectServer) { - server - .at(&ObjectPath::from_str_unchecked("/org/asuslinux/Led"), self) - .map_err(|err| { - error!("DbusKbdLed: add_to_server {}", err); - }) - .ok(); - } -} - -/// The main interface for changing, reading, or notfying signals -/// -/// LED commands are split between Brightness, Modes, Per-Key -#[dbus_interface(name = "org.asuslinux.Daemon")] -impl CtrlKbdLedZbus { - /// Set the keyboard brightness level (0-3) - fn set_brightness(&mut self, brightness: LedBrightness) { - if let Ok(ctrl) = self.inner.try_lock() { - ctrl.set_brightness(brightness) - .map_err(|err| warn!("{}", err)) - .ok(); - } - } - - /// Set the keyboard LED to enabled while the device is awake - fn set_awake_enabled(&mut self, enabled: bool) { - if let Ok(ctrl) = self.inner.try_lock() { - ctrl.set_awake_enable(enabled) - .map_err(|err| warn!("{}", err)) - .ok(); - } - } - - /// Set the keyboard LED suspend animation to enabled while the device is suspended - fn set_sleep_enabled(&mut self, enabled: bool) { - if let Ok(ctrl) = self.inner.try_lock() { - ctrl.set_sleep_anim_enable(enabled) - .map_err(|err| warn!("{}", err)) - .ok(); - } - } - - fn set_led_mode(&mut self, effect: AuraEffect) { - if let Ok(mut ctrl) = self.inner.try_lock() { - let mode_name = effect.mode_name(); - match ctrl.do_command(effect) { - Ok(_) => { - self.notify_led(&mode_name).ok(); - } - Err(err) => { - warn!("{}", err); - } - } - } - } - - fn next_led_mode(&self) { - if let Ok(mut ctrl) = self.inner.try_lock() { - ctrl.toggle_mode(false) - .unwrap_or_else(|err| warn!("{}", err)); - - if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { - if let Ok(json) = serde_json::to_string(&mode) { - self.notify_led(&json) - .unwrap_or_else(|err| warn!("{}", err)); - } - } - } - } - - fn prev_led_mode(&self) { - if let Ok(mut ctrl) = self.inner.try_lock() { - ctrl.toggle_mode(true) - .unwrap_or_else(|err| warn!("{}", err)); - - if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { - if let Ok(json) = serde_json::to_string(&mode) { - self.notify_led(&json) - .unwrap_or_else(|err| warn!("{}", err)); - } - } - } - } - - /// Return the current mode data - #[dbus_interface(property)] - fn led_mode(&self) -> String { - if let Ok(ctrl) = self.inner.try_lock() { - if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { - if let Ok(json) = serde_json::to_string(&mode) { - return json; - } - } - } - warn!("SetKeyBacklight could not deserialise"); - "SetKeyBacklight could not deserialise".to_string() - } - - /// Return a list of available modes - #[dbus_interface(property)] - fn led_modes(&self) -> String { - if let Ok(ctrl) = self.inner.try_lock() { - if let Ok(json) = serde_json::to_string(&ctrl.config.builtins) { - return json; - } - } - warn!("SetKeyBacklight could not deserialise"); - "SetKeyBacklight could not serialise".to_string() - } - - /// Return the current LED brightness - #[dbus_interface(property)] - fn led_brightness(&self) -> i8 { - if let Ok(ctrl) = self.inner.try_lock() { - return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1); - } - warn!("SetKeyBacklight could not serialise"); - -1 - } - - #[dbus_interface(signal)] - fn notify_led(&self, data: &str) -> zbus::Result<()>; -} - impl CtrlKbdLed { #[inline] pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result { @@ -280,7 +154,7 @@ impl CtrlKbdLed { None } - fn get_brightness(&self) -> Result { + pub(super) fn get_brightness(&self) -> Result { let mut file = OpenOptions::new() .read(true) .open(&self.bright_node) @@ -296,7 +170,7 @@ impl CtrlKbdLed { Ok(buf[0]) } - fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> { + pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> { let path = Path::new(&self.bright_node); let mut file = OpenOptions::new() @@ -313,19 +187,19 @@ impl CtrlKbdLed { Ok(()) } - /// Set the keyboard LED to active if laptop is awake - fn set_awake_enable(&self, enabled: bool) -> Result<(), RogError> { - let bytes = if enabled { LED_AWAKE_ON } else { LED_AWAKE_OFF }; - self.write_bytes(&bytes)?; - self.write_bytes(&LED_SET)?; - // Changes won't persist unless apply is set - self.write_bytes(&LED_APPLY)?; - Ok(()) - } - - /// Set the keyboard suspend animation to on if plugged in - fn set_sleep_anim_enable(&self, enabled: bool) -> Result<(), RogError> { - let bytes = if enabled { LED_SLEEP_ON } else { LED_SLEEP_OFF }; + /// Set if awake/on LED active, and/or sleep animation active + pub(super) fn set_states_enabled(&self, awake: bool, sleep: bool) -> Result<(), RogError> { + let bytes = if awake && sleep { + LED_AWAKE_ON_SLEEP_ON + } else if awake && !sleep { + LED_AWAKE_ON_SLEEP_OFF + } else if !awake && sleep { + LED_AWAKE_OFF_SLEEP_ON + } else if !awake && !sleep { + LED_AWAKE_OFF_SLEEP_OFF + } else { + LED_AWAKE_ON_SLEEP_ON + }; self.write_bytes(&bytes)?; self.write_bytes(&LED_SET)?; // Changes won't persist unless apply is set @@ -391,7 +265,7 @@ impl CtrlKbdLed { /// Write an effect block #[inline] - fn write_effect(&mut self, effect: &[Vec]) -> Result<(), RogError> { + fn _write_effect(&mut self, effect: &[Vec]) -> Result<(), RogError> { if self.flip_effect_write { for row in effect.iter().rev() { self.write_bytes(row)?; @@ -419,7 +293,7 @@ impl CtrlKbdLed { } #[inline] - fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> { + pub(super) fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> { let current = self.config.current_mode; if let Some(idx) = self .supported_modes diff --git a/daemon/src/ctrl_leds/mod.rs b/daemon/src/ctrl_leds/mod.rs new file mode 100644 index 00000000..65359c9f --- /dev/null +++ b/daemon/src/ctrl_leds/mod.rs @@ -0,0 +1,2 @@ +pub mod controller; +pub mod zbus; diff --git a/daemon/src/ctrl_leds/zbus.rs b/daemon/src/ctrl_leds/zbus.rs new file mode 100644 index 00000000..d96fa095 --- /dev/null +++ b/daemon/src/ctrl_leds/zbus.rs @@ -0,0 +1,165 @@ +use log::{error, warn}; +use rog_aura::{AuraEffect, LedBrightness, LedPowerStates}; +use zbus::dbus_interface; +use zvariant::ObjectPath; + +use super::controller::CtrlKbdLedZbus; + +impl crate::ZbusAdd for CtrlKbdLedZbus { + fn add_to_server(self, server: &mut zbus::ObjectServer) { + server + .at(&ObjectPath::from_str_unchecked("/org/asuslinux/Led"), self) + .map_err(|err| { + error!("DbusKbdLed: add_to_server {}", err); + }) + .ok(); + } +} + +/// The main interface for changing, reading, or notfying signals +/// +/// LED commands are split between Brightness, Modes, Per-Key +#[dbus_interface(name = "org.asuslinux.Daemon")] +impl CtrlKbdLedZbus { + /// Set the keyboard brightness level (0-3) + fn set_brightness(&mut self, brightness: LedBrightness) { + if let Ok(ctrl) = self.0.try_lock() { + ctrl.set_brightness(brightness) + .map_err(|err| warn!("{}", err)) + .ok(); + } + } + + /// Set the keyboard LED to enabled while the device is awake + fn set_awake_enabled(&mut self, enabled: bool) { + if let Ok(mut ctrl) = self.0.try_lock() { + ctrl.set_states_enabled(enabled, ctrl.config.sleep_anim_enabled) + .map_err(|err| warn!("{}", err)) + .ok(); + ctrl.config.awake_enabled = enabled; + ctrl.config.write(); + + let states = LedPowerStates { + enabled: ctrl.config.awake_enabled, + sleep_anim_enabled: ctrl.config.sleep_anim_enabled, + }; + self.notify_power_states(&states) + .unwrap_or_else(|err| warn!("{}", err)); + } + } + + /// Set the keyboard LED suspend animation to enabled while the device is suspended + fn set_sleep_enabled(&mut self, enabled: bool) { + if let Ok(mut ctrl) = self.0.try_lock() { + ctrl.set_states_enabled(ctrl.config.awake_enabled, enabled) + .map_err(|err| warn!("{}", err)) + .ok(); + ctrl.config.sleep_anim_enabled = enabled; + ctrl.config.write(); + let states = LedPowerStates { + enabled: ctrl.config.awake_enabled, + sleep_anim_enabled: ctrl.config.sleep_anim_enabled, + }; + self.notify_power_states(&states) + .unwrap_or_else(|err| warn!("{}", err)); + } + } + + fn set_led_mode(&mut self, effect: AuraEffect) { + if let Ok(mut ctrl) = self.0.try_lock() { + match ctrl.do_command(effect) { + Ok(_) => { + if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { + self.notify_led(mode.clone()) + .unwrap_or_else(|err| warn!("{}", err)); + } + } + Err(err) => { + warn!("{}", err); + } + } + } + } + + fn next_led_mode(&self) { + if let Ok(mut ctrl) = self.0.try_lock() { + ctrl.toggle_mode(false) + .unwrap_or_else(|err| warn!("{}", err)); + + if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { + self.notify_led(mode.clone()) + .unwrap_or_else(|err| warn!("{}", err)); + } + } + } + + fn prev_led_mode(&self) { + if let Ok(mut ctrl) = self.0.try_lock() { + ctrl.toggle_mode(true) + .unwrap_or_else(|err| warn!("{}", err)); + + if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { + self.notify_led(mode.clone()) + .unwrap_or_else(|err| warn!("{}", err)); + } + } + } + + #[dbus_interface(property)] + fn awake_enabled(&self) -> bool { + if let Ok(ctrl) = self.0.try_lock() { + return ctrl.config.awake_enabled; + } + true + } + + #[dbus_interface(property)] + fn sleep_enabled(&self) -> bool { + if let Ok(ctrl) = self.0.try_lock() { + return ctrl.config.sleep_anim_enabled; + } + true + } + + /// Return the current mode data + #[dbus_interface(property)] + fn led_mode(&self) -> String { + if let Ok(ctrl) = self.0.try_lock() { + if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) { + if let Ok(json) = serde_json::to_string(&mode) { + return json; + } + } + } + warn!("SetKeyBacklight could not deserialise"); + "SetKeyBacklight could not deserialise".to_string() + } + + /// Return a list of available modes + #[dbus_interface(property)] + fn led_modes(&self) -> String { + if let Ok(ctrl) = self.0.try_lock() { + if let Ok(json) = serde_json::to_string(&ctrl.config.builtins) { + return json; + } + } + warn!("SetKeyBacklight could not deserialise"); + "SetKeyBacklight could not serialise".to_string() + } + + /// Return the current LED brightness + #[dbus_interface(property)] + fn led_brightness(&self) -> i8 { + if let Ok(ctrl) = self.0.try_lock() { + return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1); + } + warn!("SetKeyBacklight could not serialise"); + -1 + } + + #[dbus_interface(signal)] + fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>; + + #[dbus_interface(signal)] + fn notify_power_states(&self, data: &LedPowerStates) -> zbus::Result<()>; +} diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 640bb409..ab016900 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -1,21 +1,12 @@ use crate::error::RogError; use crate::{config::Config, GetSupported}; -use log::{info, warn}; -use rog_types::{ - profile::{FanLevel, Profile, ProfileEvent}, - supported::FanCpuSupportedFunctions, -}; -use std::fs::OpenOptions; -use std::io::Write; -use std::path::Path; +use log::info; +use rog_profiles::profiles::Profile; +use rog_types::supported::FanCpuSupportedFunctions; use std::sync::Arc; use std::sync::Mutex; -use super::*; - - pub struct CtrlFanAndCpu { - pub path: &'static str, pub config: Arc>, } @@ -24,8 +15,8 @@ impl GetSupported for CtrlFanAndCpu { fn get_supported() -> Self::A { FanCpuSupportedFunctions { - stock_fan_modes: CtrlFanAndCpu::get_fan_path().is_ok(), - min_max_freq: intel_pstate::PState::new().is_ok(), + stock_fan_modes: Profile::get_fan_path().is_ok(), + min_max_freq: Profile::get_intel_supported(), fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(), } } @@ -33,13 +24,12 @@ impl GetSupported for CtrlFanAndCpu { impl crate::Reloadable for CtrlFanAndCpu { fn reload(&mut self) -> Result<(), RogError> { - if let Ok(mut config) = self.config.clone().try_lock() { - let profile = config.active_profile.clone(); - self.set(&profile, &mut config)?; - // info!( - // "Reloaded fan mode: {:?}", - // FanLevel::from(config.power_profile) - // ); + if let Ok(mut cfg) = self.config.clone().try_lock() { + let active = cfg.active_profile.clone(); + if let Some(existing) = cfg.power_profiles.get_mut(&active) { + existing.set_system_all()?; + cfg.write(); + } } Ok(()) } @@ -47,21 +37,9 @@ impl crate::Reloadable for CtrlFanAndCpu { impl CtrlFanAndCpu { pub fn new(config: Arc>) -> Result { - let path = CtrlFanAndCpu::get_fan_path()?; + Profile::get_fan_path()?; info!("Device has thermal throttle control"); - Ok(CtrlFanAndCpu { path, config }) - } - - fn get_fan_path() -> Result<&'static str, RogError> { - if Path::new(FAN_TYPE_1_PATH).exists() { - Ok(FAN_TYPE_1_PATH) - } else if Path::new(FAN_TYPE_2_PATH).exists() { - Ok(FAN_TYPE_2_PATH) - } else { - Err(RogError::MissingFunction( - "Fan mode not available, you may require a v5.8.10 series kernel or newer".into(), - )) - } + Ok(CtrlFanAndCpu { config }) } /// Toggle to next profile in list @@ -84,157 +62,39 @@ impl CtrlFanAndCpu { .unwrap_or(&config.active_profile) .clone(); - self.set(&new_profile, config)?; + self.set_active(&new_profile)?; info!("Profile was changed: {}", &new_profile); Ok(()) } - fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> { - let mode = config.active_profile.clone(); - let mut fan_ctrl = OpenOptions::new() - .write(true) - .open(self.path) - .map_err(|err| RogError::Path(self.path.into(), err))?; - config.read(); - let mut mode_config = config - .power_profiles - .get_mut(&mode) - .ok_or_else(|| RogError::MissingProfile(mode.clone()))?; - config.curr_fan_mode = preset; - mode_config.fan_preset = preset; - config.write(); - fan_ctrl - .write_all(format!("{}\n", preset).as_bytes()) - .map_err(|err| RogError::Write(self.path.into(), err))?; - info!("Fan mode set to: {:?}", FanLevel::from(preset)); - Ok(()) - } + pub(super) fn set_active(&mut self, profile: &str) -> Result<(), RogError> { + if let Ok(mut cfg) = self.config.clone().try_lock() { + cfg.read(); - pub(super) fn handle_profile_event( - &mut self, - event: &ProfileEvent, - config: &mut Config, - ) -> Result<(), RogError> { - match event { - ProfileEvent::Toggle => self.do_next_profile(config)?, - ProfileEvent::ChangeMode(mode) => { - self.set_fan_mode(*mode, config)?; - let mode = config.active_profile.clone(); - self.set_pstate_for_fan_mode(&mode, config)?; - self.set_fan_curve_for_fan_mode(&mode, config)?; - } - ProfileEvent::Cli(command) => { - let profile_key = match command.profile.as_ref() { - Some(k) => k.clone(), - None => config.active_profile.clone(), - }; - - let mut profile = if command.create { - config - .power_profiles - .entry(profile_key.clone()) - .or_insert_with(Profile::default) - } else { - config - .power_profiles - .get_mut(&profile_key) - .ok_or_else(|| RogError::MissingProfile(profile_key.clone()))? - }; - - if command.turbo.is_some() { - profile.turbo = command.turbo.unwrap(); - } - if let Some(min_perc) = command.min_percentage { - profile.min_percentage = min_perc; - } - if let Some(max_perc) = command.max_percentage { - profile.max_percentage = max_perc; - } - if let Some(ref preset) = command.fan_preset { - profile.fan_preset = preset.into(); - } - if let Some(ref curve) = command.curve { - profile.fan_curve = Some(curve.clone()); - } - - self.set(&profile_key, config)?; + if let Some(existing) = cfg.power_profiles.get_mut(profile) { + existing.set_system_all()?; + cfg.active_profile = existing.name.clone(); + cfg.write(); } } Ok(()) } - pub(super) fn set(&mut self, profile: &str, config: &mut Config) -> Result<(), RogError> { - let mode_config = config - .power_profiles - .get(profile) - .ok_or_else(|| RogError::MissingProfile(profile.into()))?; - let mut fan_ctrl = OpenOptions::new() - .write(true) - .open(self.path) - .map_err(|err| RogError::Path(self.path.into(), err))?; - config.curr_fan_mode = mode_config.fan_preset; - fan_ctrl - .write_all(format!("{}\n", mode_config.fan_preset).as_bytes()) - .map_err(|err| RogError::Write(self.path.into(), err))?; + pub(super) fn new_or_modify(&mut self, profile: &Profile) -> Result<(), RogError> { + if let Ok(mut cfg) = self.config.clone().try_lock() { + cfg.read(); - self.set_pstate_for_fan_mode(profile, config)?; - self.set_fan_curve_for_fan_mode(profile, config)?; - - config.active_profile = profile.into(); - - config.write(); - Ok(()) - } - - fn set_pstate_for_fan_mode(&self, mode: &str, config: &mut Config) -> Result<(), RogError> { - info!("Setting pstate"); - let mode_config = config - .power_profiles - .get(mode) - .ok_or_else(|| RogError::MissingProfile(mode.into()))?; - - // Set CPU pstate - if let Ok(pstate) = intel_pstate::PState::new() { - pstate.set_min_perf_pct(mode_config.min_percentage)?; - pstate.set_max_perf_pct(mode_config.max_percentage)?; - pstate.set_no_turbo(!mode_config.turbo)?; - info!( - "Intel CPU Power: min: {}%, max: {}%, turbo: {}", - mode_config.min_percentage, mode_config.max_percentage, mode_config.turbo - ); - } else { - info!("Setting pstate for AMD CPU"); - // must be AMD CPU - let mut file = OpenOptions::new() - .write(true) - .open(AMD_BOOST_PATH) - .map_err(|err| RogError::Path(self.path.into(), err))?; - - let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel - file.write_all(boost.as_bytes()) - .map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?; - info!("AMD CPU Turbo: {}", boost); - } - Ok(()) - } - - fn set_fan_curve_for_fan_mode(&self, mode: &str, config: &Config) -> Result<(), RogError> { - let mode_config = &config - .power_profiles - .get(mode) - .ok_or_else(|| RogError::MissingProfile(mode.into()))?; - - if let Some(ref curve) = mode_config.fan_curve { - use rog_fan_curve::{Board, Fan}; - if let Some(board) = Board::from_board_name() { - curve.apply(board, Fan::Cpu)?; - curve.apply(board, Fan::Gpu)?; + if let Some(existing) = cfg.power_profiles.get_mut(&profile.name) { + *existing = profile.clone(); + existing.set_system_all()?; } else { - warn!("Fan curve unsupported on this board.") + cfg.power_profiles + .insert(profile.name.clone(), profile.clone()); } + cfg.active_profile = profile.name.clone(); + cfg.write(); } - Ok(()) } } diff --git a/daemon/src/ctrl_profiles/mod.rs b/daemon/src/ctrl_profiles/mod.rs index ffd9ec54..7df7470d 100644 --- a/daemon/src/ctrl_profiles/mod.rs +++ b/daemon/src/ctrl_profiles/mod.rs @@ -1,7 +1,3 @@ pub mod zbus; pub mod controller; - -static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy"; -static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode"; -static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost"; diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index dcd688fd..c03895ba 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -1,5 +1,5 @@ use log::warn; -use rog_fan_curve::Curve; +use rog_profiles::profiles::Profile; use std::sync::Arc; use std::sync::Mutex; @@ -20,115 +20,36 @@ impl FanAndCpuZbus { #[dbus_interface(name = "org.asuslinux.Daemon")] impl FanAndCpuZbus { - /// Set profile details + /// Create new profile and make active fn set_profile(&self, profile: String) { - if let Ok(event) = serde_json::from_str(&profile) { - if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - cfg.read(); - ctrl.handle_profile_event(&event, &mut cfg) + if let Ok(mut ctrl) = self.inner.try_lock() { + ctrl.set_active(&profile) + .unwrap_or_else(|err| warn!("{}", err)); + // Do notification + if let Ok(cfg) = ctrl.config.clone().try_lock() { + // Do notify + if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) { + self.notify_profile(&profile) .unwrap_or_else(|err| warn!("{}", err)); - if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) { - if let Ok(json) = serde_json::to_string(profile) { - self.notify_profile(&json) - .unwrap_or_else(|err| warn!("{}", err)); - } - } } } } } - /// Modify the active profile - fn set_turbo(&self, enable: bool) -> zbus::fdo::Result<()> { + /// New or modify profile details and make active, will create if it does not exist + fn new_or_modify(&self, profile: Profile) { if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - // Update the profile then set it - cfg.read(); - let profile = cfg.active_profile.clone(); - if let Some(profile) = cfg.power_profiles.get_mut(&profile) { - profile.turbo = enable; + ctrl.new_or_modify(&profile) + .unwrap_or_else(|err| warn!("{}", err)); + // Do notification + if let Ok(cfg) = ctrl.config.clone().try_lock() { + // Do notify + if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) { + self.notify_profile(&profile) + .unwrap_or_else(|err| warn!("{}", err)); } - ctrl.set(&profile, &mut cfg)?; - return Ok(()); } } - Ok(()) - } - - /// Modify the active profile - fn set_min_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> { - if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - // Update the profile then set it - cfg.read(); - let profile = cfg.active_profile.clone(); - if let Some(profile) = cfg.power_profiles.get_mut(&profile) { - profile.min_percentage = percentage; - } - ctrl.set(&profile, &mut cfg)?; - return Ok(()); - } - } - Ok(()) - } - - /// Modify the active profile - fn set_max_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> { - if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - // Update the profile then set it - cfg.read(); - let profile = cfg.active_profile.clone(); - if let Some(profile) = cfg.power_profiles.get_mut(&profile) { - profile.max_percentage = percentage; - } - ctrl.set(&profile, &mut cfg)?; - return Ok(()); - } - } - Ok(()) - } - - /// Modify the active profile - fn set_fan_preset(&self, preset: u8) -> zbus::fdo::Result<()> { - if preset > 2 { - return Err(zbus::fdo::Error::InvalidArgs( - "Fan preset must be 0, 1, or 2".to_string(), - )); - } - if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - // Update the profile then set it - cfg.read(); - let profile = cfg.active_profile.clone(); - if let Some(profile) = cfg.power_profiles.get_mut(&profile) { - profile.fan_preset = preset; - } - ctrl.set(&profile, &mut cfg)?; - return Ok(()); - } - } - Ok(()) - } - - /// Modify the active profile - fn set_fan_curve(&self, curve: String) -> zbus::fdo::Result<()> { - let curve = Curve::from_config_str(&curve) - .map_err(|err| zbus::fdo::Error::InvalidArgs(format!("Fan curve error: {}", err)))?; - if let Ok(mut ctrl) = self.inner.try_lock() { - if let Ok(mut cfg) = ctrl.config.clone().try_lock() { - // Update the profile then set it - cfg.read(); - let profile = cfg.active_profile.clone(); - if let Some(profile) = cfg.power_profiles.get_mut(&profile) { - profile.fan_curve = Some(curve); - } - ctrl.set(&profile, &mut cfg)?; - return Ok(()); - } - } - Ok(()) } /// Fetch the active profile name @@ -139,17 +60,15 @@ impl FanAndCpuZbus { ctrl.do_next_profile(&mut cfg) .unwrap_or_else(|err| warn!("{}", err)); if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) { - if let Ok(json) = serde_json::to_string(profile) { - self.notify_profile(&json) - .unwrap_or_else(|err| warn!("{}", err)); - } + self.notify_profile(&profile) + .unwrap_or_else(|err| warn!("{}", err)); } } } } /// Fetch the active profile name - fn active_profile_name(&mut self) -> zbus::fdo::Result { + fn active_name(&mut self) -> zbus::fdo::Result { if let Ok(ctrl) = self.inner.try_lock() { if let Ok(mut cfg) = ctrl.config.try_lock() { cfg.read(); @@ -163,14 +82,12 @@ impl FanAndCpuZbus { // TODO: Profile can't implement Type because of Curve /// Fetch the active profile details - fn profile(&mut self) -> zbus::fdo::Result { + fn active_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(profile) = cfg.power_profiles.get(&cfg.active_profile) { - if let Ok(json) = serde_json::to_string_pretty(profile) { - return Ok(json); - } + return Ok(profile.clone()); } } } @@ -180,13 +97,11 @@ impl FanAndCpuZbus { } /// Fetch all profile data - fn profiles(&mut self) -> zbus::fdo::Result { + fn 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 Ok(json) = serde_json::to_string_pretty(&cfg.power_profiles) { - return Ok(json); - } + return Ok(cfg.power_profiles.values().cloned().collect()); } } Err(Error::Failed( @@ -236,7 +151,7 @@ impl FanAndCpuZbus { } #[dbus_interface(signal)] - fn notify_profile(&self, profile: &str) -> zbus::Result<()> {} + fn notify_profile(&self, profile: &Profile) -> zbus::Result<()> {} } impl crate::ZbusAdd for FanAndCpuZbus { diff --git a/daemon/src/ctrl_rog_bios.rs b/daemon/src/ctrl_rog_bios.rs index ab181353..f3c7d6bf 100644 --- a/daemon/src/ctrl_rog_bios.rs +++ b/daemon/src/ctrl_rog_bios.rs @@ -309,11 +309,9 @@ impl CtrlRogBios { let mut buf = Vec::new(); // remove modules - for line in std::io::BufReader::new(file).lines() { - if let Ok(l) = line { - if !modules.contains(&l.as_ref()) { - buf.append(&mut l.as_bytes().to_vec()); - } + for line in std::io::BufReader::new(file).lines().flatten() { + if !modules.contains(&line.as_str()) { + buf.append(&mut line.as_bytes().to_vec()); } } diff --git a/daemon/src/ctrl_supported.rs b/daemon/src/ctrl_supported.rs index 9b05e472..60fedf07 100644 --- a/daemon/src/ctrl_supported.rs +++ b/daemon/src/ctrl_supported.rs @@ -2,15 +2,19 @@ use log::warn; use serde_derive::{Deserialize, Serialize}; use zbus::dbus_interface; use zvariant::ObjectPath; +use zvariant_derive::Type; -use crate::{GetSupported, ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::CtrlKbdLed, ctrl_profiles::controller::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios}; +use crate::{ + ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::controller::CtrlKbdLed, + ctrl_profiles::controller::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios, GetSupported, +}; use rog_types::supported::{ AnimeSupportedFunctions, ChargeSupportedFunctions, FanCpuSupportedFunctions, LedSupportedFunctions, RogBiosSupportedFunctions, }; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type)] pub struct SupportedFunctions { pub anime_ctrl: AnimeSupportedFunctions, pub charge_ctrl: ChargeSupportedFunctions, @@ -21,8 +25,8 @@ pub struct SupportedFunctions { #[dbus_interface(name = "org.asuslinux.Daemon")] impl SupportedFunctions { - fn supported_functions(&self) -> String { - serde_json::to_string_pretty(self).unwrap() + fn supported_functions(&self) -> &SupportedFunctions { + self } } @@ -46,8 +50,8 @@ impl GetSupported for SupportedFunctions { fn get_supported() -> Self::A { SupportedFunctions { - keyboard_led: CtrlKbdLed::get_supported(), anime_ctrl: CtrlAnime::get_supported(), + keyboard_led: CtrlKbdLed::get_supported(), charge_ctrl: CtrlCharge::get_supported(), fan_cpu_ctrl: CtrlFanAndCpu::get_supported(), rog_bios_ctrl: CtrlRogBios::get_supported(), diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 5e9d3ea9..28685a85 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -1,11 +1,13 @@ -use daemon::ctrl_leds::{CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus}; +use daemon::ctrl_leds::controller::{ + CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus, +}; use daemon::{ config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, }; use daemon::{config_anime::AnimeConfig, config_aura::AuraConfig, ctrl_charge::CtrlCharge}; use daemon::{ctrl_anime::*, ctrl_gfx::controller::CtrlGraphics}; use daemon::{ - ctrl_profiles::{zbus::FanAndCpuZbus, controller::CtrlFanAndCpu}, + ctrl_profiles::{controller::CtrlFanAndCpu, zbus::FanAndCpuZbus}, laptops::LaptopLedData, }; @@ -33,9 +35,12 @@ pub fn main() -> Result<(), Box> { .filter(None, LevelFilter::Info) .init(); - info!(" daemon v{}", daemon::VERSION); - info!(" rog-dbus v{}", rog_dbus::VERSION); - info!("rog-types v{}", rog_types::VERSION); + info!(" daemon v{}", daemon::VERSION); + info!(" rog-anime v{}", rog_anime::VERSION); + info!(" rog-aura v{}", rog_aura::VERSION); + info!(" rog-dbus v{}", rog_dbus::VERSION); + info!("rog-profiles v{}", rog_profiles::VERSION); + info!(" rog-types v{}", rog_types::VERSION); start_daemon()?; Ok(()) diff --git a/daemon/src/error.rs b/daemon/src/error.rs index ce9edb17..fdb85342 100644 --- a/daemon/src/error.rs +++ b/daemon/src/error.rs @@ -1,5 +1,5 @@ -use intel_pstate::PStateError; use rog_fan_curve::CurveError; +use rog_profiles::error::ProfileError; use rog_types::error::GraphicsError; use std::convert::From; use std::fmt; @@ -18,13 +18,13 @@ pub enum RogError { Write(String, std::io::Error), NotSupported, NotFound(String), - IntelPstate(PStateError), FanCurve(CurveError), DoTask(String), MissingFunction(String), MissingLedBrightNode(String, std::io::Error), ReloadFail(String), GfxSwitching(GfxError), + Profiles(ProfileError), Initramfs(String), Modprobe(String), Command(String, std::io::Error), @@ -46,13 +46,13 @@ impl fmt::Display for RogError { RogError::Write(path, error) => write!(f, "Write {}: {}", path, error), RogError::NotSupported => write!(f, "Not supported"), RogError::NotFound(deets) => write!(f, "Not found: {}", deets), - RogError::IntelPstate(err) => write!(f, "Intel pstate error: {}", err), RogError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err), RogError::DoTask(deets) => write!(f, "Task error: {}", deets), RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets), RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error), RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets), RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets), + RogError::Profiles(deets) => write!(f, "Profile error: {}", deets), RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail), RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail), RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error), @@ -64,12 +64,6 @@ impl fmt::Display for RogError { impl std::error::Error for RogError {} -impl From for RogError { - fn from(err: PStateError) -> Self { - RogError::IntelPstate(err) - } -} - impl From for RogError { fn from(err: CurveError) -> Self { RogError::FanCurve(err) @@ -85,6 +79,12 @@ impl From for RogError { } } +impl From for RogError { + fn from(err: ProfileError) -> Self { + RogError::Profiles(err) + } +} + impl From for RogError { fn from(err: zbus::Error) -> Self { RogError::Zbus(err) diff --git a/rog-anime/Cargo.toml b/rog-anime/Cargo.toml index 0ba544ad..dcd3b3bc 100644 --- a/rog-anime/Cargo.toml +++ b/rog-anime/Cargo.toml @@ -14,7 +14,7 @@ exclude = ["data"] [features] default = ["dbus"] -dbus = ["zbus", "zvariant", "zvariant_derive"] +dbus = ["zvariant", "zvariant_derive"] [dependencies] png_pong = "^0.8.0" @@ -26,6 +26,5 @@ serde_derive = "^1.0" glam = { version = "0.14.0", features = ["serde"] } -zbus = { version = "^1.9.1", optional = true } zvariant = { version = "^2.6", optional = true } zvariant_derive = { version = "^2.6", optional = true } diff --git a/rog-anime/src/data.rs b/rog-anime/src/data.rs index 9280be6b..ab5e6735 100644 --- a/rog-anime/src/data.rs +++ b/rog-anime/src/data.rs @@ -14,6 +14,14 @@ pub const ANIME_DATA_LEN: usize = PANE_LEN * 2; const USB_PREFIX1: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02]; const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02]; +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)] + +pub struct AnimePowerStates { + pub enabled: bool, + pub boot_anim_enabled: bool, +} + /// The minimal serializable data that can be transferred over wire types. /// Other data structures in `rog_anime` will convert to this. #[cfg_attr(feature = "dbus", derive(Type))] diff --git a/rog-anime/src/error.rs b/rog-anime/src/error.rs index f3e9ab8c..f52ee35b 100644 --- a/rog-anime/src/error.rs +++ b/rog-anime/src/error.rs @@ -3,9 +3,6 @@ use png_pong::decode::Error as PngError; use std::error::Error; use std::fmt; -#[cfg(feature = "dbus")] -use zbus::fdo; - #[derive(Debug)] pub enum AnimeError { NoFrames, @@ -15,8 +12,6 @@ pub enum AnimeError { Format, /// The input was incorrect size, expected size is `IncorrectSize(width, height)` IncorrectSize(u32, u32), - #[cfg(feature = "dbus")] - Zbus(fdo::Error), } impl fmt::Display for AnimeError { @@ -33,8 +28,6 @@ impl fmt::Display for AnimeError { "The input image size is incorrect, expected {}x{}", width, height ), - #[cfg(feature = "dbus")] - AnimeError::Zbus(e) => write!(f, "ZBUS error: {}", e), } } } @@ -61,11 +54,3 @@ impl From for AnimeError { AnimeError::Gif(err) } } - -#[cfg(feature = "dbus")] -impl From for fdo::Error { - #[inline] - fn from(err: AnimeError) -> Self { - fdo::Error::Failed(format!("{}", err)) - } -} diff --git a/rog-anime/src/image.rs b/rog-anime/src/image.rs index fec4aad7..f94a6098 100644 --- a/rog-anime/src/image.rs +++ b/rog-anime/src/image.rs @@ -180,36 +180,34 @@ impl AnimeImage { let du = led_from_px * Vec3::new(-0.5, 0.5, 0.0); let dv = led_from_px * Vec3::new(0.5, 0.5, 0.0); - for led in self.led_pos.iter_mut() { - if let Some(led) = led { - let mut sum = 0.0; - let mut alpha = 0.0; - let mut count = 0; + for led in self.led_pos.iter_mut().flatten() { + let mut sum = 0.0; + let mut alpha = 0.0; + let mut count = 0; - let pos = Vec3::new(led.x(), led.y(), 1.0); - let x0 = led_from_px.mul_vec3(pos + Vec3::new(0.0, -0.5, 0.0)); + let pos = Vec3::new(led.x(), led.y(), 1.0); + let x0 = led_from_px.mul_vec3(pos + Vec3::new(0.0, -0.5, 0.0)); - const GROUP: [f32; 4] = [0.0, 0.5, 1.0, 1.5]; - for u in GROUP.iter() { - for v in GROUP.iter() { - let sample = x0 + *u * du + *v * dv; + const GROUP: [f32; 4] = [0.0, 0.5, 1.0, 1.5]; + for u in GROUP.iter() { + for v in GROUP.iter() { + let sample = x0 + *u * du + *v * dv; - let x = sample.x as i32; - let y = sample.y as i32; - if x > width - 1 || y > height - 1 || x < 0 || y < 0 { - continue; - } - - let p = self.img_pixels[(x + (y * width)) as usize]; - sum += p.color as f32; - alpha += p.alpha; - count += 1; + let x = sample.x as i32; + let y = sample.y as i32; + if x > width - 1 || y > height - 1 || x < 0 || y < 0 { + continue; } + + let p = self.img_pixels[(x + (y * width)) as usize]; + sum += p.color as f32; + alpha += p.alpha; + count += 1; } - alpha /= count as f32; - sum /= count as f32; - led.set_bright((sum * self.bright * alpha) as u8); } + alpha /= count as f32; + sum /= count as f32; + led.set_bright((sum * self.bright * alpha) as u8); } } diff --git a/rog-anime/src/lib.rs b/rog-anime/src/lib.rs index 112e6814..a38c9b21 100644 --- a/rog-anime/src/lib.rs +++ b/rog-anime/src/lib.rs @@ -32,4 +32,4 @@ pub mod error; /// Provides const methods to create the USB HID control packets pub mod usb; -pub static VERSION: &str = env!("CARGO_PKG_VERSION"); \ No newline at end of file +pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/rog-aura/Cargo.toml b/rog-aura/Cargo.toml index 0bf9ff42..051af929 100644 --- a/rog-aura/Cargo.toml +++ b/rog-aura/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rog_aura" -version = "1.0.1" +version = "1.1.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] @@ -14,12 +14,11 @@ exclude = ["data"] [features] default = ["dbus"] -dbus = ["zbus", "zvariant", "zvariant_derive"] +dbus = ["zvariant", "zvariant_derive"] [dependencies] serde = "^1.0" serde_derive = "^1.0" -zbus = { version = "^1.9.1", optional = true } zvariant = { version = "^2.6", optional = true } zvariant_derive = { version = "^2.6", optional = true } diff --git a/rog-aura/src/builtin_modes.rs b/rog-aura/src/builtin_modes.rs index 8ec0bce1..52640c13 100644 --- a/rog-aura/src/builtin_modes.rs +++ b/rog-aura/src/builtin_modes.rs @@ -11,6 +11,13 @@ use zvariant_derive::Type; use crate::{error::Error, LED_MSG_LEN}; +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)] +pub struct LedPowerStates { + pub enabled: bool, + pub sleep_anim_enabled: bool, +} + #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)] pub enum LedBrightness { diff --git a/rog-aura/src/lib.rs b/rog-aura/src/lib.rs index c570522f..f309260f 100644 --- a/rog-aura/src/lib.rs +++ b/rog-aura/src/lib.rs @@ -14,3 +14,5 @@ pub mod usb; pub mod error; pub const LED_MSG_LEN: usize = 17; + +pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/rog-aura/src/usb.rs b/rog-aura/src/usb.rs index b3dbb11c..257809df 100644 --- a/rog-aura/src/usb.rs +++ b/rog-aura/src/usb.rs @@ -15,22 +15,18 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { ] } -/// Enable the keyboard when laptop is awake -pub const LED_AWAKE_ON: [u8; 17] = [ +pub const LED_AWAKE_ON_SLEEP_OFF: [u8; 17] = [ 0x5d, 0xbd, 0x01, 0xcf, 0x17, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; -/// Disable the keyboard when laptop is awake -pub const LED_AWAKE_OFF: [u8; 17] = [ - 0x5d, 0xbd, 0x01, 0xc3, 0x13, 0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -]; - -/// Enable animations when the laptop is suspended while plugged in -pub const LED_SLEEP_ON: [u8; 17] = [ +pub const LED_AWAKE_ON_SLEEP_ON: [u8; 17] = [ 0x5d, 0xbd, 0x01, 0xff, 0x1f, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; -/// Disable animations when the laptop is suspended while plugged in -pub const LED_SLEEP_OFF: [u8; 17] = [ - 0x5d, 0xbd, 0x01, 0xcf, 0x17, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +pub const LED_AWAKE_OFF_SLEEP_OFF: [u8; 17] = [ + 0x5d, 0xbd, 0x01, 0xc3, 0x13, 0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub const LED_AWAKE_OFF_SLEEP_ON: [u8; 17] = [ + 0x5d, 0xbd, 0x01, 0xf3, 0x1b, 0x0d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; diff --git a/rog-dbus/Cargo.toml b/rog-dbus/Cargo.toml index e8e880c0..a6bdb907 100644 --- a/rog-dbus/Cargo.toml +++ b/rog-dbus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rog_dbus" -version = "3.2.0" +version = "3.4.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] @@ -10,11 +10,10 @@ description = "dbus interface methods for asusctl" edition = "2018" [dependencies] -serde_json = "^1.0" rog_anime = { path = "../rog-anime" } rog_aura = { path = "../rog-aura" } +rog_profiles = { path = "../rog-profiles" } rog_types = { path = "../rog-types" } -rog_fan_curve = { version = "^0.1", features = ["serde"] } -zbus = "^1.8" -zbus_macros = "^1.8" +zbus = "^1.9" +zbus_macros = "^1.9" zvariant = "^2.5" diff --git a/rog-dbus/src/lib.rs b/rog-dbus/src/lib.rs index 8c64a733..c72fb62c 100644 --- a/rog-dbus/src/lib.rs +++ b/rog-dbus/src/lib.rs @@ -10,9 +10,11 @@ pub mod zbus_profile; pub mod zbus_rogbios; pub mod zbus_supported; -use rog_aura::AuraEffect; +use rog_anime::AnimePowerStates; +use rog_aura::{AuraEffect, LedPowerStates}; +use rog_profiles::profiles::Profile; use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors}; -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::{channel, Receiver}; use zbus::{Connection, Result, SignalReceiver}; pub static VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -45,9 +47,9 @@ impl<'a> DbusProxies<'a> { )) } - pub fn setup_recv(&'a self, conn: Connection) -> SignalReceiver { + pub fn setup_recv(&'a self, conn: Connection) -> SignalReceiver<'a, 'a> { let mut recv = SignalReceiver::new(conn); - //recv.receive_for(&self.proxy_anime); + recv.receive_for(self.anime.proxy()); recv.receive_for(self.led.proxy()); recv.receive_for(self.charge.proxy()); recv.receive_for(self.gfx.proxy()); @@ -86,68 +88,91 @@ impl<'a> DbusProxies<'a> { // Signals separated out pub struct Signals { - pub gfx_vendor: Arc>>, - pub gfx_action: Arc>>, - pub profile: Arc>>, - pub led_mode: Arc>>, - pub charge: Arc>>, + pub gfx_vendor: Receiver, + pub gfx_action: Receiver, + pub profile: Receiver, + pub led_mode: Receiver, + pub led_power_state: Receiver, + pub anime_power_state: Receiver, + pub charge: Receiver, } impl Signals { #[inline] pub fn new(proxies: &DbusProxies) -> Result { - // - let charge_signal = Arc::new(Mutex::new(None)); - proxies - .charge - .connect_notify_charge(charge_signal.clone())?; - - // - let ledmode_signal = Arc::new(Mutex::new(None)); - proxies.led.connect_notify_led(ledmode_signal.clone())?; - - let gfx_action_signal = Arc::new(Mutex::new(None)); - proxies - .gfx - .connect_notify_action(gfx_action_signal.clone())?; - - let gfx_vendor_signal = Arc::new(Mutex::new(None)); - proxies.gfx.connect_notify_gfx(gfx_vendor_signal.clone())?; - - let profile_signal = Arc::new(Mutex::new(None)); - proxies - .profile - .connect_notify_profile(profile_signal.clone())?; - Ok(Signals { - gfx_vendor: gfx_vendor_signal, - gfx_action: gfx_action_signal, - profile: profile_signal, - led_mode: ledmode_signal, - charge: charge_signal, + gfx_vendor: { + let (tx, rx) = channel(); + proxies.gfx.connect_notify_gfx(tx)?; + rx + }, + gfx_action: { + let (tx, rx) = channel(); + proxies.gfx.connect_notify_action(tx)?; + rx + }, + profile: { + let (tx, rx) = channel(); + proxies.profile.connect_notify_profile(tx)?; + rx + }, + charge: { + let (tx, rx) = channel(); + proxies.charge.connect_notify_charge(tx)?; + rx + }, + led_mode: { + let (tx, rx) = channel(); + proxies.led.connect_notify_led(tx)?; + rx + }, + led_power_state: { + let (tx, rx) = channel(); + proxies.led.connect_notify_power_states(tx)?; + rx + }, + anime_power_state: { + let (tx, rx) = channel(); + proxies.anime.connect_notify_power_states(tx)?; + rx + }, }) } } /// This is the main way to communicate with the DBUS interface -pub struct AuraDbusClient<'a> { +pub struct RogDbusClient<'a> { proxies: DbusProxies<'a>, signals: Signals, } -impl<'a> AuraDbusClient<'a> { +impl<'a> RogDbusClient<'a> { #[inline] pub fn new() -> Result<(Self, Connection)> { let (proxies, conn) = DbusProxies::new()?; let signals = Signals::new(&proxies)?; - Ok((AuraDbusClient { proxies, signals }, conn)) + Ok((RogDbusClient { proxies, signals }, conn)) } pub fn proxies(&self) -> &DbusProxies { &self.proxies } + pub fn signals(&self) -> &Signals { + &self.signals + } + + pub fn setup_recv(&'a self, conn: Connection) -> SignalReceiver<'a, 'a> { + let mut recv = SignalReceiver::new(conn); + recv.receive_for(self.proxies.anime.proxy()); + recv.receive_for(self.proxies.led.proxy()); + recv.receive_for(self.proxies.charge.proxy()); + recv.receive_for(self.proxies.gfx.proxy()); + recv.receive_for(self.proxies.profile.proxy()); + recv + } + /* * GFX */ @@ -155,10 +180,8 @@ impl<'a> AuraDbusClient<'a> { loop { if let Ok(res) = self.proxies.gfx.proxy().next_signal() { if res.is_none() { - if let Ok(lock) = self.signals.gfx_action.lock() { - if let Some(stuff) = lock.as_ref() { - return Ok(*stuff); - } + if let Ok(stuff) = self.signals.gfx_action.try_recv() { + return Ok(stuff); } // return Ok("Failed for unknown reason".to_owned()); } diff --git a/rog-dbus/src/zbus_anime.rs b/rog-dbus/src/zbus_anime.rs index 3f5c92e3..dbcc2db1 100644 --- a/rog-dbus/src/zbus_anime.rs +++ b/rog-dbus/src/zbus_anime.rs @@ -19,7 +19,9 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use rog_anime::AnimeDataBuffer; +use std::sync::mpsc::Sender; + +use rog_anime::{AnimeDataBuffer, AnimePowerStates}; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -35,6 +37,15 @@ trait Daemon { /// WriteDirect method fn write(&self, input: &[u8]) -> zbus::Result<()>; + + #[dbus_proxy(property)] + fn awake_enabled(&self) -> zbus::Result; + + #[dbus_proxy(property)] + fn boot_enabled(&self) -> zbus::Result; + + #[dbus_proxy(signal)] + fn notify_power_states(&self, data: AnimePowerStates) -> zbus::Result<()>; } pub struct AnimeProxy<'a>(DaemonProxy<'a>); @@ -63,4 +74,26 @@ impl<'a> AnimeProxy<'a> { pub fn write(&self, input: AnimeDataBuffer) -> Result<()> { self.0.write(input.get()) } + + #[inline] + pub fn awake_enabled(&self) -> Result { + self.0.awake_enabled() + } + + #[inline] + pub fn boot_enabled(&self) -> Result { + self.0.boot_enabled() + } + + #[inline] + pub fn connect_notify_power_states( + &self, + send: Sender, + ) -> zbus::fdo::Result<()> { + self.0.connect_notify_power_states(move |data| { + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; + Ok(()) + }) + } } diff --git a/rog-dbus/src/zbus_charge.rs b/rog-dbus/src/zbus_charge.rs index 5237d3a8..95d7568d 100644 --- a/rog-dbus/src/zbus_charge.rs +++ b/rog-dbus/src/zbus_charge.rs @@ -19,7 +19,7 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::Sender; use zbus::{dbus_proxy, Connection, Result}; @@ -62,11 +62,10 @@ impl<'a> ChargeProxy<'a> { } #[inline] - pub fn connect_notify_charge(&self, charge: Arc>>) -> zbus::fdo::Result<()> { + pub fn connect_notify_charge(&self, send: Sender) -> zbus::fdo::Result<()> { self.0.connect_notify_charge(move |data| { - if let Ok(mut lock) = charge.lock() { - *lock = Some(data); - } + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; Ok(()) }) } diff --git a/rog-dbus/src/zbus_gfx.rs b/rog-dbus/src/zbus_gfx.rs index a8263b42..0c91dee8 100644 --- a/rog-dbus/src/zbus_gfx.rs +++ b/rog-dbus/src/zbus_gfx.rs @@ -19,7 +19,7 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::Sender; use rog_types::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; use zbus::{dbus_proxy, Connection, Result}; @@ -77,25 +77,20 @@ impl<'a> GfxProxy<'a> { #[inline] pub fn connect_notify_action( &self, - action: Arc>>, + send: Sender, ) -> zbus::fdo::Result<()> { self.0.connect_notify_action(move |data| { - if let Ok(mut lock) = action.lock() { - *lock = Some(data); - } + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; Ok(()) }) } #[inline] - pub fn connect_notify_gfx( - &self, - vendor: Arc>>, - ) -> zbus::fdo::Result<()> { + pub fn connect_notify_gfx(&self, send: Sender) -> zbus::fdo::Result<()> { self.0.connect_notify_gfx(move |data| { - if let Ok(mut lock) = vendor.lock() { - *lock = Some(data); - } + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; Ok(()) }) } diff --git a/rog-dbus/src/zbus_led.rs b/rog-dbus/src/zbus_led.rs index 047ae2e4..f1366191 100644 --- a/rog-dbus/src/zbus_led.rs +++ b/rog-dbus/src/zbus_led.rs @@ -19,11 +19,11 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::Sender; use zbus::{dbus_proxy, Connection, Result}; -use rog_aura::{AuraEffect, KeyColourArray, LedBrightness}; +use rog_aura::{AuraEffect, KeyColourArray, LedBrightness, LedPowerStates}; const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS @@ -52,7 +52,10 @@ trait Daemon { /// NotifyLed signal #[dbus_proxy(signal)] - fn notify_led(&self, data: &str) -> zbus::Result<()>; + fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>; + + #[dbus_proxy(signal)] + fn notify_power_states(&self, data: LedPowerStates) -> zbus::Result<()>; /// LedBrightness property #[dbus_proxy(property)] @@ -65,6 +68,12 @@ trait Daemon { /// LedModes property #[dbus_proxy(property)] fn led_modes(&self) -> zbus::Result; + + #[dbus_proxy(property)] + fn awake_enabled(&self) -> zbus::Result; + + #[dbus_proxy(property)] + fn sleep_enabled(&self) -> zbus::Result; } pub struct LedProxy<'a>(DaemonProxy<'a>); @@ -119,6 +128,16 @@ impl<'a> LedProxy<'a> { self.0.set_led_mode(mode) } + #[inline] + pub fn awake_enabled(&self) -> Result { + self.0.awake_enabled() + } + + #[inline] + pub fn sleep_enabled(&self) -> Result { + self.0.sleep_enabled() + } + /// Write a single colour block. /// /// Intentionally blocks for 10ms after sending to allow the block to @@ -152,13 +171,22 @@ impl<'a> LedProxy<'a> { } #[inline] - pub fn connect_notify_led(&self, led: Arc>>) -> zbus::fdo::Result<()> { + pub fn connect_notify_led(&self, send: Sender) -> zbus::fdo::Result<()> { self.0.connect_notify_led(move |data| { - if let Ok(mut lock) = led.lock() { - if let Ok(dat) = serde_json::from_str(&data) { - *lock = Some(dat); - } - } + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; + Ok(()) + }) + } + + #[inline] + pub fn connect_notify_power_states( + &self, + send: Sender, + ) -> zbus::fdo::Result<()> { + self.0.connect_notify_power_states(move |data| { + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; Ok(()) }) } diff --git a/rog-dbus/src/zbus_profile.rs b/rog-dbus/src/zbus_profile.rs index 994e2bfd..826da81b 100644 --- a/rog-dbus/src/zbus_profile.rs +++ b/rog-dbus/src/zbus_profile.rs @@ -19,9 +19,9 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::Sender; -use rog_types::profile::ProfileEvent; +use rog_profiles::profiles::Profile; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -29,14 +29,14 @@ use zbus::{dbus_proxy, Connection, Result}; default_path = "/org/asuslinux/Profile" )] trait Daemon { - /// ActiveProfileName method - fn active_profile_name(&self) -> zbus::Result; - /// NextProfile method fn next_profile(&self) -> zbus::Result<()>; /// Profile, get the active profile - fn profile(&self) -> zbus::Result; + fn active_name(&self) -> zbus::Result; + + /// Get the active `Profile` data + fn active_data(&self) -> zbus::Result; /// Profiles method fn profiles(&self) -> zbus::Result; @@ -48,26 +48,11 @@ trait Daemon { fn remove(&self, profile: &str) -> zbus::Result<()>; /// SetProfile method - fn set_profile(&self, profile: &str) -> zbus::Result<()>; - - /// SetFanCurve method - fn set_fan_curve(&self, curve: &str) -> zbus::Result<()>; - - /// SetFanPreset method - fn set_fan_preset(&self, preset: u8) -> zbus::Result<()>; - - /// SetMaxFrequency method - fn set_max_frequency(&self, percentage: u8) -> zbus::Result<()>; - - /// SetMinFrequency method - fn set_min_frequency(&self, percentage: u8) -> zbus::Result<()>; - - /// SetTurbo method - fn set_turbo(&self, enable: bool) -> zbus::Result<()>; + fn new_or_modify(&self, profile: &Profile) -> zbus::Result<()>; /// NotifyProfile signal #[dbus_proxy(signal)] - fn notify_profile(&self, profile: &str) -> zbus::Result<()>; + fn notify_profile(&self, profile: Profile) -> zbus::Result<()>; } pub struct ProfileProxy<'a>(DaemonProxy<'a>); @@ -83,13 +68,13 @@ impl<'a> ProfileProxy<'a> { } #[inline] - pub fn active_profile_name(&self) -> Result { - self.0.active_profile_name() + pub fn active_name(&self) -> Result { + self.0.active_name() } #[inline] - pub fn active_profile_data(&self) -> Result { - self.0.profile() + pub fn active_data(&self) -> Result { + self.0.active_data() } #[inline] @@ -102,49 +87,6 @@ impl<'a> ProfileProxy<'a> { self.0.next_profile() } - /// SetFanCurve, set fan curve for active profile - #[inline] - pub fn set_fan_curve(&self, curve: &str) -> zbus::Result<()> { - self.0.set_fan_curve(curve) - } - - /// SetFanPreset, set fan preset for active profile - #[inline] - pub fn set_fan_preset(&self, preset: u8) -> zbus::Result<()> { - self.0.set_fan_preset(preset) - } - - /// SetMaxFrequency, set max percentage of frequency for active profile - #[inline] - pub fn set_max_frequency(&self, percentage: u8) -> zbus::Result<()> { - self.0.set_max_frequency(percentage) - } - - /// SetMinFrequency, set min percentage of frequency for active profile - #[inline] - pub fn set_min_frequency(&self, percentage: u8) -> zbus::Result<()> { - self.0.set_min_frequency(percentage) - } - - /// SetTurbo, set turbo enable for active profile - #[inline] - pub fn set_turbo(&self, enable: bool) -> zbus::Result<()> { - self.0.set_turbo(enable) - } - - // TODO: remove - #[inline] - pub fn write_fan_mode(&self, level: u8) -> Result<()> { - self.0 - .set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level)).unwrap()) - } - - // TODO: remove - #[inline] - pub fn write_command(&self, cmd: &ProfileEvent) -> Result<()> { - self.0.set_profile(&serde_json::to_string(cmd).unwrap()) - } - #[inline] pub fn profile_names(&self) -> Result> { self.0.profile_names() @@ -156,14 +98,15 @@ impl<'a> ProfileProxy<'a> { } #[inline] - pub fn connect_notify_profile( - &self, - charge: Arc>>, - ) -> zbus::fdo::Result<()> { + pub fn new_or_modify(&self, profile: &Profile) -> Result<()> { + self.0.new_or_modify(profile) + } + + #[inline] + pub fn connect_notify_profile(&self, send: Sender) -> zbus::fdo::Result<()> { self.0.connect_notify_profile(move |data| { - if let Ok(mut lock) = charge.lock() { - *lock = Some(data.to_owned()); - } + send.send(data) + .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; Ok(()) }) } diff --git a/rog-dbus/src/zbus_supported.rs b/rog-dbus/src/zbus_supported.rs index 4e8cd49b..f292a3ff 100644 --- a/rog-dbus/src/zbus_supported.rs +++ b/rog-dbus/src/zbus_supported.rs @@ -19,6 +19,7 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. +use rog_types::supported::SupportedFunctions; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -27,7 +28,7 @@ use zbus::{dbus_proxy, Connection, Result}; )] trait Daemon { /// SupportedFunctions method - fn supported_functions(&self) -> zbus::Result; + fn supported_functions(&self) -> zbus::Result; } pub struct SupportProxy<'a>(DaemonProxy<'a>); @@ -43,7 +44,7 @@ impl<'a> SupportProxy<'a> { } #[inline] - pub fn get_supported_functions(&self) -> Result { + pub fn get_supported_functions(&self) -> Result { self.0.supported_functions() } } diff --git a/rog-profiles/Cargo.toml b/rog-profiles/Cargo.toml new file mode 100644 index 00000000..5e5d6d17 --- /dev/null +++ b/rog-profiles/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "rog_profiles" +version = "0.1.0" +authors = ["Luke D. Jones "] +edition = "2018" + +[features] +default = ["dbus"] +dbus = ["zvariant", "zvariant_derive"] + +[dependencies] +rog_fan_curve = { version = "^0.1", features = ["serde"] } +serde = "^1.0" +serde_derive = "^1.0" +intel-pstate = "^0.2" + +zvariant = { version = "^2.6", optional = true } +zvariant_derive = { version = "^2.6", optional = true } \ No newline at end of file diff --git a/rog-profiles/src/error.rs b/rog-profiles/src/error.rs new file mode 100644 index 00000000..e73538e4 --- /dev/null +++ b/rog-profiles/src/error.rs @@ -0,0 +1,54 @@ +use std::fmt; + +use intel_pstate::PStateError; +use rog_fan_curve::CurveError; + +#[derive(Debug)] +pub enum ProfileError { + ParseFanLevel, + MissingProfile(String), + Path(String, std::io::Error), + Read(String, std::io::Error), + Write(String, std::io::Error), + NotSupported, + NotFound(String), + IntelPstate(PStateError), + FanCurve(CurveError), + Io(std::io::Error), + //Zbus(zbus::Error), +} + +impl fmt::Display for ProfileError { + // This trait requires `fmt` with this exact signature. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ProfileError::ParseFanLevel => write!(f, "Parse profile error"), + ProfileError::MissingProfile(profile) => { + write!(f, "Profile does not exist {}", profile) + } + ProfileError::Path(path, error) => write!(f, "Path {}: {}", path, error), + ProfileError::Read(path, error) => write!(f, "Read {}: {}", path, error), + ProfileError::Write(path, error) => write!(f, "Write {}: {}", path, error), + ProfileError::NotSupported => write!(f, "Not supported"), + ProfileError::NotFound(deets) => write!(f, "Not found: {}", deets), + ProfileError::IntelPstate(err) => write!(f, "Intel pstate error: {}", err), + ProfileError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err), + ProfileError::Io(detail) => write!(f, "std::io error: {}", detail), + //Error::Zbus(detail) => write!(f, "Zbus error: {}", detail), + } + } +} + +impl std::error::Error for ProfileError {} + +impl From for ProfileError { + fn from(err: PStateError) -> Self { + ProfileError::IntelPstate(err) + } +} + +impl From for ProfileError { + fn from(err: CurveError) -> Self { + ProfileError::FanCurve(err) + } +} diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs new file mode 100644 index 00000000..96d68664 --- /dev/null +++ b/rog-profiles/src/lib.rs @@ -0,0 +1,8 @@ +pub mod error; +pub mod profiles; + +static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy"; +static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode"; +static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost"; + +pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/rog-profiles/src/profiles.rs b/rog-profiles/src/profiles.rs new file mode 100644 index 00000000..2460d494 --- /dev/null +++ b/rog-profiles/src/profiles.rs @@ -0,0 +1,185 @@ +use rog_fan_curve::{Curve, Fan}; +use serde_derive::{Deserialize, Serialize}; +use std::io::Write; +use std::{fs::OpenOptions, path::Path, str::FromStr}; +#[cfg(feature = "dbus")] +use zvariant_derive::Type; + +use crate::{error::ProfileError, AMD_BOOST_PATH, FAN_TYPE_1_PATH, FAN_TYPE_2_PATH}; + +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct Profile { + pub name: String, + pub min_percentage: u8, + pub max_percentage: u8, + pub turbo: bool, + pub fan_preset: FanLevel, + pub fan_curve: String, +} + +impl Default for Profile { + fn default() -> Self { + Profile { + name: "new".into(), + min_percentage: 0, + max_percentage: 100, + turbo: false, + fan_preset: FanLevel::Normal, + fan_curve: "".to_string(), + } + } +} + +impl Profile { + pub fn new( + name: String, + min_percentage: u8, + max_percentage: u8, + turbo: bool, + fan_preset: FanLevel, + fan_curve: String, + ) -> Self { + Profile { + name, + min_percentage, + max_percentage, + turbo, + fan_preset, + fan_curve, + } + } + + pub fn get_intel_supported() -> bool { + intel_pstate::PState::new().is_ok() + } + + pub fn get_fan_path() -> Result<&'static str, ProfileError> { + if Path::new(FAN_TYPE_1_PATH).exists() { + Ok(FAN_TYPE_1_PATH) + } else if Path::new(FAN_TYPE_2_PATH).exists() { + Ok(FAN_TYPE_2_PATH) + } else { + Err(ProfileError::NotSupported) + } + } + + pub fn set_system_pstate(&self) -> Result<(), ProfileError> { + // Set CPU pstate + if let Ok(pstate) = intel_pstate::PState::new() { + pstate.set_min_perf_pct(self.min_percentage)?; + pstate.set_max_perf_pct(self.max_percentage)?; + pstate.set_no_turbo(!self.turbo)?; + } else { + // must be AMD CPU + let mut file = OpenOptions::new() + .write(true) + .open(AMD_BOOST_PATH) + .map_err(|err| ProfileError::Path(AMD_BOOST_PATH.into(), err))?; + + let boost = if self.turbo { "1" } else { "0" }; // opposite of Intel + file.write_all(boost.as_bytes()) + .map_err(|err| ProfileError::Write(AMD_BOOST_PATH.into(), err))?; + } + Ok(()) + } + + pub fn set_system_fan_mode(&self) -> Result<(), ProfileError> { + let path = Profile::get_fan_path()?; + let mut fan_ctrl = OpenOptions::new() + .write(true) + .open(path) + .map_err(|err| ProfileError::Path(path.into(), err))?; + fan_ctrl + .write_all(format!("{}\n", ::from(self.fan_preset)).as_bytes()) + .map_err(|err| ProfileError::Write(path.into(), err))?; + Ok(()) + } + + pub fn set_system_fan_curve(&self) -> Result<(), ProfileError> { + if !self.fan_curve.is_empty() { + if let Ok(curve) = Profile::parse_fan_curve(&self.fan_curve) { + use rog_fan_curve::Board; + if let Some(board) = Board::from_board_name() { + curve.apply(board, Fan::Cpu)?; + curve.apply(board, Fan::Gpu)?; + } + } + } + + Ok(()) + } + + pub fn set_system_all(&self) -> Result<(), ProfileError> { + self.set_system_pstate()?; + if !self.fan_curve.is_empty() { + self.set_system_fan_mode()?; + } else { + self.set_system_fan_curve()?; + } + Ok(()) + } + + fn parse_fan_curve(data: &str) -> Result { + let curve = Curve::from_config_str(data)?; + if let Err(err) = curve.check_safety(Fan::Cpu) { + return Err(format!("Unsafe curve {:?}", err)); + } + if let Err(err) = curve.check_safety(Fan::Gpu) { + return Err(format!("Unsafe curve {:?}", err)); + } + Ok(curve) + } +} + +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub enum FanLevel { + Normal, + Boost, + Silent, +} + +impl FromStr for FanLevel { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "normal" => Ok(FanLevel::Normal), + "boost" => Ok(FanLevel::Boost), + "silent" => Ok(FanLevel::Silent), + _ => Err("Invalid fan level"), + } + } +} + +impl From for FanLevel { + fn from(n: u8) -> Self { + match n { + 0 => FanLevel::Normal, + 1 => FanLevel::Boost, + 2 => FanLevel::Silent, + _ => FanLevel::Normal, + } + } +} + +impl From for u8 { + fn from(n: FanLevel) -> Self { + match n { + FanLevel::Normal => 0, + FanLevel::Boost => 1, + FanLevel::Silent => 2, + } + } +} + +impl From<&FanLevel> for u8 { + fn from(n: &FanLevel) -> Self { + match n { + FanLevel::Normal => 0, + FanLevel::Boost => 1, + FanLevel::Silent => 2, + } + } +} diff --git a/rog-types/Cargo.toml b/rog-types/Cargo.toml index ac2b6e7a..34d07c45 100644 --- a/rog-types/Cargo.toml +++ b/rog-types/Cargo.toml @@ -10,9 +10,7 @@ description = "A small library of effect types and conversions for ROG Aura" edition = "2018" [dependencies] -gumdrop = "^0.8" rog_aura = { path = "../rog-aura" } -rog_fan_curve = { version = "^0.1", features = ["serde"] } serde = "^1.0" serde_derive = "^1.0" zvariant = "^2.6" diff --git a/rog-types/src/lib.rs b/rog-types/src/lib.rs index 97c605f3..15078b86 100644 --- a/rog-types/src/lib.rs +++ b/rog-types/src/lib.rs @@ -6,8 +6,6 @@ pub static DBUS_NAME: &str = "org.asuslinux.Daemon"; pub static DBUS_PATH: &str = "/org/asuslinux/Daemon"; pub static DBUS_IFACE: &str = "org.asuslinux.Daemon"; -pub mod profile; - pub mod gfx_vendors; pub mod supported; diff --git a/rog-types/src/profile.rs b/rog-types/src/profile.rs deleted file mode 100644 index e6519847..00000000 --- a/rog-types/src/profile.rs +++ /dev/null @@ -1,153 +0,0 @@ -use gumdrop::Options; -use rog_fan_curve::{Curve, Fan}; -use serde_derive::{Deserialize, Serialize}; -use std::str::FromStr; - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Profile { - pub min_percentage: u8, - pub max_percentage: u8, - pub turbo: bool, - pub fan_preset: u8, - pub fan_curve: Option, -} - -#[deprecated] -pub type CpuSettings = Profile; - -impl Default for Profile { - fn default() -> Self { - Profile { - min_percentage: 0, - max_percentage: 100, - turbo: false, - fan_preset: 0, - fan_curve: None, - } - } -} - -impl Profile { - pub fn new( - min_percentage: u8, - max_percentage: u8, - turbo: bool, - fan_preset: u8, - fan_curve: Option, - ) -> Self { - Profile { - min_percentage, - max_percentage, - turbo, - fan_preset, - fan_curve, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum ProfileEvent { - Cli(ProfileCommand), - ChangeMode(u8), - Toggle, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum FanLevel { - Normal, - Boost, - Silent, -} - -impl FromStr for FanLevel { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "normal" => Ok(FanLevel::Normal), - "boost" => Ok(FanLevel::Boost), - "silent" => Ok(FanLevel::Silent), - _ => Err("Invalid fan level"), - } - } -} - -impl From for FanLevel { - fn from(n: u8) -> Self { - match n { - 0 => FanLevel::Normal, - 1 => FanLevel::Boost, - 2 => FanLevel::Silent, - _ => FanLevel::Normal, - } - } -} - -impl From for u8 { - fn from(n: FanLevel) -> Self { - match n { - FanLevel::Normal => 0, - FanLevel::Boost => 1, - FanLevel::Silent => 2, - } - } -} - -impl From<&FanLevel> for u8 { - fn from(n: &FanLevel) -> Self { - match n { - FanLevel::Normal => 0, - FanLevel::Boost => 1, - FanLevel::Silent => 2, - } - } -} - -fn parse_fan_curve(data: &str) -> Result { - let curve = Curve::from_config_str(data)?; - if let Err(err) = curve.check_safety(Fan::Cpu) { - return Err(format!("Unsafe curve {:?}", err)); - } - if let Err(err) = curve.check_safety(Fan::Gpu) { - return Err(format!("Unsafe curve {:?}", err)); - } - Ok(curve) -} - -#[derive(Debug, Clone, Options, Serialize, Deserialize)] -pub struct ProfileCommand { - #[options(help = "print help message")] - pub help: bool, - #[options(help = "toggle to next profile in list")] - pub next: bool, - #[options(help = "create the profile if it doesn't exist")] - pub create: bool, - #[options(meta = "", help = "remove a profile by name")] - pub remove: Option, - #[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, - - #[options(meta = "", help = "enable or disable cpu turbo")] - pub turbo: Option, - #[options(meta = "", help = "set min cpu scaling (intel)")] - pub min_percentage: Option, - #[options(meta = "", help = "set max cpu scaling (intel)")] - pub max_percentage: Option, - - #[options(meta = "", help = "")] - pub fan_preset: Option, - #[options( - meta = "", - parse(try_from_str = "parse_fan_curve"), - help = "set fan curve" - )] - pub curve: Option, - #[options(free)] - pub profile: Option, -} diff --git a/rog-types/src/supported.rs b/rog-types/src/supported.rs index 35ef22fd..cca29c12 100644 --- a/rog-types/src/supported.rs +++ b/rog-types/src/supported.rs @@ -1,7 +1,8 @@ use rog_aura::AuraModeNum; use serde_derive::{Deserialize, Serialize}; +use zvariant_derive::Type; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct SupportedFunctions { pub anime_ctrl: AnimeSupportedFunctions, pub charge_ctrl: ChargeSupportedFunctions, @@ -10,30 +11,30 @@ pub struct SupportedFunctions { pub rog_bios_ctrl: RogBiosSupportedFunctions, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct AnimeSupportedFunctions(pub bool); -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct ChargeSupportedFunctions { pub charge_level_set: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct FanCpuSupportedFunctions { pub stock_fan_modes: bool, pub min_max_freq: bool, pub fan_curve_set: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct LedSupportedFunctions { pub brightness_set: bool, - pub stock_led_modes: Option>, + pub stock_led_modes: Vec, pub multizone_led_mode: bool, pub per_key_led_mode: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Type, Debug)] pub struct RogBiosSupportedFunctions { pub post_sound_toggle: bool, pub dedicated_gfx_toggle: bool,