Further improve the daemon controller pattern and reduce cloned code

This commit is contained in:
Luke D. Jones
2022-09-23 20:07:43 +12:00
parent 7ea1f41286
commit 30550aaa91
21 changed files with 382 additions and 416 deletions

View File

@@ -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 <luke@ljones.dev>"]

View File

@@ -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<Mutex<CtrlAnime>>,
}
impl CtrlAnimeTask {
pub async fn new(inner: Arc<Mutex<CtrlAnime>>) -> 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<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
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<Mutex<CtrlAnime>>);
#[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(())
}
}

View File

@@ -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<Mutex<CtrlAnime>>);
/// 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<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
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(())
}
}

View File

@@ -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<Mutex<CtrlKbdLed>>,
}
impl CtrlKbdLedTask {
pub fn new(inner: Arc<Mutex<CtrlKbdLed>>) -> 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<CtrlKbdLed>| {
// 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<Mutex<CtrlKbdLed>>);
#[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<Mutex<CtrlKbdLed>>);
impl CtrlKbdLedZbus {
pub fn new(inner: Arc<Mutex<CtrlKbdLed>>) -> Self {
Self(inner)
}
}
impl CtrlKbdLed {
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
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;

View File

@@ -1,3 +1,4 @@
pub mod config;
pub mod controller;
pub mod zbus;
/// Implements CtrlTask, Reloadable, ZbusRun
pub mod trait_impls;

View File

@@ -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<Mutex<CtrlKbdLed>>);
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<CtrlKbdLed>| {
// 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(())
}
}

View File

@@ -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<Mutex<Config>>,
}
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<Mutex<Config>>) -> Result<Self, RogError> {
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();

View File

@@ -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();

View File

@@ -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<Self, RogError> {
let platform = AsusPlatform::new()?;

View File

@@ -1,3 +1,4 @@
pub mod config;
pub mod controller;
pub mod zbus;
/// Implements CtrlTask, Reloadable, ZbusRun
pub mod trait_impls;

View File

@@ -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<Mutex<CtrlPlatformProfile>>,
}
impl ProfileZbus {
pub fn new(inner: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
Self { inner }
}
}
#[derive(Clone)]
pub struct ProfileZbus(pub Arc<Mutex<CtrlPlatformProfile>>);
#[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<Profile> {
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<Vec<Profile>> {
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<FanCurveSet> {
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(())
}
}

View File

@@ -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(),
}
}
}

View File

@@ -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<dyn Error>> {
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<dyn Error>> {
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<dyn Error>> {
sleep(Duration::from_millis(1000)).await;
}
}
async fn start_tasks<T>(mut zbus: T, connection: &mut Connection) -> Result<(), Box<dyn Error>>
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(())
}

View File

@@ -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_<name>()`. 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<SignalContext<'static>, 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>;