mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Groundwork for 'advanced' aura modes Add single zone + Doom light flash Fix mocking for ROGCC Better prepare & change to mapping of keyboard layouts to models and functions Refactor and begin using new key layout stuff Enable first arg to rogcc to set layout in mocking feature mode Complete refactor of key layouts, and to RON serde
221 lines
7.3 KiB
Rust
221 lines
7.3 KiB
Rust
use std::sync::atomic::Ordering;
|
|
use std::sync::Arc;
|
|
|
|
use async_trait::async_trait;
|
|
use log::{info, warn};
|
|
use rog_anime::usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on};
|
|
use rog_anime::{AnimeDataBuffer, AnimePowerStates};
|
|
use zbus::export::futures_util::lock::{Mutex, MutexGuard};
|
|
use zbus::{dbus_interface, Connection, SignalContext};
|
|
|
|
use super::CtrlAnime;
|
|
use crate::error::RogError;
|
|
|
|
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime";
|
|
|
|
#[derive(Clone)]
|
|
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
|
|
|
|
/// The struct with the main dbus methods requires this trait
|
|
#[async_trait]
|
|
impl crate::ZbusRun for CtrlAnimeZbus {
|
|
async fn add_to_server(self, server: &mut Connection) {
|
|
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
|
}
|
|
}
|
|
|
|
// None of these calls can be guarnateed to succeed unless we loop until okay
|
|
// If the try_lock *does* succeed then any other thread trying to lock will not
|
|
// grab it until we finish.
|
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
impl CtrlAnimeZbus {
|
|
/// Writes a data stream of length. Will force system thread to exit until
|
|
/// it is restarted
|
|
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
|
|
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 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();
|
|
|
|
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 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();
|
|
|
|
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
|
|
async fn run_main_loop(&self, start: bool) {
|
|
if start {
|
|
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)]
|
|
async fn awake_enabled(&self) -> bool {
|
|
let lock = self.0.lock().await;
|
|
lock.config.awake_enabled
|
|
}
|
|
|
|
/// Get the status of if factory system-status animations are enabled
|
|
#[dbus_interface(property)]
|
|
async fn boot_enabled(&self) -> bool {
|
|
let lock = self.0.lock().await;
|
|
lock.config.boot_anim_enabled
|
|
}
|
|
|
|
/// Notify listeners of the status of AniMe LED power and factory
|
|
/// system-status animations
|
|
#[dbus_interface(signal)]
|
|
async fn notify_power_states(
|
|
ctxt: &SignalContext<'_>,
|
|
data: AnimePowerStates,
|
|
) -> zbus::Result<()>;
|
|
}
|
|
|
|
#[async_trait]
|
|
impl crate::CtrlTask for CtrlAnimeZbus {
|
|
fn zbus_path() -> &'static str {
|
|
ZBUS_PATH
|
|
}
|
|
|
|
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
|
|
let run_action =
|
|
|start: bool, lock: MutexGuard<'_, CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
|
|
if start {
|
|
info!("CtrlAnimeTask running sleep animation");
|
|
CtrlAnime::run_thread(inner, lock.cache.shutdown.clone(), true);
|
|
} else {
|
|
info!("CtrlAnimeTask running wake animation");
|
|
CtrlAnime::run_thread(inner, lock.cache.wake.clone(), true);
|
|
}
|
|
};
|
|
|
|
let inner1 = self.0.clone();
|
|
let inner2 = self.0.clone();
|
|
let inner3 = self.0.clone();
|
|
let inner4 = self.0.clone();
|
|
self.create_sys_event_tasks(
|
|
// Loop is required to try an attempt to get the mutex *without* blocking
|
|
// other threads - it is possible to end up with deadlocks otherwise.
|
|
move || {
|
|
let inner1 = inner1.clone();
|
|
async move {
|
|
let lock = inner1.lock().await;
|
|
run_action(true, lock, inner1.clone());
|
|
}
|
|
},
|
|
move || {
|
|
let inner2 = inner2.clone();
|
|
async move {
|
|
let lock = inner2.lock().await;
|
|
run_action(true, lock, inner2.clone());
|
|
}
|
|
},
|
|
move || {
|
|
let inner3 = inner3.clone();
|
|
async move {
|
|
let lock = inner3.lock().await;
|
|
run_action(true, lock, inner3.clone());
|
|
}
|
|
},
|
|
move || {
|
|
let inner4 = inner4.clone();
|
|
async move {
|
|
let lock = inner4.lock().await;
|
|
run_action(true, lock, inner4.clone());
|
|
}
|
|
},
|
|
)
|
|
.await;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl crate::Reloadable for CtrlAnimeZbus {
|
|
async fn reload(&mut self) -> Result<(), RogError> {
|
|
if let Some(lock) = self.0.try_lock() {
|
|
lock.node
|
|
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
|
|
lock.node.write_bytes(&pkt_for_apply())?;
|
|
lock.node
|
|
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
|
|
lock.node.write_bytes(&pkt_for_apply())?;
|
|
|
|
let action = lock.cache.boot.clone();
|
|
CtrlAnime::run_thread(self.0.clone(), action, true);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|