Convert chunk of daemon to use async mutex

This commit is contained in:
Luke D. Jones
2022-09-23 10:50:09 +12:00
parent 9608d190b9
commit 7ea1f41286
16 changed files with 435 additions and 500 deletions

View File

@@ -17,10 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use loops to ensure that mutex is gained for LED changes.
- asusctl now uses tokio for async runtime. This helps simplify some code.
### Breaking
- DBUS: all charge control methods renamed:
- DBUS: all charge control methods renamed to:
- `ChargeControlEndThreshold`
- `SetChargeControlEndThreshold`
- `NotifyChargeControlEndThreshold`
- `PanelOd` (form PanelOverdrive)
- `SetPanelOd`
- `NotifyPanelOd`
## [v4.4.0] - 2022-08-29
### Added

3
Cargo.lock generated
View File

@@ -572,12 +572,11 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]]
name = "daemon"
version = "4.4.0"
version = "4.5.0-rc1"
dependencies = [
"async-trait",
"concat-idents",
"env_logger",
"inotify",
"log",
"logind-zbus",
"rog_anime",

View File

@@ -1,6 +1,6 @@
[package]
name = "daemon"
version = "4.4.0"
version = "4.5.0-rc1"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
@@ -44,5 +44,4 @@ toml = "^0.5.8"
# Device control
sysfs-class = "^0.1.2" # used for backlight control and baord ID
inotify = { version = "0.10.0", default-features = false }
concat-idents = "1.1.3"

View File

@@ -1,6 +1,7 @@
pub mod config;
pub mod zbus;
use ::zbus::export::futures_util::lock::{Mutex, MutexGuard};
use ::zbus::SignalContext;
use async_trait::async_trait;
use log::{error, info, warn};
@@ -14,12 +15,7 @@ use rog_anime::{
};
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, Mutex, MutexGuard},
thread::sleep,
};
use std::{convert::TryFrom, error::Error, sync::Arc, thread::sleep};
use crate::{error::RogError, GetSupported};
@@ -85,6 +81,7 @@ impl CtrlAnime {
// The only reason for this outer thread is to prevent blocking while waiting for the
// next spawned thread to exit
// TODO: turn this in to async task (maybe? COuld still risk blocking main thread)
std::thread::Builder::new()
.name("AniMe system thread start".into())
.spawn(move || {
@@ -95,7 +92,7 @@ impl CtrlAnime {
let thread_running;
let anime_type;
loop {
if let Ok(lock) = inner.try_lock() {
if let Some(lock) = inner.try_lock() {
thread_exit = lock.thread_exit.clone();
thread_running = lock.thread_running.clone();
anime_type = lock.anime_type;
@@ -139,9 +136,10 @@ impl CtrlAnime {
.ok();
false // Don't exit yet
})
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
AnimeError::NoFrames
.map(|r| Ok(r))
.unwrap_or_else(|| {
warn!("rog_anime::run_animation:callback failed");
Err(AnimeError::NoFrames)
})
}) {
warn!("rog_anime::run_animation:Animation {}", err);
@@ -150,7 +148,7 @@ impl CtrlAnime {
}
ActionData::Image(image) => {
once = false;
if let Ok(lock) = inner.try_lock() {
if let Some(lock) = inner.try_lock() {
lock.write_data_buffer(image.as_ref().clone())
.map_err(|e| error!("{}", e))
.ok();
@@ -171,7 +169,7 @@ impl CtrlAnime {
}
}
// Clear the display on exit
if let Ok(lock) = inner.try_lock() {
if let Some(lock) = inner.try_lock() {
if let Ok(data) =
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()])
.map_err(|e| error!("{}", e))
@@ -249,25 +247,25 @@ impl crate::CtrlTask for CtrlAnimeTask {
// 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 Ok(lock) = inner1.clone().try_lock() {
if let Some(lock) = inner1.try_lock() {
run_action(true, lock, inner1.clone());
break;
}
},
move || loop {
if let Ok(lock) = inner2.clone().try_lock() {
if let Some(lock) = inner2.try_lock() {
run_action(false, lock, inner2.clone());
break;
}
},
move || loop {
if let Ok(lock) = inner3.clone().try_lock() {
if let Some(lock) = inner3.try_lock() {
run_action(true, lock, inner3.clone());
break;
}
},
move || loop {
if let Ok(lock) = inner4.clone().try_lock() {
if let Some(lock) = inner4.try_lock() {
run_action(false, lock, inner4.clone());
break;
}
@@ -281,9 +279,10 @@ impl crate::CtrlTask for CtrlAnimeTask {
pub struct CtrlAnimeReloader(pub Arc<Mutex<CtrlAnime>>);
#[async_trait]
impl crate::Reloadable for CtrlAnimeReloader {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(lock) = self.0.try_lock() {
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())?;

View File

@@ -1,14 +1,12 @@
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 zbus::{dbus_interface, export::futures_util::lock::Mutex, Connection, SignalContext};
use std::sync::atomic::Ordering;
use std::sync::{atomic::Ordering, Arc};
use super::CtrlAnime;
@@ -16,7 +14,7 @@ pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
/// The struct with the main dbus methods requires this trait
#[async_trait]
impl crate::ZbusAdd for CtrlAnimeZbus {
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;
}
@@ -28,127 +26,105 @@ impl crate::ZbusAdd for CtrlAnimeZbus {
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlAnimeZbus {
/// Writes a data stream of length. Will force system thread to exit until it is restarted
fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
'outer: loop {
if let Ok(lock) = self.0.try_lock() {
lock.thread_exit.store(true, Ordering::SeqCst);
lock.write_data_buffer(input).map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
err
})?;
break 'outer;
}
}
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
lock.write_data_buffer(input).map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
err
})?;
Ok(())
}
/// Set the global AniMe brightness
fn set_brightness(&self, bright: f32) {
'outer: loop {
if let Ok(mut lock) = self.0.try_lock() {
let mut bright = bright;
if bright < 0.0 {
bright = 0.0
} else if bright > 1.0 {
bright = 1.0;
}
lock.config.brightness = bright;
lock.config.write();
break 'outer;
}
async fn set_brightness(&self, bright: f32) {
let mut lock = self.0.lock().await;
let mut bright = bright;
if bright < 0.0 {
bright = 0.0
} else if bright > 1.0 {
bright = 1.0;
}
lock.config.brightness = bright;
lock.config.write();
}
/// Set whether the AniMe is displaying images/data
async fn set_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
let states;
'outer: loop {
if let Ok(mut lock) = self.0.try_lock() {
lock.node
.write_bytes(&pkt_for_set_on(status))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.awake_enabled = status;
lock.config.write();
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_for_set_on(status))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.awake_enabled = status;
lock.config.write();
states = Some(AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
});
break 'outer;
}
}
if let Some(state) = states {
Self::notify_power_states(&ctxt, state).await.ok();
}
Self::notify_power_states(
&ctxt,
AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
},
)
.await
.ok();
}
/// Set whether the AniMe will show boot, suspend, or off animations
async fn set_boot_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, on: bool) {
let states;
'outer: loop {
if let Ok(mut lock) = self.0.try_lock() {
lock.node
.write_bytes(&pkt_for_set_boot(on))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.node
.write_bytes(&pkt_for_apply())
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.boot_anim_enabled = on;
lock.config.write();
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_for_set_boot(on))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.node
.write_bytes(&pkt_for_apply())
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.boot_anim_enabled = on;
lock.config.write();
states = Some(AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
});
break 'outer;
}
}
if let Some(state) = states {
Self::notify_power_states(&ctxt, state).await.ok();
}
Self::notify_power_states(
&ctxt,
AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
},
)
.await
.ok();
}
/// The main loop is the base system set action if the user isn't running
/// the user daemon
fn run_main_loop(&self, start: bool) {
async fn run_main_loop(&self, start: bool) {
if start {
'outer: loop {
if let Ok(lock) = self.0.try_lock() {
lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
break 'outer;
}
}
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
}
}
/// Get status of if the AniMe LEDs are on/displaying while system is awake
#[dbus_interface(property)]
fn awake_enabled(&self) -> bool {
if let Ok(ctrl) = self.0.try_lock() {
return ctrl.config.awake_enabled;
}
true
async fn awake_enabled(&self) -> bool {
let lock = self.0.lock().await;
return lock.config.awake_enabled;
}
/// Get the status of if factory system-status animations are enabled
#[dbus_interface(property)]
fn boot_enabled(&self) -> bool {
if let Ok(ctrl) = self.0.try_lock() {
return ctrl.config.boot_anim_enabled;
}
true
async fn boot_enabled(&self) -> bool {
let lock = self.0.lock().await;
return lock.config.boot_anim_enabled;
}
/// Notify listeners of the status of AniMe LED power and factory system-status animations

View File

@@ -13,9 +13,13 @@ 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 std::sync::Mutex;
use std::sync::MutexGuard;
use zbus::{export::futures_util::StreamExt, SignalContext};
use zbus::{
export::futures_util::{
lock::{Mutex, MutexGuard},
StreamExt,
},
SignalContext,
};
use crate::GetSupported;
@@ -121,25 +125,25 @@ impl CtrlTask for CtrlKbdLedTask {
// Loop so that we do aquire the lock but also don't block other
// threads (prevents potential deadlocks)
move || loop {
if let Ok(lock) = inner1.clone().try_lock() {
if let Some(lock) = inner1.try_lock() {
load_save(true, lock);
break;
}
},
move || loop {
if let Ok(lock) = inner2.clone().try_lock() {
if let Some(lock) = inner2.try_lock() {
load_save(false, lock);
break;
}
},
move || loop {
if let Ok(lock) = inner3.clone().try_lock() {
if let Some(lock) = inner3.try_lock() {
load_save(true, lock);
break;
}
},
move || loop {
if let Ok(lock) = inner4.clone().try_lock() {
if let Some(lock) = inner4.try_lock() {
load_save(false, lock);
break;
}
@@ -148,21 +152,20 @@ impl CtrlTask for CtrlKbdLedTask {
.await;
let ctrl2 = self.inner.clone();
if let Ok(ctrl) = self.inner.lock() {
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 Ok(lock) = ctrl2.try_lock() {
load_save(true, lock);
}
})
.await;
});
}
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(())
}
@@ -170,12 +173,12 @@ impl CtrlTask for CtrlKbdLedTask {
pub struct CtrlKbdLedReloader(pub Arc<Mutex<CtrlKbdLed>>);
#[async_trait]
impl crate::Reloadable for CtrlKbdLedReloader {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.write_current_config_mode()?;
ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
}
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

@@ -8,7 +8,7 @@ use zbus::{dbus_interface, Connection, SignalContext};
use super::controller::CtrlKbdLedZbus;
#[async_trait]
impl crate::ZbusAdd for CtrlKbdLedZbus {
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;
}
@@ -21,11 +21,10 @@ impl crate::ZbusAdd for CtrlKbdLedZbus {
impl CtrlKbdLedZbus {
/// Set the keyboard brightness level (0-3)
async fn set_brightness(&mut self, brightness: LedBrightness) {
if let Ok(ctrl) = self.0.try_lock() {
ctrl.set_brightness(brightness)
.map_err(|err| warn!("{}", err))
.ok();
}
let ctrl = self.0.lock().await;
ctrl.set_brightness(brightness)
.map_err(|err| warn!("{}", err))
.ok();
}
/// Set a variety of states, input is array of enum.
@@ -64,36 +63,27 @@ impl CtrlKbdLedZbus {
options: AuraPowerDev,
enabled: bool,
) -> zbus::fdo::Result<()> {
let mut states = None;
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
for p in options.tuf {
ctrl.config.enabled.set_tuf(p, enabled);
}
for p in options.x1866 {
ctrl.config.enabled.set_0x1866(p, enabled);
}
for p in options.x19b6 {
ctrl.config.enabled.set_0x19b6(p, enabled);
}
ctrl.config.write();
ctrl.set_power_states().map_err(|e| {
warn!("{}", e);
e
})?;
states = Some(AuraPowerDev::from(&ctrl.config.enabled));
}
break;
let mut ctrl = self.0.lock().await;
for p in options.tuf {
ctrl.config.enabled.set_tuf(p, enabled);
}
// Need to pull state out like this due to MutexGuard
if let Some(states) = states {
Self::notify_power_states(&ctxt, &states)
.await
.unwrap_or_else(|err| warn!("{}", err));
for p in options.x1866 {
ctrl.config.enabled.set_0x1866(p, enabled);
}
for p in options.x19b6 {
ctrl.config.enabled.set_0x19b6(p, enabled);
}
ctrl.config.write();
ctrl.set_power_states().map_err(|e| {
warn!("{}", e);
e
})?;
Self::notify_power_states(&ctxt, &AuraPowerDev::from(&ctrl.config.enabled))
.await
.unwrap_or_else(|err| warn!("{}", err));
Ok(())
}
@@ -102,21 +92,15 @@ impl CtrlKbdLedZbus {
#[zbus(signal_context)] ctxt: SignalContext<'_>,
effect: AuraEffect,
) -> zbus::fdo::Result<()> {
let mut led = None;
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.set_effect(effect).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
led = Some(mode.clone());
}
break;
}
}
if let Some(led) = led {
Self::notify_led(&ctxt, led)
let mut ctrl = self.0.lock().await;
ctrl.set_effect(effect).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
@@ -127,22 +111,15 @@ impl CtrlKbdLedZbus {
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
) -> zbus::fdo::Result<()> {
let mut led = None;
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.toggle_mode(false).map_err(|e| {
warn!("{}", e);
e
})?;
let mut ctrl = self.0.lock().await;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
led = Some(mode.clone());
}
break;
}
}
if let Some(led) = led {
Self::notify_led(&ctxt, led)
ctrl.toggle_mode(false).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
@@ -154,100 +131,70 @@ impl CtrlKbdLedZbus {
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
) -> zbus::fdo::Result<()> {
let mut led = None;
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.toggle_mode(true).map_err(|e| {
warn!("{}", e);
e
})?;
let mut ctrl = self.0.lock().await;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
led = Some(mode.clone());
}
break;
}
}
if let Some(led) = led {
Self::notify_led(&ctxt, led)
ctrl.toggle_mode(true).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
Ok(())
}
async fn next_led_brightness(&self) -> zbus::fdo::Result<()> {
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.next_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
break;
}
}
let mut ctrl = self.0.lock().await;
ctrl.next_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
Ok(())
}
async fn prev_led_brightness(&self) -> zbus::fdo::Result<()> {
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.prev_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
break;
}
}
let mut ctrl = self.0.lock().await;
ctrl.prev_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
Ok(())
}
// As property doesn't work for AuraPowerDev (complexity of serialization?)
// #[dbus_interface(property)]
async fn leds_enabled(&self) -> AuraPowerDev {
loop {
if let Ok(ctrl) = self.0.try_lock() {
return AuraPowerDev::from(&ctrl.config.enabled);
}
}
let ctrl = self.0.lock().await;
return AuraPowerDev::from(&ctrl.config.enabled);
}
/// Return the current mode data
async fn led_mode(&self) -> AuraModeNum {
loop {
if let Ok(ctrl) = self.0.try_lock() {
return ctrl.config.current_mode;
}
}
let ctrl = self.0.lock().await;
return ctrl.config.current_mode;
}
/// Return a list of available modes
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
loop {
if let Ok(ctrl) = self.0.try_lock() {
return ctrl.config.builtins.clone();
}
}
let ctrl = self.0.lock().await;
return ctrl.config.builtins.clone();
}
async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> {
loop {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.write_effect_block(&data)?;
break;
}
}
let mut ctrl = self.0.lock().await;
ctrl.write_effect_block(&data)?;
Ok(())
}
/// Return the current LED brightness
#[dbus_interface(property)]
async fn led_brightness(&self) -> i8 {
loop {
if let Ok(ctrl) = self.0.try_lock() {
return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1);
}
}
let ctrl = self.0.lock().await;
ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1)
}
#[dbus_interface(signal)]

