rog-aura: add per-zone effects

This commit is contained in:
Luke D. Jones
2022-08-26 18:29:17 +12:00
parent 4f39c01139
commit 97481cd45e
12 changed files with 281 additions and 57 deletions

View File

@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added (v4.4.0) ### Added (v4.4.0)
- Support for per-key config has been added to `asusd-user`. At the moment it is - Support for per-key config has been added to `asusd-user`. At the moment it is
basic with only two effects done. Please see the manual for more information. basic with only two effects done. Please see the manual for more information.
- Support for per-zone effects on some laptops. As above.
### Changed ### Changed
- Create new rog-platform crate to manage all i/o in a universal way - Create new rog-platform crate to manage all i/o in a universal way
+ kbd-led handling (requires kernel patches, TUF specific) + kbd-led handling (requires kernel patches, TUF specific)

4
Cargo.lock generated
View File

@@ -552,7 +552,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]] [[package]]
name = "daemon" name = "daemon"
version = "4.4.0-rc2" version = "4.4.0-rc3"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"env_logger", "env_logger",
@@ -2025,7 +2025,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_aura" name = "rog_aura"
version = "1.3.1" version = "1.3.2"
dependencies = [ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",

View File

@@ -141,7 +141,9 @@ An Aura config itself is a file with contents:
{ {
[ [
{ {
"key": "F", "led_type": {
"Key": "W"
},
"action": { "action": {
"Breathe": { "Breathe": {
"colour1": [ "colour1": [
@@ -159,18 +161,34 @@ An Aura config itself is a file with contents:
} }
}, },
{ {
"key": "Esc", "led_type": {
"action": { "Key": "Esc"
"Static": [ },
0, "action": {
0, "Static": [
255 0,
] 0,
255
]
}
} }
] ]
} }
``` ```
If your laptop supports multizone, `"led_type"` can also be `"PerZone": <one of the following>`
- `"None"`
- `"KeyboardLeft"`
- `"KeyboardCenterLeft"`
- `"KeyboardCenterRight"`
- `"KeyboardRight"`
- `"LightbarRight"`
- `"LightbarRightCorner"`
- `"LightbarRightBottom"`
- `"LightbarLeftBottom"`
- `"LightbarLeftCorner"`
- `"LightbarLeft"`
At the moment there are only two effects available as shown in the example. More will come in the future At the moment there are only two effects available as shown in the example. More will come in the future
but this may take me some time. but this may take me some time.

View File

@@ -1,6 +1,6 @@
//! Using a combination of key-colour array plus a key layout to generate outputs. //! Using a combination of key-colour array plus a key layout to generate outputs.
use rog_aura::{keys::Key, layouts::KeyLayout, ActionData, Colour, Sequences, Speed}; use rog_aura::{keys::Key, layouts::KeyLayout, ActionData, Colour, LedType, Sequences, Speed};
use rog_dbus::RogDbusClientBlocking; use rog_dbus::RogDbusClientBlocking;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -9,40 +9,44 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let (client, _) = RogDbusClientBlocking::new().unwrap(); let (client, _) = RogDbusClientBlocking::new().unwrap();
let mut seq = Sequences::new(); let mut seq = Sequences::new();
let mut key = let mut key = ActionData::new_breathe(
ActionData::new_breathe(Key::W, Colour(255, 127, 0), Colour(127, 0, 255), Speed::Med); LedType::Key(Key::W),
Colour(255, 127, 0),
Colour(127, 0, 255),
Speed::Med,
);
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::A); key.set_led_type(LedType::Key(Key::A));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::S); key.set_led_type(LedType::Key(Key::S));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::D); key.set_led_type(LedType::Key(Key::D));
seq.push(key.clone()); seq.push(key.clone());
let mut key = ActionData::new_breathe( let mut key = ActionData::new_breathe(
Key::Q, LedType::Key(Key::Q),
Colour(127, 127, 127), Colour(127, 127, 127),
Colour(127, 255, 255), Colour(127, 255, 255),
Speed::Low, Speed::Low,
); );
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::E); key.set_led_type(LedType::Key(Key::E));
seq.push(key.clone()); seq.push(key.clone());
let mut key = ActionData::new_breathe( let mut key = ActionData::new_breathe(
Key::N1, LedType::Key(Key::N1),
Colour(166, 127, 166), Colour(166, 127, 166),
Colour(127, 155, 20), Colour(127, 155, 20),
Speed::High, Speed::High,
); );
key.set_key(Key::Tilde); key.set_led_type(LedType::Key(Key::Tilde));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::N2); key.set_led_type(LedType::Key(Key::N2));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::N3); key.set_led_type(LedType::Key(Key::N3));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::N4); key.set_led_type(LedType::Key(Key::N4));
seq.push(key.clone()); seq.push(key.clone());
loop { loop {

View File

@@ -0,0 +1,44 @@
//! Using a combination of key-colour array plus a key layout to generate outputs.
use rog_aura::{layouts::KeyLayout, ActionData, Colour, LedType, PerZone, Sequences, Speed};
use rog_dbus::RogDbusClientBlocking;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let layout = KeyLayout::gx502_layout();
let (client, _) = RogDbusClientBlocking::new().unwrap();
let mut seq = Sequences::new();
let zone = ActionData::new_breathe(
LedType::Zone(PerZone::KeyboardLeft),
Colour(166, 127, 166),
Colour(127, 155, 20),
Speed::High,
);
seq.push(zone);
let zone = ActionData::new_breathe(
LedType::Zone(PerZone::KeyboardCenterLeft),
Colour(16, 127, 255),
Colour(127, 15, 20),
Speed::Low,
);
seq.push(zone);
let zone = ActionData::new_breathe(
LedType::Zone(PerZone::LightbarRightCorner),
Colour(0, 255, 255),
Colour(255, 0, 255),
Speed::Med,
);
seq.push(zone);
loop {
seq.next_state(&layout);
let packets = seq.create_packets();
client.proxies().led().per_key_raw(packets)?;
std::thread::sleep(std::time::Duration::from_millis(60));
}
}

View File

@@ -5,7 +5,7 @@ use std::{
}; };
use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences, Vec2}; use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences, Vec2};
use rog_aura::{keys::Key, Colour, Speed}; use rog_aura::{keys::Key, Colour, LedType, Speed};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@@ -198,33 +198,33 @@ impl Default for UserAuraConfig {
fn default() -> Self { fn default() -> Self {
let mut seq = rog_aura::Sequences::new(); let mut seq = rog_aura::Sequences::new();
let mut key = rog_aura::ActionData::new_breathe( let mut key = rog_aura::ActionData::new_breathe(
Key::W, LedType::Key(Key::W),
Colour(255, 0, 20), Colour(255, 0, 20),
Colour(20, 255, 0), Colour(20, 255, 0),
Speed::Low, Speed::Low,
); );
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::A); key.set_led_type(LedType::Key(Key::A));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::S); key.set_led_type(LedType::Key(Key::S));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::D); key.set_led_type(LedType::Key(Key::D));
seq.push(key); seq.push(key);
let key = rog_aura::ActionData::new_breathe( let key = rog_aura::ActionData::new_breathe(
Key::F, LedType::Key(Key::F),
Colour(255, 0, 0), Colour(255, 0, 0),
Colour(255, 0, 0), Colour(255, 0, 0),
Speed::High, Speed::High,
); );
seq.push(key); seq.push(key);
let mut key = rog_aura::ActionData::new_static(Key::RCtrl, Colour(0, 0, 255)); let mut key = rog_aura::ActionData::new_static(LedType::Key(Key::RCtrl), Colour(0, 0, 255));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::LCtrl); key.set_led_type(LedType::Key(Key::LCtrl));
seq.push(key.clone()); seq.push(key.clone());
key.set_key(Key::Esc); key.set_led_type(LedType::Key(Key::Esc));
seq.push(key); seq.push(key);
Self { Self {

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "daemon" name = "daemon"
version = "4.4.0-rc2" version = "4.4.0-rc3"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rog_aura" name = "rog_aura"
version = "1.3.1" version = "1.3.2"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]

View File

@@ -251,9 +251,10 @@ impl From<u8> for AuraModeNum {
/// Base effects have no zoning, while multizone is 1-4 /// Base effects have no zoning, while multizone is 1-4
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)] #[derive(Debug, Default, Copy, Clone, PartialEq, Deserialize, Serialize)]
pub enum AuraZone { pub enum AuraZone {
/// Used if keyboard has no zones, or if setting all /// Used if keyboard has no zones, or if setting all
#[default]
None, None,
/// Leftmost zone /// Leftmost zone
Key1, Key1,
@@ -271,12 +272,6 @@ pub enum AuraZone {
BarRight, BarRight,
} }
impl Default for AuraZone {
fn default() -> Self {
AuraZone::None
}
}
impl FromStr for AuraZone { impl FromStr for AuraZone {
type Err = Error; type Err = Error;

View File

@@ -8,6 +8,10 @@ pub use builtin_modes::*;
mod per_key_rgb; mod per_key_rgb;
pub use per_key_rgb::*; pub use per_key_rgb::*;
mod per_zone;
pub use per_zone::*;
pub mod error; pub mod error;
pub mod key_to_str; pub mod key_to_str;
pub mod keys; pub mod keys;

124
rog-aura/src/per_zone.rs Normal file
View File

@@ -0,0 +1,124 @@
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "dbus")]
use zvariant::Type;
/// Represents the zoned raw USB packets
pub type ZonedRaw = Vec<u8>;
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
pub enum PerZone {
None,
KeyboardLeft,
KeyboardCenterLeft,
KeyboardCenterRight,
KeyboardRight,
LightbarRight,
LightbarRightCorner,
LightbarRightBottom,
LightbarLeftBottom,
LightbarLeftCorner,
LightbarLeft,
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ZonedColourArray(ZonedRaw);
impl Default for ZonedColourArray {
fn default() -> Self {
Self::new()
}
}
impl ZonedColourArray {
pub fn new() -> Self {
let mut pkt = vec![0u8; 64];
pkt[0] = 0x5d; // Report ID
pkt[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
pkt[2] = 0x01;
pkt[3] = 0x01; // ??
pkt[4] = 0x04; // ??, 4,5,6 are normally RGB for builtin mode colours
ZonedColourArray(pkt)
}
pub fn rgb_for_zone(&mut self, zone: PerZone) -> &mut [u8] {
match zone {
PerZone::None => &mut self.0[9..=11],
PerZone::KeyboardLeft => &mut self.0[9..=11],
PerZone::KeyboardCenterLeft => &mut self.0[12..=14],
PerZone::KeyboardCenterRight => &mut self.0[15..=17],
PerZone::KeyboardRight => &mut self.0[18..=20],
// Two sections missing here?
PerZone::LightbarRight => &mut self.0[27..=29],
PerZone::LightbarRightCorner => &mut self.0[30..=32],
PerZone::LightbarRightBottom => &mut self.0[33..=35],
PerZone::LightbarLeftBottom => &mut self.0[36..=38],
PerZone::LightbarLeftCorner => &mut self.0[39..=41],
PerZone::LightbarLeft => &mut self.0[42..=44],
}
}
#[inline]
pub fn get(&self) -> ZonedRaw {
self.0.clone()
}
#[inline]
pub fn get_ref(&self) -> &ZonedRaw {
&self.0
}
#[inline]
pub fn get_mut(&mut self) -> &mut ZonedRaw {
&mut self.0
}
}
impl From<ZonedColourArray> for ZonedRaw {
fn from(k: ZonedColourArray) -> Self {
k.0
}
}
#[cfg(test)]
mod tests {
use crate::{PerZone, ZonedColourArray, ZonedRaw};
macro_rules! colour_check {
($zone:expr, $pkt_idx_start:expr) => {
let mut zone = ZonedColourArray::new();
let c = zone.rgb_for_zone($zone);
c[0] = 255;
c[1] = 255;
c[2] = 255;
let pkt: ZonedRaw = zone.get();
assert_eq!(pkt[$pkt_idx_start], 0xff);
assert_eq!(pkt[$pkt_idx_start + 1], 0xff);
assert_eq!(pkt[$pkt_idx_start + 2], 0xff);
};
}
#[test]
fn zone_to_packet_check() {
let zone = ZonedColourArray::new();
let pkt: ZonedRaw = zone.into();
assert_eq!(pkt[0], 0x5d);
assert_eq!(pkt[1], 0xbc);
assert_eq!(pkt[2], 0x01);
assert_eq!(pkt[3], 0x01);
assert_eq!(pkt[4], 0x04);
colour_check!(PerZone::KeyboardLeft, 9);
colour_check!(PerZone::KeyboardCenterLeft, 12);
colour_check!(PerZone::KeyboardCenterRight, 15);
colour_check!(PerZone::KeyboardRight, 18);
colour_check!(PerZone::LightbarRight, 27);
colour_check!(PerZone::LightbarRightCorner, 30);
colour_check!(PerZone::LightbarRightBottom, 33);
colour_check!(PerZone::LightbarLeftBottom, 36);
colour_check!(PerZone::LightbarLeftCorner, 39);
colour_check!(PerZone::LightbarLeft, 42);
}
}

View File

@@ -1,6 +1,21 @@
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use crate::{keys::Key, layouts::KeyLayout, Colour, KeyColourArray, PerKeyRaw, Speed}; use crate::{
keys::Key, layouts::KeyLayout, Colour, KeyColourArray, PerKeyRaw, PerZone, Speed,
ZonedColourArray,
};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum LedType {
Key(Key),
Zone(PerZone),
}
impl Default for LedType {
fn default() -> Self {
Self::Zone(PerZone::None)
}
}
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub(super) enum Action { pub(super) enum Action {
@@ -30,7 +45,7 @@ impl Default for Action {
#[derive(Debug, Default, Clone, Deserialize, Serialize)] #[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct ActionData { pub struct ActionData {
key: Key, led_type: LedType,
action: Action, action: Action,
// TODO: time // TODO: time
/// The end resulting colour after stepping through effect /// The end resulting colour after stepping through effect
@@ -39,21 +54,21 @@ pub struct ActionData {
} }
impl ActionData { impl ActionData {
pub fn set_key(&mut self, key: Key) { pub fn set_led_type(&mut self, led_type: LedType) {
self.key = key self.led_type = led_type
} }
pub fn new_static(key: Key, colour: Colour) -> Self { pub fn new_static(led_type: LedType, colour: Colour) -> Self {
Self { Self {
key, led_type,
action: Action::Static(colour), action: Action::Static(colour),
colour: Default::default(), colour: Default::default(),
} }
} }
pub fn new_breathe(key: Key, colour1: Colour, colour2: Colour, speed: Speed) -> Self { pub fn new_breathe(led_type: LedType, colour1: Colour, colour2: Colour, speed: Speed) -> Self {
Self { Self {
key, led_type,
action: Action::Breathe { action: Action::Breathe {
colour1, colour1,
colour2, colour2,
@@ -153,27 +168,46 @@ impl Sequences {
pub fn create_packets(&self) -> PerKeyRaw { pub fn create_packets(&self) -> PerKeyRaw {
let mut keys = KeyColourArray::new(); let mut keys = KeyColourArray::new();
let mut zones = ZonedColourArray::new();
let mut is_per_key = false;
for effect in self.0.iter() { for effect in self.0.iter() {
if let Some(rgb) = keys.rgb_for_key(effect.key) { match effect.led_type {
rgb[0] = effect.colour.0; LedType::Key(key) => {
rgb[1] = effect.colour.1; is_per_key = true;
rgb[2] = effect.colour.2; if let Some(rgb) = keys.rgb_for_key(key) {
rgb[0] = effect.colour.0;
rgb[1] = effect.colour.1;
rgb[2] = effect.colour.2;
}
}
LedType::Zone(z) => {
let rgb = zones.rgb_for_zone(z);
rgb[0] = effect.colour.0;
rgb[1] = effect.colour.1;
rgb[2] = effect.colour.2;
}
} }
} }
keys.into() if is_per_key {
keys.into()
} else {
vec![zones.into()]
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{keys::Key, layouts::KeyLayout, Action, ActionData, Colour, Sequences, Speed}; use crate::{
keys::Key, layouts::KeyLayout, Action, ActionData, Colour, LedType, Sequences, Speed,
};
#[test] #[test]
fn single_key_next_state_then_create() { fn single_key_next_state_then_create() {
let layout = KeyLayout::gx502_layout(); let layout = KeyLayout::gx502_layout();
let mut seq = Sequences::new(); let mut seq = Sequences::new();
seq.0.push(ActionData { seq.0.push(ActionData {
key: Key::F, led_type: LedType::Key(Key::F),
action: Action::Static(Colour(255, 127, 0)), action: Action::Static(Colour(255, 127, 0)),
colour: Default::default(), colour: Default::default(),
}); });
@@ -192,7 +226,7 @@ mod tests {
let layout = KeyLayout::gx502_layout(); let layout = KeyLayout::gx502_layout();
let mut seq = Sequences::new(); let mut seq = Sequences::new();
seq.0.push(ActionData { seq.0.push(ActionData {
key: Key::F, led_type: LedType::Key(Key::F),
action: Action::Breathe { action: Action::Breathe {
colour1: Colour(255, 127, 0), colour1: Colour(255, 127, 0),
colour2: Colour(127, 0, 255), colour2: Colour(127, 0, 255),