From 32e9e63809ede0bfc40231c520e2e3ff71e87788 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 29 Jun 2020 15:52:49 +1200 Subject: [PATCH] Refactor dbus commands and internal data structures --- CHANGELOG.md | 6 + Cargo.lock | 35 +++- Makefile | 2 +- data/rogcore.conf | 181 ++++++++++++++---- rog-client/Cargo.toml | 1 + rog-client/examples/animatrix.rs | 3 +- rog-client/examples/ball.rs | 5 +- rog-client/examples/comet.rs | 5 +- rog-client/examples/iterate-keys.rs | 5 +- rog-client/examples/per-key-effect-2.rs | 5 +- rog-client/examples/pulser.rs | 5 +- .../src/{animatrix_dbus.rs => anime_dbus.rs} | 3 +- rog-client/src/anime_matrix.rs | 2 +- rog-client/src/aura_dbus.rs | 150 --------------- rog-client/src/aura_modes.rs | 107 +++++++++++ rog-client/src/builtins.rs | 164 ---------------- rog-client/src/cli_options.rs | 27 ++- rog-client/src/core_dbus.rs | 140 ++++++++++++++ rog-client/src/lib.rs | 84 ++++---- rog-core/Cargo.toml | 2 +- rog-core/src/config.rs | 51 +++-- rog-core/src/daemon.rs | 50 +++-- rog-core/src/laptops.rs | 112 ++++++----- rog-core/src/led_control.rs | 151 +++++---------- rog-core/src/main.rs | 25 +-- rog-core/src/rog_dbus.rs | 52 +++-- 26 files changed, 720 insertions(+), 653 deletions(-) rename rog-client/src/{animatrix_dbus.rs => anime_dbus.rs} (96%) delete mode 100644 rog-client/src/aura_dbus.rs create mode 100644 rog-client/src/aura_modes.rs delete mode 100644 rog-client/src/builtins.rs create mode 100644 rog-client/src/core_dbus.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c000d4f5..e3b26e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Dbus command LedWriteBytes renamed to SetKeyBacklight +- Dbus signal LedCancelEffect renamed to KeyBacklightChanged +- Dbus command SetKeyBacklight will now take a JSON string instead of an array of bytes +- Config file is now in JSON format, and will store only the LED modes that a laptop + supports rather than the whole set ## [0.12.2] - 2020-29-06 ### Changed diff --git a/Cargo.lock b/Cargo.lock index c93eef0b..223b3f3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,6 +419,12 @@ dependencies = [ "libc", ] +[[package]] +name = "itoa" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -736,6 +742,7 @@ dependencies = [ "gumdrop", "serde", "serde_derive", + "serde_json", "thiserror", "tinybmp", "yansi-term", @@ -755,10 +762,10 @@ dependencies = [ "rusb", "serde", "serde_derive", + "serde_json", "sysfs-class", "thiserror", "tokio", - "toml", "uhid-virt", ] @@ -799,6 +806,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + [[package]] name = "scoped-tls" version = "0.1.2" @@ -837,6 +850,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "shlex" version = "0.1.1" @@ -1011,15 +1035,6 @@ dependencies = [ "syn", ] -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - [[package]] name = "uhid-virt" version = "0.0.4" diff --git a/Makefile b/Makefile index ecf8b03f..1eadf9fd 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,6 @@ vendor: target/release/$(BIN): $(SRC) ifeq ($(VENDORED),1) - tar pxf vendor.tar.xz + tar pxf vendor_rog-core_.tar.xz endif cargo build $(ARGS) diff --git a/data/rogcore.conf b/data/rogcore.conf index 9594c1b6..80153154 100644 --- a/data/rogcore.conf +++ b/data/rogcore.conf @@ -1,32 +1,149 @@ -fan_mode = 0 -brightness = 1 -current_mode = [93, 179, 0, 0] - -[builtin_modes] -stable = [93, 179, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -breathe = [93, 179, 0, 1, 255, 0, 0, 235, 0, 0, 255, 0, 0, 0, 0, 0, 0] -strobe = [93, 179, 0, 2, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] -rainbow = [93, 179, 0, 3, 0, 0, 0, 225, 2, 0, 0, 0, 0, 0, 0, 0, 0] -star = [93, 179, 0, 4, 255, 255, 255, 225, 0, 255, 0, 0, 0, 0, 0, 0, 0] -rain = [93, 179, 0, 5, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] -highlight = [93, 179, 0, 6, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] -laser = [93, 179, 0, 7, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] -ripple = [93, 179, 0, 8, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] -pulse = [93, 179, 0, 10, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -comet = [93, 179, 0, 11, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -flash = [93, 179, 0, 12, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -multi_static = [[93, 179, 1, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 2, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 3, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 4, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] -[mode_performance.normal] -min_percentage = 0 -max_percentage = 100 -no_turbo = false - -[mode_performance.boost] -min_percentage = 0 -max_percentage = 100 -no_turbo = false - -[mode_performance.silent] -min_percentage = 0 -max_percentage = 100 -no_turbo = true +{ + "fan_mode": 1, + "bat_charge_limit": 100, + "brightness": 1, + "current_mode": 0, + "builtin_modes": [ + { + "Stable": { + "help": false, + "colour": [ + 255, + 0, + 0 + ] + } + }, + { + "Breathe": { + "help": false, + "colour": [ + 255, + 0, + 0 + ], + "colour2": [ + 255, + 0, + 0 + ], + "speed": "Med" + } + }, + { + "Strobe": { + "help": false, + "speed": "Med" + } + }, + { + "Rainbow": { + "help": false, + "direction": "Up", + "speed": "Low" + } + }, + { + "Star": { + "help": false, + "colour": [ + 255, + 0, + 0 + ], + "colour2": [ + 255, + 0, + 0 + ], + "speed": "Med" + } + }, + { + "Rain": { + "help": false, + "speed": "Med" + } + }, + { + "Highlight": { + "help": false, + "colour": [ + 255, + 0, + 0 + ], + "speed": "Med" + } + }, + { + "Laser": { + "help": false, + "colour": [ + 255, + 0, + 0 + ], + "speed": "Med" + } + }, + { + "Ripple": { + "help": false, + "colour": [ + 255, + 0, + 0 + ], + "speed": "Med" + } + }, + { + "Pulse": { + "help": false, + "colour": [ + 255, + 0, + 0 + ] + } + }, + { + "Comet": { + "help": false, + "colour": [ + 255, + 0, + 0 + ] + } + }, + { + "Flash": { + "help": false, + "colour": [ + 255, + 0, + 0 + ] + } + } + ], + "mode_performance": { + "normal": { + "min_percentage": 0, + "max_percentage": 100, + "no_turbo": false + }, + "boost": { + "min_percentage": 0, + "max_percentage": 100, + "no_turbo": false + }, + "silent": { + "min_percentage": 0, + "max_percentage": 80, + "no_turbo": false + } + } +} \ No newline at end of file diff --git a/rog-client/Cargo.toml b/rog-client/Cargo.toml index 154956b9..d032a04b 100644 --- a/rog-client/Cargo.toml +++ b/rog-client/Cargo.toml @@ -14,6 +14,7 @@ gumdrop = "^0.8.0" dbus = { version = "^0.8.2" } serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" thiserror = "^1.0.15" yansi-term = "0.1.2" diff --git a/rog-client/examples/animatrix.rs b/rog-client/examples/animatrix.rs index cb1da328..b3a85b2d 100644 --- a/rog-client/examples/animatrix.rs +++ b/rog-client/examples/animatrix.rs @@ -1,4 +1,5 @@ -use rog_client::{AniMeDbusWriter, AniMeMatrix, AniMePacketType, HEIGHT, WIDTH}; +use rog_client::anime_dbus::AniMeDbusWriter; +use rog_client::anime_matrix::{AniMeMatrix, AniMePacketType, HEIGHT, WIDTH}; use tinybmp::{Bmp, Pixel}; fn main() { diff --git a/rog-client/examples/ball.rs b/rog-client/examples/ball.rs index b2fea301..c5bcc428 100644 --- a/rog-client/examples/ball.rs +++ b/rog-client/examples/ball.rs @@ -1,4 +1,7 @@ -use rog_client::{AuraDbusWriter, GX502Layout, Key, KeyColourArray, KeyLayout}; +use rog_client::{ + core_dbus::AuraDbusWriter, + fancy::{GX502Layout, Key, KeyColourArray, KeyLayout}, +}; use std::collections::LinkedList; #[derive(Debug, Clone)] diff --git a/rog-client/examples/comet.rs b/rog-client/examples/comet.rs index 0aad01d9..35a54eb1 100644 --- a/rog-client/examples/comet.rs +++ b/rog-client/examples/comet.rs @@ -1,4 +1,7 @@ -use rog_client::{AuraDbusWriter, GX502Layout, KeyColourArray, KeyLayout}; +use rog_client::{ + core_dbus::AuraDbusWriter, + fancy::{GX502Layout, KeyColourArray, KeyLayout}, +}; fn main() -> Result<(), Box> { let mut writer = AuraDbusWriter::new()?; diff --git a/rog-client/examples/iterate-keys.rs b/rog-client/examples/iterate-keys.rs index 94fef264..1240fda3 100644 --- a/rog-client/examples/iterate-keys.rs +++ b/rog-client/examples/iterate-keys.rs @@ -1,4 +1,7 @@ -use rog_client::{AuraDbusWriter, GX502Layout, Key, KeyColourArray, KeyLayout}; +use rog_client::{ + core_dbus::AuraDbusWriter, + fancy::{GX502Layout, Key, KeyColourArray, KeyLayout}, +}; fn main() -> Result<(), Box> { let mut writer = AuraDbusWriter::new()?; diff --git a/rog-client/examples/per-key-effect-2.rs b/rog-client/examples/per-key-effect-2.rs index e9c1eb0e..50ae2150 100644 --- a/rog-client/examples/per-key-effect-2.rs +++ b/rog-client/examples/per-key-effect-2.rs @@ -1,4 +1,7 @@ -use rog_client::{AuraDbusWriter, Key, KeyColourArray}; +use rog_client::{ + core_dbus::AuraDbusWriter, + fancy::{Key, KeyColourArray}, +}; fn main() -> Result<(), Box> { let mut writer = AuraDbusWriter::new()?; diff --git a/rog-client/examples/pulser.rs b/rog-client/examples/pulser.rs index 7c104624..f7eaf329 100644 --- a/rog-client/examples/pulser.rs +++ b/rog-client/examples/pulser.rs @@ -1,4 +1,7 @@ -use rog_client::{AuraDbusWriter, GX502Layout, KeyColourArray, KeyLayout}; +use rog_client::{ + core_dbus::AuraDbusWriter, + fancy::{GX502Layout, KeyColourArray, KeyLayout}, +}; fn main() -> Result<(), Box> { let mut writer = AuraDbusWriter::new()?; diff --git a/rog-client/src/animatrix_dbus.rs b/rog-client/src/anime_dbus.rs similarity index 96% rename from rog-client/src/animatrix_dbus.rs rename to rog-client/src/anime_dbus.rs index 15d324ff..c044046c 100644 --- a/rog-client/src/animatrix_dbus.rs +++ b/rog-client/src/anime_dbus.rs @@ -1,4 +1,5 @@ -use super::*; +use crate::anime_matrix::AniMePacketType; +use crate::{DBUS_IFACE, DBUS_NAME, DBUS_PATH}; use dbus::channel::Sender; use dbus::{blocking::Connection, Message}; use std::error::Error; diff --git a/rog-client/src/anime_matrix.rs b/rog-client/src/anime_matrix.rs index 2720dfc5..895bdcdc 100644 --- a/rog-client/src/anime_matrix.rs +++ b/rog-client/src/anime_matrix.rs @@ -153,7 +153,7 @@ impl From for AniMePacketType { #[cfg(test)] mod tests { - use crate::{AniMeMatrix, AniMePacketType}; + use crate::anime_matrix::{AniMeMatrix, AniMePacketType}; #[test] fn check_data_alignment() { diff --git a/rog-client/src/aura_dbus.rs b/rog-client/src/aura_dbus.rs deleted file mode 100644 index 49615b40..00000000 --- a/rog-client/src/aura_dbus.rs +++ /dev/null @@ -1,150 +0,0 @@ -use super::*; -use dbus::blocking::BlockingSender; -use dbus::channel::Sender; -use dbus::{blocking::Connection, Message}; -use std::error::Error; -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; -use std::{thread, time::Duration}; - -/// Simplified way to write a effect block -pub struct AuraDbusWriter { - connection: Box, - block_time: u64, - stop: Arc, -} - -impl AuraDbusWriter { - #[inline] - pub fn new() -> Result> { - let connection = Connection::new_system()?; - Ok(AuraDbusWriter { - connection: Box::new(connection), - block_time: 33333, - stop: Arc::new(AtomicBool::new(false)), - }) - } - - /// This method must always be called before the very first write to initialise - /// the keyboard LED EC in the correct mode - #[inline] - pub fn init_effect(&self) -> Result> { - let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "LedCancelEffect"); - let stopper = self.stop.clone(); - self.connection - .add_match(match_rule, move |_: (), _, msg| { - println!("GOT {:?}", msg); - if let Ok(stop) = msg.read1::() { - if stop { - stopper.store(true, Ordering::Relaxed); - } - } - true - })?; - - let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteBytes")? - .append1(KeyColourArray::get_init_msg()); - let r = self - .connection - .send_with_reply_and_block(msg, Duration::from_millis(5000))?; - if let Some(reply) = r.get1::<&str>() { - return Ok(reply.to_owned()); - } - Err(Box::new(dbus::Error::new_custom("name", "message"))) - } - - /// Write a single colour block. - /// - /// Intentionally blocks for 10ms after sending to allow the block to - /// be written to the keyboard EC. This should not be async. - #[inline] - pub fn write_colour_block( - &mut self, - key_colour_array: &KeyColourArray, - ) -> Result<(), Box> { - let group = key_colour_array.get(); - let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteEffect")? - .append3(&group[0].to_vec(), &group[1].to_vec(), &group[2].to_vec()) - .append3(&group[3].to_vec(), &group[4].to_vec(), &group[5].to_vec()) - .append3(&group[6].to_vec(), &group[7].to_vec(), &group[8].to_vec()) - .append2(&group[9].to_vec(), &group[10].to_vec()); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); - thread::sleep(Duration::from_micros(self.block_time)); - if self.stop.load(Ordering::Relaxed) { - panic!("Got signal to stop!"); - } - Ok(()) - } - - #[inline] - pub fn write_multizone( - &mut self, - group: &[[u8; LED_MSG_LEN]; 4], - ) -> Result<(), Box> { - let mut msg = - Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteMultizone")? - .append1(&group[0].to_vec()) - .append1(&group[1].to_vec()) - .append1(&group[2].to_vec()) - .append1(&group[3].to_vec()); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); - Ok(()) - } - - #[inline] - pub fn write_bytes(&self, bytes: &[u8]) -> Result> { - let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteBytes")? - .append1(bytes.to_vec()); - let r = self - .connection - .send_with_reply_and_block(msg, Duration::from_millis(5000))?; - if let Some(reply) = r.get1::<&str>() { - return Ok(reply.to_owned()); - } - Err(Box::new(dbus::Error::new_custom("name", "message"))) - } - - #[inline] - pub fn write_fan_mode(&self, level: u8) -> Result> { - let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetFanMode")? - .append1(level); - let r = self - .connection - .send_with_reply_and_block(msg, Duration::from_millis(5000))?; - if let Some(reply) = r.get1::<&str>() { - return Ok(reply.to_owned()); - } - Err(Box::new(dbus::Error::new_custom("name", "message"))) - } - - #[inline] - pub fn write_charge_limit(&self, level: u8) -> Result> { - let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetChargeLimit")? - .append1(level); - let r = self - .connection - .send_with_reply_and_block(msg, Duration::from_millis(5000))?; - if let Some(reply) = r.get1::<&str>() { - return Ok(reply.to_owned()); - } - Err(Box::new(dbus::Error::new_custom("name", "message"))) - } - - #[inline] - pub fn write_builtin_mode( - &self, - mode: &SetAuraBuiltin, - ) -> Result> { - let bytes = <[u8; LED_MSG_LEN]>::from(mode); - self.write_bytes(&bytes) - } - - #[inline] - pub fn write_brightness(&self, level: u8) -> Result> { - self.write_bytes(&aura_brightness_bytes(level)) - } -} diff --git a/rog-client/src/aura_modes.rs b/rog-client/src/aura_modes.rs new file mode 100644 index 00000000..7d52e610 --- /dev/null +++ b/rog-client/src/aura_modes.rs @@ -0,0 +1,107 @@ +use crate::cli_options::*; +use serde_derive::{Deserialize, Serialize}; + +pub const SINGLE: u8 = 0x00; +pub const BREATHING: u8 = 0x01; +pub const STROBE: u8 = 0x02; +pub const RAINBOW: u8 = 0x03; +pub const STAR: u8 = 0x04; +pub const RAIN: u8 = 0x05; +pub const HIGHLIGHT: u8 = 0x06; +pub const LASER: u8 = 0x07; +pub const RIPPLE: u8 = 0x08; +pub const PULSE: u8 = 0x0a; +pub const COMET: u8 = 0x0b; +pub const FLASH: u8 = 0x0c; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum AuraModes { + Stable(SingleColour), + Breathe(TwoColourSpeed), + Strobe(SingleSpeed), + Rainbow(SingleSpeedDirection), + Star(TwoColourSpeed), + Rain(SingleSpeed), + Highlight(SingleColourSpeed), + Laser(SingleColourSpeed), + Ripple(SingleColourSpeed), + Pulse(SingleColour), + Comet(SingleColour), + Flash(SingleColour), + MultiStatic(MultiColour), + LedBrightness(u8), + Aura, +} + +impl From for AuraModes { + fn from(mode: SetAuraBuiltin) -> Self { + match mode { + SetAuraBuiltin::Stable(x) => AuraModes::Stable(x), + SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x), + SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x), + SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x), + SetAuraBuiltin::Star(x) => AuraModes::Star(x), + SetAuraBuiltin::Rain(x) => AuraModes::Rain(x), + SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x), + SetAuraBuiltin::Laser(x) => AuraModes::Laser(x), + SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x), + SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x), + SetAuraBuiltin::Comet(x) => AuraModes::Comet(x), + SetAuraBuiltin::Flash(x) => AuraModes::Flash(x), + SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x), + } + } +} + +impl From for u8 { + fn from(mode: AuraModes) -> Self { + u8::from(&mode) + } +} + +impl From<&mut AuraModes> for u8 { + fn from(mode: &mut AuraModes) -> Self { + u8::from(&*mode) + } +} + +impl From<&AuraModes> for u8 { + fn from(mode: &AuraModes) -> Self { + match mode { + AuraModes::Stable(_) => 0x00, + AuraModes::Breathe(_) => 0x01, + AuraModes::Strobe(_) => 0x02, + AuraModes::Rainbow(_) => 0x03, + AuraModes::Star(_) => 0x04, + AuraModes::Rain(_) => 0x05, + AuraModes::Highlight(_) => 0x06, + AuraModes::Laser(_) => 0x07, + AuraModes::Ripple(_) => 0x08, + AuraModes::Pulse(_) => 0x0a, + AuraModes::Comet(_) => 0x0b, + AuraModes::Flash(_) => 0x0c, + AuraModes::MultiStatic(_) => 0x0d, + _ => panic!("Invalid mode"), + } + } +} + +impl From for AuraModes { + fn from(byte: u8) -> Self { + match byte { + SINGLE => AuraModes::Stable(SingleColour::default()), + BREATHING => AuraModes::Breathe(TwoColourSpeed::default()), + STROBE => AuraModes::Strobe(SingleSpeed::default()), + RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()), + STAR => AuraModes::Star(TwoColourSpeed::default()), + RAIN => AuraModes::Rain(SingleSpeed::default()), + HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()), + LASER => AuraModes::Laser(SingleColourSpeed::default()), + RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()), + PULSE => AuraModes::Pulse(SingleColour::default()), + COMET => AuraModes::Comet(SingleColour::default()), + FLASH => AuraModes::Flash(SingleColour::default()), + _ => panic!("Invalid mode byte"), + } + } +} diff --git a/rog-client/src/builtins.rs b/rog-client/src/builtins.rs deleted file mode 100644 index ffbbb30f..00000000 --- a/rog-client/src/builtins.rs +++ /dev/null @@ -1,164 +0,0 @@ -use super::cli_options::*; -use super::LED_MSG_LEN; -use serde_derive::{Deserialize, Serialize}; - -/// Container for the byte strings used in modes. Generally useful for settings -/// and other usecases. -#[derive(Deserialize, Serialize)] -pub struct BuiltInModeBytes { - pub stable: [u8; LED_MSG_LEN], - pub breathe: [u8; LED_MSG_LEN], - pub strobe: [u8; LED_MSG_LEN], - pub rainbow: [u8; LED_MSG_LEN], - pub star: [u8; LED_MSG_LEN], - pub rain: [u8; LED_MSG_LEN], - pub highlight: [u8; LED_MSG_LEN], - pub laser: [u8; LED_MSG_LEN], - pub ripple: [u8; LED_MSG_LEN], - pub pulse: [u8; LED_MSG_LEN], - pub comet: [u8; LED_MSG_LEN], - pub flash: [u8; LED_MSG_LEN], - pub multi_static: [[u8; LED_MSG_LEN]; 4], -} -impl BuiltInModeBytes { - #[inline] - pub fn set_field_from(&mut self, bytes: &[u8]) { - if bytes[0] == 0x5d && bytes[1] == 0xb3 { - let b = BuiltInModeByte::from(bytes[3]); - match b { - BuiltInModeByte::Single => self.stable.copy_from_slice(bytes), - BuiltInModeByte::Breathing => self.breathe.copy_from_slice(bytes), - BuiltInModeByte::Strobe => self.strobe.copy_from_slice(bytes), - BuiltInModeByte::Rainbow => self.rainbow.copy_from_slice(bytes), - BuiltInModeByte::Star => self.star.copy_from_slice(bytes), - BuiltInModeByte::Rain => self.rain.copy_from_slice(bytes), - BuiltInModeByte::Highlight => self.highlight.copy_from_slice(bytes), - BuiltInModeByte::Laser => self.laser.copy_from_slice(bytes), - BuiltInModeByte::Ripple => self.ripple.copy_from_slice(bytes), - BuiltInModeByte::Pulse => self.pulse.copy_from_slice(bytes), - BuiltInModeByte::Comet => self.comet.copy_from_slice(bytes), - BuiltInModeByte::Flash => self.flash.copy_from_slice(bytes), - _ => {} - } - } - } - - #[inline] - pub fn get_field_from(&self, byte: u8) -> Option<&[u8]> { - let bytes = match BuiltInModeByte::from(byte) { - BuiltInModeByte::Single => &self.stable, - BuiltInModeByte::Breathing => &self.breathe, - BuiltInModeByte::Strobe => &self.strobe, - BuiltInModeByte::Rainbow => &self.rainbow, - BuiltInModeByte::Star => &self.star, - BuiltInModeByte::Rain => &self.rain, - BuiltInModeByte::Highlight => &self.highlight, - BuiltInModeByte::Laser => &self.laser, - BuiltInModeByte::Ripple => &self.ripple, - BuiltInModeByte::Pulse => &self.pulse, - BuiltInModeByte::Comet => &self.comet, - BuiltInModeByte::Flash => &self.flash, - _ => return None, - }; - Some(bytes) - } -} -impl Default for BuiltInModeBytes { - fn default() -> Self { - BuiltInModeBytes { - stable: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Stable(SingleColour::default())), - breathe: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Breathe(TwoColourSpeed::default())), - strobe: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Strobe(SingleSpeed::default())), - rainbow: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rainbow( - SingleSpeedDirection::default(), - )), - star: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Star(TwoColourSpeed::default())), - rain: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rain(SingleSpeed::default())), - highlight: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Highlight( - SingleColourSpeed::default(), - )), - laser: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Laser(SingleColourSpeed::default())), - ripple: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Ripple(SingleColourSpeed::default())), - pulse: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Pulse(SingleColour::default())), - comet: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Comet(SingleColour::default())), - flash: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Flash(SingleColour::default())), - multi_static: <[[u8; LED_MSG_LEN]; 4]>::from(SetAuraBuiltin::MultiStatic( - MultiColour::default(), - )), - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] -pub enum BuiltInModeByte { - Single = 0x00, - Breathing = 0x01, - Strobe = 0x02, - Rainbow = 0x03, - Star = 0x04, - Rain = 0x05, - Highlight = 0x06, - Laser = 0x07, - Ripple = 0x08, - Pulse = 0x0a, - Comet = 0x0b, - Flash = 0x0c, - MultiStatic, - None, -} -impl Default for BuiltInModeByte { - #[inline] - fn default() -> Self { - BuiltInModeByte::Single - } -} - -impl From for BuiltInModeByte { - #[inline] - fn from(byte: u8) -> Self { - match byte { - 0x00 => Self::Single, - 0x01 => Self::Breathing, - 0x02 => Self::Strobe, - 0x03 => Self::Rainbow, - 0x04 => Self::Star, - 0x05 => Self::Rain, - 0x06 => Self::Highlight, - 0x07 => Self::Laser, - 0x08 => Self::Ripple, - 0x0a => Self::Pulse, - 0x0b => Self::Comet, - 0x0c => Self::Flash, - _ => Self::None, - } - } -} - -impl From<&u8> for BuiltInModeByte { - #[inline] - fn from(byte: &u8) -> Self { - Self::from(*byte) - } -} - -impl From for u8 { - #[inline] - fn from(byte: BuiltInModeByte) -> Self { - match byte { - BuiltInModeByte::Single => 0x00, - BuiltInModeByte::Breathing => 0x01, - BuiltInModeByte::Strobe => 0x02, - BuiltInModeByte::Rainbow => 0x03, - BuiltInModeByte::Star => 0x04, - BuiltInModeByte::Rain => 0x05, - BuiltInModeByte::Highlight => 0x06, - BuiltInModeByte::Laser => 0x07, - BuiltInModeByte::Ripple => 0x08, - BuiltInModeByte::Pulse => 0x0a, - BuiltInModeByte::Comet => 0x0b, - BuiltInModeByte::Flash => 0x0c, - BuiltInModeByte::MultiStatic => 0x00, - BuiltInModeByte::None => 0xff, - } - } -} diff --git a/rog-client/src/cli_options.rs b/rog-client/src/cli_options.rs index ffbeafa1..e6eb69c4 100644 --- a/rog-client/src/cli_options.rs +++ b/rog-client/src/cli_options.rs @@ -1,5 +1,6 @@ use crate::error::AuraError; use gumdrop::Options; +use serde_derive::{Deserialize, Serialize}; use std::fmt::Debug; use std::str::FromStr; @@ -30,7 +31,7 @@ impl FromStr for LedBrightness { } } -#[derive(Debug)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct Colour(pub u8, pub u8, pub u8); impl Default for Colour { fn default() -> Self { @@ -51,7 +52,7 @@ impl FromStr for Colour { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Deserialize, Serialize)] pub enum Speed { Low = 0xe1, Med = 0xeb, @@ -79,7 +80,7 @@ impl FromStr for Speed { /// Used for Rainbow mode. /// /// Enum corresponds to the required integer value -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Deserialize, Serialize)] pub enum Direction { Right, Left, @@ -106,7 +107,7 @@ impl FromStr for Direction { } } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct TwoColourSpeed { #[options(help = "print help message")] help: bool, @@ -118,7 +119,7 @@ pub struct TwoColourSpeed { pub speed: Speed, } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct SingleSpeed { #[options(help = "print help message")] help: bool, @@ -126,7 +127,7 @@ pub struct SingleSpeed { pub speed: Speed, } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct SingleColour { #[options(help = "print help message")] help: bool, @@ -134,7 +135,7 @@ pub struct SingleColour { pub colour: Colour, } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct MultiColour { #[options(help = "print help message")] help: bool, @@ -148,7 +149,7 @@ pub struct MultiColour { pub colour4: Colour, } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct SingleSpeedDirection { #[options(help = "print help message")] help: bool, @@ -162,7 +163,7 @@ pub struct SingleSpeedDirection { pub speed: Speed, } -#[derive(Debug, Default, Options)] +#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)] pub struct SingleColourSpeed { #[options(help = "print help message")] help: bool, @@ -172,10 +173,16 @@ pub struct SingleColourSpeed { pub speed: Speed, } +#[derive(Debug, Options, Clone, Deserialize, Serialize, Default)] +pub struct FreeOpts { + #[options(free)] + free: Vec, +} + /// Byte value for setting the built-in mode. /// /// Enum corresponds to the required integer value -#[derive(Debug, Options)] +#[derive(Debug, Clone, Options, Deserialize, Serialize)] pub enum SetAuraBuiltin { #[options(help = "set a single static colour")] Stable(SingleColour), diff --git a/rog-client/src/core_dbus.rs b/rog-client/src/core_dbus.rs new file mode 100644 index 00000000..47106052 --- /dev/null +++ b/rog-client/src/core_dbus.rs @@ -0,0 +1,140 @@ +use super::*; +use crate::fancy::KeyColourArray; +use dbus::channel::Sender; +use dbus::{blocking::Connection, channel::Token, Message}; +use std::error::Error; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; +use std::{thread, time::Duration}; + +/// Simplified way to write a effect block +pub struct AuraDbusWriter { + connection: Box, + block_time: u64, + stop: Arc, + stop_token: Token, +} + +impl AuraDbusWriter { + #[inline] + pub fn new() -> Result> { + let connection = Connection::new_system()?; + let stop = Arc::new(AtomicBool::new(false)); + + let stopper2 = stop.clone(); + let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "KeyBacklightChanged"); + let stop_token = connection.add_match(match_rule, move |_: (), _, msg| { + dbg!(&msg); + if let Ok(stop) = msg.read1::() { + if stop { + stopper2.store(true, Ordering::Relaxed); + } + } + true + })?; + + Ok(AuraDbusWriter { + connection: Box::new(connection), + block_time: 33333, + stop, + stop_token, + }) + } + + /// This method must always be called before the very first write to initialise + /// the keyboard LED EC in the correct mode + #[inline] + pub fn init_effect(&self) -> Result<(), Box> { + let mode = AuraModes::Aura; + let mut msg = + Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetKeyBacklight")? + .append1(serde_json::to_string(&mode)?); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + Ok(()) + } + + /// Write a single colour block. + /// + /// Intentionally blocks for 10ms after sending to allow the block to + /// be written to the keyboard EC. This should not be async. + #[inline] + pub fn write_colour_block( + &mut self, + key_colour_array: &KeyColourArray, + ) -> Result<(), Box> { + let group = key_colour_array.get(); + let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteEffect")? + .append3(&group[0].to_vec(), &group[1].to_vec(), &group[2].to_vec()) + .append3(&group[3].to_vec(), &group[4].to_vec(), &group[5].to_vec()) + .append3(&group[6].to_vec(), &group[7].to_vec(), &group[8].to_vec()) + .append2(&group[9].to_vec(), &group[10].to_vec()); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + thread::sleep(Duration::from_micros(self.block_time)); + self.connection.process(Duration::from_micros(500))?; + if self.stop.load(Ordering::Relaxed) { + self.connection.remove_match(self.stop_token)?; + println!("Keyboard backlight was changed, exiting"); + std::process::exit(1) + } + Ok(()) + } + + #[inline] + pub fn write_multizone( + &mut self, + group: &[[u8; LED_MSG_LEN]; 4], + ) -> Result<(), Box> { + let mut msg = + Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteMultizone")? + .append1(&group[0].to_vec()) + .append1(&group[1].to_vec()) + .append1(&group[2].to_vec()) + .append1(&group[3].to_vec()); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + Ok(()) + } + + #[inline] + pub fn write_bytes(&self, mode: &AuraModes) -> Result<(), Box> { + let mut msg = + Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetKeyBacklight")? + .append1(serde_json::to_string(mode)?); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + Ok(()) + } + + #[inline] + pub fn write_fan_mode(&self, level: u8) -> Result<(), Box> { + let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetFanMode")? + .append1(level); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + Ok(()) + } + + #[inline] + pub fn write_charge_limit(&self, level: u8) -> Result<(), Box> { + let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetChargeLimit")? + .append1(level); + msg.set_no_reply(true); + self.connection.send(msg).unwrap(); + Ok(()) + } + + #[inline] + pub fn write_builtin_mode(&self, mode: &AuraModes) -> Result<(), Box> { + self.write_bytes(mode) + } + + #[inline] + pub fn write_brightness(&self, level: u8) -> Result> { + self.write_bytes(&AuraModes::LedBrightness(level))?; + Ok(String::new()) + } +} diff --git a/rog-client/src/lib.rs b/rog-client/src/lib.rs index fe3127af..c5e371cb 100644 --- a/rog-client/src/lib.rs +++ b/rog-client/src/lib.rs @@ -3,26 +3,25 @@ pub static DBUS_PATH: &str = "/org/rogcore/Daemon"; pub static DBUS_IFACE: &str = "org.rogcore.Daemon"; pub const LED_MSG_LEN: usize = 17; -mod builtins; -pub use builtins::*; +pub mod aura_modes; +use aura_modes::AuraModes; /// Contains mostly only what is required for parsing CLI options pub mod cli_options; -mod fancy; -mod aura_dbus; -pub use aura_dbus::*; +/// Enables you to create fancy RGB effects +pub mod fancy; -pub use fancy::*; +/// The main dbus group for system controls, e.g, fan control, keyboard LED's +pub mod core_dbus; -mod animatrix_dbus; -pub use animatrix_dbus::*; +/// Specific dbus for writing to the AniMe Matrix display (if supported) +pub mod anime_dbus; -mod anime_matrix; -pub use anime_matrix::*; +/// Helper functions for the AniMe display +pub mod anime_matrix; pub mod error; -use crate::cli_options::*; /// Writes aout the correct byte string for brightness /// @@ -56,7 +55,7 @@ pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { ] } -/// Parses `SetAuraBuiltin` in to packet data +/// Parses `AuraCommands` in to packet data /// /// Byte structure: /// @@ -133,40 +132,41 @@ pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { /// ``` /// /// This descriptor is also used for the per-key LED settings -impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] { - fn from(mode: &SetAuraBuiltin) -> Self { +impl From<&AuraModes> for [u8; LED_MSG_LEN] { + fn from(mode: &AuraModes) -> Self { let mut msg = [0u8; LED_MSG_LEN]; msg[0] = 0x5d; msg[1] = 0xb3; match mode { - SetAuraBuiltin::Stable(_) => msg[3] = 0x00, - SetAuraBuiltin::Breathe(_) => msg[3] = 0x01, - SetAuraBuiltin::Strobe(_) => msg[3] = 0x02, - SetAuraBuiltin::Rainbow(_) => msg[3] = 0x03, - SetAuraBuiltin::Star(_) => msg[3] = 0x04, - SetAuraBuiltin::Rain(_) => msg[3] = 0x05, - SetAuraBuiltin::Highlight(_) => msg[3] = 0x06, - SetAuraBuiltin::Laser(_) => msg[3] = 0x07, - SetAuraBuiltin::Ripple(_) => msg[3] = 0x08, - SetAuraBuiltin::Pulse(_) => msg[3] = 0x0a, - SetAuraBuiltin::Comet(_) => msg[3] = 0x0b, - SetAuraBuiltin::Flash(_) => msg[3] = 0x0c, + AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n), + AuraModes::Stable(_) => msg[3] = 0x00, + AuraModes::Breathe(_) => msg[3] = 0x01, + AuraModes::Strobe(_) => msg[3] = 0x02, + AuraModes::Rainbow(_) => msg[3] = 0x03, + AuraModes::Star(_) => msg[3] = 0x04, + AuraModes::Rain(_) => msg[3] = 0x05, + AuraModes::Highlight(_) => msg[3] = 0x06, + AuraModes::Laser(_) => msg[3] = 0x07, + AuraModes::Ripple(_) => msg[3] = 0x08, + AuraModes::Pulse(_) => msg[3] = 0x0a, + AuraModes::Comet(_) => msg[3] = 0x0b, + AuraModes::Flash(_) => msg[3] = 0x0c, _ => panic!("Mode not convertable to array"), } match mode { - SetAuraBuiltin::Rainbow(settings) => { + AuraModes::Rainbow(settings) => { msg[7] = settings.speed as u8; msg[8] = settings.direction as u8; } - SetAuraBuiltin::Star(settings) => { + AuraModes::Star(settings) => { msg[4] = settings.colour.0; msg[5] = settings.colour.1; msg[6] = settings.colour.2; msg[7] = settings.speed as u8; msg[9] = settings.colour2.2; } - SetAuraBuiltin::Breathe(settings) => { + AuraModes::Breathe(settings) => { msg[4] = settings.colour.0; msg[5] = settings.colour.1; msg[6] = settings.colour.2; @@ -175,21 +175,21 @@ impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] { msg[11] = settings.colour2.1; msg[12] = settings.colour2.2; } - SetAuraBuiltin::Strobe(settings) | SetAuraBuiltin::Rain(settings) => { + AuraModes::Strobe(settings) | AuraModes::Rain(settings) => { msg[7] = settings.speed as u8; } - SetAuraBuiltin::Highlight(settings) - | SetAuraBuiltin::Laser(settings) - | SetAuraBuiltin::Ripple(settings) => { + AuraModes::Highlight(settings) + | AuraModes::Laser(settings) + | AuraModes::Ripple(settings) => { msg[4] = settings.colour.0; msg[5] = settings.colour.1; msg[6] = settings.colour.2; msg[7] = settings.speed as u8; } - SetAuraBuiltin::Stable(settings) - | SetAuraBuiltin::Pulse(settings) - | SetAuraBuiltin::Comet(settings) - | SetAuraBuiltin::Flash(settings) => { + AuraModes::Stable(settings) + | AuraModes::Pulse(settings) + | AuraModes::Comet(settings) + | AuraModes::Flash(settings) => { msg[4] = settings.colour.0; msg[5] = settings.colour.1; msg[6] = settings.colour.2; @@ -200,16 +200,16 @@ impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] { } } -impl From for [u8; LED_MSG_LEN] { +impl From for [u8; LED_MSG_LEN] { #[inline] - fn from(mode: SetAuraBuiltin) -> Self { + fn from(mode: AuraModes) -> Self { <[u8; LED_MSG_LEN]>::from(&mode) } } -impl From for [[u8; LED_MSG_LEN]; 4] { +impl From for [[u8; LED_MSG_LEN]; 4] { #[inline] - fn from(mode: SetAuraBuiltin) -> Self { + fn from(mode: AuraModes) -> Self { let mut msg = [[0u8; LED_MSG_LEN]; 4]; for (i, row) in msg.iter_mut().enumerate() { row[0] = 0x5d; @@ -218,7 +218,7 @@ impl From for [[u8; LED_MSG_LEN]; 4] { } match mode { - SetAuraBuiltin::MultiStatic(settings) => { + AuraModes::MultiStatic(settings) => { msg[0][4] = settings.colour1.0; msg[0][5] = settings.colour1.1; msg[0][6] = settings.colour1.2; diff --git a/rog-core/Cargo.toml b/rog-core/Cargo.toml index 0ee05008..122bac38 100644 --- a/rog-core/Cargo.toml +++ b/rog-core/Cargo.toml @@ -34,7 +34,7 @@ tokio = { version = "0.2.4", features = ["rt-threaded", "sync"] } # serialisation serde = "1.0" serde_derive = "1.0" -toml = "0.5" +serde_json = "1.0" # Device control sysfs-class = "^0.1.2" # used for backlight control and baord ID diff --git a/rog-core/src/config.rs b/rog-core/src/config.rs index 5663c276..2cf40a3d 100644 --- a/rog-core/src/config.rs +++ b/rog-core/src/config.rs @@ -1,4 +1,4 @@ -use rog_client::BuiltInModeBytes; +use rog_client::aura_modes::AuraModes; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; @@ -10,15 +10,15 @@ pub struct Config { pub fan_mode: u8, pub bat_charge_limit: u8, pub brightness: u8, - pub current_mode: [u8; 4], - pub builtin_modes: BuiltInModeBytes, + pub current_mode: u8, + pub builtin_modes: Vec, pub mode_performance: FanModeSettings, } impl Config { /// `load` will attempt to read the config, but if it is not found it /// will create a new default config and write that out. - pub fn load(mut self) -> Self { + pub fn load(mut self, supported_led_modes: &[u8]) -> Self { let mut file = OpenOptions::new() .read(true) .write(true) @@ -31,15 +31,20 @@ impl Config { // create a default config here let mut c = Config::default(); c.bat_charge_limit = 100; - c.current_mode[0] = 0x5d; - c.current_mode[1] = 0xb3; + c.current_mode = 0; + + for n in supported_led_modes { + c.builtin_modes.push(AuraModes::from(*n)) + } + dbg!(&c.builtin_modes); + // Should be okay to unwrap this as is since it is a Default - let toml = toml::to_string(&c).unwrap(); - file.write_all(toml.as_bytes()) + let json = serde_json::to_string_pretty(&c).unwrap(); + file.write_all(json.as_bytes()) .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); self = c; } else { - self = toml::from_str(&buf) + self = serde_json::from_str(&buf) .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); } } @@ -56,7 +61,7 @@ impl Config { if l == 0 { panic!("Missing {}", CONFIG_PATH); } else { - let x: Config = toml::from_str(&buf) + let x: Config = serde_json::from_str(&buf) .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); *self = x; } @@ -65,19 +70,29 @@ impl Config { pub fn write(&self) { let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config"); - let toml = toml::to_string(self).expect("Parse config to JSON failed"); - file.write_all(toml.as_bytes()) + let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed"); + file.write_all(json.as_bytes()) .expect("Saving config failed"); } - pub fn set_field_from(&mut self, bytes: &[u8]) { - if bytes[0] == 0x5a && bytes[1] == 0xba { - self.brightness = bytes[4]; - } else if bytes[0] == 0x5d && bytes[1] == 0xb3 { - self.current_mode.copy_from_slice(&bytes[0..4]); - self.builtin_modes.set_field_from(bytes); + pub fn set_mode_data(&mut self, mode: AuraModes) { + let byte: u8 = (&mode).into(); + for (index, n) in self.builtin_modes.iter().enumerate() { + if byte == u8::from(n) { + self.builtin_modes[index] = mode; + break; + } } } + + pub fn get_led_mode_data(&self, num: u8) -> Option<&AuraModes> { + for mode in &self.builtin_modes { + if u8::from(mode) == num { + return Some(mode); + } + } + None + } } #[derive(Default, Deserialize, Serialize)] diff --git a/rog-core/src/daemon.rs b/rog-core/src/daemon.rs index 3b60af8e..07e7859b 100644 --- a/rog-core/src/daemon.rs +++ b/rog-core/src/daemon.rs @@ -11,7 +11,7 @@ use dbus::{channel::Sender, nonblock::Process}; use dbus_tokio::connection; use log::{error, info, warn}; -use rog_client::{DBUS_IFACE, DBUS_NAME, DBUS_PATH}; +use rog_client::{aura_modes::AuraModes, DBUS_IFACE, DBUS_NAME, DBUS_PATH}; use std::error::Error; use std::sync::Arc; use tokio::sync::Mutex; @@ -29,7 +29,8 @@ pub(super) type DbusU8Type = Arc>>; // DBUS processing takes 6ms if not tokiod pub async fn start_daemon() -> Result<(), Box> { let laptop = match_laptop(); - let mut config = Config::default().load(); + let mut config = Config::default().load(laptop.supported_modes()); + info!("Config loaded"); let mut rogcore = RogCore::new( @@ -59,12 +60,9 @@ pub async fn start_daemon() -> Result<(), Box> { let mut led_writer = LedWriter::new( rogcore.get_raw_device_handle(), laptop.led_endpoint(), - (laptop.min_led_bright(), laptop.max_led_bright()), laptop.supported_modes().to_owned(), ); - led_writer - .do_command(AuraCommand::ReloadLast, &mut config) - .await?; + led_writer.reload_last_builtin(&mut config).await?; // Set up the mutexes let config = Arc::new(Mutex::new(config)); @@ -148,6 +146,7 @@ pub async fn start_daemon() -> Result<(), Box> { } }); + // For helping with processing signals let connection1 = connection.clone(); let config1 = config.clone(); tokio::spawn(async move { @@ -188,20 +187,39 @@ pub async fn start_daemon() -> Result<(), Box> { while let Some(command) = aura_command_recv.recv().await { let mut config = config.lock().await; - match command { + match &command { AuraCommand::WriteEffect(_) | AuraCommand::WriteMultizone(_) => led_writer .do_command(command, &mut config) .await .unwrap_or_else(|err| warn!("{:?}", err)), - _ => { - led_writer - .do_command(command, &mut config) - .await - .unwrap_or_else(|err| warn!("{:?}", err)); - connection - .send(effect_cancel_signal.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())) - .unwrap_or_else(|_| 0); - } + AuraCommand::WriteMode(mode) => match mode { + AuraModes::Aura => { + led_writer + .do_command(command, &mut config) + .await + .unwrap_or_else(|err| warn!("{:?}", err)); + } + _ => { + led_writer + .do_command(command, &mut config) + .await + .unwrap_or_else(|err| warn!("{:?}", err)); + connection + .send( + effect_cancel_signal + .msg(&DBUS_PATH.into(), &DBUS_IFACE.into()) + .append1(true), + ) + .unwrap_or_else(|_| 0); + connection + .send( + effect_cancel_signal + .msg(&DBUS_PATH.into(), &DBUS_IFACE.into()) + .append1(false), + ) + .unwrap_or_else(|_| 0); + } + }, } } } diff --git a/rog-core/src/laptops.rs b/rog-core/src/laptops.rs index 0876e05f..fd76c269 100644 --- a/rog-core/src/laptops.rs +++ b/rog-core/src/laptops.rs @@ -1,5 +1,11 @@ use crate::{config::Config, led_control::AuraCommand, rogcore::RogCore}; -use rog_client::{error::AuraError, BuiltInModeByte}; +use rog_client::{ + aura_modes::{ + AuraModes, BREATHING, COMET, FLASH, HIGHLIGHT, LASER, PULSE, RAIN, RAINBOW, RIPPLE, SINGLE, + STAR, STROBE, + }, + error::AuraError, +}; //use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState}; use crate::virt_device::ConsumerKeys; use log::{info, warn}; @@ -22,11 +28,7 @@ pub(crate) fn match_laptop() -> LaptopBase { led_endpoint: 0x04, //from `lsusb -vd 0b05:1866` key_endpoint: 0x83, - supported_modes: vec![ - BuiltInModeByte::Single, - BuiltInModeByte::Breathing, - BuiltInModeByte::Strobe, - ], + supported_modes: vec![SINGLE, BREATHING, STROBE], support_animatrix: false, // backlight: Backlight::new("intel_backlight").unwrap(), }; @@ -71,39 +73,18 @@ fn choose_1866_device(prod: u16) -> LaptopBase { // GX502, G712 } else if board_name.starts_with("GX502") { laptop.supported_modes = vec![ - BuiltInModeByte::Single, - BuiltInModeByte::Breathing, - BuiltInModeByte::Strobe, - BuiltInModeByte::Rainbow, - BuiltInModeByte::Star, - BuiltInModeByte::Rain, - BuiltInModeByte::Highlight, - BuiltInModeByte::Laser, - BuiltInModeByte::Ripple, - BuiltInModeByte::Pulse, - BuiltInModeByte::Comet, - BuiltInModeByte::Flash, + SINGLE, BREATHING, STROBE, RAINBOW, STAR, RAIN, HIGHLIGHT, LASER, RIPPLE, PULSE, COMET, + FLASH, ]; // GM501 } else if board_name.starts_with("GM501") { - laptop.supported_modes = vec![ - BuiltInModeByte::Single, - BuiltInModeByte::Breathing, - BuiltInModeByte::Strobe, - BuiltInModeByte::Rainbow, - ]; + laptop.supported_modes = vec![SINGLE, BREATHING, STROBE, RAINBOW]; // G531 } else if board_name.starts_with("GX531") || board_name.starts_with("G531") || board_name.starts_with("G712") { - laptop.supported_modes = vec![ - BuiltInModeByte::Single, - BuiltInModeByte::Breathing, - BuiltInModeByte::Strobe, - BuiltInModeByte::Rainbow, - BuiltInModeByte::Pulse, - ]; + laptop.supported_modes = vec![SINGLE, BREATHING, STROBE, RAINBOW, PULSE]; } else { panic!( "Unsupported laptop, please request support at\nhttps://github.com/flukejones/rog-core" @@ -121,7 +102,7 @@ pub(super) struct LaptopBase { max_led_bright: u8, led_endpoint: u8, key_endpoint: u8, - supported_modes: Vec, + supported_modes: Vec, support_animatrix: bool, //backlight: Backlight, } @@ -137,30 +118,68 @@ impl LaptopBase { key_buf: [u8; 32], mut aura_command: mpsc::Sender, ) -> Result<(), AuraError> { + let mut config = config.lock().await; match FnKeys::from(key_buf[1]) { FnKeys::LedBrightUp => { + let mut bright = config.brightness; + if bright < self.max_led_bright { + bright += 1; + info!("Increased LED brightness to {:#?}", bright); + } aura_command - .send(AuraCommand::BrightInc) + .send(AuraCommand::WriteMode(AuraModes::LedBrightness(bright))) .await .unwrap_or_else(|err| warn!("LedBrightUp: {}", err)); } FnKeys::LedBrightDown => { + let mut bright = config.brightness; + if bright > self.min_led_bright { + bright -= 1; + } aura_command - .send(AuraCommand::BrightDec) + .send(AuraCommand::WriteMode(AuraModes::LedBrightness(bright))) .await .unwrap_or_else(|err| warn!("LedBrightDown: {}", err)); } FnKeys::AuraNext => { - aura_command - .send(AuraCommand::BuiltinNext) - .await - .unwrap_or_else(|_| {}); + if let Ok(idx) = self + .supported_modes + .binary_search(&config.current_mode.into()) + { + let idx_next = if idx < self.supported_modes.len() - 1 { + idx + 1 + } else { + 0 + }; + if let Some(data) = config.get_led_mode_data(self.supported_modes[idx_next]) { + aura_command + .send(AuraCommand::WriteMode(data.to_owned())) + .await + .unwrap_or_else(|_| {}); + } + } else { + warn!("Tried to step to next LED mode while in non-supported mode"); + } } FnKeys::AuraPrevious => { - aura_command - .send(AuraCommand::BuiltinPrev) - .await - .unwrap_or_else(|_| {}); + if let Ok(idx) = self + .supported_modes + .binary_search(&config.current_mode.into()) + { + let idx_next = if idx > 0 { + idx - 1 + } else { + self.supported_modes.len() - 1 + }; + if let Some(data) = config.get_led_mode_data(self.supported_modes[idx_next]) { + aura_command + .send(AuraCommand::WriteMode(data.to_owned())) + .await + .unwrap_or_else(|_| {}); + } + } else { + warn!("Tried to step to next LED mode while in non-supported mode"); + } } FnKeys::ScreenBrightUp => rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()), //self.backlight.step_up(), FnKeys::ScreenBrightDn => rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()), @@ -169,7 +188,6 @@ impl LaptopBase { FnKeys::AirplaneMode => rogcore.toggle_airplane_mode(), FnKeys::MicToggle => {} FnKeys::Fan => { - let mut config = config.lock().await; rogcore.fan_mode_step(&mut config).unwrap_or_else(|err| { warn!("Couldn't toggle fan mode: {:?}", err); }); @@ -199,12 +217,6 @@ impl LaptopBase { Ok(()) } - pub(super) fn min_led_bright(&self) -> u8 { - self.min_led_bright - } - pub(super) fn max_led_bright(&self) -> u8 { - self.max_led_bright - } pub(super) fn led_endpoint(&self) -> u8 { self.led_endpoint } @@ -220,7 +232,7 @@ impl LaptopBase { pub(super) fn usb_product(&self) -> u16 { self.usb_product } - pub(super) fn supported_modes(&self) -> &[BuiltInModeByte] { + pub(super) fn supported_modes(&self) -> &[u8] { &self.supported_modes } pub(super) fn support_animatrix(&self) -> bool { diff --git a/rog-core/src/led_control.rs b/rog-core/src/led_control.rs index 8407dc94..2dd1f0b3 100644 --- a/rog-core/src/led_control.rs +++ b/rog-core/src/led_control.rs @@ -10,7 +10,10 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 use crate::config::Config; use log::{error, info, warn}; -use rog_client::{aura_brightness_bytes, error::AuraError, BuiltInModeByte}; +use rog_client::{ + aura_brightness_bytes, aura_modes::AuraModes, error::AuraError, fancy::KeyColourArray, + LED_MSG_LEN, +}; use rusb::DeviceHandle; use std::marker::PhantomData; use std::ptr::NonNull; @@ -18,13 +21,8 @@ use std::time::Duration; #[derive(Clone)] pub enum AuraCommand { - BrightInc, - BrightDec, - BuiltinNext, - BuiltinPrev, - WriteBytes(Vec), + WriteMode(AuraModes), WriteEffect(Vec>), - ReloadLast, WriteMultizone(Vec>), } @@ -38,8 +36,7 @@ where C: rusb::UsbContext, { handle: NonNull>, - bright_min_max: (u8, u8), - supported_modes: Vec, + supported_modes: Vec, led_endpoint: u8, initialised: bool, flip_effect_write: bool, @@ -58,13 +55,11 @@ where pub fn new( device_handle: NonNull>, led_endpoint: u8, - bright_min_max: (u8, u8), - supported_modes: Vec, + supported_modes: Vec, ) -> Self { LedWriter { handle: device_handle, led_endpoint, - bright_min_max, supported_modes, initialised: false, flip_effect_write: false, @@ -87,60 +82,9 @@ where } match command { - AuraCommand::BrightInc => { - let mut bright = config.brightness; - if bright < self.bright_min_max.1 { - bright += 1; - config.brightness = bright; - let bytes = aura_brightness_bytes(bright); - self.set_and_save(&bytes, config).await?; - info!("Increased LED brightness to {:#?}", bright); - } - } - AuraCommand::BrightDec => { - let mut bright = config.brightness; - if bright > self.bright_min_max.0 { - bright -= 1; - config.brightness = bright; - let bytes = aura_brightness_bytes(bright); - self.set_and_save(&bytes, config).await?; - info!("Decreased LED brightness to {:#?}", bright); - } - } - AuraCommand::BuiltinNext => { - // TODO: different path for multi-zone (byte 2 controlled, non-zero) - let mode_curr = config.current_mode[3]; - if let Ok(idx) = self.supported_modes.binary_search(&mode_curr.into()) { - let idx_next = if idx < self.supported_modes.len() - 1 { - idx + 1 - } else { - 0 - }; - self.set_builtin(config, idx_next).await?; - } else { - warn!("Tried to step to next LED mode while in non-supported mode"); - self.set_builtin(config, 0).await?; - } - } - AuraCommand::BuiltinPrev => { - // TODO: different path for multi-zone (byte 2 controlled, non-zero) - let mode_curr = config.current_mode[3]; - if let Ok(idx) = self.supported_modes.binary_search(&mode_curr.into()) { - let idx_next = if idx > 0 { - idx - 1 - } else { - self.supported_modes.len() - 1 - }; - self.set_builtin(config, idx_next).await?; - } else { - warn!("Tried to step to next LED mode while in non-supported mode"); - self.set_builtin(config, 0).await?; - } - } - AuraCommand::WriteBytes(bytes) => self.set_and_save(&bytes, config).await?, + AuraCommand::WriteMode(mode) => self.set_and_save(mode, config).await?, AuraCommand::WriteMultizone(effect) => self.write_multizone(effect).await?, AuraCommand::WriteEffect(effect) => self.write_effect(effect).await?, - AuraCommand::ReloadLast => self.reload_last_builtin(&config).await?, } Ok(()) } @@ -162,17 +106,6 @@ where Ok(()) } - #[inline] - async fn write_array_of_bytes(&self, messages: &[&[u8]]) -> Result<(), AuraError> { - for message in messages { - self.write_bytes(*message).await?; - self.write_bytes(&LED_SET).await?; - } - // Changes won't persist unless apply is set - self.write_bytes(&LED_APPLY).await?; - Ok(()) - } - /// Write an effect block /// /// `aura_effect_init` must be called any effect routine, and called only once. @@ -202,34 +135,55 @@ where } /// Used to set a builtin mode and save the settings for it + /// + /// This needs to be universal so that settings applied by dbus stick #[inline] - async fn set_and_save(&self, bytes: &[u8], config: &mut Config) -> Result<(), AuraError> { - let mode = BuiltInModeByte::from(bytes[3]); - // safety pass-through of possible effect write - if bytes[1] == 0xbc { - self.write_bytes(bytes).await?; - return Ok(()); - } else if self.supported_modes.contains(&mode) || bytes[1] == 0xba { - let messages = [bytes]; - self.write_array_of_bytes(&messages).await?; - config.set_field_from(bytes); - config.write(); - return Ok(()); + async fn set_and_save(&self, mode: AuraModes, config: &mut Config) -> Result<(), AuraError> { + match mode { + AuraModes::Aura => { + let bytes = KeyColourArray::get_init_msg(); + self.write_bytes(&bytes).await?; + return Ok(()); + } + AuraModes::LedBrightness(n) => { + let bytes: [u8; LED_MSG_LEN] = (&mode).into(); + self.write_bytes(&bytes).await?; + config.brightness = n; + config.write(); + info!("LED brightness set to {:#?}", n); + return Ok(()); + } + _ => { + let mode_num: u8 = u8::from(&mode).into(); + if self.supported_modes.contains(&mode_num) { + let bytes: [u8; LED_MSG_LEN] = (&mode).into(); + self.write_bytes(&bytes).await?; + self.write_bytes(&LED_SET).await?; + // Changes won't persist unless apply is set + self.write_bytes(&LED_APPLY).await?; + + config.current_mode = mode_num; + config.set_mode_data(mode); + config.write(); + info!("Switched LED mode to {:#?}", config.current_mode); + return Ok(()); + } + } } + warn!("{:?} not supported", mode); Err(AuraError::NotSupported) } #[inline] - async fn reload_last_builtin(&self, config: &Config) -> Result<(), AuraError> { + pub async fn reload_last_builtin(&self, config: &Config) -> Result<(), AuraError> { // set current mode (if any) if self.supported_modes.len() > 1 { - let mode_curr = config.current_mode[3]; let mode = config - .builtin_modes - .get_field_from(mode_curr) + .get_led_mode_data(config.current_mode) .ok_or(AuraError::NotSupported)? .to_owned(); + let mode: [u8; LED_MSG_LEN] = mode.into(); self.write_bytes(&mode).await?; info!("Reloaded last used mode"); } @@ -241,19 +195,4 @@ where info!("Reloaded last used brightness"); Ok(()) } - - #[inline] - async fn set_builtin(&self, config: &mut Config, index: usize) -> Result<(), AuraError> { - if let Some(mode) = self.supported_modes.get(index) { - let mode_next = config - .builtin_modes - .get_field_from(mode.to_owned().into()) - .ok_or(AuraError::NotSupported)? - .to_owned(); - self.set_and_save(&mode_next, config).await?; - info!("Switched LED mode to {:#?}", self.supported_modes[index]); - return Ok(()); - } - Err(AuraError::NotSupported) - } } diff --git a/rog-core/src/main.rs b/rog-core/src/main.rs index dc5cedee..a01cb44d 100644 --- a/rog-core/src/main.rs +++ b/rog-core/src/main.rs @@ -4,8 +4,10 @@ use env_logger::{Builder, Target}; use gumdrop::Options; use log::LevelFilter; use rog_client::{ + aura_modes::AuraModes, cli_options::{LedBrightness, SetAuraBuiltin}, - AuraDbusWriter, LED_MSG_LEN, + core_dbus::AuraDbusWriter, + LED_MSG_LEN, }; static VERSION: &str = "0.12.2"; @@ -67,33 +69,22 @@ pub async fn main() -> Result<(), Box> { // Check for special modes here, eg, per-key or multi-zone match command { SetAuraBuiltin::MultiStatic(_) => { + let command: AuraModes = command.into(); let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command); writer.write_multizone(&byte_arr)?; } - _ => match writer.write_builtin_mode(&command) { - Ok(msg) => println!("Daemon response: {}", msg), - Err(err) => println!("Error: {}", err), - }, + _ => writer.write_builtin_mode(&command.into())?, } } } if let Some(brightness) = parsed.bright { - match writer.write_brightness(brightness.level()) { - Ok(msg) => println!("Daemon response: {}", msg), - Err(err) => println!("Error: {}", err), - } + writer.write_brightness(brightness.level())?; } if let Some(fan_level) = parsed.fan_mode { - match writer.write_fan_mode(fan_level.into()) { - Ok(msg) => println!("Daemon response: {}", msg), - Err(err) => println!("Error: {}", err), - } + writer.write_fan_mode(fan_level.into())?; } if let Some(charge_limit) = parsed.charge_limit { - match writer.write_charge_limit(charge_limit) { - Ok(msg) => println!("Daemon response: {}", msg), - Err(err) => println!("Error: {}", err), - } + writer.write_charge_limit(charge_limit)?; } Ok(()) } diff --git a/rog-core/src/rog_dbus.rs b/rog-core/src/rog_dbus.rs index 17b52ede..e6cbf51e 100644 --- a/rog-core/src/rog_dbus.rs +++ b/rog-core/src/rog_dbus.rs @@ -1,7 +1,6 @@ use crate::config::Config; use crate::daemon::DbusU8Type; use crate::led_control::AuraCommand; -use crate::rogcore::FanLevel; use dbus::tree::{Factory, MTSync, Method, MethodErr, Signal, Tree}; use log::warn; use rog_client::{DBUS_IFACE, DBUS_PATH}; @@ -15,25 +14,26 @@ pub(super) fn dbus_set_ledmsg(sender: Mutex>) -> Method(); factory // method for ledmessage - .method("LedWriteBytes", (), { + .method("SetKeyBacklight", (), { move |m| { - let bytes: Vec = m.msg.read1()?; + let json: &str = m.msg.read1()?; if let Ok(mut lock) = sender.try_lock() { - let command = AuraCommand::WriteBytes(bytes.to_vec()); - lock.try_send(command) - .unwrap_or_else(|err| warn!("LedWriteBytes over mpsc failed: {}", err)); - let mret = m - .msg - .method_return() - .append1(&format!("Wrote {:x?}", bytes)); - Ok(vec![mret]) + if let Ok(data) = serde_json::from_str(json) { + let command = AuraCommand::WriteMode(data); + lock.try_send(command).unwrap_or_else(|err| { + warn!("SetKeyBacklight over mpsc failed: {}", err) + }); + } else { + warn!("SetKeyBacklight could not deserialise"); + } + Ok(vec![]) } else { Err(MethodErr::failed("Could not lock daemon for access")) } } }) - .outarg::<&str, _>("reply") - .inarg::, _>("bytearray") + .inarg::<&str, _>("json") + .annotate("org.freedesktop.DBus.Method.NoReply", "true") } pub(super) fn dbus_set_ledmultizone(sender: Mutex>) -> Method { @@ -145,18 +145,14 @@ pub(super) fn dbus_set_fan_mode(data: DbusU8Type) -> Method { let mut iter = m.msg.iter_init(); let byte: u8 = iter.read()?; *lock = Some(byte); - let mret = m - .msg - .method_return() - .append1(format!("Fan level set to {:?}", FanLevel::from(byte))); - Ok(vec![mret]) + Ok(vec![]) } else { Err(MethodErr::failed("Could not lock daemon for access")) } } }) - .outarg::<&str, _>("reply") .inarg::("byte") + .annotate("org.freedesktop.DBus.Method.NoReply", "true") } pub(super) fn dbus_get_fan_mode(config: Arc>) -> Method { @@ -201,18 +197,14 @@ pub(super) fn dbus_set_charge_limit(data: DbusU8Type) -> Method { let mut iter = m.msg.iter_init(); let byte: u8 = iter.read()?; *lock = Some(byte); - let mret = m - .msg - .method_return() - .append1(format!("Battery charge limit set to {}", byte)); - Ok(vec![mret]) + Ok(vec![]) } else { Err(MethodErr::failed("Could not lock daemon for access")) } } }) - .outarg::<&str, _>("reply") .inarg::("byte") + .annotate("org.freedesktop.DBus.Method.NoReply", "true") } #[allow(clippy::type_complexity)] @@ -236,7 +228,11 @@ pub(super) fn dbus_create_tree( let factory = Factory::new_sync::<()>(); - let effect_cancel_sig = Arc::new(factory.signal("LedCancelEffect", ())); + let builtin_mode_sig = Arc::new( + factory + .signal("KeyBacklightChanged", ()) + .sarg::("value"), + ); let fanmode_changed_sig = Arc::new(factory.signal("FanModeChanged", ()).sarg::("value")); let chrg_limit_changed_sig = Arc::new( factory @@ -258,7 +254,7 @@ pub(super) fn dbus_create_tree( .add_m(dbus_set_charge_limit(charge_limit.clone())) .add_m(dbus_get_fan_mode(config.clone())) .add_m(dbus_get_charge_limit(config)) - .add_s(effect_cancel_sig.clone()) + .add_s(builtin_mode_sig.clone()) .add_s(fanmode_changed_sig.clone()) .add_s(chrg_limit_changed_sig.clone()), ), @@ -271,7 +267,7 @@ pub(super) fn dbus_create_tree( animatrix_recv, fan_mode, charge_limit, - effect_cancel_sig, + builtin_mode_sig, fanmode_changed_sig, chrg_limit_changed_sig, )