mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Convert chunk of daemon to use async mutex
This commit is contained in:
@@ -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
3
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
@@ -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())?;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
///
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user