Better settings, save proper defaults, check supported modes

This commit is contained in:
Luke
2020-04-17 21:41:12 +12:00
parent e1d2e913c5
commit a8a97bcece
13 changed files with 382 additions and 303 deletions

4
Cargo.lock generated
View File

@@ -163,7 +163,7 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
[[package]] [[package]]
name = "rog-core" name = "rog-core"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"dbus", "dbus",
"gumdrop", "gumdrop",
@@ -174,7 +174,7 @@ dependencies = [
[[package]] [[package]]
name = "rog-lib" name = "rog-lib"
version = "0.3.1" version = "0.4.0"
dependencies = [ dependencies = [
"gumdrop", "gumdrop",
"rusb", "rusb",

View File

@@ -7,7 +7,7 @@ includedir = $(prefix)/include
datarootdir = $(prefix)/share datarootdir = $(prefix)/share
datadir = $(datarootdir) 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 .PHONY: all clean distclean install uninstall update

View File

@@ -6,7 +6,7 @@ The laptop I currently have is the GX502RW and so I'll be using that for the bas
## Requirements ## Requirements
- Rust! - `rustc`, `cargo`
- `libusb-1.0-0-dev` or equivalent package for your distro - `libusb-1.0-0-dev` or equivalent package for your distro
- `libdbus-1-dev` or equivalent package for your distro - `libdbus-1-dev` or equivalent package for your distro
@@ -45,22 +45,24 @@ rog-core <command> <subcommand> --help
## Daemon mode ## 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 ## Implemented
- [X] Setting/modifying built-in LED modes - [X] Setting/modifying built-in LED modes
- [ ] Per-key LED setting - [ ] Per-key LED setting
- [ ] Fancy LED modes (custom programs) - [ ] Fancy LED modes (custom programs)
- [X] Daemon mode (functionally done) - [X] Daemon mode
- [X] Saving settings for reload (needs further work) - [X] Saving settings for reload
- [ ] System control - [ ] 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 - [ ] Logging - required for journalctl
## Wireshark captures ## Wireshark captures
TODO TODO: see `./wireshark_data/` for some captures.
## License ## License

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rog-core" name = "rog-core"
version = "0.3.1" version = "0.3.2"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
edition = "2018" edition = "2018"

View File

@@ -46,8 +46,10 @@ impl Daemon {
let bytes: Vec<u8> = m.msg.read1()?; let bytes: Vec<u8> = m.msg.read1()?;
let s = format!("Wrote {:x?}", bytes); let s = format!("Wrote {:x?}", bytes);
let supported =
unsafe { (*daemon.as_ptr()).hotkeys.supported_modes() };
let mut daemon = daemon.borrow_mut(); let mut daemon = daemon.borrow_mut();
match daemon.rogcore.aura_set_and_save(&bytes[..]) { match daemon.rogcore.aura_set_and_save(&bytes[..], supported) {
Ok(_) => { Ok(_) => {
let mret = m.msg.method_return().append1(s); let mret = m.msg.method_return().append1(s);
Ok(vec![mret]) Ok(vec![mret])
@@ -71,18 +73,8 @@ impl Daemon {
connection.process(Duration::from_millis(1))?; connection.process(Duration::from_millis(1))?;
// READ KEYBOARD // READ KEYBOARD
// TODO: this needs to move to a thread, but there is unsafety // TODO: this needs to move to a thread, but there is unsafety
match daemon.borrow_mut().rogcore.poll_keyboard(&mut key_buf) { match daemon.borrow_mut().rogcore.poll_keyboard(&mut key_buf) {
Ok(read) => { 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 hotkeys = unsafe { &mut (*daemon.as_ptr()).hotkeys };
let mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore }; let mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore };

View File

@@ -5,8 +5,10 @@ use crate::daemon::*;
use dbus::Error as DbusError; use dbus::Error as DbusError;
use dbus::{ffidisp::Connection, Message}; use dbus::{ffidisp::Connection, Message};
use gumdrop::Options; use gumdrop::Options;
use rog_lib::aura::*; use rog_lib::{
use rog_lib::core::{LedBrightness, RogCore, LED_MSG_LEN}; cli_options::SetAuraBuiltin,
core::{LedBrightness, RogCore, LED_MSG_LEN},
};
pub static DBUS_NAME: &'static str = "org.rogcore.Daemon"; pub static DBUS_NAME: &'static str = "org.rogcore.Daemon";
pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon"; pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon";

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rog-lib" name = "rog-lib"
version = "0.3.1" version = "0.4.0"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
edition = "2018" edition = "2018"

View File

@@ -1,177 +1,6 @@
use crate::cli_options::*;
use crate::core::LED_MSG_LEN; use crate::core::LED_MSG_LEN;
use crate::error::AuraError;
use gumdrop::Options;
use serde_derive::{Deserialize, Serialize}; 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<Self, Self::Err> {
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<Self, Self::Err> {
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<Self, Self::Err> {
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 /// Parses `SetAuraBuiltin` in to packet data
/// ///
@@ -221,43 +50,20 @@ impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
msg[0] = 0x5d; msg[0] = 0x5d;
msg[1] = 0xb3; msg[1] = 0xb3;
match mode { match mode {
SetAuraBuiltin::Stable(_) => { SetAuraBuiltin::Stable(_) => msg[3] = 0x00,
msg[3] = 0x00; SetAuraBuiltin::Breathe(_) => msg[3] = 0x01,
} SetAuraBuiltin::Cycle(_) => msg[3] = 0x02,
SetAuraBuiltin::Breathe(_) => { SetAuraBuiltin::Rainbow(_) => msg[3] = 0x03,
msg[3] = 0x01; SetAuraBuiltin::Rain(_) => msg[3] = 0x04,
} SetAuraBuiltin::Random(_) => msg[3] = 0x05,
SetAuraBuiltin::Cycle(_) => { SetAuraBuiltin::Highlight(_) => msg[3] = 0x06,
msg[3] = 0x02; SetAuraBuiltin::Laser(_) => msg[3] = 0x07,
} SetAuraBuiltin::Ripple(_) => msg[3] = 0x08,
SetAuraBuiltin::Rainbow(_) => { SetAuraBuiltin::Pulse(_) => msg[3] = 0x0a,
msg[3] = 0x03; SetAuraBuiltin::ThinZoomy(_) => msg[3] = 0x0b,
} SetAuraBuiltin::WideZoomy(_) => msg[3] = 0x0c,
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 { match mode {
SetAuraBuiltin::Rainbow(settings) => { SetAuraBuiltin::Rainbow(settings) => {
msg[7] = settings.speed as u8; msg[7] = settings.speed as u8;
@@ -298,7 +104,92 @@ impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
} }
} }
/// Container for the byte strings used in modes. Generally useful for settings
/// and other usecases.
#[derive(Deserialize, Serialize)] #[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 { pub enum BuiltInModeByte {
Stable = 0x00, Stable = 0x00,
Breathe = 0x01, Breathe = 0x01,
@@ -310,11 +201,31 @@ pub enum BuiltInModeByte {
Laser = 0x07, Laser = 0x07,
Ripple = 0x08, Ripple = 0x08,
Pulse = 0x0a, Pulse = 0x0a,
Thinzoomy = 0x0b, ThinZoomy = 0x0b,
Widezoomy = 0x0c, WideZoomy = 0x0c,
None,
} }
impl Default for BuiltInModeByte { impl Default for BuiltInModeByte {
fn default() -> Self { fn default() -> Self {
BuiltInModeByte::Stable BuiltInModeByte::Stable
} }
} }
impl From<u8> 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,
}
}
}

172
rog-lib/src/cli_options.rs Normal file
View File

@@ -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<Self, Self::Err> {
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<Self, Self::Err> {
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<Self, Self::Err> {
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),
})
}
}

View File

@@ -1,4 +1,4 @@
use crate::core::LED_MSG_LEN; use crate::aura::BuiltInModeBytes;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
@@ -9,18 +9,7 @@ pub static CONFIG_PATH: &'static str = "/etc/rogcore.conf";
pub struct Config { pub struct Config {
pub brightness: u8, pub brightness: u8,
pub current_mode: [u8; 4], pub current_mode: [u8; 4],
stable: [u8; LED_MSG_LEN], builtin_modes: BuiltInModeBytes,
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 { impl Config {
@@ -35,7 +24,9 @@ impl Config {
if let Ok(l) = file.read_to_string(&mut buf) { if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 { if l == 0 {
// create a default config here // 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(); let toml = toml::to_string(&c).unwrap();
file.write_all(toml.as_bytes()) file.write_all(toml.as_bytes())
.expect("Writing default config failed"); .expect("Writing default config failed");
@@ -59,44 +50,17 @@ impl Config {
self.brightness = bytes[4]; self.brightness = bytes[4];
} else if bytes[0] == 0x5d && bytes[1] == 0xb3 { } else if bytes[0] == 0x5d && bytes[1] == 0xb3 {
self.current_mode.copy_from_slice(&bytes[0..4]); self.current_mode.copy_from_slice(&bytes[0..4]);
self.builtin_modes.set_field_from(bytes);
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<Vec<u8>> { pub fn get_current(&mut self) -> Option<Vec<u8>> {
let bytes = self.current_mode; let bytes = self.current_mode;
if bytes[0] == 0x5d && bytes[1] == 0xb3 { if bytes[0] == 0x5d && bytes[1] == 0xb3 {
let bytes = match bytes[3] { return self
0x00 => &self.stable, .builtin_modes
0x01 => &self.breathe, .get_field_from(bytes[3])
0x02 => &self.cycle, .map(|b| b.to_vec());
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 None
} }

View File

@@ -1,3 +1,4 @@
use crate::aura::BuiltInModeByte;
use crate::config::Config; use crate::config::Config;
use crate::error::AuraError; use crate::error::AuraError;
use gumdrop::Options; use gumdrop::Options;
@@ -116,7 +117,6 @@ impl RogCore {
} }
for message in messages { for message in messages {
println!("{:x?}", &message);
write(*message)?; write(*message)?;
write(&LED_SET)?; write(&LED_SET)?;
} }
@@ -138,22 +138,30 @@ impl RogCore {
Ok(bright) Ok(bright)
} }
pub fn aura_set_and_save(&mut self, bytes: &[u8]) -> Result<(), Error> { pub fn aura_set_and_save(
let messages = [bytes]; &mut self,
self.aura_write_messages(&messages)?; bytes: &[u8],
self.config.set_field_from(bytes); supported: &[BuiltInModeByte],
self.config.write(); ) -> Result<(), Error> {
Ok(()) 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> { // pub fn load_config(&mut self) -> Result<(), Error> {
if let Some(current) = self.config.get_current() { // if let Some(current) = self.config.get_current() {
self.aura_set_and_save(&current)?; // self.aura_set_and_save(&current)?;
} // }
let bright = RogCore::aura_brightness_bytes(self.config.brightness)?; // let bright = RogCore::aura_brightness_bytes(self.config.brightness)?;
self.aura_set_and_save(&bright)?; // self.aura_set_and_save(&bright)?;
Ok(()) // Ok(())
} // }
pub fn poll_keyboard(&mut self, buf: &mut [u8; 32]) -> Result<Option<usize>, Error> { pub fn poll_keyboard(&mut self, buf: &mut [u8; 32]) -> Result<Option<usize>, Error> {
match self match self

View File

@@ -1,13 +1,16 @@
use crate::aura::BuiltInModeByte;
use crate::core::RogCore; use crate::core::RogCore;
pub trait Laptop { pub trait Laptop {
fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8); fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8);
fn hotkey_group_byte(&self) -> u8; fn hotkey_group_byte(&self) -> u8;
fn supported_modes(&self) -> &[BuiltInModeByte];
} }
pub struct LaptopGX502GW { pub struct LaptopGX502GW {
hotkey_group_byte: u8, hotkey_group_byte: u8,
min_bright: u8, min_bright: u8,
max_bright: u8, max_bright: u8,
supported_modes: Vec<BuiltInModeByte>,
} }
impl LaptopGX502GW { impl LaptopGX502GW {
pub fn new() -> Self { pub fn new() -> Self {
@@ -15,6 +18,20 @@ impl LaptopGX502GW {
hotkey_group_byte: 0x5a, hotkey_group_byte: 0x5a,
min_bright: 0x00, min_bright: 0x00,
max_bright: 0x03, 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; rogcore.config.brightness = bright;
} }
let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
rogcore.aura_set_and_save(&bytes).unwrap(); rogcore
rogcore.config.write(); .aura_set_and_save(&bytes, &self.supported_modes)
.unwrap();
} }
GX502GWKeys::LedBrightDown => { GX502GWKeys::LedBrightDown => {
let mut bright = rogcore.config.brightness; let mut bright = rogcore.config.brightness;
@@ -41,8 +59,9 @@ impl Laptop for LaptopGX502GW {
rogcore.config.brightness = bright; rogcore.config.brightness = bright;
} }
let bytes = RogCore::aura_brightness_bytes(bright).unwrap(); let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
rogcore.aura_set_and_save(&bytes).unwrap(); rogcore
rogcore.config.write(); .aura_set_and_save(&bytes, &self.supported_modes)
.unwrap();
} }
GX502GWKeys::AuraNext => { GX502GWKeys::AuraNext => {
let mut mode = rogcore.config.current_mode[3] + 1; let mut mode = rogcore.config.current_mode[3] + 1;
@@ -53,8 +72,9 @@ impl Laptop for LaptopGX502GW {
} }
rogcore.config.current_mode[3] = mode; rogcore.config.current_mode[3] = mode;
if let Some(bytes) = rogcore.config.get_current() { if let Some(bytes) = rogcore.config.get_current() {
rogcore.aura_set_and_save(&bytes).unwrap(); rogcore
rogcore.config.write(); .aura_set_and_save(&bytes, &self.supported_modes)
.unwrap();
} }
} }
GX502GWKeys::AuraPrevious => { GX502GWKeys::AuraPrevious => {
@@ -68,16 +88,22 @@ impl Laptop for LaptopGX502GW {
} }
rogcore.config.current_mode[3] = mode; rogcore.config.current_mode[3] = mode;
if let Some(bytes) = rogcore.config.get_current() { 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(); rogcore.config.write();
} }
} }
_ => println!("{:X?}", key_byte), _ => {}
} }
} }
fn hotkey_group_byte(&self) -> u8 { fn hotkey_group_byte(&self) -> u8 {
self.hotkey_group_byte self.hotkey_group_byte
} }
fn supported_modes(&self) -> &[BuiltInModeByte] {
&self.supported_modes
}
} }
pub enum GX502GWKeys { pub enum GX502GWKeys {

View File

@@ -1,4 +1,6 @@
pub mod aura; pub mod aura;
/// Contains mostly only what is required for parsing CLI options
pub mod cli_options;
pub mod config; pub mod config;
pub mod core; pub mod core;
mod error; mod error;