From 49f5686f19449ac9ea51e34913929dfd5a88dbd7 Mon Sep 17 00:00:00 2001 From: Marco Scardovi Date: Sun, 18 Oct 2026 14:29:10 +0200 Subject: [PATCH 1/3] chore: remove asusd-user crate from the workspace The session daemon had no in-tree consumers and only proxied AniMe and Aura frames to asusd. Drop the crate and its workspace membership. BREAKING CHANGE: the asusd-user binary is no longer built. Signed-off-by: Marco Scardovi --- Cargo.lock | 19 -- Cargo.toml | 3 +- asusd-user/Cargo.toml | 49 ---- asusd-user/README.md | 14 -- asusd-user/src/config.rs | 232 ------------------ asusd-user/src/ctrl_anime.rs | 360 ---------------------------- asusd-user/src/daemon.rs | 175 -------------- asusd-user/src/error.rs | 39 --- asusd-user/src/lib.rs | 9 - asusd-user/src/zbus_anime.rs | 70 ------ asusd/src/aura_anime/trait_impls.rs | 3 +- 11 files changed, 2 insertions(+), 971 deletions(-) delete mode 100644 asusd-user/Cargo.toml delete mode 100644 asusd-user/README.md delete mode 100644 asusd-user/src/config.rs delete mode 100644 asusd-user/src/ctrl_anime.rs delete mode 100644 asusd-user/src/daemon.rs delete mode 100644 asusd-user/src/error.rs delete mode 100644 asusd-user/src/lib.rs delete mode 100644 asusd-user/src/zbus_anime.rs diff --git a/Cargo.lock b/Cargo.lock index 412dec6db..2857bb0d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,25 +321,6 @@ dependencies = [ "zbus", ] -[[package]] -name = "asusd-user" -version = "6.5.0" -dependencies = [ - "config-traits", - "dirs", - "env_logger", - "log", - "rog_anime", - "rog_aura", - "rog_dbus", - "rog_platform", - "ron", - "serde", - "thiserror 2.0.21", - "tokio", - "zbus", -] - [[package]] name = "async-broadcast" version = "0.7.2" diff --git a/Cargo.toml b/Cargo.toml index 5d882afb4..a98378cfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ members = [ "asusctl", "asusd", "asus-shutdown", - "asusd-user", "config-traits", "dmi-id", "rog-platform", @@ -32,7 +31,7 @@ members = [ "rog-scsi", ] -default-members = ["asusctl", "asusd", "asus-shutdown", "asusd-user", "rog-control-center"] +default-members = ["asusctl", "asusd", "asus-shutdown", "rog-control-center"] [workspace.dependencies] argh = "^0.1.19" diff --git a/asusd-user/Cargo.toml b/asusd-user/Cargo.toml deleted file mode 100644 index d8d3f22b2..000000000 --- a/asusd-user/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "asusd-user" -license.workspace = true -version.workspace = true -readme.workspace = true -authors.workspace = true -repository.workspace = true -homepage.workspace = true -edition.workspace = true - -[[bin]] -name = "asusd-user" -path = "src/daemon.rs" - -[features] -default = [] -local_data = [] - -[dependencies] -dirs.workspace = true -tokio = { workspace = true, features = ["rt", "macros"] } - -# serialisation -serde.workspace = true -ron.workspace = true - -rog_anime = { path = "../rog-anime" } -rog_aura = { path = "../rog-aura" } -rog_dbus = { path = "../rog-dbus" } -rog_platform = { path = "../rog-platform" } -config-traits = { path = "../config-traits" } - -zbus.workspace = true -log.workspace = true -env_logger.workspace = true -thiserror.workspace = true - -[package.metadata.deb] -license-file = ["../LICENSE", "4"] -extended-description = """\ -An user utility for Linux to control fancy things on various ASUS laptops -like keyboard effects or anime matrix animation cycles.""" -depends = "$auto" -section = "utility" -priority = "optional" -assets = [ - ["target/release/asusd-user", "usr/bin/", "755"], - ["../asusd_user-fakeinstall/usr/lib/systemd/user/*", "usr/lib/systemd/user/", "644"], -] diff --git a/asusd-user/README.md b/asusd-user/README.md deleted file mode 100644 index be3b4e23b..000000000 --- a/asusd-user/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# daemon-user - -This crate is for the binary of `asusd-user` and its helper lib. - -The purpose of `asusd-user` is to run in userland and provide the user + third-party apps an interface for such things as creating AniMe sequences (and more in future, see todo list). - -`asusd-user` should try to be as simple as possible while allowing a decent degree of control. - -## TODO - -- [ ] CLI for basic settings/interaction -- [ ] RGB keyboard per-key programs -- [ ] User profiles (fan, cpu etc). These would be replacing the system-daemon profiles only when the user is active, otherwise system-daemon defaults to system settings. -- [ ] Audio EQ visualiser - for use with anime + keyboard lighting \ No newline at end of file diff --git a/asusd-user/src/config.rs b/asusd-user/src/config.rs deleted file mode 100644 index 36b554786..000000000 --- a/asusd-user/src/config.rs +++ /dev/null @@ -1,232 +0,0 @@ -use std::path::PathBuf; -use std::time::Duration; - -use config_traits::{StdConfig, StdConfigLoad}; -use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences as AnimeSequences, Vec2}; -use rog_aura::effects::{AdvancedEffects as AuraSequences, Breathe, DoomFlicker, Effect, Static}; -use rog_aura::keyboard::LedCode; -use rog_aura::{Colour, Speed}; -use serde::{Deserialize, Serialize}; - -use crate::error::Error; - -const ROOT_CONF_DIR: &str = "rog"; - -fn root_conf_dir() -> PathBuf { - let mut dir = dirs::config_dir().unwrap_or_else(|| PathBuf::from("/tmp")); - dir.push(ROOT_CONF_DIR); - dir -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct ConfigAnime { - pub name: String, - pub anime: Vec, -} - -impl ConfigAnime { - pub fn create(&self, anime_type: AnimeType) -> Result { - let mut seq = AnimeSequences::new(anime_type); - - for (idx, action) in self.anime.iter().enumerate() { - seq.insert(idx, action)?; - } - - Ok(seq) - } - - pub fn set_name(mut self, name: String) -> Self { - self.name = name; - self - } -} - -impl Default for ConfigAnime { - fn default() -> Self { - Self { - name: "anime-default".to_owned(), - anime: vec![ - ActionLoader::AsusImage { - file: "/usr/share/asusd/anime/custom/diagonal-template.png".into(), - brightness: 1.0, - time: AnimTime::Fade(Fade::new( - Duration::from_secs(2), - None, - Duration::from_secs(2), - )), - }, - ActionLoader::AsusAnimation { - file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(), - brightness: 0.5, - time: AnimTime::Fade(Fade::new( - Duration::from_secs(6), - None, - Duration::from_secs(3), - )), - }, - ActionLoader::ImageAnimation { - file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(), - scale: 0.9, - angle: 0.65, - translation: Vec2::default(), - brightness: 0.5, - time: AnimTime::Fade(Fade::new( - Duration::from_secs(2), - Some(Duration::from_secs(2)), - Duration::from_secs(2), - )), - }, - ActionLoader::Image { - file: "/usr/share/asusd/anime/custom/rust.png".into(), - scale: 1.0, - angle: 0.0, - translation: Vec2::default(), - time: AnimTime::Fade(Fade::new( - Duration::from_secs(2), - Some(Duration::from_secs(1)), - Duration::from_secs(2), - )), - brightness: 0.6, - }, - ActionLoader::Pause(Duration::from_secs(1)), - ActionLoader::ImageAnimation { - file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(), - scale: 0.9, - angle: 0.0, - translation: Vec2::new(3.0, 2.0), - brightness: 0.5, - time: AnimTime::Count(2), - }, - ], - } - } -} - -impl StdConfig for ConfigAnime { - fn new() -> Self { - Self::default() - } - - fn file_name(&self) -> String { - format!("{}.ron", self.name) - } - - fn config_dir() -> std::path::PathBuf { - root_conf_dir() - } -} - -impl StdConfigLoad for ConfigAnime {} - -#[derive(Debug, Deserialize, Serialize)] -pub struct ConfigAura { - pub name: String, - pub aura: AuraSequences, -} - -impl ConfigAura { - pub fn set_name(mut self, name: String) -> Self { - self.name = name; - self - } -} - -impl Default for ConfigAura { - fn default() -> Self { - let mut seq = AuraSequences::new(false); - let mut key = Effect::Breathe(Breathe::new( - LedCode::W, - Colour { - r: 255, - g: 0, - b: 20, - }, - Colour { - r: 20, - g: 255, - b: 0, - }, - Speed::Low, - )); - - seq.push(key.clone()); - key.set_led(LedCode::A); - seq.push(key.clone()); - key.set_led(LedCode::S); - seq.push(key.clone()); - key.set_led(LedCode::D); - seq.push(key); - - let key = Effect::Breathe(Breathe::new( - LedCode::F, - Colour { r: 255, g: 0, b: 0 }, - Colour { r: 255, g: 0, b: 0 }, - Speed::High, - )); - seq.push(key); - - let mut key = Effect::Static(Static::new(LedCode::RCtrl, Colour { r: 0, g: 0, b: 255 })); - seq.push(key.clone()); - key.set_led(LedCode::LCtrl); - seq.push(key.clone()); - key.set_led(LedCode::Esc); - seq.push(key); - - let key = Effect::DoomFlicker(DoomFlicker::new( - LedCode::N9, - Colour { r: 0, g: 0, b: 255 }, - 80, - 40, - )); - seq.push(key); - - Self { - name: "aura-default".to_owned(), - aura: seq, - } - } -} - -impl StdConfig for ConfigAura { - fn new() -> Self { - Self::default() - } - - fn file_name(&self) -> String { - format!("{}.ron", self.name) - } - - fn config_dir() -> std::path::PathBuf { - root_conf_dir() - } -} - -impl StdConfigLoad for ConfigAura {} - -#[derive(Debug, Default, Deserialize, Serialize)] -#[serde(default)] -pub struct ConfigBase { - /// Name of active anime config file in the user config directory - pub active_anime: Option, - /// Name of active aura config file in the user config directory - pub active_aura: Option, -} - -impl StdConfig for ConfigBase { - fn new() -> Self { - Self { - active_anime: Some("anime-default".to_owned()), - active_aura: Some("aura-default".to_owned()), - } - } - - fn file_name(&self) -> String { - "rog-user.ron".to_owned() - } - - fn config_dir() -> std::path::PathBuf { - root_conf_dir() - } -} - -impl StdConfigLoad for ConfigBase {} diff --git a/asusd-user/src/ctrl_anime.rs b/asusd-user/src/ctrl_anime.rs deleted file mode 100644 index 2ae6f9a2c..000000000 --- a/asusd-user/src/ctrl_anime.rs +++ /dev/null @@ -1,360 +0,0 @@ -use std::path::Path; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; -use std::thread::sleep; -use std::time::{Duration, Instant}; - -use log::error; - -use config_traits::StdConfig; -use rog_anime::error::AnimeError; -use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2}; -use rog_dbus::zbus_anime::AnimeProxyBlocking; -use ron::ser::PrettyConfig; -use serde::{Deserialize, Serialize}; -use zbus::interface; -use zbus::zvariant::{ObjectPath, Type}; - -use crate::config::ConfigAnime; -use crate::error::Error; - -#[derive(Debug, Clone, Deserialize, Serialize, Type)] -pub struct Timer { - type_of: TimeType, - /// If time type is Timer then this is milliseonds, otherwise it is - /// animation loop count - count: u64, - /// Used only for `TimeType::Timer`, milliseonds to fade the image in for - fade_in: u64, - /// Used only for `TimeType::Timer`, milliseonds to fade the image out for - fade_out: u64, -} - -impl From for AnimTime { - fn from(time: Timer) -> Self { - match time.type_of { - TimeType::Timer => { - if time.fade_in != 0 && time.fade_out != 0 { - let fade_in = Duration::from_millis(time.fade_in); - let fade_out = Duration::from_millis(time.fade_out); - let show_for = if time.count != 0 { - Some(Duration::from_millis(time.count)) - } else { - None - }; - AnimTime::Fade(Fade::new(fade_in, show_for, fade_out)) - } else { - AnimTime::Time(Duration::from_millis(time.count)) - } - } - TimeType::Count => AnimTime::Count(time.count as u32), - TimeType::Infinite => AnimTime::Infinite, - } - } -} - -#[derive(Debug, Clone, Deserialize, Serialize, Type)] -pub enum TimeType { - Timer, - Count, - Infinite, -} - -/// The inner object exists to allow the zbus proxy to share it with a runner -/// thread and a zbus server behind `Arc>` -pub struct CtrlAnimeInner<'a> { - sequences: Sequences, - client: AnimeProxyBlocking<'a>, - do_early_return: Arc, -} - -impl CtrlAnimeInner<'static> { - pub fn new( - sequences: Sequences, - client: AnimeProxyBlocking<'static>, - do_early_return: Arc, - ) -> Result { - Ok(Self { - sequences, - client, - do_early_return, - }) - } - - /// To be called on each main loop iteration to pump out commands to the - /// anime - pub fn run(&self) -> Result<(), Error> { - if self.do_early_return.load(Ordering::SeqCst) { - return Ok(()); - } - - for action in self.sequences.iter() { - match action { - ActionData::Animation(frames) => { - rog_anime::run_animation(frames, &|output| { - if self.do_early_return.load(Ordering::Acquire) { - return Ok(true); // Do safe exit - } - self.client - .write(output) - .map_err(|e| AnimeError::Dbus(format!("{}", e))) - .map(|_| false) - }); - } - ActionData::Image(image) => { - self.client.write(image.as_ref().clone()).ok(); - } - ActionData::Pause(duration) => { - let start = Instant::now(); - 'pause: loop { - if self.do_early_return.load(Ordering::SeqCst) { - return Ok(()); - } - if Instant::now().duration_since(start) > *duration { - break 'pause; - } - sleep(Duration::from_millis(1)); - } - } - ActionData::AudioEq - | ActionData::SystemInfo - | ActionData::TimeDate - | ActionData::Matrix => {} - } - } - - Ok(()) - } -} - -pub struct CtrlAnime<'a> { - config: Arc>, - client: AnimeProxyBlocking<'a>, - inner: Arc>>, - /// Must be the same Atomic as in CtrlAnimeInner - inner_early_return: Arc, -} - -impl CtrlAnime<'static> { - pub fn new( - config: Arc>, - inner: Arc>>, - client: AnimeProxyBlocking<'static>, - inner_early_return: Arc, - ) -> Result { - Ok(CtrlAnime { - config, - client, - inner, - inner_early_return, - }) - } - - pub async fn add_to_server(self, server: &mut zbus::Connection) { - server - .object_server() - .at(&ObjectPath::from_str_unchecked("/xyz/ljones/Anime"), self) - .await - .map_err(|err| { - error!("CtrlAnime: add_to_server {}", err); - err - }) - .ok(); - } -} - -// The pattern for a zbus method is: -// - Get config lock if required -// - Set inner_early_return to stop the inner run loop temporarily -// - Do actions -// - Write config if required -// - Unset inner_early_return -#[interface(name = "xyz.ljones.Asusd")] -impl CtrlAnime<'static> { - pub fn insert_asus_gif( - &mut self, - index: u32, - file: &str, - time: Timer, - brightness: f32, - ) -> zbus::fdo::Result { - if let Ok(mut config) = self.config.try_lock() { - let time: AnimTime = time.into(); - let file = Path::new(&file); - let action = ActionLoader::AsusAnimation { - file: file.into(), - brightness, - time, - }; - - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - - if let Ok(mut controller) = self.inner.lock() { - controller - .sequences - .insert(index as usize, &action) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - } - config.anime.push(action); - config.write(); - - let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); - - // Release the inner run loop again - self.inner_early_return.store(false, Ordering::SeqCst); - return Ok(ron); - } - Err(zbus::fdo::Error::Failed("UserConfig lock fail".into())) - } - - #[allow(clippy::too_many_arguments)] - pub fn insert_image_gif( - &mut self, - index: u32, - file: &str, - scale: f32, - angle: f32, - xy: (f32, f32), - time: Timer, - brightness: f32, - ) -> zbus::fdo::Result { - if let Ok(mut config) = self.config.try_lock() { - let time: AnimTime = time.into(); - let file = Path::new(&file); - let translation = Vec2::new(xy.0, xy.1); - let action = ActionLoader::ImageAnimation { - file: file.into(), - scale, - angle, - translation, - brightness, - time, - }; - - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - - if let Ok(mut controller) = self.inner.lock() { - controller - .sequences - .insert(index as usize, &action) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - } - config.anime.push(action); - config.write(); - - let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); - // Release the inner run loop again - self.inner_early_return.store(false, Ordering::SeqCst); - return Ok(ron); - } - Err(zbus::fdo::Error::Failed("UserConfig lock fail".into())) - } - - #[allow(clippy::too_many_arguments)] - pub fn insert_image( - &mut self, - index: u32, - file: &str, - scale: f32, - angle: f32, - xy: (f32, f32), - time: Timer, - brightness: f32, - ) -> zbus::fdo::Result { - if let Ok(mut config) = self.config.try_lock() { - let file = Path::new(&file); - let time = time.into(); - let action = ActionLoader::Image { - file: file.into(), - scale, - angle, - translation: Vec2::new(xy.0, xy.1), - brightness, - time, - }; - - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - - if let Ok(mut controller) = self.inner.lock() { - controller - .sequences - .insert(index as usize, &action) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - } - config.anime.push(action); - config.write(); - - let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); - // Release the inner run loop again - self.inner_early_return.store(false, Ordering::SeqCst); - return Ok(ron); - } - Err(zbus::fdo::Error::Failed("UserConfig lock fail".into())) - } - - pub fn insert_pause(&mut self, index: u32, millis: u64) -> zbus::fdo::Result { - if let Ok(mut config) = self.config.try_lock() { - let action = ActionLoader::Pause(Duration::from_millis(millis)); - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - - if let Ok(mut controller) = self.inner.lock() { - controller - .sequences - .insert(index as usize, &action) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - } - config.anime.push(action); - config.write(); - - let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); - // Release the inner run loop again - self.inner_early_return.store(false, Ordering::SeqCst); - return Ok(ron); - } - Err(zbus::fdo::Error::Failed("UserConfig lock fail".into())) - } - - pub fn remove_item(&mut self, index: u32) -> zbus::fdo::Result { - if let Ok(mut config) = self.config.try_lock() { - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - - if let Ok(mut controller) = self.inner.lock() { - controller.sequences.remove_item(index as usize); - } - if (index as usize) < config.anime.len() { - config.anime.remove(index as usize); - } - config.write(); - - let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4)) - .expect("Parse config to RON failed"); - // Release the inner run loop again - self.inner_early_return.store(false, Ordering::SeqCst); - return Ok(ron); - } - Err(zbus::fdo::Error::Failed("UserConfig lock fail".into())) - } - - pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> { - // Operations here need to be in specific order - if on { - self.client.set_enable_display(on).ok(); - // Let the inner loop run - self.inner_early_return.store(false, Ordering::SeqCst); - } else { - // Must make the inner run loop return early - self.inner_early_return.store(true, Ordering::SeqCst); - self.client.set_enable_display(on).ok(); - } - Ok(()) - } -} diff --git a/asusd-user/src/daemon.rs b/asusd-user/src/daemon.rs deleted file mode 100644 index abf3bfd62..000000000 --- a/asusd-user/src/daemon.rs +++ /dev/null @@ -1,175 +0,0 @@ -use std::io::Write; -use std::path::PathBuf; -use std::sync::atomic::AtomicBool; -use std::sync::{Arc, Mutex}; - -use asusd_user::config::*; -use asusd_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner}; -use config_traits::{StdConfig, StdConfigLoad}; -use log::{error, info}; -use rog_anime::usb::get_anime_type; -use rog_aura::aura_detection::LedSupportData; -use rog_aura::keyboard::KeyLayout; -use rog_dbus::zbus_anime::AnimeProxyBlocking; -use rog_dbus::zbus_aura::AuraProxyBlocking; -use rog_dbus::{DBUS_NAME, list_iface_blocking}; -use zbus::Connection; - -#[cfg(not(feature = "local_data"))] -const DATA_DIR: &str = "/usr/share/rog-gui/"; -#[cfg(feature = "local_data")] -const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR"); -const BOARD_NAME: &str = "/sys/class/dmi/id/board_name"; - -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { - let mut logger = env_logger::Builder::new(); - logger - .filter_level(log::LevelFilter::Info) - .parse_default_env() - .target(env_logger::Target::Stdout) - .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) - .init(); - - info!(" user daemon v{}", asusd_user::VERSION); - info!(" rog-anime v{}", rog_anime::VERSION); - info!(" rog-dbus v{}", rog_dbus::VERSION); - info!("rog-platform v{}", rog_platform::VERSION); - - let conn = zbus::blocking::Connection::system()?; - - let dbus = zbus::blocking::fdo::DBusProxy::new(&conn)?; - let name = zbus::names::BusName::try_from(DBUS_NAME)?; - if !dbus.name_has_owner(name.clone())? { - info!(" waiting for system daemon to become ready on D-Bus..."); - let mut stream = dbus.receive_name_owner_changed()?; - if !dbus.name_has_owner(name.clone())? { - let (tx, rx) = std::sync::mpsc::channel(); - let name_clone = name.clone(); - std::thread::spawn(move || { - for signal in stream.by_ref() { - if let Ok(args) = signal.args() - && args.name() == &name_clone - && args.new_owner().is_some() - { - let _ = tx.send(()); - break; - } - } - }); - - if rx.recv_timeout(std::time::Duration::from_secs(30)).is_err() - && !dbus.name_has_owner(name.clone())? - { - error!("Timed out waiting for system daemon to become ready on D-Bus"); - return Err(std::io::Error::new( - std::io::ErrorKind::TimedOut, - "Timed out waiting for system daemon on D-Bus", - ) - .into()); - } - } - info!(" system daemon is ready!"); - } - - let supported = list_iface_blocking()?; - let config = ConfigBase::new().load(); - - let early_return = Arc::new(AtomicBool::new(false)); - // Set up the anime data and run loop/thread - if supported.contains(&"xyz.ljones.Anime".to_string()) - && let Some(cfg) = config.active_anime - { - let anime_type = get_anime_type(); - let anime_config = ConfigAnime::new().set_name(cfg).load(); - let anime = anime_config.create(anime_type)?; - let anime_config = Arc::new(Mutex::new(anime_config)); - - let anime_proxy_blocking = AnimeProxyBlocking::new(&conn)?; - tokio::spawn(async move { - // Create server - let mut connection = match Connection::session().await { - Ok(c) => c, - Err(e) => { - error!("Failed to connect to D-Bus session bus: {e}"); - return; - } - }; - if let Err(e) = connection.request_name(DBUS_NAME).await { - error!("Failed to request D-Bus name {DBUS_NAME}: {e}"); - return; - } - - // Inner behind mutex required for thread safety - let inner = match CtrlAnimeInner::new( - anime, - anime_proxy_blocking.clone(), - early_return.clone(), - ) { - Ok(i) => Arc::new(Mutex::new(i)), - Err(e) => { - error!("Failed to initialize AniMe inner controller: {e}"); - return; - } - }; - // Need new client object for dbus control part - let anime_control = match CtrlAnime::new( - anime_config, - inner.clone(), - anime_proxy_blocking, - early_return, - ) { - Ok(c) => c, - Err(e) => { - error!("Failed to initialize AniMe controller: {e}"); - return; - } - }; - anime_control.add_to_server(&mut connection).await; - if let Err(e) = - tokio::task::spawn_blocking(move || -> Result<(), std::convert::Infallible> { - loop { - if let Ok(inner) = inner.clone().try_lock() { - inner.run().ok(); - } - } - }) - .await - { - error!("AniMe task failed: {e}"); - } - }); - } - - // if supported.keyboard_led.per_key_led_mode { - if let Some(cfg) = config.active_aura { - let mut aura_config = ConfigAura::new().set_name(cfg).load(); - // let baord_name = std::fs::read_to_string(BOARD_NAME)?; - - let led_support = LedSupportData::get_data(""); - - let layout = KeyLayout::find_layout(led_support, PathBuf::from(DATA_DIR)) - .map_err(|e| { - error!("{BOARD_NAME}, {e}"); - }) - .unwrap_or_else(|_| KeyLayout::default_layout()); - - let aura_proxy_blocking = AuraProxyBlocking::new(&conn)?; - tokio::task::spawn_blocking(move || { - loop { - aura_config.aura.next_state(&layout); - let packets = aura_config.aura.create_packets(); - - if let Err(e) = aura_proxy_blocking.direct_addressing_raw(packets) { - error!("Aura direct addressing error: {e}"); - break; - } - std::thread::sleep(std::time::Duration::from_millis(33)); - } - }); - } - // } - - std::future::pending::<()>().await; - Ok(()) -} diff --git a/asusd-user/src/error.rs b/asusd-user/src/error.rs deleted file mode 100644 index 33b771a36..000000000 --- a/asusd-user/src/error.rs +++ /dev/null @@ -1,39 +0,0 @@ -use thiserror::Error; - -use rog_anime::error::AnimeError; - -#[derive(Error, Debug)] -pub enum Error { - #[error("Failed to open: {0}")] - Io(#[source] std::io::Error), - - #[error("Failed to load user config")] - ConfigLoadFail, - - #[error("Failed to lock user config")] - ConfigLockFail, - - #[error("XDG environment vars appear unset")] - XdgVars, - - #[error("Anime error: {0}")] - Anime(#[source] AnimeError), -} - -impl From for Error { - fn from(err: std::io::Error) -> Self { - Error::Io(err) - } -} - -impl From for Error { - fn from(err: AnimeError) -> Self { - Error::Anime(err) - } -} - -impl From for zbus::fdo::Error { - fn from(err: Error) -> Self { - zbus::fdo::Error::Failed(err.to_string()) - } -} diff --git a/asusd-user/src/lib.rs b/asusd-user/src/lib.rs deleted file mode 100644 index 7c7c7816a..000000000 --- a/asusd-user/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod config; - -pub mod error; - -pub mod ctrl_anime; - -pub mod zbus_anime; - -pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/asusd-user/src/zbus_anime.rs b/asusd-user/src/zbus_anime.rs deleted file mode 100644 index 910e038bf..000000000 --- a/asusd-user/src/zbus_anime.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! # `DBus` interface proxy for: `xyz.ljones.Asusd` -//! -//! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection -//! data. Source: `Interface '/xyz/ljones/Anime' from service -//! 'xyz.ljones.Asusd' on session bus`. -//! -//! You may prefer to adapt it, instead of using it verbatim. -//! -//! More information can be found in the -//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html) -//! section of the zbus documentation. -//! -//! This `DBus` object implements -//! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), -//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: -//! -//! * [`zbus::fdo::PeerProxy`] -//! * [`zbus::fdo::IntrospectableProxy`] -//! * [`zbus::fdo::PropertiesProxy`] -//! -//! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -#![allow(clippy::too_many_arguments)] - -use zbus::proxy; - -#[proxy(interface = "xyz.ljones.Asusd", default_path = "/xyz/ljones/Anime")] -trait Daemon { - /// InsertAsusGif method - fn insert_asus_gif( - &self, - index: u32, - file: &str, - time: u32, - count: u32, - brightness: f64, - ) -> zbus::Result; - - /// InsertImage method - fn insert_image( - &self, - index: u32, - file: &str, - scale: f64, - angle: f64, - xy: &(f64, f64), - brightness: f64, - ) -> zbus::Result; - - /// InsertImageGif method - fn insert_image_gif( - &self, - index: u32, - file: &str, - scale: f64, - angle: f64, - xy: &(f64, f64), - time: u32, - count: u32, - brightness: f64, - ) -> zbus::Result; - - /// InsertPause method - fn insert_pause(&self, index: u32, millis: u64) -> zbus::Result; - - /// RemoveItem method - fn remove_item(&self, index: u32) -> zbus::Result; - - /// SetState method - fn set_state(&self, on: bool) -> zbus::Result<()>; -} diff --git a/asusd/src/aura_anime/trait_impls.rs b/asusd/src/aura_anime/trait_impls.rs index 337c868b5..dddd914f4 100644 --- a/asusd/src/aura_anime/trait_impls.rs +++ b/asusd/src/aura_anime/trait_impls.rs @@ -290,8 +290,7 @@ impl AniMeZbus { config.write(); } - /// The main loop is the base system set action if the user isn't running - /// the user daemon + /// Run the continuous `system` playlist from `/etc/asusd/anime.ron`. async fn run_main_loop(&self, start: bool) { if start { self.0.thread_exit.store(true, Ordering::SeqCst); From 40f0f02f2e0083eb99d85da474bbca54b73565c0 Mon Sep 17 00:00:00 2001 From: Marco Scardovi Date: Sun, 18 Oct 2026 14:29:10 +0200 Subject: [PATCH 2/3] chore: drop asusd-user install and systemd packaging Remove Makefile install/uninstall/strip hooks for asusd-user, the unused user unit, and the PKGBUILD cleanup line for that binary. Signed-off-by: Marco Scardovi --- Makefile | 17 ++++------------- data/asusd-user.service | 11 ----------- distro-packaging/PKGBUILD | 1 - 3 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 data/asusd-user.service diff --git a/Makefile b/Makefile index df3d75db9..8778e4723 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,6 @@ APP_ID := org.opengamingcollective.rog-control-center BIN_C := asusctl BIN_D := asusd BIN_S := asus-shutdown -BIN_U := asusd-user LEDCFG := aura_support.ron DESTDIR_REALPATH := $(if $(DESTDIR),$(shell realpath $(DESTDIR)),) @@ -70,9 +69,6 @@ target/$(TARGET)/$(BIN_S): $(SRC) target/$(TARGET)/$(BIN_C): $(SRC) $(MAKE) build -target/$(TARGET)/$(BIN_U): $(SRC) - $(MAKE) build - target/$(TARGET)/$(BIN_ROG): $(SRC) $(MAKE) build @@ -85,15 +81,12 @@ install-asus-shutdown: target/$(TARGET)/$(BIN_S) install-asusctl: target/$(TARGET)/$(BIN_C) $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" -install-asusd_user: target/$(TARGET)/$(BIN_U) - $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)" - install-rog_gui: target/$(TARGET)/$(BIN_ROG) $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)" -.PHONY: install-asusd install-asus-shutdown install-asusctl install-asusd_user install-rog_gui +.PHONY: install-asusd install-asus-shutdown install-asusctl install-rog_gui -install-program: install-asusd install-asus-shutdown install-asusctl install-asusd_user install-rog_gui +install-program: install-asusd install-asus-shutdown install-asusctl install-rog_gui install-data-rog_gui: target/$(TARGET)/$(BIN_ROG) $(INSTALL_DATA) "./rog-control-center/data/$(APP_ID).desktop" "$(DESTDIR)$(datarootdir)/applications/$(APP_ID).desktop" @@ -131,9 +124,9 @@ install-data-asusd: cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR_REALPATH)$(datarootdir)/asusd/{}" \; -.PHONY: install-data-asusd install-data-asusd_user +.PHONY: install-data-asusd -install-data: install-data-asusd install-data-asusd_user install-data-rog_gui +install-data: install-data-asusd install-data-rog_gui install: install-program install-data $(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE" @@ -149,7 +142,6 @@ uninstall: rm -f "$(DESTDIR)$(bindir)/$(BIN_C)" rm -f "$(DESTDIR)$(bindir)/$(BIN_D)" rm -f "$(DESTDIR)$(bindir)/$(BIN_S)" - rm -f "$(DESTDIR)$(bindir)/$(BIN_U)" rm -f "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules" rm -f "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)" rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf" @@ -201,7 +193,6 @@ ifeq ($(STRIP_BINARIES),1) strip -s ./target/$(TARGET)/$(BIN_C) strip -s ./target/$(TARGET)/$(BIN_D) strip -s ./target/$(TARGET)/$(BIN_S) - strip -s ./target/$(TARGET)/$(BIN_U) strip -s ./target/$(TARGET)/$(BIN_ROG) endif diff --git a/data/asusd-user.service b/data/asusd-user.service deleted file mode 100644 index 6dbb8c11b..000000000 --- a/data/asusd-user.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=ASUS User Daemon - -[Service] -ExecStart=/usr/bin/asusd-user -Restart=on-failure -RestartSec=1 -Type=simple - -[Install] -WantedBy=default.target \ No newline at end of file diff --git a/distro-packaging/PKGBUILD b/distro-packaging/PKGBUILD index 8d5593333..c522ebd1a 100644 --- a/distro-packaging/PKGBUILD +++ b/distro-packaging/PKGBUILD @@ -61,7 +61,6 @@ _package-rog-control-center() { make DESTDIR="$pkgdir" install rm -rf "$pkgdir"/usr/bin/asusctl rm -rf "$pkgdir"/usr/bin/asusd - rm -rf "$pkgdir"/usr/bin/asusd-user rm -rf "$pkgdir"/usr/bin/asus-shutdown rm -rf "$pkgdir"/usr/lib rm -rf "$pkgdir"/usr/share/dbus-1 From 2f3f55668e8f6b68d1b11712e10d7d6f36cfaa7c Mon Sep 17 00:00:00 2001 From: Marco Scardovi Date: Sun, 18 Oct 2026 14:29:11 +0200 Subject: [PATCH 3/3] docs: migrate asusd-user guidance to anime.ron Document continuous AniMe playlists via anime.ron system sequences and RunMainLoop, and remove asusd-user from distro setup and issue templates. Clarify system playlist lifecycle and cache reload, keep uninstall cleanup for a leftover asusd-user binary, and document D-Bus group membership plus concrete busctl/asusctl steps for starting the migrated playlist. Signed-off-by: Marco Scardovi --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .github/ISSUE_TEMPLATE/new_feature.yml | 1 - MANUAL.md | 332 ++++--------------------- Makefile | 1 + docs/distributions/pikaos.md | 2 - docs/distributions/ubuntu.md | 2 - 6 files changed, 44 insertions(+), 295 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 84e54c009..e08194399 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -20,7 +20,6 @@ body: description: Select the main component where the issue occurs. options: - "asusd (System Daemon / D-Bus)" - - "asusd-user (User Session Daemon)" - "asusctl (CLI Tool)" - "rog-control-center (GUI / Slint / System Tray)" - "rog-aura (Keyboard / Aura RGB)" diff --git a/.github/ISSUE_TEMPLATE/new_feature.yml b/.github/ISSUE_TEMPLATE/new_feature.yml index bc5abdc4b..607e31f40 100644 --- a/.github/ISSUE_TEMPLATE/new_feature.yml +++ b/.github/ISSUE_TEMPLATE/new_feature.yml @@ -30,7 +30,6 @@ body: description: Select the main component or crate where this feature belongs. options: - "asusd (System Daemon / D-Bus)" - - "asusd-user (User Session Daemon)" - "asusctl (CLI Tool)" - "rog-control-center (GUI / Slint / System Tray)" - "rog-aura (Keyboard / Aura RGB)" diff --git a/MANUAL.md b/MANUAL.md index 35be9f19f..90f99cf02 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -8,8 +8,8 @@ but can also be used with non-asus laptops with reduced features. ## Programs Available - `asusd`: The main system daemon. It is autostarted by a udev rule and systemd unit. -- `asusd-user`: The user level daemon. Currently will run an anime sequence, with RGB keyboard sequences soon. - `asusctl`: The CLI for interacting with the system daemon +- `rog-control-center`: Optional GUI for `asusd` ## `asusd` @@ -32,15 +32,39 @@ Controller for the fancy AniMe matrix display on the lid of some machines. This #### Config options -If you have an AniMe device a few system-level config options are enabled for you in `/etc/asusd/anime.conf`; +If you have an AniMe device, system-level options live in `/etc/asusd/anime.ron`: -1. `"system": [],`: currently unused, is intended to be a default continuous sequence in future versions -2. `"boot": [],`: a sequence that plays on system boot (when asusd is loaded) -3. `"wake": [],`: a sequence that plays when waking from suspend -4. `"shutdown": [],`: a sequence that plays when shutdown begins -5. `"brightness": `: global brightness control, where ` is 0.0-1.0 +1. `system: []`: continuous playlist while its loop is running (replaces the old `asusd-user` session daemon). Start it with the D-Bus method `RunMainLoop(true)` on `xyz.ljones.Anime`, and call it again after restarting `asusd` or resuming from suspend. +2. `boot: []`: sequence that plays on system boot (when asusd is loaded) +3. `wake: []`: sequence that plays when waking from suspend +4. `shutdown: []`: sequence that plays when shutdown begins +5. Display / builtin animation toggles and brightness (see the generated defaults on first run) -Some default examples are provided but are minimal. The full range of configuration options will be covered in another section of this manual. +Each list entry is an `ActionLoader` from `rog-anime` (AsusAnimation, AsusImage, ImageAnimation, Image, Pause). Paths must be absolute. + +### Migrating from `asusd-user` (removed) + +`asusd-user` and `~/.config/rog/` user playlists are removed. To keep a continuous AniMe sequence: + +1. Ensure your account can talk to `asusd` on the system bus. The caller of `RunMainLoop` must be `root` or a member of `adm`, `sudo`, `users`, or `wheel` (see `data/asusd.conf`). Package installation does not add you to those groups. Check with `groups`; if none match, add one that exists on your distro (for example `users` or `wheel`) and re-login: + +``` +sudo usermod -aG users "$USER" +``` + +2. Open the old user file (for example `~/.config/rog/anime-default.ron`) and copy the `anime: [...]` array into `/etc/asusd/anime.ron` as `system: [...]` (same `ActionLoader` shape). Paths must stay absolute. Editing `/etc/asusd/` needs root (`sudoedit /etc/asusd/anime.ron`). + +3. If you want only the custom playlist, disable firmware builtins, restart `asusd` so it reloads the cached `system` playlist, then start the loop: + +``` +asusctl anime --enable-powersave-anim false +sudo systemctl restart asusd +busctl --system call xyz.ljones.Asusd /xyz/ljones/aura/anime xyz.ljones.Anime RunMainLoop b true +``` + +Call `RunMainLoop` again after every `asusd` restart or resume from suspend. There is no `asusctl` subcommand for that method yet; use `busctl` (or any D-Bus client) as above. + +Per-key / zoned Aura effect loops that lived under `asusd-user` are not stored in `aura_*.ron`. Use `asusctl` examples that call `direct_addressing_raw`, or drive that D-Bus method yourself. `/etc/asusd/asusd_user_ledmodes.ron` is unrelated — it remains the optional LED-mode override for `asusd`. ### Led keyboard control @@ -118,292 +142,22 @@ The config file is located at `/etc/asusd/profile.conf` and is self-descriptive. There is one more controller; the support controller. The sole pupose of this controller is to querie all the other controllers for information about their support level for the host laptop. Returns a json string. -## asusd-user - -`asusd-user` is a usermode daemon. The intended purpose is to provide a method for users to run there own custom per-key keyboard effects and modes, AniMe sequences, and possibly their own profiles - all without overwriting the _base_ system config. As such some parts of the system daemon will migrate to the user daemon over time with the expectation that the Linux system runs both. - -As of now only AniMe is active in this with configuration in `~/.config/rog/`. On first run defaults are created that are intended to work as examples. - -The main config is `~/.config/rog/rog-user.cfg` - -#### Config options: Aura, per-key and zoned - -I'm unsure of how many laptops this works on, so please try it. - -`led_type: Key` works only on actual per-key RGB keyboards. - -`led_type: Zone` works on zoned laptops. - -`led_type: Zone` set to `None` works on zoned ROG laptops, unzoned ROG laptops, and TUF laptops (and yes this does mean an audio EQ can be done now). - -`~/.config/rog/rog-user.cfg` contains a setting `"active_aura": ""` where `` is the name of the Aura config to use, located in the same directory and without the file postfix, e.g, `"active_anime": "aura-default"` - -An Aura config itself is a file with contents: - -```ron -( - name: "aura-default", - aura: ( - effects: [ - Breathe(( - led: W, - start_colour1: (255, 0, 20), - start_colour2: (20, 255, 0), - speed: Low, - )), - Breathe(( - led: A, - start_colour1: (255, 0, 20), - start_colour2: (20, 255, 0), - speed: Low, - )), - Breathe(( - led: S, - start_colour1: (255, 0, 20), - start_colour2: (20, 255, 0), - speed: Low, - )), - Breathe(( - led: D, - start_colour1: (255, 0, 20), - start_colour2: (20, 255, 0), - speed: Low, - )), - Breathe(( - led: F, - start_colour1: (255, 0, 0), - start_colour2: (255, 0, 0), - speed: High, - )), - Static(( - led: RCtrl, - colour: (0, 0, 255), - )), - Static(( - led: LCtrl, - colour: (0, 0, 255), - )), - Static(( - led: Esc, - colour: (0, 0, 255), - )), - DoomFlicker(( - led: N9, - start_colour: (0, 0, 255), - max_percentage: 80, - min_percentage: 40, - )), - ], - zoned: false, - ), -) -``` - -If your laptop supports multizone, `"led"` can also be `"Zone": ` - -- `SingleZone` // Keyboards with only one zone -- `ZonedKbLeft` // keyboard left -- `ZonedKbLeftMid` // keyboard left-middle -- `ZonedKbRightMid` // etc -- `ZonedKbRight` -- `LightbarRight` -- `LightbarRightCorner` -- `LightbarRightBottom` -- `LightbarLeftBottom` -- `LightbarLeftCorner` -- `LightbarLeft` - -Single zone example: - -```ron -( - name: "aura-default", - aura: ( - effects: [ - DoomFlicker(( - led: SingleZone, - start_colour: (200, 40, 5), - max_percentage: 80, - min_percentage: 40, - )), - ], - zoned: true, - ), -) -``` - -At the moment there are only three effects available as shown in the example. More will come in the future -but this may take me some time. - -#### Config options: AniMe - -`~/.config/rog/rog-user.cfg` contains a setting `"active_anime": ""` where `` is the name of the AniMe config to use, located in the same directory and without the file postfix, e.g, `"active_anime": "anime-doom"` - -An AniMe config itself is a file with contents: - -```json -{ - "name": "", - "anime": [] -} -``` - -`` is used as a reference internally. `"anime": []` is an array of sequences (WIP). - -##### "anime" array options - -Each object in the array can be one of: - -1. AsusAnimation -2. ImageAnimation -3. Image -4. Pause - -##### AsusAnimation - -`AsusAnimation` is specifically for running the gif files that Armory Crate comes with. `asusctl` includes all of these in `/usr/share/asusd/anime/asus/` - -```json - "AsusAnimation": { - "file": "", - "time":