diff --git a/asus-nb-ctrl/src/main.rs b/asus-nb-ctrl/src/main.rs index f7d624fd..84a8f7c1 100644 --- a/asus-nb-ctrl/src/main.rs +++ b/asus-nb-ctrl/src/main.rs @@ -1,6 +1,7 @@ use asus_nb::{ - cli_options::{LedBrightness, SetAuraBuiltin}, + cli_options::{LedBrightness, SetAuraBuiltin, AniMeActions}, core_dbus::AuraDbusClient, + anime_dbus::AniMeDbusWriter, profile::{ProfileCommand, ProfileEvent}, }; use ctrl_gfx::vendors::GfxVendors; @@ -36,6 +37,8 @@ enum CliCommand { Profile(ProfileCommand), #[options(help = "Set the graphics mode")] Graphics(GraphicsCommand), + #[options(name = "anime", help = "Manage AniMe Matrix")] + AniMe(AniMeCommand), } #[derive(Options)] @@ -60,6 +63,14 @@ struct GraphicsCommand { force: bool, } +#[derive(Debug, Options)] +struct AniMeCommand { + #[options(help = "print help message")] + help: bool, + #[options(command, required)] + command: Option, +} + fn main() -> Result<(), Box> { let mut logger = env_logger::Builder::new(); logger @@ -75,6 +86,7 @@ fn main() -> Result<(), Box> { } let writer = AuraDbusClient::new()?; + let anime = AniMeDbusWriter::new()?; match parsed.command { Some(CliCommand::LedMode(mode)) => { @@ -86,7 +98,14 @@ fn main() -> Result<(), Box> { writer.write_profile_command(&ProfileEvent::Cli(command))? } Some(CliCommand::Graphics(command)) => do_gfx(command, &writer)?, - None => (), + Some(CliCommand::AniMe( + AniMeCommand { + command: Some(AniMeActions::Leds(anime_leds)), .. + })) => { + anime.set_leds_brightness(anime_leds.led_brightness())?; + }, + Some(CliCommand::AniMe(_)) + | None => (), } if let Some(brightness) = parsed.kbd_bright { diff --git a/asus-nb/src/anime_dbus.rs b/asus-nb/src/anime_dbus.rs index acc8a8a3..cdf74cb9 100644 --- a/asus-nb/src/anime_dbus.rs +++ b/asus-nb/src/anime_dbus.rs @@ -1,16 +1,18 @@ -use crate::anime_matrix::AniMePacketType; -use crate::{DBUS_IFACE, DBUS_NAME}; -use dbus::channel::Sender; -use dbus::{blocking::Connection, Message}; +const DBUS_ANIME_PATH : &str = "/org/asuslinux/Anime"; +pub const ANIME_PANE1_PREFIX: [u8; 7] = + [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02]; +pub const ANIME_PANE2_PREFIX: [u8; 7] = + [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02]; + +use crate::anime_matrix::{AniMeMatrix, AniMePacketType}; +use crate::DBUS_NAME; +use dbus::blocking::Connection; use std::error::Error; -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; use std::{thread, time::Duration}; -pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02]; -pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02]; +use crate::dbus_anime::{ + OrgAsuslinuxDaemon as OrgAsuslinuxDaemonAniMe, +}; /// Interface for the AniMe dot-matrix display /// @@ -23,7 +25,6 @@ pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x0 pub struct AniMeDbusWriter { connection: Box, block_time: u64, - stop: Arc, } impl AniMeDbusWriter { @@ -33,47 +34,60 @@ impl AniMeDbusWriter { Ok(AniMeDbusWriter { connection: Box::new(connection), block_time: 25, - stop: Arc::new(AtomicBool::new(false)), }) } + /// Create D-Bus proxy and send the message + #[inline] + fn write_anime(&self, input: Vec>) + -> Result<(), Box> { + let proxy = self.connection.with_proxy( + DBUS_NAME, + DBUS_ANIME_PATH, + Duration::from_millis(200), + ); + + proxy.set_anime(input)?; + thread::sleep(Duration::from_millis(self.block_time)); + + Ok(()) + } + pub fn write_image_to_buf(_buf: &mut AniMePacketType, _image_data: &[u8]) { unimplemented!("Image format is in progress of being worked out") } /// Write an Animatrix image /// - /// The expected input here is *two* Vectors, 640 bytes in length. The two vectors - /// are each one half of the full image write. + /// The expected input here is *two* Vectors, 640 bytes in length. + /// The two vectors are each one half of the full image write. /// - /// After each write a flush is written, it is assumed that this tells the device to - /// go ahead and display the written bytes + /// After each write a flush is written, it is assumed that this tells the + /// device to go ahead and display the written bytes /// - /// # Note: - /// The vectors are expected to contain the full sequence of bytes as follows + /// # Note: The vectors are expected to contain the full sequence of bytes + /// as follows /// /// - Write packet 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. /// - Write packet 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. /// /// Where led brightness is 0..255, low to high #[inline] - pub fn write_image(&mut self, image: &mut AniMePacketType) -> Result<(), Box> { - if image[0][0] != ANIME_PANE1_PREFIX[0] && image[0][6] != ANIME_PANE1_PREFIX[6] { - image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX); - } - if image[1][0] != ANIME_PANE2_PREFIX[0] && image[1][6] != ANIME_PANE2_PREFIX[6] { - image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX); - } + pub fn write_image(&self, image: &mut AniMePacketType) + -> Result<(), Box> { + image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX); + image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX); + self.write_anime(vec![image[0].to_vec(), image[1].to_vec()])?; + Ok(()) + } - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Anime", DBUS_IFACE, "SetAnime")? - .append2(image[0].to_vec(), image[1].to_vec()); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); - thread::sleep(Duration::from_millis(self.block_time)); - if self.stop.load(Ordering::Relaxed) { - panic!("Got signal to stop!"); - } + #[inline] + pub fn set_leds_brightness(&self, led_brightness: u8) + -> Result<(), Box> { + let mut anime_matrix = AniMeMatrix::new(); + + anime_matrix.fill_with(led_brightness); + self.write_image(&mut AniMePacketType::from(anime_matrix))?; Ok(()) } } diff --git a/asus-nb/src/cli_options.rs b/asus-nb/src/cli_options.rs index cfddab69..d1b175ad 100644 --- a/asus-nb/src/cli_options.rs +++ b/asus-nb/src/cli_options.rs @@ -213,3 +213,26 @@ impl Default for SetAuraBuiltin { }) } } + + +#[derive(Debug, Options)] +pub struct AniMeLeds { + #[options(help = "print help message")] + help: bool, + #[options(no_long, required, + short = "b", meta = "BYTE", + help = "set all leds brightness value")] + led_brightness: u8, +} + +impl AniMeLeds { + pub fn led_brightness(&self) -> u8 { + self.led_brightness + } +} + +#[derive(Debug, Options)] +pub enum AniMeActions { + #[options(help = "change all leds brightness")] + Leds(AniMeLeds) +} diff --git a/asus-nb/src/dbus_anime.rs b/asus-nb/src/dbus_anime.rs new file mode 100644 index 00000000..a7b655ba --- /dev/null +++ b/asus-nb/src/dbus_anime.rs @@ -0,0 +1,16 @@ +// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Anime -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs +use dbus as dbus; +#[allow(unused_imports)] +use dbus::arg; +use dbus::blocking; + +pub trait OrgAsuslinuxDaemon { + fn set_anime(&self, input: Vec>) -> Result<(), dbus::Error>; +} + +impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> { + + fn set_anime(&self, input: Vec>) -> Result<(), dbus::Error> { + self.method_call("org.asuslinux.Daemon", "SetAnime", (input, )) + } +} diff --git a/asus-nb/src/error.rs b/asus-nb/src/error.rs index cec0b64d..21556c22 100644 --- a/asus-nb/src/error.rs +++ b/asus-nb/src/error.rs @@ -7,6 +7,7 @@ pub enum AuraError { ParseSpeed, ParseDirection, ParseBrightness, + ParseAnime, } impl fmt::Display for AuraError { @@ -17,6 +18,7 @@ impl fmt::Display for AuraError { AuraError::ParseSpeed => write!(f, "Could not parse speed"), AuraError::ParseDirection => write!(f, "Could not parse direction"), AuraError::ParseBrightness => write!(f, "Could not parse brightness"), + AuraError::ParseAnime => write!(f, "Could not parse anime"), } } } diff --git a/asus-nb/src/lib.rs b/asus-nb/src/lib.rs index 91417c0f..90bd27c4 100644 --- a/asus-nb/src/lib.rs +++ b/asus-nb/src/lib.rs @@ -27,6 +27,7 @@ pub mod dbus_gfx; pub mod dbus_ledmode; pub mod dbus_profile; pub mod dbus_charge; +pub mod dbus_anime; pub mod error;