diff --git a/CHANGELOG.md b/CHANGELOG.md index aed342bd..7a203535 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `PanelOd` (form PanelOverdrive) - `SetPanelOd` - `NotifyPanelOd` + - Path `/org/asuslinux/Charge` changed to `/org/asuslinux/Power` ## [v4.4.0] - 2022-08-29 ### Added diff --git a/Cargo.lock b/Cargo.lock index 87f21e71..ac355b19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -572,7 +572,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "daemon" -version = "4.5.0-rc1" +version = "4.5.0-rc2" dependencies = [ "async-trait", "concat-idents", diff --git a/asus-notify/src/main.rs b/asus-notify/src/main.rs index 95654357..3d0016d1 100644 --- a/asus-notify/src/main.rs +++ b/asus-notify/src/main.rs @@ -1,7 +1,7 @@ use notify_rust::{Hint, Notification, NotificationHandle}; use rog_aura::AuraEffect; use rog_dbus::{ - zbus_charge::ChargeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy, + zbus_led::LedProxy, zbus_platform::RogBiosProxy, zbus_power::PowerProxy, zbus_profile::ProfileProxy, }; use rog_profiles::Profile; @@ -69,7 +69,7 @@ fn main() -> Result<(), Box> { executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); - let proxy = ChargeProxy::new(&conn).await.unwrap(); + let proxy = PowerProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await { p.for_each(|e| { if let Ok(out) = e.args() { diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index ad498d8d..d1f69bcf 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "daemon" -version = "4.5.0-rc1" +version = "4.5.0-rc2" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index 0de821d0..96959350 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -1,26 +1,20 @@ pub mod config; -pub mod zbus; +/// Implements CtrlTask, Reloadable, ZbusRun +pub mod trait_impls; -use ::zbus::export::futures_util::lock::{Mutex, MutexGuard}; -use ::zbus::SignalContext; -use async_trait::async_trait; +use self::config::{AnimeConfig, AnimeConfigCached}; +use crate::{error::RogError, GetSupported}; +use ::zbus::export::futures_util::lock::Mutex; use log::{error, info, warn}; use rog_anime::{ error::AnimeError, - usb::{ - get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, - pkts_for_init, - }, + usb::{get_anime_type, pkt_for_flush, pkts_for_init}, ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, }; use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw}; use std::sync::atomic::{AtomicBool, Ordering}; use std::{convert::TryFrom, error::Error, sync::Arc, thread::sleep}; -use crate::{error::RogError, GetSupported}; - -use self::config::{AnimeConfig, AnimeConfigCached}; - impl GetSupported for CtrlAnime { type A = AnimeSupportedFunctions; @@ -214,85 +208,3 @@ impl CtrlAnime { Ok(()) } } - -pub struct CtrlAnimeTask { - inner: Arc>, -} - -impl CtrlAnimeTask { - pub async fn new(inner: Arc>) -> CtrlAnimeTask { - Self { inner } - } -} - -#[async_trait] -impl crate::CtrlTask for CtrlAnimeTask { - async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { - let run_action = - |start: bool, lock: MutexGuard, inner: Arc>| { - if start { - info!("CtrlAnimeTask running sleep animation"); - CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true); - } else { - info!("CtrlAnimeTask running wake animation"); - CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true); - } - }; - - let inner1 = self.inner.clone(); - let inner2 = self.inner.clone(); - let inner3 = self.inner.clone(); - let inner4 = self.inner.clone(); - self.create_sys_event_tasks( - // Loop is required to try an attempt to get the mutex *without* blocking - // other threads - it is possible to end up with deadlocks otherwise. - move || loop { - if let Some(lock) = inner1.try_lock() { - run_action(true, lock, inner1.clone()); - break; - } - }, - move || loop { - if let Some(lock) = inner2.try_lock() { - run_action(false, lock, inner2.clone()); - break; - } - }, - move || loop { - if let Some(lock) = inner3.try_lock() { - run_action(true, lock, inner3.clone()); - break; - } - }, - move || loop { - if let Some(lock) = inner4.try_lock() { - run_action(false, lock, inner4.clone()); - break; - } - }, - ) - .await; - - Ok(()) - } -} - -pub struct CtrlAnimeReloader(pub Arc>); - -#[async_trait] -impl crate::Reloadable for CtrlAnimeReloader { - async fn reload(&mut self) -> Result<(), RogError> { - if let Some(lock) = self.0.try_lock() { - lock.node - .write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?; - lock.node.write_bytes(&pkt_for_apply())?; - lock.node - .write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?; - lock.node.write_bytes(&pkt_for_apply())?; - - let action = lock.cache.boot.clone(); - CtrlAnime::run_thread(self.0.clone(), action, true); - } - Ok(()) - } -} diff --git a/daemon/src/ctrl_anime/zbus.rs b/daemon/src/ctrl_anime/trait_impls.rs similarity index 60% rename from daemon/src/ctrl_anime/zbus.rs rename to daemon/src/ctrl_anime/trait_impls.rs index a1210612..e005e4c0 100644 --- a/daemon/src/ctrl_anime/zbus.rs +++ b/daemon/src/ctrl_anime/trait_impls.rs @@ -1,22 +1,28 @@ +use super::CtrlAnime; +use crate::error::RogError; use async_trait::async_trait; -use log::warn; +use log::{info, warn}; use rog_anime::{ usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on}, AnimeDataBuffer, AnimePowerStates, }; -use zbus::{dbus_interface, export::futures_util::lock::Mutex, Connection, SignalContext}; - use std::sync::{atomic::Ordering, Arc}; +use zbus::{ + dbus_interface, + export::futures_util::lock::{Mutex, MutexGuard}, + Connection, SignalContext, +}; -use super::CtrlAnime; +pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime"; +#[derive(Clone)] pub struct CtrlAnimeZbus(pub Arc>); /// The struct with the main dbus methods requires this trait #[async_trait] impl crate::ZbusRun for CtrlAnimeZbus { async fn add_to_server(self, server: &mut Connection) { - Self::add_to_server_helper(self, "/org/asuslinux/Anime", server).await; + Self::add_to_server_helper(self, ZBUS_PATH, server).await; } } @@ -134,3 +140,77 @@ impl CtrlAnimeZbus { data: AnimePowerStates, ) -> zbus::Result<()>; } + +#[async_trait] +impl crate::CtrlTask for CtrlAnimeZbus { + fn zbus_path() -> &'static str { + ZBUS_PATH + } + + async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { + let run_action = + |start: bool, lock: MutexGuard, inner: Arc>| { + if start { + info!("CtrlAnimeTask running sleep animation"); + CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true); + } else { + info!("CtrlAnimeTask running wake animation"); + CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true); + } + }; + + let inner1 = self.0.clone(); + let inner2 = self.0.clone(); + let inner3 = self.0.clone(); + let inner4 = self.0.clone(); + self.create_sys_event_tasks( + // Loop is required to try an attempt to get the mutex *without* blocking + // other threads - it is possible to end up with deadlocks otherwise. + move || loop { + if let Some(lock) = inner1.try_lock() { + run_action(true, lock, inner1.clone()); + break; + } + }, + move || loop { + if let Some(lock) = inner2.try_lock() { + run_action(false, lock, inner2.clone()); + break; + } + }, + move || loop { + if let Some(lock) = inner3.try_lock() { + run_action(true, lock, inner3.clone()); + break; + } + }, + move || loop { + if let Some(lock) = inner4.try_lock() { + run_action(false, lock, inner4.clone()); + break; + } + }, + ) + .await; + + Ok(()) + } +} + +#[async_trait] +impl crate::Reloadable for CtrlAnimeZbus { + async fn reload(&mut self) -> Result<(), RogError> { + if let Some(lock) = self.0.try_lock() { + lock.node + .write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?; + lock.node.write_bytes(&pkt_for_apply())?; + lock.node + .write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?; + lock.node.write_bytes(&pkt_for_apply())?; + + let action = lock.cache.boot.clone(); + CtrlAnime::run_thread(self.0.clone(), action, true); + } + Ok(()) + } +} diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index e7c1833d..4ad21fad 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -1,10 +1,8 @@ use crate::{ error::RogError, laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES}, - CtrlTask, }; -use async_trait::async_trait; -use log::{error, info, warn}; +use log::{info, warn}; use rog_aura::{ usb::{AuraDevice, LED_APPLY, LED_SET}, AuraEffect, KeyColourArray, LedBrightness, PerKeyRaw, LED_MSG_LEN, @@ -12,14 +10,6 @@ use rog_aura::{ use rog_aura::{AuraZone, Direction, Speed, GRADIENT}; use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions}; use std::collections::BTreeMap; -use std::sync::Arc; -use zbus::{ - export::futures_util::{ - lock::{Mutex, MutexGuard}, - StreamExt, - }, - SignalContext, -}; use crate::GetSupported; @@ -78,119 +68,6 @@ pub struct CtrlKbdLed { pub config: AuraConfig, } -pub struct CtrlKbdLedTask { - inner: Arc>, -} - -impl CtrlKbdLedTask { - pub fn new(inner: Arc>) -> Self { - Self { inner } - } - - fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { - let bright = lock.kd_brightness.get_brightness()?; - lock.config.read(); - lock.config.brightness = (bright as u32).into(); - lock.config.write(); - return Ok(()); - } -} - -#[async_trait] -impl CtrlTask for CtrlKbdLedTask { - async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { - let load_save = |start: bool, mut lock: MutexGuard| { - // If waking up - if !start { - info!("CtrlKbdLedTask reloading brightness and modes"); - lock.set_brightness(lock.config.brightness) - .map_err(|e| error!("CtrlKbdLedTask: {e}")) - .ok(); - lock.write_current_config_mode() - .map_err(|e| error!("CtrlKbdLedTask: {e}")) - .ok(); - } else if start { - info!("CtrlKbdLedTask saving last brightness"); - Self::update_config(&mut lock) - .map_err(|e| error!("CtrlKbdLedTask: {e}")) - .ok(); - } - }; - - let inner1 = self.inner.clone(); - let inner2 = self.inner.clone(); - let inner3 = self.inner.clone(); - let inner4 = self.inner.clone(); - self.create_sys_event_tasks( - // Loop so that we do aquire the lock but also don't block other - // threads (prevents potential deadlocks) - move || loop { - if let Some(lock) = inner1.try_lock() { - load_save(true, lock); - break; - } - }, - move || loop { - if let Some(lock) = inner2.try_lock() { - load_save(false, lock); - break; - } - }, - move || loop { - if let Some(lock) = inner3.try_lock() { - load_save(true, lock); - break; - } - }, - move || loop { - if let Some(lock) = inner4.try_lock() { - load_save(false, lock); - break; - } - }, - ) - .await; - - let ctrl2 = self.inner.clone(); - let ctrl = self.inner.lock().await; - let mut watch = ctrl.kd_brightness.monitor_brightness()?; - tokio::spawn(async move { - let mut buffer = [0; 32]; - watch - .event_stream(&mut buffer) - .unwrap() - .for_each(|_| async { - if let Some(lock) = ctrl2.try_lock() { - load_save(true, lock); - } - }) - .await; - }); - - Ok(()) - } -} - -pub struct CtrlKbdLedReloader(pub Arc>); - -#[async_trait] -impl crate::Reloadable for CtrlKbdLedReloader { - async fn reload(&mut self) -> Result<(), RogError> { - let mut ctrl = self.0.lock().await; - ctrl.write_current_config_mode()?; - ctrl.set_power_states().map_err(|err| warn!("{err}")).ok(); - Ok(()) - } -} - -pub struct CtrlKbdLedZbus(pub Arc>); - -impl CtrlKbdLedZbus { - pub fn new(inner: Arc>) -> Self { - Self(inner) - } -} - impl CtrlKbdLed { pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result { let mut led_prod = None; @@ -412,7 +289,7 @@ impl CtrlKbdLed { Ok(()) } - fn write_current_config_mode(&mut self) -> Result<(), RogError> { + pub(super) fn write_current_config_mode(&mut self) -> Result<(), RogError> { if self.config.multizone_on { let mode = self.config.current_mode; let mut create = false; diff --git a/daemon/src/ctrl_aura/mod.rs b/daemon/src/ctrl_aura/mod.rs index 85a4d229..9c365c20 100644 --- a/daemon/src/ctrl_aura/mod.rs +++ b/daemon/src/ctrl_aura/mod.rs @@ -1,3 +1,4 @@ pub mod config; pub mod controller; -pub mod zbus; +/// Implements CtrlTask, Reloadable, ZbusRun +pub mod trait_impls; diff --git a/daemon/src/ctrl_aura/zbus.rs b/daemon/src/ctrl_aura/trait_impls.rs similarity index 60% rename from daemon/src/ctrl_aura/zbus.rs rename to daemon/src/ctrl_aura/trait_impls.rs index 2849b749..39b24afd 100644 --- a/daemon/src/ctrl_aura/zbus.rs +++ b/daemon/src/ctrl_aura/trait_impls.rs @@ -1,16 +1,39 @@ -use std::collections::BTreeMap; - use async_trait::async_trait; -use log::warn; +use log::{error, info, warn}; use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum, LedBrightness, PerKeyRaw}; -use zbus::{dbus_interface, Connection, SignalContext}; +use std::{collections::BTreeMap, sync::Arc}; +use zbus::{ + dbus_interface, + export::futures_util::{ + lock::{Mutex, MutexGuard}, + StreamExt, + }, + Connection, SignalContext, +}; -use super::controller::CtrlKbdLedZbus; +use crate::{error::RogError, CtrlTask}; + +use super::controller::CtrlKbdLed; + +pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Aura"; + +#[derive(Clone)] +pub struct CtrlKbdLedZbus(pub Arc>); + +impl CtrlKbdLedZbus { + fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { + let bright = lock.kd_brightness.get_brightness()?; + lock.config.read(); + lock.config.brightness = (bright as u32).into(); + lock.config.write(); + return Ok(()); + } +} #[async_trait] impl crate::ZbusRun for CtrlKbdLedZbus { async fn add_to_server(self, server: &mut Connection) { - Self::add_to_server_helper(self, "/org/asuslinux/Aura", server).await; + Self::add_to_server_helper(self, ZBUS_PATH, server).await; } } @@ -206,3 +229,92 @@ impl CtrlKbdLedZbus { data: &AuraPowerDev, ) -> zbus::Result<()>; } + +#[async_trait] +impl CtrlTask for CtrlKbdLedZbus { + fn zbus_path() -> &'static str { + ZBUS_PATH + } + + async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { + let load_save = |start: bool, mut lock: MutexGuard| { + // If waking up + if !start { + info!("CtrlKbdLedTask reloading brightness and modes"); + lock.set_brightness(lock.config.brightness) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + lock.write_current_config_mode() + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + } else if start { + info!("CtrlKbdLedTask saving last brightness"); + Self::update_config(&mut lock) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + } + }; + + let inner1 = self.0.clone(); + let inner2 = self.0.clone(); + let inner3 = self.0.clone(); + let inner4 = self.0.clone(); + self.create_sys_event_tasks( + // Loop so that we do aquire the lock but also don't block other + // threads (prevents potential deadlocks) + move || loop { + if let Some(lock) = inner1.try_lock() { + load_save(true, lock); + break; + } + }, + move || loop { + if let Some(lock) = inner2.try_lock() { + load_save(false, lock); + break; + } + }, + move || loop { + if let Some(lock) = inner3.try_lock() { + load_save(true, lock); + break; + } + }, + move || loop { + if let Some(lock) = inner4.try_lock() { + load_save(false, lock); + break; + } + }, + ) + .await; + + let ctrl2 = self.0.clone(); + let ctrl = self.0.lock().await; + let mut watch = ctrl.kd_brightness.monitor_brightness()?; + tokio::spawn(async move { + let mut buffer = [0; 32]; + watch + .event_stream(&mut buffer) + .unwrap() + .for_each(|_| async { + if let Some(lock) = ctrl2.try_lock() { + load_save(true, lock); + } + }) + .await; + }); + + Ok(()) + } +} + +#[async_trait] +impl crate::Reloadable for CtrlKbdLedZbus { + async fn reload(&mut self) -> Result<(), RogError> { + let mut ctrl = self.0.lock().await; + ctrl.write_current_config_mode()?; + ctrl.set_power_states().map_err(|err| warn!("{err}")).ok(); + Ok(()) + } +} diff --git a/daemon/src/ctrl_platform.rs b/daemon/src/ctrl_platform.rs index 7c89e158..27c00e7d 100644 --- a/daemon/src/ctrl_platform.rs +++ b/daemon/src/ctrl_platform.rs @@ -13,16 +13,17 @@ use zbus::export::futures_util::lock::Mutex; use zbus::Connection; use zbus::{dbus_interface, SignalContext}; -static ASUS_POST_LOGO_SOUND: &str = +const ZBUS_PATH: &str = "/org/asuslinux/Platform"; +const ASUS_POST_LOGO_SOUND: &str = "/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e"; #[derive(Clone)] -pub struct CtrlRogBios { +pub struct CtrlPlatform { platform: AsusPlatform, config: Arc>, } -impl GetSupported for CtrlRogBios { +impl GetSupported for CtrlPlatform { type A = RogBiosSupportedFunctions; fn get_supported() -> Self::A { @@ -48,7 +49,7 @@ impl GetSupported for CtrlRogBios { } } -impl CtrlRogBios { +impl CtrlPlatform { pub fn new(config: Arc>) -> Result { let platform = AsusPlatform::new()?; @@ -58,12 +59,12 @@ impl CtrlRogBios { } if Path::new(ASUS_POST_LOGO_SOUND).exists() { - CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?; + CtrlPlatform::set_path_mutable(ASUS_POST_LOGO_SOUND)?; } else { info!("Switch for POST boot sound not detected"); } - Ok(CtrlRogBios { platform, config }) + Ok(CtrlPlatform { platform, config }) } fn set_path_mutable(path: &str) -> Result<(), RogError> { @@ -138,7 +139,7 @@ impl CtrlRogBios { } #[dbus_interface(name = "org.asuslinux.Daemon")] -impl CtrlRogBios { +impl CtrlPlatform { async fn set_gpu_mux_mode( &mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>, @@ -241,14 +242,14 @@ impl CtrlRogBios { } #[async_trait] -impl crate::ZbusRun for CtrlRogBios { +impl crate::ZbusRun for CtrlPlatform { async fn add_to_server(self, server: &mut Connection) { Self::add_to_server_helper(self, "/org/asuslinux/Platform", server).await; } } #[async_trait] -impl crate::Reloadable for CtrlRogBios { +impl crate::Reloadable for CtrlPlatform { async fn reload(&mut self) -> Result<(), RogError> { if self.platform.has_panel_od() { let p = if let Some(lock) = self.config.try_lock() { @@ -262,13 +263,17 @@ impl crate::Reloadable for CtrlRogBios { } } -impl CtrlRogBios { +impl CtrlPlatform { task_watch_item!(panel_od platform); task_watch_item!(gpu_mux_mode platform); } #[async_trait] -impl CtrlTask for CtrlRogBios { +impl CtrlTask for CtrlPlatform { + fn zbus_path() -> &'static str { + ZBUS_PATH + } + async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> { let platform1 = self.clone(); let platform2 = self.clone(); diff --git a/daemon/src/ctrl_power.rs b/daemon/src/ctrl_power.rs index aef69094..268a3c0b 100644 --- a/daemon/src/ctrl_power.rs +++ b/daemon/src/ctrl_power.rs @@ -10,6 +10,8 @@ use zbus::export::futures_util::lock::Mutex; use zbus::Connection; use zbus::SignalContext; +const ZBUS_PATH: &str = "/org/asuslinux/Power"; + impl GetSupported for CtrlPower { type A = ChargeSupportedFunctions; @@ -82,7 +84,7 @@ impl CtrlPower { #[async_trait] impl crate::ZbusRun for CtrlPower { async fn add_to_server(self, server: &mut Connection) { - Self::add_to_server_helper(self, "/org/asuslinux/Charge", server).await; + Self::add_to_server_helper(self, ZBUS_PATH, server).await; } } @@ -128,6 +130,10 @@ impl CtrlPower { #[async_trait] impl CtrlTask for CtrlPower { + fn zbus_path() -> &'static str { + ZBUS_PATH + } + async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> { let power1 = self.clone(); let power2 = self.clone(); diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index ae7a3f2f..331a1458 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -1,6 +1,5 @@ use crate::error::RogError; use crate::GetSupported; -use async_trait::async_trait; use log::{info, warn}; use rog_platform::platform::AsusPlatform; use rog_platform::supported::PlatformProfileFunctions; @@ -39,22 +38,6 @@ impl GetSupported for CtrlPlatformProfile { } } -#[async_trait] -impl crate::Reloadable for CtrlPlatformProfile { - /// Fetch the active profile and use that to set all related components up - async fn reload(&mut self) -> Result<(), RogError> { - if let Some(curves) = &mut self.config.fan_curves { - if let Ok(mut device) = FanCurveProfiles::get_device() { - // There is a possibility that the curve was default zeroed, so this call initialises - // the data from system read and we need to save it after - curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?; - self.config.write(); - } - } - Ok(()) - } -} - impl CtrlPlatformProfile { pub fn new(config: ProfileConfig) -> Result { let platform = AsusPlatform::new()?; diff --git a/daemon/src/ctrl_profiles/mod.rs b/daemon/src/ctrl_profiles/mod.rs index 85a4d229..9c365c20 100644 --- a/daemon/src/ctrl_profiles/mod.rs +++ b/daemon/src/ctrl_profiles/mod.rs @@ -1,3 +1,4 @@ pub mod config; pub mod controller; -pub mod zbus; +/// Implements CtrlTask, Reloadable, ZbusRun +pub mod trait_impls; diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/trait_impls.rs similarity index 81% rename from daemon/src/ctrl_profiles/zbus.rs rename to daemon/src/ctrl_profiles/trait_impls.rs index ab8b44bf..b8f1f8eb 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/trait_impls.rs @@ -2,6 +2,7 @@ use async_trait::async_trait; use log::warn; use rog_profiles::fan_curve_set::CurveData; use rog_profiles::fan_curve_set::FanCurveSet; +use rog_profiles::FanCurveProfiles; use rog_profiles::Profile; use zbus::export::futures_util::lock::Mutex; use zbus::export::futures_util::StreamExt; @@ -16,18 +17,12 @@ use crate::CtrlTask; use super::controller::CtrlPlatformProfile; -static UNSUPPORTED_MSG: &str = +const ZBUS_PATH: &str = "/org/asuslinux/Profile"; +const UNSUPPORTED_MSG: &str = "Fan curves are not supported on this laptop or you require a patched kernel"; -pub struct ProfileZbus { - inner: Arc>, -} - -impl ProfileZbus { - pub fn new(inner: Arc>) -> Self { - Self { inner } - } -} +#[derive(Clone)] +pub struct ProfileZbus(pub Arc>); #[dbus_interface(name = "org.asuslinux.Daemon")] impl ProfileZbus { @@ -44,7 +39,7 @@ impl ProfileZbus { /// Toggle to next platform_profile. Names provided by `Profiles`. /// If fan-curves are supported will also activate a fan curve for profile. async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.set_next_profile() .unwrap_or_else(|err| warn!("{}", err)); ctrl.save_config(); @@ -56,7 +51,7 @@ impl ProfileZbus { /// Fetch the active profile name async fn active_profile(&mut self) -> zbus::fdo::Result { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); Ok(ctrl.config.active_profile) } @@ -67,7 +62,7 @@ impl ProfileZbus { #[zbus(signal_context)] ctxt: SignalContext<'_>, profile: Profile, ) { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; // Read first just incase the user has modified the config before calling this ctrl.config.read(); Profile::set_profile(profile) @@ -87,7 +82,7 @@ impl ProfileZbus { /// Get a list of profiles that have fan-curves enabled. async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result> { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); if let Some(curves) = &ctrl.config.fan_curves { return Ok(curves.get_enabled_curve_profiles().to_vec()); @@ -102,7 +97,7 @@ impl ProfileZbus { profile: Profile, enabled: bool, ) -> zbus::fdo::Result<()> { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); return if let Some(curves) = &mut ctrl.config.fan_curves { curves.set_profile_curve_enabled(profile, enabled); @@ -120,7 +115,7 @@ impl ProfileZbus { /// Get the fan-curve data for the currently active Profile async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); if let Some(curves) = &ctrl.config.fan_curves { let curve = curves.get_fan_curves_for(profile); @@ -132,7 +127,7 @@ impl ProfileZbus { /// Set the fan curve for the specified profile. /// Will also activate the fan curve if the user is in the same mode. async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); if let Some(curves) = &mut ctrl.config.fan_curves { curves @@ -154,7 +149,7 @@ impl ProfileZbus { /// Each platform_profile has a different default and the defualt can be read /// only for the currently active profile. async fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); ctrl.set_active_curve_to_defaults() .map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e)) @@ -168,7 +163,7 @@ impl ProfileZbus { /// Each platform_profile has a different default and the defualt can be read /// only for the currently active profile. async fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> { - let mut ctrl = self.inner.lock().await; + let mut ctrl = self.0.lock().await; ctrl.config.read(); let active = Profile::get_active_profile().unwrap_or(Profile::Balanced); @@ -194,20 +189,19 @@ impl ProfileZbus { #[async_trait] impl crate::ZbusRun for ProfileZbus { async fn add_to_server(self, server: &mut Connection) { - Self::add_to_server_helper(self, "/org/asuslinux/Profile", server).await; + Self::add_to_server_helper(self, ZBUS_PATH, server).await; } } #[async_trait] impl CtrlTask for ProfileZbus { + fn zbus_path() -> &'static str { + ZBUS_PATH + } + async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> { - let ctrl = self.inner.clone(); - let mut watch = self - .inner - .lock() - .await - .platform - .monitor_platform_profile()?; + let ctrl = self.0.clone(); + let mut watch = self.0.lock().await.platform.monitor_platform_profile()?; tokio::spawn(async move { let mut buffer = [0; 32]; @@ -233,3 +227,21 @@ impl CtrlTask for ProfileZbus { Ok(()) } } + +#[async_trait] +impl crate::Reloadable for ProfileZbus { + /// Fetch the active profile and use that to set all related components up + async fn reload(&mut self) -> Result<(), RogError> { + let mut ctrl = self.0.lock().await; + let active = ctrl.config.active_profile; + if let Some(curves) = &mut ctrl.config.fan_curves { + if let Ok(mut device) = FanCurveProfiles::get_device() { + // There is a possibility that the curve was default zeroed, so this call initialises + // the data from system read and we need to save it after + curves.write_profile_curve_to_platform(active, &mut device)?; + ctrl.config.write(); + } + } + Ok(()) + } +} diff --git a/daemon/src/ctrl_supported.rs b/daemon/src/ctrl_supported.rs index 9fe99a15..993d8271 100644 --- a/daemon/src/ctrl_supported.rs +++ b/daemon/src/ctrl_supported.rs @@ -5,7 +5,7 @@ use zbus::Connection; use zvariant::Type; use crate::{ - ctrl_anime::CtrlAnime, ctrl_aura::controller::CtrlKbdLed, ctrl_platform::CtrlRogBios, + ctrl_anime::CtrlAnime, ctrl_aura::controller::CtrlKbdLed, ctrl_platform::CtrlPlatform, ctrl_power::CtrlPower, ctrl_profiles::controller::CtrlPlatformProfile, GetSupported, }; @@ -43,7 +43,7 @@ impl GetSupported for SupportedFunctions { keyboard_led: CtrlKbdLed::get_supported(), charge_ctrl: CtrlPower::get_supported(), platform_profile: CtrlPlatformProfile::get_supported(), - rog_bios_ctrl: CtrlRogBios::get_supported(), + rog_bios_ctrl: CtrlPlatform::get_supported(), } } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 9796f7d3..e093dc1e 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -5,28 +5,23 @@ use std::sync::Arc; use std::time::Duration; use ::zbus::export::futures_util::lock::Mutex; -use ::zbus::{Connection, SignalContext}; +use ::zbus::Connection; +use daemon::ctrl_anime::CtrlAnime; use log::LevelFilter; use log::{error, info, warn}; use tokio::time::sleep; -use daemon::ctrl_anime::config::AnimeConfig; -use daemon::ctrl_anime::zbus::CtrlAnimeZbus; -use daemon::ctrl_anime::*; -use daemon::ctrl_aura::config::AuraConfig; -use daemon::ctrl_aura::controller::{ - CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus, -}; -use daemon::ctrl_platform::CtrlRogBios; +use daemon::ctrl_anime::{config::AnimeConfig, trait_impls::CtrlAnimeZbus}; +use daemon::ctrl_aura::{config::AuraConfig, controller::CtrlKbdLed, trait_impls::CtrlKbdLedZbus}; +use daemon::ctrl_platform::CtrlPlatform; use daemon::ctrl_power::CtrlPower; -use daemon::ctrl_profiles::config::ProfileConfig; +use daemon::ctrl_profiles::{ + config::ProfileConfig, controller::CtrlPlatformProfile, trait_impls::ProfileZbus, +}; +use daemon::laptops::LaptopLedData; use daemon::{ config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, }; -use daemon::{ - ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus}, - laptops::LaptopLedData, -}; use daemon::{CtrlTask, Reloadable, ZbusRun}; use rog_dbus::DBUS_NAME; use rog_profiles::Profile; @@ -81,80 +76,43 @@ async fn start_daemon() -> Result<(), Box> { supported.add_to_server(&mut connection).await; - match CtrlRogBios::new(config.clone()) { - Ok(mut ctrl) => { - // Do a reload of any settings - ctrl.reload() - .await - .unwrap_or_else(|err| warn!("CtrlRogBios: {}", err)); - // Then register to dbus server - ctrl.add_to_server(&mut connection).await; - - let task = CtrlRogBios::new(config.clone())?; - let sig = SignalContext::new(&connection, "/org/asuslinux/Platform")?; - task.create_tasks(sig).await.ok(); + match CtrlPlatform::new(config.clone()) { + Ok(ctrl) => { + start_tasks(ctrl, &mut connection).await?; } Err(err) => { - error!("rog_bios_control: {}", err); + error!("CtrlPlatform: {}", err); } } match CtrlPower::new(config.clone()) { - Ok(mut ctrl) => { - // Do a reload of any settings - ctrl.reload() - .await - .unwrap_or_else(|err| warn!("CtrlPower: {}", err)); - // Then register to dbus server - ctrl.add_to_server(&mut connection).await; - - let task = CtrlPower::new(config)?; - let sig = SignalContext::new(&connection, "/org/asuslinux/Charge")?; - task.create_tasks(sig).await.ok(); + Ok(ctrl) => { + start_tasks(ctrl, &mut connection).await?; } Err(err) => { - error!("charge_control: {}", err); + error!("CtrlPower: {}", err); } } if Profile::is_platform_profile_supported() { let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into()); match CtrlPlatformProfile::new(profile_config) { - Ok(mut ctrl) => { - ctrl.reload() - .await - .unwrap_or_else(|err| warn!("Profile control: {}", err)); - - let sig = SignalContext::new(&connection, "/org/asuslinux/Profile")?; - - let task = ProfileZbus::new(Arc::new(Mutex::new(ctrl))); - task.create_tasks(sig).await.ok(); - task.add_to_server(&mut connection).await; + Ok(ctrl) => { + let zbus = ProfileZbus(Arc::new(Mutex::new(ctrl))); + start_tasks(zbus, &mut connection).await?; } Err(err) => { error!("Profile control: {}", err); } } } else { - warn!("platform_profile support not found. This requires kernel 5.15.x or the patch applied: https://lkml.org/lkml/2021/8/18/1022"); + warn!("platform_profile support not found"); } match CtrlAnime::new(AnimeConfig::load()) { Ok(ctrl) => { - let inner = Arc::new(Mutex::new(ctrl)); - - let mut reload = CtrlAnimeReloader(inner.clone()); - reload - .reload() - .await - .unwrap_or_else(|err| warn!("AniMe: {}", err)); - - let zbus = CtrlAnimeZbus(inner.clone()); - zbus.add_to_server(&mut connection).await; - - let task = CtrlAnimeTask::new(inner).await; - let sig = SignalContext::new(&connection, "/org/asuslinux/Anime")?; - task.create_tasks(sig).await.ok(); + let zbus = CtrlAnimeZbus(Arc::new(Mutex::new(ctrl))); + start_tasks(zbus, &mut connection).await?; } Err(err) => { error!("AniMe control: {}", err); @@ -165,21 +123,8 @@ async fn start_daemon() -> Result<(), Box> { let aura_config = AuraConfig::load(&laptop); match CtrlKbdLed::new(laptop, aura_config) { Ok(ctrl) => { - let inner = Arc::new(Mutex::new(ctrl)); - - let mut reload = CtrlKbdLedReloader(inner.clone()); - reload - .reload() - .await - .unwrap_or_else(|err| warn!("Keyboard LED control: {}", err)); - - CtrlKbdLedZbus::new(inner.clone()) - .add_to_server(&mut connection) - .await; - - let task = CtrlKbdLedTask::new(inner); - let sig = SignalContext::new(&connection, "/org/asuslinux/Aura")?; - task.create_tasks(sig).await.ok(); + let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl))); + start_tasks(zbus, &mut connection).await?; } Err(err) => { error!("Keyboard control: {}", err); @@ -194,3 +139,20 @@ async fn start_daemon() -> Result<(), Box> { sleep(Duration::from_millis(1000)).await; } } + +async fn start_tasks(mut zbus: T, connection: &mut Connection) -> Result<(), Box> +where + T: ZbusRun + Reloadable + CtrlTask + Clone, +{ + let task = zbus.clone(); + + zbus.reload() + .await + .unwrap_or_else(|err| warn!("Controller error: {}", err)); + zbus.add_to_server(connection).await; + + task.create_tasks(CtrlKbdLedZbus::signal_context(&connection)?) + .await + .ok(); + Ok(()) +} diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index bb6c41c1..31881edd 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -26,34 +26,6 @@ use logind_zbus::manager::ManagerProxy; use zbus::{export::futures_util::StreamExt, Connection, SignalContext}; use zvariant::ObjectPath; -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[async_trait] -pub trait Reloadable { - async fn reload(&mut self) -> Result<(), RogError>; -} - -#[async_trait] -pub trait ZbusRun { - async fn add_to_server(self, server: &mut Connection); - - async fn add_to_server_helper( - iface: impl zbus::Interface, - path: &str, - server: &mut Connection, - ) { - server - .object_server() - .at(&ObjectPath::from_str_unchecked(path), iface) - .await - .map_err(|err| { - warn!("{}: add_to_server {}", path, err); - err - }) - .ok(); - } -} - /// This macro adds a function which spawns an `inotify` task on the passed in `Executor`. /// /// The generated function is `watch_()`. Self requires the following methods to be available: @@ -101,9 +73,43 @@ macro_rules! task_watch_item { }; } +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[async_trait] +pub trait Reloadable { + async fn reload(&mut self) -> Result<(), RogError>; +} + +#[async_trait] +pub trait ZbusRun { + async fn add_to_server(self, server: &mut Connection); + + async fn add_to_server_helper( + iface: impl zbus::Interface, + path: &str, + server: &mut Connection, + ) { + server + .object_server() + .at(&ObjectPath::from_str_unchecked(path), iface) + .await + .map_err(|err| { + warn!("{}: add_to_server {}", path, err); + err + }) + .ok(); + } +} + /// Set up a task to run on the async executor #[async_trait] pub trait CtrlTask { + fn zbus_path() -> &'static str; + + fn signal_context(connection: &Connection) -> Result, zbus::Error> { + SignalContext::new(connection, Self::zbus_path()) + } + /// Implement to set up various tasks that may be required, using the `Executor`. /// No blocking loops are allowed, or they must be run on a separate thread. async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>; diff --git a/design-patterns.md b/design-patterns.md index 8b21e1bf..abe6f135 100644 --- a/design-patterns.md +++ b/design-patterns.md @@ -18,35 +18,43 @@ Then for each trait that is required a new struct is required that can have the Main controller: +For a very simple controller that doesn't need exclusive access you can clone across threads + ```rust -/// For a very simple controller that doesn't need exclusive access you can clone across threads #[derive(Clone)] pub struct CtrlAnime { config: Arc>, } +// This is the task trait used for such things as file watches, or logind +// notifications (boot/suspend/shutdown etc) impl crate::CtrlTask for CtrlAnime {} + +// The trait to easily add the controller to Zbus to enable the zbus derived functions +// to be polled, run, react etc. impl crate::ZbusAdd for CtrlAnime {} impl CtrlAnime {} ``` + Otherwise, you will need to share the controller via mutex + ```rust -/// Otherwise, you will need to share the controller via mutex pub struct CtrlAnime { } // Like this #[derive(Clone)] pub struct CtrlAnimeTask(Arc>); + #[derive(Clone)] pub struct CtrlAnimeZbus(Arc>); impl CtrlAnime {} ``` -The task trait. There are three ways to implement this: +The task trait: ```rust // Mutex should always be async mutex diff --git a/rog-control-center/src/notify.rs b/rog-control-center/src/notify.rs index 80092770..8c6fc275 100644 --- a/rog-control-center/src/notify.rs +++ b/rog-control-center/src/notify.rs @@ -4,8 +4,8 @@ use notify_rust::{Hint, Notification, NotificationHandle}; use rog_aura::AuraEffect; use rog_dbus::{ - zbus_anime::AnimeProxy, zbus_charge::ChargeProxy, zbus_led::LedProxy, - zbus_platform::RogBiosProxy, zbus_profile::ProfileProxy, + zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy, + zbus_power::PowerProxy, zbus_profile::ProfileProxy, }; use rog_profiles::Profile; use smol::{future, Executor}; @@ -102,7 +102,7 @@ pub fn start_notifications( executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); - let proxy = ChargeProxy::new(&conn).await.unwrap(); + let proxy = PowerProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await { p.for_each(|e| { if let Ok(out) = e.args() { diff --git a/rog-dbus/src/lib.rs b/rog-dbus/src/lib.rs index b44eb28b..1bd15dd7 100644 --- a/rog-dbus/src/lib.rs +++ b/rog-dbus/src/lib.rs @@ -3,9 +3,9 @@ pub static DBUS_PATH: &str = "/org/asuslinux/Daemon"; pub static DBUS_IFACE: &str = "org.asuslinux.Daemon"; pub mod zbus_anime; -pub mod zbus_charge; pub mod zbus_led; pub mod zbus_platform; +pub mod zbus_power; pub mod zbus_profile; pub mod zbus_supported; @@ -19,7 +19,7 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub struct DbusProxiesBlocking<'a> { anime: zbus_anime::AnimeProxyBlocking<'a>, - charge: zbus_charge::ChargeProxyBlocking<'a>, + charge: zbus_power::PowerProxyBlocking<'a>, led: zbus_led::LedProxyBlocking<'a>, profile: zbus_profile::ProfileProxyBlocking<'a>, rog_bios: zbus_platform::RogBiosProxyBlocking<'a>, @@ -35,7 +35,7 @@ impl<'a> DbusProxiesBlocking<'a> { DbusProxiesBlocking { anime: zbus_anime::AnimeProxyBlocking::new(&conn)?, led: zbus_led::LedProxyBlocking::new(&conn)?, - charge: zbus_charge::ChargeProxyBlocking::new(&conn)?, + charge: zbus_power::PowerProxyBlocking::new(&conn)?, profile: zbus_profile::ProfileProxyBlocking::new(&conn)?, rog_bios: zbus_platform::RogBiosProxyBlocking::new(&conn)?, supported: zbus_supported::SupportedProxyBlocking::new(&conn)?, @@ -48,7 +48,7 @@ impl<'a> DbusProxiesBlocking<'a> { &self.anime } - pub fn charge(&self) -> &zbus_charge::ChargeProxyBlocking<'a> { + pub fn charge(&self) -> &zbus_power::PowerProxyBlocking<'a> { &self.charge } @@ -88,7 +88,7 @@ impl<'a> RogDbusClientBlocking<'a> { pub struct DbusProxies<'a> { anime: zbus_anime::AnimeProxy<'a>, - charge: zbus_charge::ChargeProxy<'a>, + charge: zbus_power::PowerProxy<'a>, led: zbus_led::LedProxy<'a>, profile: zbus_profile::ProfileProxy<'a>, rog_bios: zbus_platform::RogBiosProxy<'a>, @@ -104,7 +104,7 @@ impl<'a> DbusProxies<'a> { DbusProxies { anime: zbus_anime::AnimeProxy::new(&conn).await?, led: zbus_led::LedProxy::new(&conn).await?, - charge: zbus_charge::ChargeProxy::new(&conn).await?, + charge: zbus_power::PowerProxy::new(&conn).await?, profile: zbus_profile::ProfileProxy::new(&conn).await?, rog_bios: zbus_platform::RogBiosProxy::new(&conn).await?, supported: zbus_supported::SupportedProxy::new(&conn).await?, @@ -117,7 +117,7 @@ impl<'a> DbusProxies<'a> { &self.anime } - pub fn charge(&self) -> &zbus_charge::ChargeProxy<'a> { + pub fn charge(&self) -> &zbus_power::PowerProxy<'a> { &self.charge } diff --git a/rog-dbus/src/zbus_charge.rs b/rog-dbus/src/zbus_power.rs similarity index 95% rename from rog-dbus/src/zbus_charge.rs rename to rog-dbus/src/zbus_power.rs index ca93550b..4b242d83 100644 --- a/rog-dbus/src/zbus_charge.rs +++ b/rog-dbus/src/zbus_power.rs @@ -23,9 +23,9 @@ use zbus_macros::dbus_proxy; #[dbus_proxy( interface = "org.asuslinux.Daemon", - default_path = "/org/asuslinux/Charge" + default_path = "/org/asuslinux/Power" )] -trait Charge { +trait Power { /// charge_control_end_threshold method fn charge_control_end_threshold(&self) -> zbus::Result;