From e1d2e913c5393d75d4c0ce9b7bba7b5c0b3a471a Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 17 Apr 2020 17:42:01 +1200 Subject: [PATCH] Start mapping hotkeys. Aura cycling done --- rog-core/src/daemon.rs | 29 +++-------------- rog-lib/src/aura.rs | 42 +++++++++++++++++++------ rog-lib/src/config.rs | 71 +++++++++++++++++++++++++++++++++++++----- rog-lib/src/core.rs | 21 +++++++++++-- rog-lib/src/hotkeys.rs | 49 ++++++++++++++++++++++------- 5 files changed, 156 insertions(+), 56 deletions(-) diff --git a/rog-core/src/daemon.rs b/rog-core/src/daemon.rs index e360d7f0..f2fa91c1 100644 --- a/rog-core/src/daemon.rs +++ b/rog-core/src/daemon.rs @@ -3,8 +3,8 @@ use dbus::{ blocking::Connection, tree::{Factory, MethodErr}, }; +use rog_lib::core::RogCore; use rog_lib::hotkeys::*; -use rog_lib::{config::Config, core::RogCore}; use std::error::Error; use std::time::Duration; use std::{cell::RefCell, rc::Rc}; @@ -12,7 +12,6 @@ use std::{cell::RefCell, rc::Rc}; pub struct Daemon { rogcore: RogCore, hotkeys: Box, - config: Config, } impl Daemon { @@ -20,33 +19,15 @@ impl Daemon { Daemon { rogcore: RogCore::new().expect("Could not start RogCore"), hotkeys: Box::new(LaptopGX502GW::new()), - config: Config::default().read(), } } - pub fn load_config(mut self) -> Result> { - self.rogcore.aura_set_mode(&self.config.builtin)?; - let bright = RogCore::aura_brightness_bytes(self.config.brightness)?; - self.rogcore.aura_set_mode(&bright)?; - Ok(self) - } - - pub fn write_config(&mut self, bytes: &[u8]) { - // TODO: create statics out of header bytes - if bytes[0] == 0x5a && bytes[1] == 0xba { - self.config.brightness = bytes[4]; - } else if bytes[0] == 0x5d && bytes[1] == 0xb3 { - self.config.builtin = bytes.to_vec(); - } - self.config.write(); - } - pub fn start() -> Result<(), Box> { let mut connection = Connection::new_system().expect("Could not set up dbus system"); connection.request_name(DBUS_IFACE, false, true, false)?; let factory = Factory::new_fnmut::<()>(); - let daemon = Self::new().load_config()?; + let daemon = Self::new(); let daemon = Rc::new(RefCell::new(daemon)); // We create a tree with one object path inside and make that path introspectable. @@ -66,9 +47,8 @@ impl Daemon { let s = format!("Wrote {:x?}", bytes); let mut daemon = daemon.borrow_mut(); - match daemon.rogcore.aura_set_mode(&bytes[..]) { + match daemon.rogcore.aura_set_and_save(&bytes[..]) { Ok(_) => { - daemon.write_config(&bytes); let mret = m.msg.method_return().append1(s); Ok(vec![mret]) } @@ -105,11 +85,10 @@ impl Daemon { // write config let hotkeys = unsafe { &mut (*daemon.as_ptr()).hotkeys }; let mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore }; - let mut config = unsafe { &mut (*daemon.as_ptr()).config }; if let Some(_count) = read { if key_buf[0] == hotkeys.hotkey_group_byte() { - hotkeys.do_hotkey_action(&mut rogcore, &mut config, key_buf[1]); + hotkeys.do_hotkey_action(&mut rogcore, key_buf[1]); } } } diff --git a/rog-lib/src/aura.rs b/rog-lib/src/aura.rs index f2882c65..aa0378e0 100644 --- a/rog-lib/src/aura.rs +++ b/rog-lib/src/aura.rs @@ -1,10 +1,11 @@ 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, PartialEq)] +#[derive(Debug)] pub struct Colour(u8, u8, u8); impl Default for Colour { fn default() -> Self { @@ -25,7 +26,7 @@ impl FromStr for Colour { } } -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum Speed { Low = 0xe1, Med = 0xeb, @@ -53,7 +54,7 @@ impl FromStr for Speed { /// Used for Rainbow mode. /// /// Enum corresponds to the required integer value -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum Direction { Right, Left, @@ -80,7 +81,7 @@ impl FromStr for Direction { } } -#[derive(Debug, PartialEq, Options)] +#[derive(Debug, Default, Options)] pub struct TwoColourSpeed { #[options(help = "print help message")] help: bool, @@ -92,7 +93,7 @@ pub struct TwoColourSpeed { speed: Speed, } -#[derive(Debug, PartialEq, Options)] +#[derive(Debug, Default, Options)] pub struct SingleSpeed { #[options(help = "print help message")] help: bool, @@ -100,7 +101,7 @@ pub struct SingleSpeed { speed: Speed, } -#[derive(Debug, PartialEq, Options)] +#[derive(Debug, Default, Options)] pub struct SingleColour { #[options(help = "print help message")] help: bool, @@ -108,7 +109,7 @@ pub struct SingleColour { colour: Colour, } -#[derive(Debug, PartialEq, Options)] +#[derive(Debug, Default, Options)] pub struct SingleSpeedDirection { #[options(help = "print help message")] help: bool, @@ -122,7 +123,7 @@ pub struct SingleSpeedDirection { speed: Speed, } -#[derive(Debug, PartialEq, Options)] +#[derive(Debug, Default, Options)] pub struct SingleColourSpeed { #[options(help = "print help message")] help: bool, @@ -223,6 +224,9 @@ impl From for [u8; LED_MSG_LEN] { SetAuraBuiltin::Stable(_) => { msg[3] = 0x00; } + SetAuraBuiltin::Breathe(_) => { + msg[3] = 0x01; + } SetAuraBuiltin::Cycle(_) => { msg[3] = 0x02; } @@ -253,7 +257,6 @@ impl From for [u8; LED_MSG_LEN] { SetAuraBuiltin::WideZoomy(_) => { msg[3] = 0x0c; } - _ => {} } match mode { SetAuraBuiltin::Rainbow(settings) => { @@ -294,3 +297,24 @@ impl From for [u8; LED_MSG_LEN] { msg } } + +#[derive(Deserialize, Serialize)] +pub enum BuiltInModeByte { + Stable = 0x00, + Breathe = 0x01, + Cycle = 0x02, + Rainbow = 0x03, + Rain = 0x04, + Random = 0x05, + Highlight = 0x06, + Laser = 0x07, + Ripple = 0x08, + Pulse = 0x0a, + Thinzoomy = 0x0b, + Widezoomy = 0x0c, +} +impl Default for BuiltInModeByte { + fn default() -> Self { + BuiltInModeByte::Stable + } +} diff --git a/rog-lib/src/config.rs b/rog-lib/src/config.rs index 70c35139..07e5cd66 100644 --- a/rog-lib/src/config.rs +++ b/rog-lib/src/config.rs @@ -1,4 +1,4 @@ -use crate::{aura::SetAuraBuiltin, core::LED_MSG_LEN}; +use crate::core::LED_MSG_LEN; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; @@ -8,7 +8,19 @@ pub static CONFIG_PATH: &'static str = "/etc/rogcore.conf"; #[derive(Default, Deserialize, Serialize)] pub struct Config { pub brightness: u8, - pub builtin: Vec, + 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], } impl Config { @@ -23,11 +35,7 @@ impl Config { if let Ok(l) = file.read_to_string(&mut buf) { if l == 0 { // create a default config here - let d = SetAuraBuiltin::default(); - let c = Config { - brightness: 1u8, - builtin: (<[u8; LED_MSG_LEN]>::from(d)).to_vec(), - }; + let c = Config::default(); let toml = toml::to_string(&c).unwrap(); file.write_all(toml.as_bytes()) .expect("Writing default config failed"); @@ -41,8 +49,55 @@ impl Config { pub fn write(&self) { let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config"); - let toml = toml::to_string_pretty(self).expect("Parse config to JSON failed"); + let toml = toml::to_string(self).expect("Parse config to JSON failed"); file.write_all(toml.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]); + + 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), + _ => {} + } + } + } + + 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()); + } + None + } } diff --git a/rog-lib/src/core.rs b/rog-lib/src/core.rs index 9825df67..712ed716 100644 --- a/rog-lib/src/core.rs +++ b/rog-lib/src/core.rs @@ -1,3 +1,4 @@ +use crate::config::Config; use crate::error::AuraError; use gumdrop::Options; use rusb::{DeviceHandle, Error}; @@ -55,6 +56,7 @@ pub struct RogCore { handle: DeviceHandle, initialised: bool, led_interface_num: u8, + pub config: Config, } impl RogCore { @@ -83,6 +85,7 @@ impl RogCore { handle, initialised: false, led_interface_num, + config: Config::default().read(), }) } @@ -135,9 +138,21 @@ impl RogCore { Ok(bright) } - pub fn aura_set_mode(&mut self, mode: &[u8]) -> Result<(), Error> { - let messages = [mode]; - self.aura_write_messages(&messages) + 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 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> { diff --git a/rog-lib/src/hotkeys.rs b/rog-lib/src/hotkeys.rs index 082c52dc..7d676daa 100644 --- a/rog-lib/src/hotkeys.rs +++ b/rog-lib/src/hotkeys.rs @@ -1,8 +1,7 @@ -use crate::config::Config; use crate::core::RogCore; pub trait Laptop { - fn do_hotkey_action(&self, core: &mut RogCore, config: &mut Config, key_byte: u8); + fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8); fn hotkey_group_byte(&self) -> u8; } pub struct LaptopGX502GW { @@ -20,30 +19,58 @@ impl LaptopGX502GW { } } impl Laptop for LaptopGX502GW { - fn do_hotkey_action(&self, core: &mut RogCore, config: &mut Config, key_byte: u8) { + fn do_hotkey_action(&self, rogcore: &mut RogCore, key_byte: u8) { match GX502GWKeys::from(key_byte) { GX502GWKeys::Rog => { println!("ROG!"); } GX502GWKeys::LedBrightUp => { - let mut bright = config.brightness; + let mut bright = rogcore.config.brightness; if bright < self.max_bright { bright += 1; - config.brightness = bright; + rogcore.config.brightness = bright; } let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); - core.aura_set_mode(&bytes).unwrap(); - config.write(); + rogcore.aura_set_and_save(&bytes).unwrap(); + rogcore.config.write(); } GX502GWKeys::LedBrightDown => { - let mut bright = config.brightness; + let mut bright = rogcore.config.brightness; if bright > self.min_bright { bright -= 1; - config.brightness = bright; + rogcore.config.brightness = bright; } let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); - core.aura_set_mode(&bytes).unwrap(); - config.write(); + rogcore.aura_set_and_save(&bytes).unwrap(); + rogcore.config.write(); + } + GX502GWKeys::AuraNext => { + let mut mode = rogcore.config.current_mode[3] + 1; + if mode > 0x0c { + mode = 0x00 + } else if mode == 0x09 { + mode = 0x0a + } + rogcore.config.current_mode[3] = mode; + if let Some(bytes) = rogcore.config.get_current() { + rogcore.aura_set_and_save(&bytes).unwrap(); + rogcore.config.write(); + } + } + GX502GWKeys::AuraPrevious => { + let mut mode = rogcore.config.current_mode[3]; + if mode == 0x00 { + mode = 0x0c + } else if mode - 1 == 0x09 { + mode = 0x08 + } else { + mode -= 1; + } + rogcore.config.current_mode[3] = mode; + if let Some(bytes) = rogcore.config.get_current() { + rogcore.aura_set_and_save(&bytes).unwrap(); + rogcore.config.write(); + } } _ => println!("{:X?}", key_byte), }