From 535e104ccc39c546a33eb4de7a5993b135fbe30a Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 14 Jul 2022 21:18:53 +1200 Subject: [PATCH] Rebuild of LED power control --- asusctl/src/aura_cli.rs | 49 +++++- asusctl/src/cli_opts.rs | 23 +-- asusctl/src/main.rs | 182 +++++++++++++++++++--- daemon/src/ctrl_aura/config.rs | 26 ++-- daemon/src/ctrl_aura/controller.rs | 12 +- daemon/src/ctrl_aura/zbus.rs | 147 +++--------------- rog-aura/src/builtin_modes.rs | 10 -- rog-aura/src/usb.rs | 233 ++++++++++++++++------------- rog-dbus/src/zbus_led.rs | 27 +--- 9 files changed, 393 insertions(+), 316 deletions(-) diff --git a/asusctl/src/aura_cli.rs b/asusctl/src/aura_cli.rs index a0449c8b..37e98415 100644 --- a/asusctl/src/aura_cli.rs +++ b/asusctl/src/aura_cli.rs @@ -2,6 +2,53 @@ use gumdrop::Options; use rog_aura::{error::Error, AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed}; use std::str::FromStr; +#[derive(Options)] +pub struct LedPowerCommand { + #[options(help = "print help message")] + pub help: bool, + #[options(command)] + pub command: Option, +} + +#[derive(Options)] +pub enum SetAuraEnabled { + #[options(help = "set to enabled while the device is booting")] + Boot(AuraEnabled), + #[options(help = "set to animate while the device is suspended")] + Sleep(AuraEnabled), + #[options(help = "set to enabled while device is awake")] + Awake(AuraEnabled), + #[options(help = "set to animate while the device is shutdown")] + Shutdown(AuraEnabled), +} + +#[derive(Debug, Clone, Default, Options)] +pub struct AuraEnabled { + #[options(help = "print help message")] + pub help: bool, + #[options(meta = "", help = "")] + pub keyboard: Option, + #[options(meta = "", help = "")] + pub logo: Option, + #[options(meta = "", help = "")] + pub lightbar: Option, +} + +// impl FromStr for AuraEnabled { +// type Err = Error; + +// fn from_str(s: &str) -> Result { +// let s = s.to_lowercase(); +// dbg!(s); +// Ok(Self { +// help: false, +// keyboard: None, +// logo: None, +// lightbar: None, +// }) +// } +// } + #[derive(Options)] pub struct LedBrightness { level: Option, @@ -57,6 +104,7 @@ pub struct SingleSpeed { )] pub zone: AuraZone, } + #[derive(Debug, Clone, Options, Default)] pub struct SingleSpeedDirection { #[options(help = "print help message")] @@ -306,7 +354,6 @@ impl From<&SetAuraBuiltin> for AuraEffect { data.mode = AuraModeNum::Flash; data } - _ => AuraEffect::default(), } } } diff --git a/asusctl/src/cli_opts.rs b/asusctl/src/cli_opts.rs index 13585ff6..21a31194 100644 --- a/asusctl/src/cli_opts.rs +++ b/asusctl/src/cli_opts.rs @@ -1,6 +1,6 @@ use crate::{ anime_cli::AnimeCommand, - aura_cli::{LedBrightness, SetAuraBuiltin}, + aura_cli::{LedBrightness, LedPowerCommand, SetAuraBuiltin}, profiles_cli::{FanCurveCommand, ProfileCommand}, }; use gumdrop::Options; @@ -29,6 +29,8 @@ pub struct CliStart { pub enum CliCommand { #[options(help = "Set the keyboard lighting from built-in modes")] LedMode(LedModeCommand), + #[options(help = "Set the keyboard lighting from built-in modes")] + LedPower(LedPowerCommand), #[options(help = "Set or select platform_profile")] Profile(ProfileCommand), #[options(help = "Set, select, or modify fan curves if supported")] @@ -49,25 +51,6 @@ pub struct LedModeCommand { pub next_mode: bool, #[options(help = "switch to previous aura mode")] pub prev_mode: bool, - #[options( - meta = "", - help = "set the keyboard LED to enabled while the device is awake" - )] - pub boot_enable: Option, - #[options( - meta = "", - help = "set the keyboard LED suspend animation to enabled while the device is suspended" - )] - pub sleep_enable: Option, - #[options( - meta = "", - help = "set the full keyboard LEDs (keys and side) to enabled" - )] - pub all_leds_enable: Option, - #[options(meta = "", help = "set the keyboard keys LEDs to enabled")] - pub keys_leds_enable: Option, - #[options(meta = "", help = "set the keyboard side LEDs to enabled")] - pub side_leds_enable: Option, #[options(command)] pub command: Option, } diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index adf39e07..f0714547 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -2,11 +2,13 @@ use std::process::Command; use std::thread::sleep; use std::{env::args, path::Path}; +use aura_cli::LedPowerCommand; use gumdrop::{Opt, Options}; use anime_cli::{AnimeActions, AnimeCommand}; use profiles_cli::{FanCurveCommand, ProfileCommand}; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2}; +use rog_aura::usb::AuraControl; use rog_aura::{self, AuraEffect}; use rog_dbus::RogDbusClientBlocking; use rog_profiles::error::ProfileError; @@ -143,6 +145,7 @@ fn do_parsed( ) -> Result<(), Box> { match &parsed.command { Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?, + Some(CliCommand::LedPower(pow)) => handle_led_power(dbus, &supported.keyboard_led, pow)?, Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?, Some(CliCommand::FanCurve(cmd)) => { handle_fan_curve(dbus, &supported.platform_profile, cmd)? @@ -339,15 +342,7 @@ fn handle_led_mode( supported: &LedSupportedFunctions, mode: &LedModeCommand, ) -> Result<(), Box> { - if mode.command.is_none() - && !mode.prev_mode - && !mode.next_mode - && mode.boot_enable.is_none() - && mode.sleep_enable.is_none() - && mode.all_leds_enable.is_none() - && mode.keys_leds_enable.is_none() - && mode.side_leds_enable.is_none() - { + if mode.command.is_none() && !mode.prev_mode && !mode.next_mode { if !mode.help { println!("Missing arg or command\n"); } @@ -396,22 +391,165 @@ fn handle_led_mode( .set_led_mode(&::from(mode))?; } - if let Some(enable) = mode.boot_enable { - dbus.proxies().led().set_boot_enabled(enable)?; + Ok(()) +} + +fn handle_led_power( + dbus: &RogDbusClientBlocking, + _supported: &LedSupportedFunctions, + power: &LedPowerCommand, +) -> Result<(), Box> { + if power.command().is_none() { + if !power.help { + println!("Missing arg or command\n"); + } + println!("{}\n", power.self_usage()); + println!("Commands available"); + + if let Some(cmdlist) = LedPowerCommand::command_list() { + let commands: Vec = cmdlist.lines().map(|s| s.to_string()).collect(); + for command in commands.iter() { + println!("{}", command); + } + } + + println!("\nHelp can also be requested on commands, e.g: boot --help"); + return Ok(()); } - if let Some(enable) = mode.sleep_enable { - dbus.proxies().led().set_sleep_enabled(enable)?; - } + if let Some(pow) = power.command.as_ref() { + if pow.help_requested() { + println!("{}", pow.self_usage()); + return Ok(()); + } - if let Some(enable) = mode.all_leds_enable { - dbus.proxies().led().set_all_leds_enabled(enable)?; - } - if let Some(enable) = mode.keys_leds_enable { - dbus.proxies().led().set_keys_leds_enabled(enable)?; - } - if let Some(enable) = mode.side_leds_enable { - dbus.proxies().led().set_side_leds_enabled(enable)?; + match pow { + // TODO: make this a macro or something + aura_cli::SetAuraEnabled::Boot(arg) => { + let mut enabled: Vec = Vec::new(); + let mut disabled: Vec = Vec::new(); + arg.keyboard.map(|v| { + if v { + enabled.push(AuraControl::BootKeyb) + } else { + disabled.push(AuraControl::BootKeyb) + } + }); + arg.logo.map(|v| { + if v { + enabled.push(AuraControl::BootLogo) + } else { + disabled.push(AuraControl::BootLogo) + } + }); + arg.lightbar.map(|v| { + if v { + enabled.push(AuraControl::BootBar) + } else { + disabled.push(AuraControl::BootBar) + } + }); + if !enabled.is_empty() { + dbus.proxies().led().set_leds_enabled(enabled)?; + } + if !disabled.is_empty() { + dbus.proxies().led().set_leds_disabled(disabled)?; + } + } + aura_cli::SetAuraEnabled::Sleep(arg) => { + let mut enabled: Vec = Vec::new(); + let mut disabled: Vec = Vec::new(); + arg.keyboard.map(|v| { + if v { + enabled.push(AuraControl::SleepKeyb) + } else { + disabled.push(AuraControl::SleepKeyb) + } + }); + arg.logo.map(|v| { + if v { + enabled.push(AuraControl::SleepLogo) + } else { + disabled.push(AuraControl::SleepLogo) + } + }); + arg.lightbar.map(|v| { + if v { + enabled.push(AuraControl::SleepBar) + } else { + disabled.push(AuraControl::SleepBar) + } + }); + if !enabled.is_empty() { + dbus.proxies().led().set_leds_enabled(enabled)?; + } + if !disabled.is_empty() { + dbus.proxies().led().set_leds_disabled(disabled)?; + } + } + aura_cli::SetAuraEnabled::Awake(arg) => { + let mut enabled: Vec = Vec::new(); + let mut disabled: Vec = Vec::new(); + arg.keyboard.map(|v| { + if v { + enabled.push(AuraControl::AwakeKeyb) + } else { + disabled.push(AuraControl::AwakeKeyb) + } + }); + arg.logo.map(|v| { + if v { + enabled.push(AuraControl::AwakeLogo) + } else { + disabled.push(AuraControl::AwakeLogo) + } + }); + arg.lightbar.map(|v| { + if v { + enabled.push(AuraControl::AwakeBar) + } else { + disabled.push(AuraControl::AwakeBar) + } + }); + if !enabled.is_empty() { + dbus.proxies().led().set_leds_enabled(enabled)?; + } + if !disabled.is_empty() { + dbus.proxies().led().set_leds_disabled(disabled)?; + } + } + aura_cli::SetAuraEnabled::Shutdown(arg) => { + let mut enabled: Vec = Vec::new(); + let mut disabled: Vec = Vec::new(); + arg.keyboard.map(|v| { + if v { + enabled.push(AuraControl::ShutdownKeyb) + } else { + disabled.push(AuraControl::ShutdownKeyb) + } + }); + arg.logo.map(|v| { + if v { + enabled.push(AuraControl::ShutdownLogo) + } else { + disabled.push(AuraControl::ShutdownLogo) + } + }); + arg.lightbar.map(|v| { + if v { + enabled.push(AuraControl::ShutdownBar) + } else { + disabled.push(AuraControl::ShutdownBar) + } + }); + if !enabled.is_empty() { + dbus.proxies().led().set_leds_enabled(enabled)?; + } + if !disabled.is_empty() { + dbus.proxies().led().set_leds_disabled(disabled)?; + } + } + } } Ok(()) diff --git a/daemon/src/ctrl_aura/config.rs b/daemon/src/ctrl_aura/config.rs index 42ed387d..bfde0275 100644 --- a/daemon/src/ctrl_aura/config.rs +++ b/daemon/src/ctrl_aura/config.rs @@ -1,6 +1,7 @@ use crate::laptops::LaptopLedData; use log::{error, warn}; -use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness, LedPowerStates}; +use rog_aura::usb::AuraControl; +use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness}; use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fs::{File, OpenOptions}; @@ -15,7 +16,7 @@ pub struct AuraConfig { pub current_mode: AuraModeNum, pub builtins: BTreeMap, pub multizone: Option>>, - pub power_states: LedPowerStates, + pub enabled: Vec, } impl Default for AuraConfig { @@ -25,13 +26,20 @@ impl Default for AuraConfig { current_mode: AuraModeNum::Static, builtins: BTreeMap::new(), multizone: None, - power_states: LedPowerStates { - boot_anim: true, - sleep_anim: true, - all_leds: true, - keys_leds: true, - side_leds: true, - }, + enabled: vec![ + AuraControl::BootLogo, + AuraControl::BootKeyb, + AuraControl::SleepLogo, + AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + AuraControl::AwakeBar, + AuraControl::BootBar, + AuraControl::SleepBar, + AuraControl::ShutdownBar, + ], } } } diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index 099433e0..6665db8d 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -9,7 +9,7 @@ use crate::{ use async_trait::async_trait; use log::{error, info, warn}; use logind_zbus::manager::ManagerProxy; -use rog_aura::usb::leds_message; +use rog_aura::usb::AuraControl; use rog_aura::{ usb::{LED_APPLY, LED_SET}, AuraEffect, LedBrightness, LED_MSG_LEN, @@ -298,17 +298,11 @@ impl CtrlKbdLed { /// Set combination state for boot animation/sleep animation/all leds/keys leds/side leds LED active pub(super) fn set_power_states(&self, config: &AuraConfig) -> Result<(), RogError> { - let bytes = leds_message( - config.power_states.boot_anim, - config.power_states.sleep_anim, - config.power_states.all_leds, - config.power_states.keys_leds, - config.power_states.side_leds, - ); + let bytes = AuraControl::to_bytes(&config.enabled); // Quite ugly, must be a more idiomatic way to do let message = [ - 0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x5d, 0xbd, 0x01, bytes[0], bytes[1], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; self.write_bytes(&message)?; diff --git a/daemon/src/ctrl_aura/zbus.rs b/daemon/src/ctrl_aura/zbus.rs index c4847340..28fee02e 100644 --- a/daemon/src/ctrl_aura/zbus.rs +++ b/daemon/src/ctrl_aura/zbus.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; use log::warn; -use rog_aura::{AuraEffect, LedBrightness, LedPowerStates}; +use rog_aura::{usb::AuraControl, AuraEffect, LedBrightness}; use zbus::{dbus_interface, Connection, SignalContext}; use super::controller::CtrlKbdLedZbus; @@ -26,22 +26,26 @@ impl CtrlKbdLedZbus { } } - /// Set the keyboard LED to enabled while the device is awake - async fn set_boot_enabled( + /// Set a variety of states + async fn set_leds_enabled( &mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>, - enabled: bool, + enabled: Vec, ) { let mut states = None; if let Ok(mut ctrl) = self.0.try_lock() { - ctrl.config.power_states.boot_anim = enabled; + for s in enabled { + if !ctrl.config.enabled.contains(&s) { + ctrl.config.enabled.push(s); + } + } ctrl.config.write(); ctrl.set_power_states(&ctrl.config) .map_err(|err| warn!("{}", err)) .ok(); - states = Some(ctrl.config.power_states); + states = Some(ctrl.config.enabled.clone()); } // Need to pull state out like this due to MutexGuard if let Some(states) = states { @@ -51,98 +55,27 @@ impl CtrlKbdLedZbus { } } - /// Set the keyboard LED suspend animation to enabled while the device is suspended - async fn set_sleep_enabled( + async fn set_leds_disabled( &mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>, - enabled: bool, + disabled: Vec, ) { let mut states = None; if let Ok(mut ctrl) = self.0.try_lock() { - ctrl.config.power_states.sleep_anim = enabled; + for s in disabled { + if ctrl.config.enabled.contains(&s) { + if let Ok(idx) = ctrl.config.enabled.binary_search(&s) { + ctrl.config.enabled.remove(idx); + } + } + } ctrl.config.write(); ctrl.set_power_states(&ctrl.config) .map_err(|err| warn!("{}", err)) .ok(); - states = Some(ctrl.config.power_states); - } - if let Some(states) = states { - Self::notify_power_states(&ctxt, &states) - .await - .unwrap_or_else(|err| warn!("{}", err)); - } - } - - /// Set all the keyboard LEDs (keys and side) to enabled - async fn set_all_leds_enabled( - &mut self, - #[zbus(signal_context)] ctxt: SignalContext<'_>, - enabled: bool, - ) { - let mut states = None; - if let Ok(mut ctrl) = self.0.try_lock() { - ctrl.config.power_states.all_leds = enabled; - ctrl.config.power_states.keys_leds = enabled; - ctrl.config.power_states.side_leds = enabled; - ctrl.config.write(); - - ctrl.set_power_states(&ctrl.config) - .map_err(|err| warn!("{}", err)) - .ok(); - - states = Some(ctrl.config.power_states); - } - // 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)); - } - } - - /// Set the keyboard keys LEDs to enabled - async fn set_keys_leds_enabled( - &mut self, - #[zbus(signal_context)] ctxt: SignalContext<'_>, - enabled: bool, - ) { - let mut states = None; - if let Ok(mut ctrl) = self.0.try_lock() { - ctrl.config.power_states.keys_leds = enabled; - ctrl.config.write(); - - ctrl.set_power_states(&ctrl.config) - .map_err(|err| warn!("{}", err)) - .ok(); - - states = Some(ctrl.config.power_states); - } - // 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)); - } - } - - /// Set the keyboard side LEDs to enabled - async fn set_side_leds_enabled( - &mut self, - #[zbus(signal_context)] ctxt: SignalContext<'_>, - enabled: bool, - ) { - let mut states = None; - if let Ok(mut ctrl) = self.0.try_lock() { - ctrl.config.power_states.side_leds = enabled; - ctrl.config.write(); - - ctrl.set_power_states(&ctrl.config) - .map_err(|err| warn!("{}", err)) - .ok(); - - states = Some(ctrl.config.power_states); + states = Some(ctrl.config.enabled.clone()); } // Need to pull state out like this due to MutexGuard if let Some(states) = states { @@ -226,43 +159,11 @@ impl CtrlKbdLedZbus { } #[dbus_interface(property)] - async fn boot_enabled(&self) -> bool { + async fn leds_enabled(&self) -> Vec { if let Ok(ctrl) = self.0.try_lock() { - return ctrl.config.power_states.boot_anim; + return AuraControl::to_bytes(&ctrl.config.enabled).to_vec(); } - true - } - - #[dbus_interface(property)] - async fn sleep_enabled(&self) -> bool { - if let Ok(ctrl) = self.0.try_lock() { - return ctrl.config.power_states.sleep_anim; - } - true - } - - #[dbus_interface(property)] - async fn all_leds_enabled(&self) -> bool { - if let Ok(ctrl) = self.0.try_lock() { - return ctrl.config.power_states.all_leds; - } - true - } - - #[dbus_interface(property)] - async fn keys_leds_enabled(&self) -> bool { - if let Ok(ctrl) = self.0.try_lock() { - return ctrl.config.power_states.keys_leds; - } - true - } - - #[dbus_interface(property)] - fn side_leds_enabled(&self) -> bool { - if let Ok(ctrl) = self.0.try_lock() { - return ctrl.config.power_states.side_leds; - } - true + vec![0, 0] } /// Return the current mode data @@ -307,6 +208,6 @@ impl CtrlKbdLedZbus { #[dbus_interface(signal)] async fn notify_power_states( signal_ctxt: &SignalContext<'_>, - data: &LedPowerStates, + data: &[AuraControl], ) -> zbus::Result<()>; } diff --git a/rog-aura/src/builtin_modes.rs b/rog-aura/src/builtin_modes.rs index c4550dfa..2a54bc49 100644 --- a/rog-aura/src/builtin_modes.rs +++ b/rog-aura/src/builtin_modes.rs @@ -11,16 +11,6 @@ use zvariant::Type; use crate::{error::Error, LED_MSG_LEN}; -#[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)] -pub struct LedPowerStates { - pub boot_anim: bool, - pub sleep_anim: bool, - pub all_leds: bool, - pub keys_leds: bool, - pub side_leds: bool, -} - #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)] pub enum LedBrightness { diff --git a/rog-aura/src/usb.rs b/rog-aura/src/usb.rs index 10de6c37..72719e02 100644 --- a/rog-aura/src/usb.rs +++ b/rog-aura/src/usb.rs @@ -1,6 +1,7 @@ -use crate::usb::LedCfgState::{Off, On}; -use std::convert::TryFrom; +use serde::{Deserialize, Serialize}; use std::ops::{BitAnd, BitOr}; +#[cfg(feature = "dbus")] +use zvariant::Type; pub const LED_INIT1: [u8; 2] = [0x5d, 0xb9]; pub const LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d @@ -12,13 +13,6 @@ pub const LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08]; pub const LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; pub const LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; -pub const BOOT_MASK: i32 = 0xc31309; -pub const SLEEP_MASK: i32 = 0x300904; -pub const ALL_LEDS_MASK: i32 = 0x000002; -pub const KBD_LEDS_MASK: i32 = 0x080000; -pub const SIDE_LEDS_MASK: i32 = 0x040500; -pub const LEDS_STATE_MASK: i32 = ALL_LEDS_MASK | KBD_LEDS_MASK | SIDE_LEDS_MASK; - /// Writes out the correct byte string for brightness pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { [ @@ -26,113 +20,152 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { ] } -#[derive(Clone, Copy)] -pub enum LedCfgState { - On = 0xffffff, - Off = 0x0, +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] +#[repr(u16)] +pub enum AuraControl { + BootLogo = 1, + BootKeyb = 1 << 1, + AwakeLogo = 1 << 2, + AwakeKeyb = 1 << 3, + SleepLogo = 1 << 4, + SleepKeyb = 1 << 5, + ShutdownLogo = 1 << 6, + ShutdownKeyb = 1 << 7, + AwakeBar = 1 << 7 + 2, + BootBar = 1 << 7 + 3, + SleepBar = 1 << 7 + 4, + ShutdownBar = 1 << 7 + 5, } -impl From for LedCfgState { - fn from(state: i32) -> Self { - match state { - 0xffffff => On, - 0x0 => Off, - _ => Off, - } +impl From for u16 { + fn from(a: AuraControl) -> Self { + a as u16 } } -impl From for LedCfgState { - fn from(state: bool) -> Self { - match state { - true => On, - false => Off, - } +impl AuraControl { + pub fn to_bytes(control: &[Self]) -> [u8; 2] { + let mut a: u16 = 0; + control.iter().for_each(|n| { + a |= *n as u16; + }); + [(a & 0xff) as u8, ((a & 0xff00) >> 8) as u8] } } -impl TryFrom<[u8; 3]> for LedCfgState { - type Error = &'static str; +impl BitOr for AuraControl { + type Output = u16; - fn try_from(value: [u8; 3]) -> Result { - match value { - [0xff, 0xff, 0xff] => Ok(On), - [0, 0, 0] => Ok(Off), - _ => Err("Unconvertible value"), - } + fn bitor(self, rhs: AuraControl) -> Self::Output { + return self as u16 | rhs as u16; } } -impl BitAnd for i32 { - type Output = i32; +impl BitAnd for AuraControl { + type Output = u16; - fn bitand(self, rhs: LedCfgState) -> i32 { - return self & rhs as i32; - } -} -impl BitOr for i32 { - type Output = i32; - - fn bitor(self, rhs: LedCfgState) -> Self::Output { - return self | rhs as i32; + fn bitand(self, rhs: AuraControl) -> Self::Output { + return self as u16 & rhs as u16; } } -impl BitOr for LedCfgState { - type Output = i32; +#[cfg(test)] +mod tests { + use crate::usb::AuraControl; - fn bitor(self, rhs: LedCfgState) -> i32 { - return self as i32 | rhs as i32; + #[test] + fn check_led_control_bytes() { + // All on + let byte1 = [ + AuraControl::BootLogo, + AuraControl::BootKeyb, + AuraControl::SleepLogo, + AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + ]; + let bytes = AuraControl::to_bytes(&byte1); + println!("{:08b}", bytes[0]); + assert_eq!(bytes[0], 0xff); + + // + let byte1 = [ + // AuraControl::BootLogo, + AuraControl::BootKeyb, + AuraControl::SleepLogo, + AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + ]; + let bytes = AuraControl::to_bytes(&byte1); + println!("{:08b}", bytes[0]); + assert_eq!(bytes[0], 0xfe); + + let byte1 = [ + AuraControl::BootLogo, + // AuraControl::BootKeyb, + AuraControl::SleepLogo, + AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + ]; + let bytes = AuraControl::to_bytes(&byte1); + println!("{:08b}", bytes[0]); + assert_eq!(bytes[0], 0xfd); + + let byte1 = [ + AuraControl::BootLogo, + AuraControl::BootKeyb, + // AuraControl::SleepLogo, + AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + ]; + let bytes = AuraControl::to_bytes(&byte1); + println!("{:08b}", bytes[0]); + assert_eq!(bytes[0], 0xef); + + let byte1 = [ + AuraControl::BootLogo, + AuraControl::BootKeyb, + AuraControl::SleepLogo, + // AuraControl::SleepKeyb, + AuraControl::AwakeLogo, + AuraControl::AwakeKeyb, + AuraControl::ShutdownLogo, + AuraControl::ShutdownKeyb, + ]; + let bytes = AuraControl::to_bytes(&byte1); + println!("{:08b}", bytes[0]); + assert_eq!(bytes[0], 0xdf); + + let byte2 = [ + AuraControl::AwakeBar, + AuraControl::BootBar, + AuraControl::SleepBar, + AuraControl::ShutdownBar, + ]; + let bytes = AuraControl::to_bytes(&byte2); + println!("{:08b}", bytes[1]); + assert_eq!(bytes[1], 0x1e); + + let byte2 = [ + AuraControl::AwakeBar, + AuraControl::BootBar, + // AuraControl::SleepBar, + AuraControl::ShutdownBar, + ]; + let bytes = AuraControl::to_bytes(&byte2); + println!("{:08b}", bytes[1]); + assert_eq!(bytes[1], 0x16); } } - -impl BitAnd for LedCfgState { - type Output = LedCfgState; - - fn bitand(self, rhs: LedCfgState) -> LedCfgState { - return (self as i32 & rhs as i32).into(); - } -} - -pub fn leds_message( - boot_state: bool, - sleep_state: bool, - all_leds_state: bool, - kbd_leds_state: bool, - side_leds_state: bool, -) -> [u8; 3] { - let raw_message = _leds_message( - boot_state.into(), - sleep_state.into(), - all_leds_state.into(), - kbd_leds_state.into(), - side_leds_state.into(), - ); - - let [_, lows @ ..] = i32::to_be_bytes(raw_message); - return lows; -} - -fn _leds_message( - boot_state: LedCfgState, - sleep_state: LedCfgState, - all_leds_state: LedCfgState, - kbd_leds_state: LedCfgState, - side_leds_state: LedCfgState, -) -> i32 { - let full_leds_state = match all_leds_state { - On => { - (ALL_LEDS_MASK & all_leds_state) - | (KBD_LEDS_MASK & kbd_leds_state) - | (SIDE_LEDS_MASK & side_leds_state) - } - Off => 0x0100 & side_leds_state, - }; - - let boot_xor_sleep = (BOOT_MASK & boot_state) ^ (SLEEP_MASK & sleep_state); - - return match (all_leds_state | kbd_leds_state | side_leds_state).into() { - On => boot_xor_sleep ^ ((boot_xor_sleep ^ full_leds_state) & LEDS_STATE_MASK), - _ => boot_xor_sleep, - }; -} diff --git a/rog-dbus/src/zbus_led.rs b/rog-dbus/src/zbus_led.rs index 3d120582..d72a900d 100644 --- a/rog-dbus/src/zbus_led.rs +++ b/rog-dbus/src/zbus_led.rs @@ -22,7 +22,7 @@ use zbus::{blocking::Connection, Result}; use zbus_macros::dbus_proxy; -use rog_aura::{AuraEffect, KeyColourArray, LedBrightness, LedPowerStates}; +use rog_aura::{usb::AuraControl, AuraEffect, KeyColourArray, LedBrightness}; const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS @@ -49,27 +49,16 @@ trait Led { /// SetLedMode method fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>; - /// SetAwakeEnabled method - fn set_boot_enabled(&self, enabled: bool) -> zbus::Result<()>; + fn set_leds_enabled(&self, enabled: Vec) -> zbus::Result<()>; - /// SetSleepEnabled method - fn set_sleep_enabled(&self, enabled: bool) -> zbus::Result<()>; - - /// SetSideLedsEnabled method - fn set_all_leds_enabled(&self, enabled: bool) -> Result<()>; - - /// SetSideLedsEnabled method - fn set_keys_leds_enabled(&self, enabled: bool) -> Result<()>; - - /// SetSideLedsEnabled method - fn set_side_leds_enabled(&self, enabled: bool) -> Result<()>; + fn set_leds_disabled(&self, disabled: Vec) -> zbus::Result<()>; /// NotifyLed signal #[dbus_proxy(signal)] fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>; #[dbus_proxy(signal)] - fn notify_power_states(&self, data: LedPowerStates) -> zbus::Result<()>; + fn notify_power_states(&self, data: Vec) -> zbus::Result<()>; /// LedBrightness property #[dbus_proxy(property)] @@ -84,13 +73,7 @@ trait Led { fn led_modes(&self) -> zbus::Result; #[dbus_proxy(property)] - fn awake_enabled(&self) -> zbus::Result; - - #[dbus_proxy(property)] - fn sleep_enabled(&self) -> zbus::Result; - - #[dbus_proxy(property)] - fn side_leds_enabled(&self) -> zbus::Result; + fn leds_enabled(&self) -> zbus::Result>; } pub struct LedProxyPerkey<'a>(LedProxyBlocking<'a>);