View File

@@ -9,7 +9,7 @@ use std::io::{Read, Write};
use std::path::Path;
use std::process::Command;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::export::futures_util::lock::Mutex;
use zbus::Connection;
use zbus::{dbus_interface, SignalContext};
@@ -210,7 +210,7 @@ impl CtrlRogBios {
})
.is_ok()
{
if let Ok(mut lock) = self.config.try_lock() {
if let Some(mut lock) = self.config.try_lock() {
lock.panel_od = overdrive;
lock.write();
}
@@ -228,7 +228,7 @@ impl CtrlRogBios {
err
})
.unwrap_or(false);
if let Ok(mut lock) = self.config.try_lock() {
if let Some(mut lock) = self.config.try_lock() {
lock.panel_od = od;
lock.write();
}
@@ -241,16 +241,17 @@ impl CtrlRogBios {
}
#[async_trait]
impl crate::ZbusAdd for CtrlRogBios {
impl crate::ZbusRun for CtrlRogBios {
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 {
fn reload(&mut self) -> Result<(), RogError> {
async fn reload(&mut self) -> Result<(), RogError> {
if self.platform.has_panel_od() {
let p = if let Ok(lock) = self.config.try_lock() {
let p = if let Some(lock) = self.config.try_lock() {
lock.panel_od
} else {
false
@@ -275,7 +276,7 @@ impl CtrlTask for CtrlRogBios {
move || {},
move || {
info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform1.config.try_lock() {
if let Some(lock) = platform1.config.try_lock() {
if platform1.platform.has_panel_od() {
platform1
.set_panel_overdrive(lock.panel_od)
@@ -290,7 +291,7 @@ impl CtrlTask for CtrlRogBios {
move || {},
move || {
info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform2.config.try_lock() {
if let Some(lock) = platform2.config.try_lock() {
if platform2.platform.has_panel_od() {
platform2
.set_panel_overdrive(lock.panel_od)

View File

@@ -5,8 +5,8 @@ use log::{info, warn};
use rog_platform::power::AsusPower;
use rog_platform::supported::ChargeSupportedFunctions;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::dbus_interface;
use zbus::export::futures_util::lock::Mutex;
use zbus::Connection;
use zbus::SignalContext;
@@ -52,7 +52,7 @@ impl CtrlPower {
fn charge_control_end_threshold(&self) -> u8 {
loop {
if let Ok(config) = self.config.try_lock() {
if let Some(config) = self.config.try_lock() {
let limit = self
.power
.get_charge_control_end_threshold()
@@ -61,7 +61,7 @@ impl CtrlPower {
err
})
.unwrap_or(100);
if let Ok(mut config) = self.config.try_lock() {
if let Some(mut config) = self.config.try_lock() {
config.read();
config.bat_charge_limit = limit;
config.write();
@@ -80,15 +80,16 @@ impl CtrlPower {
}
#[async_trait]
impl crate::ZbusAdd for CtrlPower {
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;
}
}
#[async_trait]
impl crate::Reloadable for CtrlPower {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.try_lock() {
async fn reload(&mut self) -> Result<(), RogError> {
if let Some(mut config) = self.config.try_lock() {
config.read();
self.set(config.bat_charge_limit)?;
}
@@ -113,7 +114,7 @@ impl CtrlPower {
info!("Battery charge limit: {}", limit);
if let Ok(mut config) = self.config.try_lock() {
if let Some(mut config) = self.config.try_lock() {
config.read();
config.bat_charge_limit = limit;
config.write();
@@ -134,7 +135,7 @@ impl CtrlTask for CtrlPower {
move || {},
move || {
info!("CtrlCharge reloading charge limit");
if let Ok(lock) = power1.config.try_lock() {
if let Some(lock) = power1.config.try_lock() {
power1
.set(lock.bat_charge_limit)
.map_err(|err| {
@@ -147,7 +148,7 @@ impl CtrlTask for CtrlPower {
move || {},
move || {
info!("CtrlCharge reloading charge limit");
if let Ok(lock) = power2.config.try_lock() {
if let Some(lock) = power2.config.try_lock() {
power2
.set(lock.bat_charge_limit)
.map_err(|err| {

View File

@@ -1,6 +1,8 @@
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;
use rog_profiles::error::ProfileError;
use rog_profiles::{FanCurveProfiles, Profile};
@@ -9,6 +11,7 @@ use super::config::ProfileConfig;
pub struct CtrlPlatformProfile {
pub config: ProfileConfig,
pub platform: AsusPlatform,
}
impl GetSupported for CtrlPlatformProfile {
@@ -36,9 +39,10 @@ impl GetSupported for CtrlPlatformProfile {
}
}
#[async_trait]
impl crate::Reloadable for CtrlPlatformProfile {
/// Fetch the active profile and use that to set all related components up
fn reload(&mut self) -> Result<(), RogError> {
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
@@ -53,10 +57,11 @@ impl crate::Reloadable for CtrlPlatformProfile {
impl CtrlPlatformProfile {
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
if Profile::is_platform_profile_supported() {
let platform = AsusPlatform::new()?;
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
info!("Device has profile control available");
let mut controller = CtrlPlatformProfile { config };
let mut controller = CtrlPlatformProfile { config, platform };
if FanCurveProfiles::get_device().is_ok() {
info!("Device has fan curves available");
if controller.config.fan_curves.is_none() {

View File

@@ -1,17 +1,14 @@
use async_trait::async_trait;
use inotify::Inotify;
use inotify::WatchMask;
use log::warn;
use rog_profiles::fan_curve_set::CurveData;
use rog_profiles::fan_curve_set::FanCurveSet;
use rog_profiles::Profile;
use rog_profiles::PLATFORM_PROFILE;
use zbus::export::futures_util::lock::Mutex;
use zbus::export::futures_util::StreamExt;
use zbus::Connection;
use zbus::SignalContext;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::{dbus_interface, fdo::Error};
use crate::error::RogError;
@@ -47,27 +44,21 @@ 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 profile = None;
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err));
ctrl.save_config();
profile = Some(ctrl.config.active_profile);
}
if let Some(profile) = profile {
Self::notify_profile(&ctxt, profile).await.ok();
}
let mut ctrl = self.inner.lock().await;
ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err));
ctrl.save_config();
Self::notify_profile(&ctxt, ctrl.config.active_profile)
.await
.ok();
}
/// Fetch the active profile name
fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
return Ok(ctrl.config.active_profile);
}
Err(Error::Failed(
"Failed to get active profile name".to_string(),
))
async fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
Ok(ctrl.config.active_profile)
}
/// Set this platform_profile name as active
@@ -76,93 +67,85 @@ impl ProfileZbus {
#[zbus(signal_context)] ctxt: SignalContext<'_>,
profile: Profile,
) {
let mut tmp = None;
if let Ok(mut ctrl) = self.inner.try_lock() {
// Read first just incase the user has modified the config before calling this
ctrl.config.read();
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.config.active_profile = profile;
let mut ctrl = self.inner.lock().await;
// Read first just incase the user has modified the config before calling this
ctrl.config.read();
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.config.active_profile = profile;
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
Self::notify_profile(&ctxt, ctrl.config.active_profile)
.await
.ok();
}
/// 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;
ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves {
return Ok(curves.get_enabled_curve_profiles().to_vec());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
/// same profile mode
async fn set_fan_curve_enabled(
&mut self,
profile: Profile,
enabled: bool,
) -> zbus::fdo::Result<()> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
return if let Some(curves) = &mut ctrl.config.fan_curves {
curves.set_profile_curve_enabled(profile, enabled);
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
tmp = Some(ctrl.config.active_profile);
}
if let Some(profile) = tmp {
Self::notify_profile(&ctxt, profile).await.ok();
}
}
/// Get a list of profiles that have fan-curves enabled.
fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves {
return Ok(curves.get_enabled_curve_profiles().to_vec());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
Err(Error::Failed(
"Failed to get enabled fan curve names".to_string(),
))
}
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
/// same profile mode
fn set_fan_curve_enabled(&mut self, profile: Profile, enabled: bool) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
return if let Some(curves) = &mut ctrl.config.fan_curves {
curves.set_profile_curve_enabled(profile, enabled);
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
Ok(())
} else {
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
};
}
Err(Error::Failed(
"Failed to get enabled fan curve names".to_string(),
))
Ok(())
} else {
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
};
}
/// Get the fan-curve data for the currently active Profile
fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves {
let curve = curves.get_fan_curves_for(profile);
return Ok(curve.clone());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves {
let curve = curves.get_fan_curves_for(profile);
return Ok(curve.clone());
}
Err(Error::Failed("Failed to get fan curve data".to_string()))
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
/// Set the fan curve for the specified profile.
/// Will also activate the fan curve if the user is in the same mode.
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
if let Some(curves) = &mut ctrl.config.fan_curves {
curves
.save_fan_curve(curve, profile)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
} else {
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("Profile::set_profile, {}", e))
.ok();
ctrl.save_config();
async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
if let Some(curves) = &mut ctrl.config.fan_curves {
curves
.save_fan_curve(curve, profile)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
} else {
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("Profile::set_profile, {}", e))
.ok();
ctrl.save_config();
Ok(())
}
@@ -170,14 +153,13 @@ impl ProfileZbus {
///
/// Each platform_profile has a different default and the defualt can be read
/// only for the currently active profile.
fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.ok();
ctrl.save_config();
}
async fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.ok();
ctrl.save_config();
Ok(())
}
@@ -185,23 +167,22 @@ impl ProfileZbus {
///
/// Each platform_profile has a different default and the defualt can be read
/// only for the currently active profile.
fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
async fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> {
let mut ctrl = self.inner.lock().await;
ctrl.config.read();
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.ok();
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.ok();
Profile::set_profile(active)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.save_config();
}
Profile::set_profile(active)
.map_err(|e| warn!("set_profile, {}", e))
.ok();
ctrl.save_config();
Ok(())
}
@@ -211,7 +192,7 @@ impl ProfileZbus {
}
#[async_trait]
impl crate::ZbusAdd for ProfileZbus {
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;
}
@@ -221,36 +202,32 @@ impl crate::ZbusAdd for ProfileZbus {
impl CtrlTask for ProfileZbus {
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
let ctrl = self.inner.clone();
let mut watch = Inotify::init()?;
watch.add_watch(PLATFORM_PROFILE, WatchMask::CLOSE_WRITE)?;
let mut watch = self
.inner
.lock()
.await
.platform
.monitor_platform_profile()?;
tokio::spawn(async move {
let mut buffer = [0; 32];
loop {
watch
.event_stream(&mut buffer)
.unwrap()
.for_each(|_| async {
let mut active_profile = None;
watch
.event_stream(&mut buffer)
.unwrap()
.for_each(|_| async {
let mut lock = ctrl.lock().await;
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();
}
if let Ok(ref mut lock) = ctrl.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();
active_profile = Some(lock.config.active_profile);
}
}
if let Some(active_profile) = active_profile {
Self::notify_profile(&signal_ctxt.clone(), active_profile)
.await
.ok();
}
})
.await;
}
Self::notify_profile(&signal_ctxt.clone(), lock.config.active_profile)
.await
.ok();
})
.await;
});
Ok(())

View File

@@ -28,7 +28,7 @@ impl SupportedFunctions {
}
#[async_trait]
impl crate::ZbusAdd for SupportedFunctions {
impl crate::ZbusRun for SupportedFunctions {
async fn add_to_server(self, server: &mut Connection) {
Self::add_to_server_helper(self, "/org/asuslinux/Supported", server).await;
}

View File

@@ -1,9 +1,10 @@
use std::env;
use std::error::Error;
use std::io::Write;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::time::Duration;
use ::zbus::export::futures_util::lock::Mutex;
use ::zbus::{Connection, SignalContext};
use log::LevelFilter;
use log::{error, info, warn};
@@ -26,7 +27,7 @@ use daemon::{
ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus},
laptops::LaptopLedData,
};
use daemon::{CtrlTask, Reloadable, ZbusAdd};
use daemon::{CtrlTask, Reloadable, ZbusRun};
use rog_dbus::DBUS_NAME;
use rog_profiles::Profile;
@@ -84,6 +85,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
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;
@@ -101,6 +103,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
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;
@@ -119,14 +122,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
match CtrlPlatformProfile::new(profile_config) {
Ok(mut ctrl) => {
ctrl.reload()
.await
.unwrap_or_else(|err| warn!("Profile control: {}", err));
let tmp = Arc::new(Mutex::new(ctrl));
//let task = CtrlProfileTask::new(tmp.clone());
//task.create_tasks(executor).await.ok();
let sig = SignalContext::new(&connection, "/org/asuslinux/Profile")?;
let task = ProfileZbus::new(tmp.clone());
let task = ProfileZbus::new(Arc::new(Mutex::new(ctrl)));
task.create_tasks(sig).await.ok();
task.add_to_server(&mut connection).await;
}
@@ -145,6 +146,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let mut reload = CtrlAnimeReloader(inner.clone());
reload
.reload()
.await
.unwrap_or_else(|err| warn!("AniMe: {}", err));
let zbus = CtrlAnimeZbus(inner.clone());
@@ -168,6 +170,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let mut reload = CtrlKbdLedReloader(inner.clone());
reload
.reload()
.await
.unwrap_or_else(|err| warn!("Keyboard LED control: {}", err));
CtrlKbdLedZbus::new(inner.clone())

View File

@@ -19,24 +19,22 @@ pub mod ctrl_supported;
pub mod error;
use std::time::Duration;
use crate::error::RogError;
use async_trait::async_trait;
use log::warn;
use logind_zbus::manager::ManagerProxy;
use tokio::time;
use zbus::{export::futures_util::StreamExt, Connection, SignalContext};
use zvariant::ObjectPath;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[async_trait]
pub trait Reloadable {
fn reload(&mut self) -> Result<(), RogError>;
async fn reload(&mut self) -> Result<(), RogError>;
}
#[async_trait]
pub trait ZbusAdd {
pub trait ZbusRun {
async fn add_to_server(self, server: &mut Connection);
async fn add_to_server_helper(
@@ -110,14 +108,16 @@ pub trait CtrlTask {
/// No blocking loops are allowed, or they must be run on a separate thread.
async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>;
/// Create a timed repeating task
async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + 'static) {
let mut timer = time::interval(Duration::from_millis(millis));
tokio::spawn(async move {
timer.tick().await;
task();
});
}
// /// Create a timed repeating task
// async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + 'static) {
// use std::time::Duration;
// use tokio::time;
// let mut timer = time::interval(Duration::from_millis(millis));
// tokio::spawn(async move {
// timer.tick().await;
// task();
// });
// }
/// Free helper method to create tasks to run on: sleep, wake, shutdown, boot
///

View File

@@ -19,80 +19,103 @@ Then for each trait that is required a new struct is required that can have the
Main controller:
```rust
/// For a very simple controller that doesn't need exclusive access you can clone across threads
#[derive(Clone)]
pub struct CtrlAnime {
<things the controller requires>
config: Arc<Mutex<Config>>,
}
impl crate::CtrlTask for CtrlAnime {}
impl crate::ZbusAdd for CtrlAnime {}
impl CtrlAnime {}
```
```rust
/// Otherwise, you will need to share the controller via mutex
pub struct CtrlAnime {
<things the controller requires>
}
// Like this
#[derive(Clone)]
pub struct CtrlAnimeTask(Arc<Mutex<CtrlAnime>>);
#[derive(Clone)]
pub struct CtrlAnimeZbus(Arc<Mutex<CtrlAnime>>);
impl CtrlAnime {
<functions the controller exposes>
}
impl CtrlAnime {}
```
The task trait. There are three ways to implement this:
```rust
// Mutex should always be async mutex
pub struct CtrlAnimeTask(Arc<Mutex<CtrlAnime>>);
impl crate::CtrlTask for CtrlAnimeTask {
// This will run once only
fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
if let Ok(lock) = self.inner.try_lock() {
<some action>
}
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
let lock self.inner.lock().await;
<some action>
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;
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
let inner1 = self.inner.clone();
let inner2 = self.inner.clone();
let inner3 = self.inner.clone();
let inner4 = self.inner.clone();
// This is a free method on CtrlTask trait
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;
}
})
.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
}
})
},
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;
}
}
```
The reloader trait
```rust
pub struct CtrlAnimeReloader(Arc<Mutex<CtrlAnime>>);
impl crate::Reloadable for CtrlAnimeReloader {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(lock) = self.inner.try_lock() {
<some action>
}
async fn reload(&mut self) -> Result<(), RogError> {
let lock = self.inner.lock().await;
<some action>
Ok(())
}
}
```
The Zbus requirements:
```rust
pub struct CtrlAnimeZbus(Arc<Mutex<CtrlAnime>>);
@@ -106,10 +129,9 @@ impl crate::ZbusAdd for CtrlAnimeZbus {
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlAnimeZbus {
fn <zbus method>() {
if let Ok(lock) = self.inner.try_lock() {
<some action>
}
async fn <zbus method>() {
let lock = self.inner.lock().await;
<some action>
}
}
```

View File

@@ -57,8 +57,8 @@ impl AsusPlatform {
attr_bool!("egpu_enable", path);
attr_bool!("panel_od", path);
attr_u8!("gpu_mux_mode", path);
// This is technically the same as `platform_profile` since both are tied in-kernel
attr_u8!("throttle_thermal_policy", path);
// The acpi platform_profile support
attr_u8!("platform_profile", pp_path);
}