ridiculous refactor to allow enums to be dbus strings for better TS generation

This commit is contained in:
Luke D. Jones
2023-06-27 21:16:13 +12:00
parent fca7d23a31
commit 7b17a13ce7
43 changed files with 1516 additions and 267 deletions

View File

@@ -23,6 +23,7 @@ zbus = { workspace = true, optional = true }
# cli and logging
log.workspace = true
typeshare.workspace = true
# Device control
sysfs-class.workspace = true # used for backlight control and baord ID

View File

@@ -1,5 +1,6 @@
use log::warn;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
#[cfg(feature = "dbus")]
use zbus::zvariant::Type;
@@ -190,6 +191,7 @@ impl LedCode {
}
/// Represents the per-key raw USB packets
#[typeshare]
pub type UsbPackets = Vec<Vec<u8>>;
/// A `UsbPackets` contains all data to change the full set of keyboard
@@ -199,6 +201,7 @@ pub type UsbPackets = Vec<Vec<u8>>;
/// to the keyboard EC. One row controls one group of keys, these keys are not
/// necessarily all on the same row of the keyboard, with some splitting between
/// two rows.
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct LedUsbPackets {

View File

@@ -8,13 +8,15 @@ use std::fmt::Display;
use std::str::FromStr;
use serde_derive::{Deserialize, Serialize};
use typeshare::typeshare;
#[cfg(feature = "dbus")]
use zbus::zvariant::Type;
use crate::error::Error;
use crate::LED_MSG_LEN;
#[cfg_attr(feature = "dbus", derive(Type))]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum LedBrightness {
Off,
@@ -34,13 +36,18 @@ impl From<u32> for LedBrightness {
}
}
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Copy, Deserialize, Serialize)]
pub struct Colour(pub u8, pub u8, pub u8);
#[derive(Debug, Clone, PartialEq, Eq, Copy, Deserialize, Serialize)]
pub struct Colour {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Default for Colour {
fn default() -> Self {
Colour(166, 0, 0)
Colour { r: 166, g: 0, b: 0 }
}
}
@@ -54,39 +61,44 @@ impl FromStr for Colour {
let r = u8::from_str_radix(&s[0..2], 16).or(Err(Error::ParseColour))?;
let g = u8::from_str_radix(&s[2..4], 16).or(Err(Error::ParseColour))?;
let b = u8::from_str_radix(&s[4..6], 16).or(Err(Error::ParseColour))?;
Ok(Colour(r, g, b))
Ok(Colour { r, g, b })
}
}
impl From<&[f32; 3]> for Colour {
fn from(c: &[f32; 3]) -> Self {
Self(
(255.0 * c[0]) as u8,
(255.0 * c[1]) as u8,
(255.0 * c[2]) as u8,
)
Self {
r: (255.0 * c[0]) as u8,
g: (255.0 * c[1]) as u8,
b: (255.0 * c[2]) as u8,
}
}
}
impl From<Colour> for [f32; 3] {
fn from(c: Colour) -> Self {
[c.0 as f32 / 255.0, c.1 as f32 / 255.0, c.2 as f32 / 255.0]
[c.r as f32 / 255.0, c.g as f32 / 255.0, c.b as f32 / 255.0]
}
}
impl From<&[u8; 3]> for Colour {
fn from(c: &[u8; 3]) -> Self {
Self(c[0], c[1], c[2])
Self {
r: c[0],
g: c[1],
b: c[2],
}
}
}
impl From<Colour> for [u8; 3] {
fn from(c: Colour) -> Self {
[c.0, c.1, c.2]
[c.r, c.g, c.b]
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum Speed {
Low = 0xe1,
@@ -124,7 +136,8 @@ impl From<Speed> for u8 {
/// Used for Rainbow mode.
///
/// Enum corresponds to the required integer value
#[cfg_attr(feature = "dbus", derive(Type))]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum Direction {
Right,
@@ -153,9 +166,10 @@ impl FromStr for Direction {
}
/// Enum of modes that convert to the actual number required by a USB HID packet
#[cfg_attr(feature = "dbus", derive(Type))]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(
Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize,
Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Deserialize, Serialize,
)]
pub enum AuraModeNum {
#[default]
@@ -242,7 +256,8 @@ impl From<u8> for AuraModeNum {
}
/// Base effects have no zoning, while multizone is 1-4
#[cfg_attr(feature = "dbus", derive(Type))]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum AuraZone {
/// Used if keyboard has no zones, or if setting all
@@ -288,6 +303,7 @@ impl FromStr for AuraZone {
/// ```rust
/// // let bytes: [u8; LED_MSG_LEN] = mode.into();
/// ```
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AuraEffect {
@@ -335,8 +351,8 @@ impl Default for AuraEffect {
Self {
mode: AuraModeNum::Static,
zone: AuraZone::None,
colour1: Colour(166, 0, 0),
colour2: Colour(0, 0, 0),
colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med,
direction: Direction::Right,
}
@@ -408,14 +424,14 @@ impl From<&AuraEffect> for [u8; LED_MSG_LEN] {
msg[1] = 0xb3;
msg[2] = aura.zone as u8;
msg[3] = aura.mode as u8;
msg[4] = aura.colour1.0;
msg[5] = aura.colour1.1;
msg[6] = aura.colour1.2;
msg[4] = aura.colour1.r;
msg[5] = aura.colour1.g;
msg[6] = aura.colour1.b;
msg[7] = aura.speed as u8;
msg[8] = aura.direction as u8;
msg[10] = aura.colour2.0;
msg[11] = aura.colour2.1;
msg[12] = aura.colour2.2;
msg[10] = aura.colour2.r;
msg[11] = aura.colour2.g;
msg[12] = aura.colour2.b;
msg
}
}
@@ -427,14 +443,14 @@ impl From<&AuraEffect> for Vec<u8> {
msg[1] = 0xb3;
msg[2] = aura.zone as u8;
msg[3] = aura.mode as u8;
msg[4] = aura.colour1.0;
msg[5] = aura.colour1.1;
msg[6] = aura.colour1.2;
msg[4] = aura.colour1.r;
msg[5] = aura.colour1.g;
msg[6] = aura.colour1.b;
msg[7] = aura.speed as u8;
msg[8] = aura.direction as u8;
msg[10] = aura.colour2.0;
msg[11] = aura.colour2.1;
msg[12] = aura.colour2.2;
msg[10] = aura.colour2.r;
msg[11] = aura.colour2.g;
msg[12] = aura.colour2.b;
msg
}
}
@@ -448,7 +464,11 @@ mod tests {
let st = AuraEffect {
mode: AuraModeNum::Static,
zone: AuraZone::None,
colour1: Colour(0xff, 0x11, 0xdd),
colour1: Colour {
r: 0xff,
g: 0x11,
b: 0xdd,
},
colour2: Colour::default(),
speed: Speed::Med,
direction: Direction::Right,
@@ -468,8 +488,12 @@ mod tests {
let mut st = AuraEffect {
mode: AuraModeNum::Static,
zone: AuraZone::Key1,
colour1: Colour(0xff, 0, 0),
colour2: Colour(0, 0, 0),
colour1: Colour {
r: 0xff,
g: 0,
b: 0,
},
colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Low,
direction: Direction::Left,
};
@@ -480,7 +504,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::Key2;
st.colour1 = Colour(0xff, 0xff, 0);
st.colour1 = Colour {
r: 0xff,
g: 0xff,
b: 0,
};
let capture = [
0x5d, 0xb3, 0x02, 0x00, 0xff, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
@@ -488,7 +516,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::Key3;
st.colour1 = Colour(0, 0xff, 0xff);
st.colour1 = Colour {
r: 0,
g: 0xff,
b: 0xff,
};
let capture = [
0x5d, 0xb3, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
@@ -496,7 +528,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::Key4;
st.colour1 = Colour(0xff, 0x00, 0xff);
st.colour1 = Colour {
r: 0xff,
g: 0x00,
b: 0xff,
};
let capture = [
0x5d, 0xb3, 0x04, 0x00, 0xff, 0x00, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
@@ -504,7 +540,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::Logo;
st.colour1 = Colour(0x2c, 0xff, 0x00);
st.colour1 = Colour {
r: 0x2c,
g: 0xff,
b: 0x00,
};
let capture = [
0x5d, 0xb3, 0x05, 0x00, 0x2c, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
@@ -512,7 +552,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::BarLeft;
st.colour1 = Colour(0xff, 0x00, 0x00);
st.colour1 = Colour {
r: 0xff,
g: 0x00,
b: 0x00,
};
let capture = [
0x5d, 0xb3, 0x06, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
@@ -520,7 +564,11 @@ mod tests {
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
st.zone = AuraZone::BarRight;
st.colour1 = Colour(0xff, 0x00, 0xcd);
st.colour1 = Colour {
r: 0xff,
g: 0x00,
b: 0xcd,
};
let capture = [
0x5d, 0xb3, 0x07, 0x00, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,

View File

@@ -53,30 +53,33 @@ impl EffectState for Breathe {
let speed = 4 - <u8>::from(*speed);
if *colour_actual == Colour(0, 0, 0) {
if *colour_actual == (Colour { r: 0, g: 0, b: 0 }) {
*use_colour1 = !*use_colour1;
}
let colour = if !*use_colour1 { colour2 } else { colour1 };
let r1_scale = colour.0 / speed / 2;
let g1_scale = colour.1 / speed / 2;
let b1_scale = colour.2 / speed / 2;
let r1_scale = colour.r / speed / 2;
let g1_scale = colour.g / speed / 2;
let b1_scale = colour.b / speed / 2;
if *colour_actual == Colour(0, 0, 0) {
if *colour_actual == (Colour { r: 0, g: 0, b: 0 }) {
*flipped = true;
} else if colour_actual >= colour {
} else if colour_actual.r >= colour.r
&& colour_actual.g >= colour.g
&& colour_actual.b >= colour.b
{
*flipped = false;
}
if !*flipped {
colour_actual.0 = colour_actual.0.saturating_sub(r1_scale);
colour_actual.1 = colour_actual.1.saturating_sub(g1_scale);
colour_actual.2 = colour_actual.2.saturating_sub(b1_scale);
colour_actual.r = colour_actual.r.saturating_sub(r1_scale);
colour_actual.g = colour_actual.g.saturating_sub(g1_scale);
colour_actual.b = colour_actual.b.saturating_sub(b1_scale);
} else {
colour_actual.0 = colour_actual.0.saturating_add(r1_scale);
colour_actual.1 = colour_actual.1.saturating_add(g1_scale);
colour_actual.2 = colour_actual.2.saturating_add(b1_scale);
colour_actual.r = colour_actual.r.saturating_add(r1_scale);
colour_actual.g = colour_actual.g.saturating_add(g1_scale);
colour_actual.b = colour_actual.b.saturating_add(b1_scale);
}
}
}

View File

@@ -51,17 +51,17 @@ impl EffectState for DoomFlicker {
}
// TODO: make a "percentage" method on Colour.
let max_light = Colour(
(start_colour.0 as f32 / 100.0 * *max_percentage as f32) as u8,
(start_colour.1 as f32 / 100.0 * *max_percentage as f32) as u8,
(start_colour.2 as f32 / 100.0 * *max_percentage as f32) as u8,
);
let max_light = Colour {
r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8,
};
// min light is a percentage of the set colour
let min_light = Colour(
(start_colour.0 as f32 / 100.0 * *min_percentage as f32) as u8,
(start_colour.1 as f32 / 100.0 * *min_percentage as f32) as u8,
(start_colour.2 as f32 / 100.0 * *min_percentage as f32) as u8,
);
let min_light = Colour {
r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8,
};
// Convert the 255 to percentage
let amount = (p_random() & 7) as f32 * 8.0;
@@ -76,9 +76,9 @@ impl EffectState for DoomFlicker {
*colour = (max - max_amount) as u8;
}
};
set_colour(&mut colour.0, max_light.0 as f32, min_light.0 as f32);
set_colour(&mut colour.1, max_light.1 as f32, min_light.1 as f32);
set_colour(&mut colour.2, max_light.2 as f32, min_light.2 as f32);
set_colour(&mut colour.r, max_light.r as f32, min_light.r as f32);
set_colour(&mut colour.g, max_light.g as f32, min_light.g as f32);
set_colour(&mut colour.b, max_light.b as f32, min_light.b as f32);
self.count = 4;
}
@@ -133,17 +133,17 @@ impl EffectState for DoomLightFlash {
}
// TODO: make a "percentage" method on Colour.
let max_light = Colour(
(start_colour.0 as f32 / 100.0 * *max_percentage as f32) as u8,
(start_colour.1 as f32 / 100.0 * *max_percentage as f32) as u8,
(start_colour.2 as f32 / 100.0 * *max_percentage as f32) as u8,
);
let max_light = Colour {
r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8,
};
// min light is a percentage of the set colour
let min_light = Colour(
(start_colour.0 as f32 / 100.0 * *min_percentage as f32) as u8,
(start_colour.1 as f32 / 100.0 * *min_percentage as f32) as u8,
(start_colour.2 as f32 / 100.0 * *min_percentage as f32) as u8,
);
let min_light = Colour {
r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8,
};
if *colour == max_light {
*colour = min_light;

View File

@@ -118,7 +118,7 @@ impl AdvancedEffects {
for effect in &self.effects {
let c = effect.colour();
usb_packets.set(effect.led(), c.0, c.1, c.2);
usb_packets.set(effect.led(), c.r, c.g, c.b);
}
usb_packets.into()
}
@@ -209,8 +209,14 @@ mod tests {
fn single_key_next_state_then_create() {
let layout = KeyLayout::default_layout();
let mut seq = AdvancedEffects::new(false);
seq.effects
.push(Effect::Static(Static::new(LedCode::F, Colour(255, 127, 0))));
seq.effects.push(Effect::Static(Static::new(
LedCode::F,
Colour {
r: 255,
g: 127,
b: 0,
},
)));
seq.next_state(&layout);
let packets = seq.create_packets();
@@ -227,8 +233,16 @@ mod tests {
let mut seq = AdvancedEffects::new(false);
seq.effects.push(Effect::Breathe(Breathe::new(
LedCode::F,
Colour(255, 127, 0),
Colour(127, 0, 255),
Colour {
r: 255,
g: 127,
b: 0,
},
Colour {
r: 127,
g: 0,
b: 255,
},
Speed::Med,
)));
@@ -261,7 +275,11 @@ mod tests {
let mut seq = AdvancedEffects::new(false);
seq.effects.push(Effect::DoomFlicker(DoomFlicker::new(
LedCode::F,
Colour(255, 127, 80),
Colour {
r: 255,
g: 127,
b: 80,
},
100,
10,
)));

View File

@@ -522,6 +522,7 @@ mod tests {
let mut data_path = PathBuf::from(DATA_DIR);
data_path.push("data");
data_path.push("aura_support.ron");
dbg!(&data_path);
let mut buf = std::fs::read_to_string(&data_path).unwrap();
let data: LedSupportFile = ron::from_str(&buf).unwrap();

View File

@@ -21,13 +21,41 @@ pub mod usb;
pub const LED_MSG_LEN: usize = 17;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const RED: Colour = Colour(0xff, 0x00, 0x00);
pub const GREEN: Colour = Colour(0x00, 0xff, 0x00);
pub const BLUE: Colour = Colour(0x00, 0x00, 0xff);
pub const VIOLET: Colour = Colour(0x9b, 0x26, 0xb6);
pub const TEAL: Colour = Colour(0x00, 0x7c, 0x80);
pub const YELLOW: Colour = Colour(0xff, 0xef, 0x00);
pub const ORANGE: Colour = Colour(0xff, 0xa4, 0x00);
pub const RED: Colour = Colour {
r: 0xff,
g: 0x00,
b: 0x00,
};
pub const GREEN: Colour = Colour {
r: 0x00,
g: 0xff,
b: 0x00,
};
pub const BLUE: Colour = Colour {
r: 0x00,
g: 0x00,
b: 0xff,
};
pub const VIOLET: Colour = Colour {
r: 0x9b,
g: 0x26,
b: 0xb6,
};
pub const TEAL: Colour = Colour {
r: 0x00,
g: 0x7c,
b: 0x80,
};
pub const YELLOW: Colour = Colour {
r: 0xff,
g: 0xef,
b: 0x00,
};
pub const ORANGE: Colour = Colour {
r: 0xff,
g: 0xa4,
b: 0x00,
};
pub const GRADIENT: [Colour; 7] = [RED, VIOLET, BLUE, TEAL, GREEN, YELLOW, ORANGE];
#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Deserialize, serde::Serialize)]

View File

@@ -2,6 +2,7 @@ use std::fmt::Debug;
use std::ops::{BitAnd, BitOr};
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
#[cfg(feature = "dbus")]
use zbus::zvariant::Type;
@@ -22,8 +23,9 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
]
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum AuraDevice {
Tuf,
X1854,
@@ -82,6 +84,7 @@ impl Debug for AuraDevice {
}
/// This struct is intended as a helper to pass args to generic dbus interface
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct AuraPowerDev {
@@ -90,8 +93,9 @@ pub struct AuraPowerDev {
pub x19b6: Vec<AuraDevRog2>,
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDevTuf {
Boot,
@@ -123,8 +127,9 @@ impl AuraDevTuf {
/// 0000, 0000 | Sleep | 30,08,04,00 | | 1111, 1111 | 0001, 1111 | 0000,
/// 1111 | 0000, 0000 | all on | | | 0000, 0000 | 0000, 0000 |
/// 0000, 0000 | 0000, 0010 | Rear Glow | 00,00,00,02 |
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDevRog1 {
Awake = 0x000002,
@@ -201,8 +206,9 @@ impl BitAnd<AuraDevRog1> for AuraDevRog1 {
/// | 0000 | 0100 | 04 | lightbar on | bit 3 |
/// | 0000 | 1000 | 08 | lightbar off sleep | bit 4 |
/// | 0001 | 0000 | 10 | lightbar shtdn off | bit 5 |
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[typeshare]
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDevRog2 {
BootLogo = 1,