From a8a97bcece5a3c256fc8bc6a492f47c765f6727f Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 17 Apr 2020 21:41:12 +1200 Subject: [PATCH] Better settings, save proper defaults, check supported modes --- Cargo.lock | 4 +- Makefile | 2 +- README.md | 14 +- rog-core/Cargo.toml | 2 +- rog-core/src/daemon.rs | 14 +- rog-core/src/main.rs | 6 +- rog-lib/Cargo.toml | 2 +- rog-lib/src/aura.rs | 331 ++++++++++++++----------------------- rog-lib/src/cli_options.rs | 172 +++++++++++++++++++ rog-lib/src/config.rs | 56 ++----- rog-lib/src/core.rs | 38 +++-- rog-lib/src/hotkeys.rs | 42 ++++- rog-lib/src/lib.rs | 2 + 13 files changed, 382 insertions(+), 303 deletions(-) create mode 100644 rog-lib/src/cli_options.rs diff --git a/Cargo.lock b/Cargo.lock index 9f5f92f5..b0fa6d65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,7 +163,7 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" [[package]] name = "rog-core" -version = "0.3.1" +version = "0.3.2" dependencies = [ "dbus", "gumdrop", @@ -174,7 +174,7 @@ dependencies = [ [[package]] name = "rog-lib" -version = "0.3.1" +version = "0.4.0" dependencies = [ "gumdrop", "rusb", diff --git a/Makefile b/Makefile index b8d12bbc..09e98b8d 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ includedir = $(prefix)/include datarootdir = $(prefix)/share datadir = $(datarootdir) -SRC = Cargo.toml Cargo.lock Makefile $(shell find src -type f -wholename '*/*src/*.rs') +SRC = Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '*/src/*.rs') .PHONY: all clean distclean install uninstall update diff --git a/README.md b/README.md index 46abc753..48bb26ae 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The laptop I currently have is the GX502RW and so I'll be using that for the bas ## Requirements -- Rust! +- `rustc`, `cargo` - `libusb-1.0-0-dev` or equivalent package for your distro - `libdbus-1-dev` or equivalent package for your distro @@ -45,22 +45,24 @@ rog-core --help ## Daemon mode -Currently the last used brightness and builtin mode will be saved when set, and loaded when the daemon is started. The effect here is the last settings used are the ones loaded on boot. +Currently the last used brightness and builtin mode will be saved when set, and loaded when the daemon is started. The effect here is the last settings used are the ones loaded on boot. The daemon also saves the settings per mode as the keyboard does not do this itself - this means cycling through modes with the Aura keys will use the settings that were used via CLI. + +Currently if no options are supplied for the CLI mode selection then a default is used, and this will overwrite the saved setting. I will fix this at a later date. ## Implemented - [X] Setting/modifying built-in LED modes - [ ] Per-key LED setting - [ ] Fancy LED modes (custom programs) -- [X] Daemon mode (functionally done) -- [X] Saving settings for reload (needs further work) +- [X] Daemon mode +- [X] Saving settings for reload - [ ] System control -- [ ] Capture and use hotkeys, e.g, Aura controls to control LEDs +- [X] Capture and use hotkeys **Partially completed: aura keys work** - [ ] Logging - required for journalctl ## Wireshark captures -TODO +TODO: see `./wireshark_data/` for some captures. ## License diff --git a/rog-core/Cargo.toml b/rog-core/Cargo.toml index 60fdf4c7..74fdf40a 100644 --- a/rog-core/Cargo.toml +++ b/rog-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rog-core" -version = "0.3.1" +version = "0.3.2" authors = ["Luke "] edition = "2018" diff --git a/rog-core/src/daemon.rs b/rog-core/src/daemon.rs index f2fa91c1..89ce97ef 100644 --- a/rog-core/src/daemon.rs +++ b/rog-core/src/daemon.rs @@ -46,8 +46,10 @@ impl Daemon { let bytes: Vec = m.msg.read1()?; let s = format!("Wrote {:x?}", bytes); + let supported = + unsafe { (*daemon.as_ptr()).hotkeys.supported_modes() }; let mut daemon = daemon.borrow_mut(); - match daemon.rogcore.aura_set_and_save(&bytes[..]) { + match daemon.rogcore.aura_set_and_save(&bytes[..], supported) { Ok(_) => { let mret = m.msg.method_return().append1(s); Ok(vec![mret]) @@ -71,18 +73,8 @@ impl Daemon { connection.process(Duration::from_millis(1))?; // READ KEYBOARD // TODO: this needs to move to a thread, but there is unsafety - match daemon.borrow_mut().rogcore.poll_keyboard(&mut key_buf) { Ok(read) => { - // [5a, c4, ; 32 bytes long] fn+up - // [5a, c5, ; 32 bytes long] fn+down - // [5a, b2, ; 32 bytes long] fn+left - // [5a, b3, ; 32 bytes long] fn+right - - // To handle keys for aura: - // read config + inc/dec brightness byte - // write to aura - // write config let hotkeys = unsafe { &mut (*daemon.as_ptr()).hotkeys }; let mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore }; diff --git a/rog-core/src/main.rs b/rog-core/src/main.rs index c0c9ad52..7adb303c 100644 --- a/rog-core/src/main.rs +++ b/rog-core/src/main.rs @@ -5,8 +5,10 @@ use crate::daemon::*; use dbus::Error as DbusError; use dbus::{ffidisp::Connection, Message}; use gumdrop::Options; -use rog_lib::aura::*; -use rog_lib::core::{LedBrightness, RogCore, LED_MSG_LEN}; +use rog_lib::{ + cli_options::SetAuraBuiltin, + core::{LedBrightness, RogCore, LED_MSG_LEN}, +}; pub static DBUS_NAME: &'static str = "org.rogcore.Daemon"; pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon"; diff --git a/rog-lib/Cargo.toml b/rog-lib/Cargo.toml index 6bc56cc0..a5de50d8 100644 --- a/rog-lib/Cargo.toml +++ b/rog-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rog-lib" -version = "0.3.1" +version = "0.4.0" authors = ["Luke "] edition = "2018" diff --git a/rog-lib/src/aura.rs b/rog-lib/src/aura.rs index aa0378e0..d00d003d 100644 --- a/rog-lib/src/aura.rs +++ b/rog-lib/src/aura.rs @@ -1,177 +1,6 @@ +use crate::cli_options::*; use crate::core::LED_MSG_LEN; -use crate::error::AuraError; -use gumdrop::Options; use serde_derive::{Deserialize, Serialize}; -use std::fmt::Debug; -use std::str::FromStr; - -#[derive(Debug)] -pub struct Colour(u8, u8, u8); -impl Default for Colour { - fn default() -> Self { - Colour(255, 0, 0) - } -} -impl FromStr for Colour { - type Err = AuraError; - - fn from_str(s: &str) -> Result { - if s.len() < 6 { - return Err(AuraError::ParseColour); - } - let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?; - let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?; - let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?; - Ok(Colour(r, g, b)) - } -} - -#[derive(Debug)] -pub enum Speed { - Low = 0xe1, - Med = 0xeb, - High = 0xf5, -} -impl Default for Speed { - fn default() -> Self { - Speed::Med - } -} -impl FromStr for Speed { - type Err = AuraError; - - fn from_str(s: &str) -> Result { - let s = s.to_lowercase(); - match s.as_str() { - "low" => Ok(Speed::Low), - "med" => Ok(Speed::Med), - "high" => Ok(Speed::High), - _ => Err(AuraError::ParseSpeed), - } - } -} - -/// Used for Rainbow mode. -/// -/// Enum corresponds to the required integer value -#[derive(Debug)] -pub enum Direction { - Right, - Left, - Up, - Down, -} -impl Default for Direction { - fn default() -> Self { - Direction::Right - } -} -impl FromStr for Direction { - type Err = AuraError; - - fn from_str(s: &str) -> Result { - let s = s.to_lowercase(); - match s.as_str() { - "right" => Ok(Direction::Right), - "up" => Ok(Direction::Up), - "down" => Ok(Direction::Down), - "left" => Ok(Direction::Left), - _ => Err(AuraError::ParseDirection), - } - } -} - -#[derive(Debug, Default, Options)] -pub struct TwoColourSpeed { - #[options(help = "print help message")] - help: bool, - #[options(no_long, meta = "HEX", help = "set the first RGB value e.g, ff00ff")] - colour: Colour, - #[options(no_long, meta = "HEX", help = "set the second RGB value e.g, ff00ff")] - colour2: Colour, - #[options(no_long, help = "set the speed: low, med, high")] - speed: Speed, -} - -#[derive(Debug, Default, Options)] -pub struct SingleSpeed { - #[options(help = "print help message")] - help: bool, - #[options(no_long, meta = "WORD", help = "set the speed: low, med, high")] - speed: Speed, -} - -#[derive(Debug, Default, Options)] -pub struct SingleColour { - #[options(help = "print help message")] - help: bool, - #[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")] - colour: Colour, -} - -#[derive(Debug, Default, Options)] -pub struct SingleSpeedDirection { - #[options(help = "print help message")] - help: bool, - #[options( - no_long, - meta = "DIR", - help = "set the direction: up, down, left, right" - )] - direction: Direction, - #[options(no_long, help = "set the speed: low, med, high")] - speed: Speed, -} - -#[derive(Debug, Default, Options)] -pub struct SingleColourSpeed { - #[options(help = "print help message")] - help: bool, - #[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")] - colour: Colour, - #[options(no_long, help = "set the speed: low, med, high")] - speed: Speed, -} - -/// Byte value for setting the built-in mode. -/// -/// Enum corresponds to the required integer value -#[derive(Debug, Options)] -pub enum SetAuraBuiltin { - #[options(help = "set a single static colour")] - Stable(SingleColour), - #[options(help = "pulse between one or two colours")] - Breathe(TwoColourSpeed), - #[options(help = "cycle through all colours")] - Cycle(SingleSpeed), - #[options(help = "rainbow cycling in one of four directions")] - Rainbow(SingleSpeedDirection), - #[options(help = "random pattern mimicking raindrops")] - Rain(SingleColourSpeed), - #[options(help = "random pattern of three preset colours")] - Random(SingleSpeed), - #[options(help = "pressed keys are highlighted to fade")] - Highlight(SingleColourSpeed), - #[options(help = "pressed keys generate horizontal laser")] - Laser(SingleColourSpeed), - #[options(help = "pressed keys ripple outwards like a splash")] - Ripple(SingleColourSpeed), - #[options(help = "set a rapid pulse")] - Pulse(SingleColour), - #[options(help = "set a vertical line zooming from left")] - ThinZoomy(SingleColour), - #[options(help = "set a wide vertical line zooming from left")] - WideZoomy(SingleColour), -} - -impl Default for SetAuraBuiltin { - fn default() -> Self { - SetAuraBuiltin::Stable(SingleColour { - help: false, - colour: Colour(255, 0, 0), - }) - } -} /// Parses `SetAuraBuiltin` in to packet data /// @@ -221,43 +50,20 @@ impl From for [u8; LED_MSG_LEN] { msg[0] = 0x5d; msg[1] = 0xb3; match mode { - SetAuraBuiltin::Stable(_) => { - msg[3] = 0x00; - } - SetAuraBuiltin::Breathe(_) => { - msg[3] = 0x01; - } - SetAuraBuiltin::Cycle(_) => { - msg[3] = 0x02; - } - SetAuraBuiltin::Rainbow(_) => { - msg[3] = 0x03; - } - SetAuraBuiltin::Rain(_) => { - msg[3] = 0x04; - } - SetAuraBuiltin::Random(_) => { - msg[3] = 0x05; - } - SetAuraBuiltin::Highlight(_) => { - msg[3] = 0x06; - } - SetAuraBuiltin::Laser(_) => { - msg[3] = 0x07; - } - SetAuraBuiltin::Ripple(_) => { - msg[3] = 0x08; - } - SetAuraBuiltin::Pulse(_) => { - msg[3] = 0x0a; - } - SetAuraBuiltin::ThinZoomy(_) => { - msg[3] = 0x0b; - } - SetAuraBuiltin::WideZoomy(_) => { - msg[3] = 0x0c; - } + SetAuraBuiltin::Stable(_) => msg[3] = 0x00, + SetAuraBuiltin::Breathe(_) => msg[3] = 0x01, + SetAuraBuiltin::Cycle(_) => msg[3] = 0x02, + SetAuraBuiltin::Rainbow(_) => msg[3] = 0x03, + SetAuraBuiltin::Rain(_) => msg[3] = 0x04, + SetAuraBuiltin::Random(_) => msg[3] = 0x05, + SetAuraBuiltin::Highlight(_) => msg[3] = 0x06, + SetAuraBuiltin::Laser(_) => msg[3] = 0x07, + SetAuraBuiltin::Ripple(_) => msg[3] = 0x08, + SetAuraBuiltin::Pulse(_) => msg[3] = 0x0a, + SetAuraBuiltin::ThinZoomy(_) => msg[3] = 0x0b, + SetAuraBuiltin::WideZoomy(_) => msg[3] = 0x0c, } + match mode { SetAuraBuiltin::Rainbow(settings) => { msg[7] = settings.speed as u8; @@ -298,7 +104,92 @@ impl From for [u8; LED_MSG_LEN] { } } +/// 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 cycle: [u8; LED_MSG_LEN], + pub rainbow: [u8; LED_MSG_LEN], + pub rain: [u8; LED_MSG_LEN], + pub random: [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 thinzoomy: [u8; LED_MSG_LEN], + pub widezoomy: [u8; LED_MSG_LEN], +} +impl BuiltInModeBytes { + 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::Stable => self.stable.copy_from_slice(bytes), + BuiltInModeByte::Breathe => self.breathe.copy_from_slice(bytes), + BuiltInModeByte::Cycle => self.cycle.copy_from_slice(bytes), + BuiltInModeByte::Rainbow => self.rainbow.copy_from_slice(bytes), + BuiltInModeByte::Rain => self.rain.copy_from_slice(bytes), + BuiltInModeByte::Random => self.random.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::ThinZoomy => self.thinzoomy.copy_from_slice(bytes), + BuiltInModeByte::WideZoomy => self.widezoomy.copy_from_slice(bytes), + _ => {} + } + } + } + + pub fn get_field_from(&mut self, byte: u8) -> Option<&[u8]> { + let bytes = match BuiltInModeByte::from(byte) { + BuiltInModeByte::Stable => &self.stable, + BuiltInModeByte::Breathe => &self.breathe, + BuiltInModeByte::Cycle => &self.cycle, + BuiltInModeByte::Rainbow => &self.rainbow, + BuiltInModeByte::Rain => &self.rain, + BuiltInModeByte::Random => &self.random, + BuiltInModeByte::Highlight => &self.highlight, + BuiltInModeByte::Laser => &self.laser, + BuiltInModeByte::Ripple => &self.ripple, + BuiltInModeByte::Pulse => &self.pulse, + BuiltInModeByte::ThinZoomy => &self.thinzoomy, + BuiltInModeByte::WideZoomy => &self.widezoomy, + _ => return None, + }; + return 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())), + cycle: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Cycle(SingleSpeed::default())), + rainbow: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rainbow( + SingleSpeedDirection::default(), + )), + rain: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rain(SingleColourSpeed::default())), + random: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Random(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())), + thinzoomy: <[u8; LED_MSG_LEN]>::from( + SetAuraBuiltin::ThinZoomy(SingleColour::default()), + ), + widezoomy: <[u8; LED_MSG_LEN]>::from( + SetAuraBuiltin::WideZoomy(SingleColour::default()), + ), + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)] pub enum BuiltInModeByte { Stable = 0x00, Breathe = 0x01, @@ -310,11 +201,31 @@ pub enum BuiltInModeByte { Laser = 0x07, Ripple = 0x08, Pulse = 0x0a, - Thinzoomy = 0x0b, - Widezoomy = 0x0c, + ThinZoomy = 0x0b, + WideZoomy = 0x0c, + None, } impl Default for BuiltInModeByte { fn default() -> Self { BuiltInModeByte::Stable } } +impl From for BuiltInModeByte { + fn from(byte: u8) -> Self { + match byte { + 0x00 => Self::Stable, + 0x01 => Self::Breathe, + 0x02 => Self::Cycle, + 0x03 => Self::Rainbow, + 0x04 => Self::Rain, + 0x05 => Self::Random, + 0x06 => Self::Highlight, + 0x07 => Self::Laser, + 0x08 => Self::Ripple, + 0x0a => Self::Pulse, + 0x0b => Self::ThinZoomy, + 0x0c => Self::WideZoomy, + _ => Self::None, + } + } +} diff --git a/rog-lib/src/cli_options.rs b/rog-lib/src/cli_options.rs new file mode 100644 index 00000000..a8993ddb --- /dev/null +++ b/rog-lib/src/cli_options.rs @@ -0,0 +1,172 @@ +use crate::error::AuraError; +use gumdrop::Options; +use std::fmt::Debug; +use std::str::FromStr; + +#[derive(Debug)] +pub struct Colour(pub u8, pub u8, pub u8); +impl Default for Colour { + fn default() -> Self { + Colour(255, 0, 0) + } +} +impl FromStr for Colour { + type Err = AuraError; + + fn from_str(s: &str) -> Result { + if s.len() < 6 { + return Err(AuraError::ParseColour); + } + let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?; + let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?; + let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?; + Ok(Colour(r, g, b)) + } +} + +#[derive(Debug)] +pub enum Speed { + Low = 0xe1, + Med = 0xeb, + High = 0xf5, +} +impl Default for Speed { + fn default() -> Self { + Speed::Med + } +} +impl FromStr for Speed { + type Err = AuraError; + + fn from_str(s: &str) -> Result { + let s = s.to_lowercase(); + match s.as_str() { + "low" => Ok(Speed::Low), + "med" => Ok(Speed::Med), + "high" => Ok(Speed::High), + _ => Err(AuraError::ParseSpeed), + } + } +} + +/// Used for Rainbow mode. +/// +/// Enum corresponds to the required integer value +#[derive(Debug)] +pub enum Direction { + Right, + Left, + Up, + Down, +} +impl Default for Direction { + fn default() -> Self { + Direction::Right + } +} +impl FromStr for Direction { + type Err = AuraError; + + fn from_str(s: &str) -> Result { + let s = s.to_lowercase(); + match s.as_str() { + "right" => Ok(Direction::Right), + "up" => Ok(Direction::Up), + "down" => Ok(Direction::Down), + "left" => Ok(Direction::Left), + _ => Err(AuraError::ParseDirection), + } + } +} + +#[derive(Debug, Default, Options)] +pub struct TwoColourSpeed { + #[options(help = "print help message")] + help: bool, + #[options(no_long, meta = "HEX", help = "set the first RGB value e.g, ff00ff")] + pub colour: Colour, + #[options(no_long, meta = "HEX", help = "set the second RGB value e.g, ff00ff")] + pub colour2: Colour, + #[options(no_long, help = "set the speed: low, med, high")] + pub speed: Speed, +} + +#[derive(Debug, Default, Options)] +pub struct SingleSpeed { + #[options(help = "print help message")] + help: bool, + #[options(no_long, meta = "WORD", help = "set the speed: low, med, high")] + pub speed: Speed, +} + +#[derive(Debug, Default, Options)] +pub struct SingleColour { + #[options(help = "print help message")] + help: bool, + #[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")] + pub colour: Colour, +} + +#[derive(Debug, Default, Options)] +pub struct SingleSpeedDirection { + #[options(help = "print help message")] + help: bool, + #[options( + no_long, + meta = "DIR", + help = "set the direction: up, down, left, right" + )] + pub direction: Direction, + #[options(no_long, help = "set the speed: low, med, high")] + pub speed: Speed, +} + +#[derive(Debug, Default, Options)] +pub struct SingleColourSpeed { + #[options(help = "print help message")] + help: bool, + #[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")] + pub colour: Colour, + #[options(no_long, help = "set the speed: low, med, high")] + pub speed: Speed, +} + +/// Byte value for setting the built-in mode. +/// +/// Enum corresponds to the required integer value +#[derive(Debug, Options)] +pub enum SetAuraBuiltin { + #[options(help = "set a single static colour")] + Stable(SingleColour), + #[options(help = "pulse between one or two colours")] + Breathe(TwoColourSpeed), + #[options(help = "cycle through all colours")] + Cycle(SingleSpeed), + #[options(help = "rainbow cycling in one of four directions")] + Rainbow(SingleSpeedDirection), + #[options(help = "random pattern mimicking raindrops")] + Rain(SingleColourSpeed), + #[options(help = "random pattern of three preset colours")] + Random(SingleSpeed), + #[options(help = "pressed keys are highlighted to fade")] + Highlight(SingleColourSpeed), + #[options(help = "pressed keys generate horizontal laser")] + Laser(SingleColourSpeed), + #[options(help = "pressed keys ripple outwards like a splash")] + Ripple(SingleColourSpeed), + #[options(help = "set a rapid pulse")] + Pulse(SingleColour), + #[options(help = "set a vertical line zooming from left")] + ThinZoomy(SingleColour), + #[options(help = "set a wide vertical line zooming from left")] + WideZoomy(SingleColour), +} + +impl Default for SetAuraBuiltin { + fn default() -> Self { + SetAuraBuiltin::Stable(SingleColour { + help: false, + colour: Colour(255, 0, 0), + }) + } +} diff --git a/rog-lib/src/config.rs b/rog-lib/src/config.rs index 07e5cd66..db18b94e 100644 --- a/rog-lib/src/config.rs +++ b/rog-lib/src/config.rs @@ -1,4 +1,4 @@ -use crate::core::LED_MSG_LEN; +use crate::aura::BuiltInModeBytes; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; @@ -9,18 +9,7 @@ pub static CONFIG_PATH: &'static str = "/etc/rogcore.conf"; pub struct Config { pub brightness: u8, pub current_mode: [u8; 4], - stable: [u8; LED_MSG_LEN], - breathe: [u8; LED_MSG_LEN], - cycle: [u8; LED_MSG_LEN], - rainbow: [u8; LED_MSG_LEN], - rain: [u8; LED_MSG_LEN], - random: [u8; LED_MSG_LEN], - highlight: [u8; LED_MSG_LEN], - laser: [u8; LED_MSG_LEN], - ripple: [u8; LED_MSG_LEN], - pulse: [u8; LED_MSG_LEN], - thinzoomy: [u8; LED_MSG_LEN], - widezoomy: [u8; LED_MSG_LEN], + builtin_modes: BuiltInModeBytes, } impl Config { @@ -35,7 +24,9 @@ impl Config { if let Ok(l) = file.read_to_string(&mut buf) { if l == 0 { // create a default config here - let c = Config::default(); + let mut c = Config::default(); + c.current_mode[0] = 0x5d; + c.current_mode[1] = 0xb3; let toml = toml::to_string(&c).unwrap(); file.write_all(toml.as_bytes()) .expect("Writing default config failed"); @@ -59,44 +50,17 @@ impl Config { self.brightness = bytes[4]; } else if bytes[0] == 0x5d && bytes[1] == 0xb3 { self.current_mode.copy_from_slice(&bytes[0..4]); - - match bytes[3] { - 0x00 => self.stable.copy_from_slice(bytes), - 0x01 => self.breathe.copy_from_slice(bytes), - 0x02 => self.cycle.copy_from_slice(bytes), - 0x03 => self.rainbow.copy_from_slice(bytes), - 0x04 => self.rain.copy_from_slice(bytes), - 0x05 => self.random.copy_from_slice(bytes), - 0x06 => self.highlight.copy_from_slice(bytes), - 0x07 => self.laser.copy_from_slice(bytes), - 0x08 => self.ripple.copy_from_slice(bytes), - 0x0a => self.pulse.copy_from_slice(bytes), - 0x0b => self.thinzoomy.copy_from_slice(bytes), - 0x0c => self.widezoomy.copy_from_slice(bytes), - _ => {} - } + self.builtin_modes.set_field_from(bytes); } } pub fn get_current(&mut self) -> Option> { let bytes = self.current_mode; if bytes[0] == 0x5d && bytes[1] == 0xb3 { - let bytes = match bytes[3] { - 0x00 => &self.stable, - 0x01 => &self.breathe, - 0x02 => &self.cycle, - 0x03 => &self.rainbow, - 0x04 => &self.rain, - 0x05 => &self.random, - 0x06 => &self.highlight, - 0x07 => &self.laser, - 0x08 => &self.ripple, - 0x0a => &self.pulse, - 0x0b => &self.thinzoomy, - 0x0c => &self.widezoomy, - _ => return None, - }; - return Some(bytes.to_vec()); + return self + .builtin_modes + .get_field_from(bytes[3]) + .map(|b| b.to_vec()); } None } diff --git a/rog-lib/src/core.rs b/rog-lib/src/core.rs index 712ed716..b28009f2 100644 --- a/rog-lib/src/core.rs +++ b/rog-lib/src/core.rs @@ -1,3 +1,4 @@ +use crate::aura::BuiltInModeByte; use crate::config::Config; use crate::error::AuraError; use gumdrop::Options; @@ -116,7 +117,6 @@ impl RogCore { } for message in messages { - println!("{:x?}", &message); write(*message)?; write(&LED_SET)?; } @@ -138,22 +138,30 @@ impl RogCore { Ok(bright) } - pub fn aura_set_and_save(&mut self, bytes: &[u8]) -> Result<(), Error> { - let messages = [bytes]; - self.aura_write_messages(&messages)?; - self.config.set_field_from(bytes); - self.config.write(); - Ok(()) + pub fn aura_set_and_save( + &mut self, + bytes: &[u8], + supported: &[BuiltInModeByte], + ) -> Result<(), Error> { + let mode = BuiltInModeByte::from(bytes[3]); + if supported.contains(&mode) || bytes[1] == 0xba { + let messages = [bytes]; + self.aura_write_messages(&messages)?; + self.config.set_field_from(bytes); + self.config.write(); + return Ok(()); + } + Err(Error::NotSupported) } - pub fn load_config(&mut self) -> Result<(), Error> { - if let Some(current) = self.config.get_current() { - self.aura_set_and_save(¤t)?; - } - let bright = RogCore::aura_brightness_bytes(self.config.brightness)?; - self.aura_set_and_save(&bright)?; - Ok(()) - } + // pub fn load_config(&mut self) -> Result<(), Error> { + // if let Some(current) = self.config.get_current() { + // self.aura_set_and_save(¤t)?; + // } + // let bright = RogCore::aura_brightness_bytes(self.config.brightness)?; + // self.aura_set_and_save(&bright)?; + // Ok(()) + // } pub fn poll_keyboard(&mut self, buf: &mut [u8; 32]) -> Result, Error> { match self diff --git a/rog-lib/src/hotkeys.rs b/rog-lib/src/hotkeys.rs index 7d676daa..a8440968 100644 --- a/rog-lib/src/hotkeys.rs +++ b/rog-lib/src/hotkeys.rs @@ -1,13 +1,16 @@ +use crate::aura::BuiltInModeByte; use crate::core::RogCore; pub trait Laptop { fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8); fn hotkey_group_byte(&self) -> u8; + fn supported_modes(&self) -> &[BuiltInModeByte]; } pub struct LaptopGX502GW { hotkey_group_byte: u8, min_bright: u8, max_bright: u8, + supported_modes: Vec, } impl LaptopGX502GW { pub fn new() -> Self { @@ -15,6 +18,20 @@ impl LaptopGX502GW { hotkey_group_byte: 0x5a, min_bright: 0x00, max_bright: 0x03, + supported_modes: vec![ + BuiltInModeByte::Stable, + BuiltInModeByte::Breathe, + BuiltInModeByte::Cycle, + BuiltInModeByte::Rainbow, + BuiltInModeByte::Rain, + BuiltInModeByte::Random, + BuiltInModeByte::Highlight, + BuiltInModeByte::Laser, + BuiltInModeByte::Ripple, + BuiltInModeByte::Pulse, + BuiltInModeByte::ThinZoomy, + BuiltInModeByte::WideZoomy, + ], } } } @@ -31,8 +48,9 @@ impl Laptop for LaptopGX502GW { rogcore.config.brightness = bright; } let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); - rogcore.aura_set_and_save(&bytes).unwrap(); - rogcore.config.write(); + rogcore + .aura_set_and_save(&bytes, &self.supported_modes) + .unwrap(); } GX502GWKeys::LedBrightDown => { let mut bright = rogcore.config.brightness; @@ -41,8 +59,9 @@ impl Laptop for LaptopGX502GW { rogcore.config.brightness = bright; } let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); - rogcore.aura_set_and_save(&bytes).unwrap(); - rogcore.config.write(); + rogcore + .aura_set_and_save(&bytes, &self.supported_modes) + .unwrap(); } GX502GWKeys::AuraNext => { let mut mode = rogcore.config.current_mode[3] + 1; @@ -53,8 +72,9 @@ impl Laptop for LaptopGX502GW { } rogcore.config.current_mode[3] = mode; if let Some(bytes) = rogcore.config.get_current() { - rogcore.aura_set_and_save(&bytes).unwrap(); - rogcore.config.write(); + rogcore + .aura_set_and_save(&bytes, &self.supported_modes) + .unwrap(); } } GX502GWKeys::AuraPrevious => { @@ -68,16 +88,22 @@ impl Laptop for LaptopGX502GW { } rogcore.config.current_mode[3] = mode; if let Some(bytes) = rogcore.config.get_current() { - rogcore.aura_set_and_save(&bytes).unwrap(); + rogcore + .aura_set_and_save(&bytes, &self.supported_modes) + .unwrap(); rogcore.config.write(); } } - _ => println!("{:X?}", key_byte), + _ => {} } } fn hotkey_group_byte(&self) -> u8 { self.hotkey_group_byte } + + fn supported_modes(&self) -> &[BuiltInModeByte] { + &self.supported_modes + } } pub enum GX502GWKeys { diff --git a/rog-lib/src/lib.rs b/rog-lib/src/lib.rs index 8c6ed696..862151d3 100644 --- a/rog-lib/src/lib.rs +++ b/rog-lib/src/lib.rs @@ -1,4 +1,6 @@ pub mod aura; +/// Contains mostly only what is required for parsing CLI options +pub mod cli_options; pub mod config; pub mod core; mod error;