diff --git a/CHANGELOG.md b/CHANGELOG.md index a5076cb7..5a25f93e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for G513IC LED modes (Author: dada513) - Support for G513QM LED modes (Author: Martin Piffault) - Add side-LED toggle support (Author: Martin Piffault) +- Support reloading keyboard brightness and mode on wake (from sleep/hiber) +- Support reloading charge-level on wake (from sleep/hiber) +- Support running AniMe animation blocks on wake/sleep and boot/shutdown events # [4.0.7] - 2021-12-19 ### Changed diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index d9da60d8..cdf574e8 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -300,18 +300,18 @@ impl CtrlAnime { } pub struct CtrlAnimeTask { - _inner: Arc>, + inner: Arc>, } impl CtrlAnimeTask { pub async fn new(inner: Arc>) -> CtrlAnimeTask { - Self { _inner: inner } + Self { inner } } } #[async_trait] impl crate::CtrlTask for CtrlAnimeTask { - async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { let connection = Connection::system() .await .expect("CtrlAnimeTask could not create dbus connection"); @@ -320,17 +320,37 @@ impl crate::CtrlTask for CtrlAnimeTask { .await .expect("CtrlAnimeTask could not create ManagerProxy"); - let x = self._inner.clone(); + let inner = self.inner.clone(); executor .spawn(async move { - if let Ok(p) = manager.receive_prepare_for_sleep().await { - p.for_each(|_| { - if let Ok(_lock) = x.clone().try_lock() { - info!("AniMe received sleep event (this feature is not yet complete)"); - // lock.config.system - } - }) - .await; + if let Ok(notif) = manager.receive_prepare_for_sleep().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + if args.start { + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running sleep animation"); + lock.thread_exit.store(true, Ordering::Relaxed); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.shutdown.clone(), + true, + ); + } + } else { + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running wake animation"); + lock.thread_exit.store(true, Ordering::Relaxed); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.wake.clone(), + true, + ); + } + } + } + }) + .await; } }) .detach(); @@ -339,19 +359,38 @@ impl crate::CtrlTask for CtrlAnimeTask { .await .expect("CtrlAnimeTask could not create ManagerProxy"); - let x = self._inner.clone(); + let inner = self.inner.clone(); executor .spawn(async move { - if let Ok(p) = manager.receive_prepare_for_shutdown().await { - p.for_each(|_| { - if let Ok(_lock) = x.clone().try_lock() { - info!( - "AniMe received shutdown event (this feature is not yet complete)" - ); - // lock.config.system - } - }) - .await; + if let Ok(notif) = manager.receive_prepare_for_shutdown().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + if args.start { + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running sleep animation"); + lock.thread_exit.store(true, Ordering::Relaxed); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.shutdown.clone(), + true, + ); + } + } else { + // If waking up - intention is to catch hibernation event + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running wake animation"); + lock.thread_exit.store(true, Ordering::Relaxed); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.wake.clone(), + true, + ); + } + } + } + }) + .await; } }) .detach(); diff --git a/daemon/src/ctrl_anime/zbus.rs b/daemon/src/ctrl_anime/zbus.rs index 0778e37d..f769b2da 100644 --- a/daemon/src/ctrl_anime/zbus.rs +++ b/daemon/src/ctrl_anime/zbus.rs @@ -1,13 +1,11 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use log::warn; use rog_anime::{ usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on}, AnimeDataBuffer, AnimePowerStates, }; use zbus::{dbus_interface, Connection, SignalContext}; -use zvariant::ObjectPath; use std::sync::atomic::Ordering; @@ -19,18 +17,7 @@ pub struct CtrlAnimeZbus(pub Arc>); #[async_trait] impl crate::ZbusAdd for CtrlAnimeZbus { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/Anime"), - self, - ) - .await - .map_err(|err| { - warn!("CtrlAnimeDisplay: add_to_server {}", err); - err - }) - .ok(); + Self::add_to_server_helper(self, "/org/asuslinux/Anime", server).await; } } diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index 07ed81c0..a1978db8 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -7,7 +7,7 @@ use crate::{ CtrlTask, }; use async_trait::async_trait; -use log::{info, warn}; +use log::{error, info, warn}; use logind_zbus::manager::ManagerProxy; use rog_aura::{ usb::{ @@ -92,7 +92,7 @@ impl CtrlKbdLedTask { #[async_trait] impl CtrlTask for CtrlKbdLedTask { - async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { let connection = Connection::system() .await .expect("CtrlKbdLedTask could not create dbus connection"); @@ -104,14 +104,32 @@ impl CtrlTask for CtrlKbdLedTask { let inner = self.inner.clone(); executor .spawn(async move { - if let Ok(p) = manager.receive_prepare_for_sleep().await { - p.for_each(|_| { - if let Ok(_lock) = inner.clone().try_lock() { - info!("CtrlKbdLedTask received sleep event (this feature is not yet complete)"); - // lock.config.system - } - }) - .await; + if let Ok(notif) = manager.receive_prepare_for_sleep().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + // If waking up + if !args.start { + info!("CtrlKbdLedTask reloading brightness and modes"); + if let Ok(lock) = inner.clone().try_lock() { + lock.set_brightness(lock.config.brightness) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + lock.set_side_leds_states(lock.config.side_leds_enabled) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + if let Some(mode) = + lock.config.builtins.get(&lock.config.current_mode) + { + lock.write_mode(mode) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + } + } + } + } + }) + .await; } }) .detach(); @@ -138,11 +156,11 @@ impl crate::Reloadable for CtrlKbdLedReloader { } ctrl.set_states_enabled(ctrl.config.awake_enabled, ctrl.config.sleep_anim_enabled) - .map_err(|err| warn!("{}", err)) + .map_err(|err| warn!("{err}")) .ok(); ctrl.set_side_leds_states(ctrl.config.side_leds_enabled) - .map_err(|err| warn!("{}", err)) + .map_err(|err| warn!("{err}")) .ok(); } Ok(()) @@ -166,9 +184,10 @@ impl CtrlKbdLed { match Self::find_led_node(prod) { Ok(node) => { led_node = Some(node); + info!("Found keyboard controller 0x{prod}"); break; } - Err(err) => warn!("led_node: {}", err), + Err(err) => info!("Looked for keyboard controller 0x{prod}: {err}"), } } diff --git a/daemon/src/ctrl_aura/zbus.rs b/daemon/src/ctrl_aura/zbus.rs index debca4f6..efc7f552 100644 --- a/daemon/src/ctrl_aura/zbus.rs +++ b/daemon/src/ctrl_aura/zbus.rs @@ -1,22 +1,14 @@ use async_trait::async_trait; -use log::{error, warn}; +use log::warn; use rog_aura::{AuraEffect, LedBrightness, LedPowerStates}; use zbus::{dbus_interface, Connection, SignalContext}; -use zvariant::ObjectPath; use super::controller::CtrlKbdLedZbus; #[async_trait] impl crate::ZbusAdd for CtrlKbdLedZbus { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at(&ObjectPath::from_str_unchecked("/org/asuslinux/Led"), self) - .await - .map_err(|err| { - error!("DbusKbdLed: add_to_server {}", err); - }) - .ok(); + Self::add_to_server_helper(self, "/org/asuslinux/Led", server).await; } } diff --git a/daemon/src/ctrl_charge.rs b/daemon/src/ctrl_charge.rs index 1e1bc020..d049b371 100644 --- a/daemon/src/ctrl_charge.rs +++ b/daemon/src/ctrl_charge.rs @@ -1,7 +1,11 @@ +use crate::CtrlTask; use crate::{config::Config, error::RogError, GetSupported}; use async_trait::async_trait; use log::{info, warn}; +use logind_zbus::manager::ManagerProxy; use rog_supported::ChargeSupportedFunctions; +use smol::stream::StreamExt; +use smol::Executor; use std::fs::OpenOptions; use std::io::Write; use std::path::Path; @@ -10,7 +14,6 @@ use std::sync::Mutex; use zbus::dbus_interface; use zbus::Connection; use zbus::SignalContext; -use zvariant::ObjectPath; static BAT_CHARGE_PATH0: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold"; static BAT_CHARGE_PATH1: &str = "/sys/class/power_supply/BAT1/charge_control_end_threshold"; @@ -41,7 +44,7 @@ impl CtrlCharge { return Err(RogError::ChargeLimit(limit))?; } if let Ok(mut config) = self.config.try_lock() { - self.set(limit, &mut config) + Self::set(limit, &mut config) .map_err(|err| { warn!("CtrlCharge: set_limit {}", err); err @@ -66,18 +69,7 @@ impl CtrlCharge { #[async_trait] impl crate::ZbusAdd for CtrlCharge { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/Charge"), - self, - ) - .await - .map_err(|err| { - warn!("CtrlCharge: add_to_server {}", err); - err - }) - .ok(); + Self::add_to_server_helper(self, "/org/asuslinux/Charge", server).await; } } @@ -85,7 +77,7 @@ impl crate::Reloadable for CtrlCharge { fn reload(&mut self) -> Result<(), RogError> { if let Ok(mut config) = self.config.try_lock() { config.read(); - self.set(config.bat_charge_limit, &mut config)?; + Self::set(config.bat_charge_limit, &mut config)?; } Ok(()) } @@ -112,7 +104,7 @@ impl CtrlCharge { } } - pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> { + pub(super) fn set(limit: u8, config: &mut Config) -> Result<(), RogError> { if !(20..=100).contains(&limit) { return Err(RogError::ChargeLimit(limit)); } @@ -134,3 +126,73 @@ impl CtrlCharge { Ok(()) } } + +#[async_trait] +impl CtrlTask for CtrlCharge { + async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { + let connection = Connection::system() + .await + .expect("CtrlCharge could not create dbus connection"); + + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlCharge could not create ManagerProxy"); + + let config1 = self.config.clone(); + executor + .spawn(async move { + if let Ok(notif) = manager.receive_prepare_for_sleep().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + // If waking up + if !args.start { + info!("CtrlCharge reloading charge limit"); + if let Ok(mut lock) = config1.try_lock() { + Self::set(lock.bat_charge_limit, &mut lock) + .map_err(|err| { + warn!("CtrlCharge: set_limit {}", err); + err + }) + .ok(); + } + } + } + }) + .await; + } + }) + .detach(); + + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlCharge could not create ManagerProxy"); + + let config = self.config.clone(); + executor + .spawn(async move { + if let Ok(notif) = manager.receive_prepare_for_shutdown().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + // If waking up - intention is to catch hibernation event + if !args.start { + info!("CtrlCharge reloading charge limit"); + if let Ok(mut lock) = config.clone().try_lock() { + Self::set(lock.bat_charge_limit, &mut lock) + .map_err(|err| { + warn!("CtrlCharge: set_limit {}", err); + err + }) + .ok(); + } + } + } + }) + .await; + } + }) + .detach(); + Ok(()) + } +} diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 52c6fafe..b25fde0a 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -139,7 +139,7 @@ impl CtrlProfileTask { #[async_trait] impl CtrlTask for CtrlProfileTask { - async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { let ctrl = self.ctrl.clone(); self.repeating_task(666, executor, move || { if let Ok(ref mut lock) = ctrl.try_lock() { diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index 3ea9a793..3282c519 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -3,17 +3,12 @@ use log::warn; use rog_profiles::fan_curve_set::CurveData; use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::Profile; -use smol::Executor; use zbus::Connection; use zbus::SignalContext; use std::sync::Arc; use std::sync::Mutex; use zbus::{dbus_interface, fdo::Error}; -use zvariant::ObjectPath; - -use crate::error::RogError; -use crate::CtrlTask; use super::controller::CtrlPlatformProfile; @@ -187,36 +182,6 @@ impl ProfileZbus { #[async_trait] impl crate::ZbusAdd for ProfileZbus { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/Profile"), - self, - ) - .await - .map_err(|err| { - warn!("DbusFanAndCpu: add_to_server {}", err); - err - }) - .ok(); - } -} - -#[async_trait] -impl CtrlTask for ProfileZbus { - async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { - let inner = self.inner.clone(); - self.repeating_task(500, executor, move || { - if let Ok(ref mut lock) = inner.try_lock() { - let new_profile = Profile::get_active_profile().unwrap(); - if new_profile != lock.config.active_profile { - lock.config.active_profile = new_profile; - lock.write_profile_curve_to_platform().unwrap(); - lock.save_config(); - } - } - }) - .await; - Ok(()) + Self::add_to_server_helper(self, "/org/asuslinux/Profile", server).await; } } diff --git a/daemon/src/ctrl_rog_bios.rs b/daemon/src/ctrl_rog_bios.rs index e739b1c5..e66d7249 100644 --- a/daemon/src/ctrl_rog_bios.rs +++ b/daemon/src/ctrl_rog_bios.rs @@ -11,7 +11,6 @@ use std::sync::Arc; use std::sync::Mutex; use zbus::Connection; use zbus::{dbus_interface, SignalContext}; -use zvariant::ObjectPath; const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs"; const DRACUT_PATH: &str = "/usr/bin/dracut"; @@ -100,18 +99,7 @@ impl CtrlRogBios { #[async_trait] impl crate::ZbusAdd for CtrlRogBios { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/RogBios"), - self, - ) - .await - .map_err(|err| { - warn!("CtrlRogBios: add_to_server {}", err); - err - }) - .ok(); + Self::add_to_server_helper(self, "/org/asuslinux/RogBios", server).await; } } diff --git a/daemon/src/ctrl_supported.rs b/daemon/src/ctrl_supported.rs index ef339d64..a956b30c 100644 --- a/daemon/src/ctrl_supported.rs +++ b/daemon/src/ctrl_supported.rs @@ -1,9 +1,7 @@ use async_trait::async_trait; -use log::warn; use serde_derive::{Deserialize, Serialize}; use zbus::dbus_interface; use zbus::Connection; -use zvariant::ObjectPath; use zvariant::Type; use crate::{ @@ -35,18 +33,7 @@ impl SupportedFunctions { #[async_trait] impl crate::ZbusAdd for SupportedFunctions { async fn add_to_server(self, server: &mut Connection) { - server - .object_server() - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/Supported"), - self, - ) - .await - .map_err(|err| { - warn!("SupportedFunctions: add_to_server {}", err); - err - }) - .ok(); + Self::add_to_server_helper(self, "/org/asuslinux/Supported", server).await; } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 0cc0fc28..77c2ce3a 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -94,13 +94,16 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> } } - match CtrlCharge::new(config) { + match CtrlCharge::new(config.clone()) { Ok(mut ctrl) => { // Do a reload of any settings ctrl.reload() .unwrap_or_else(|err| warn!("Battery charge limit: {}", err)); // Then register to dbus server ctrl.add_to_server(&mut connection).await; + + let task = CtrlCharge::new(config)?; + task.create_tasks(executor).await.ok(); } Err(err) => { error!("charge_control: {}", err); @@ -116,11 +119,9 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> let tmp = Arc::new(Mutex::new(ctrl)); let task = CtrlProfileTask::new(tmp.clone()); - task.create_task(executor).await.ok(); + task.create_tasks(executor).await.ok(); let task = ProfileZbus::new(tmp.clone()); - task.create_task(executor).await.ok(); - task.add_to_server(&mut connection).await; } Err(err) => { @@ -144,7 +145,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> zbus.add_to_server(&mut connection).await; let task = CtrlAnimeTask::new(inner).await; - task.create_task(executor).await.ok(); + task.create_tasks(executor).await.ok(); } Err(err) => { error!("AniMe control: {}", err); @@ -167,7 +168,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> .await; let task = CtrlKbdLedTask::new(inner); - task.create_task(executor).await.ok(); + task.create_tasks(executor).await.ok(); } Err(err) => { error!("Keyboard control: {}", err); @@ -176,7 +177,6 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> // Request dbus name after finishing initalizing all functions connection.request_name(DBUS_NAME).await?; - dbg!(); loop { smol::block_on(executor.tick()); } diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index f28fed00..0ad9bbde 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -34,8 +34,10 @@ use std::time::Duration; use crate::error::RogError; use async_trait::async_trait; use config::Config; +use log::warn; use smol::{stream::StreamExt, Executor, Timer}; use zbus::Connection; +use zvariant::ObjectPath; pub static VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -46,12 +48,30 @@ pub trait Reloadable { #[async_trait] pub trait ZbusAdd { 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 { - async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError>; + /// 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, executor: &mut Executor) -> Result<(), RogError>; /// Create a timed repeating task async fn repeating_task( diff --git a/design-patterns.md b/design-patterns.md index 3a091ab1..25b59b52 100644 --- a/design-patterns.md +++ b/design-patterns.md @@ -28,18 +28,53 @@ impl CtrlAnime { } ``` -The task trait: +The task trait. There are three ways to implement this: ```rust pub struct CtrlAnimeTask(Arc>); impl crate::CtrlTask for CtrlAnimeTask { - fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + // This will run once only + fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { if let Ok(lock) = self.inner.try_lock() { } Ok(()) } + + // This will run until the notification stream closes (which in most cases will be never) + fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { + let connection = Connection::system().await.unwrap(); + let manager = ManagerProxy::new(&connection).await.unwrap(); + + let inner = self.inner.clone(); + executor + .spawn(async move { + // A notification from logind dbus interface + if let Ok(p) = manager.receive_prepare_for_sleep().await { + // A stream that will continuously output events + p.for_each(|_| { + if let Ok(lock) = inner.try_lock() { + // Do stuff here + } + }) + .await; + } + }) + .detach(); + } + + // This task will run every 500 milliseconds + fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { + let inner = self.inner.clone(); + // This is a provided free trait to help set up a repeating task + self.repeating_task(500, executor, move || { + if let Ok(lock) = inner.try_lock() { + // Do stuff here + } + }) + .await; + } } ``` @@ -61,18 +96,11 @@ The Zbus requirements: ```rust pub struct CtrlAnimeZbus(Arc>); +#[async_trait] impl crate::ZbusAdd for CtrlAnimeZbus { fn add_to_server(self, server: &mut zbus::ObjectServer) { - server - .at( - &ObjectPath::from_str_unchecked("/org/asuslinux/Anime"), - self, - ) - .map_err(|err| { - warn!("CtrlAnimeDisplay: add_to_server {}", err); - err - }) - .ok(); + // This is a provided free helper trait with pre-set body. It will move self in-to. + Self::add_to_server_helper(self, "/org/asuslinux/Anime", server).await; } }