mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Big refactor out of Aura LED data structs
This commit is contained in:
21
Cargo.lock
generated
21
Cargo.lock
generated
@@ -628,9 +628,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -665,6 +665,17 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rog-aura"
|
||||||
|
version = "0.8.0"
|
||||||
|
dependencies = [
|
||||||
|
"dbus",
|
||||||
|
"gumdrop",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog-daemon"
|
name = "rog-daemon"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -675,10 +686,10 @@ dependencies = [
|
|||||||
"gumdrop",
|
"gumdrop",
|
||||||
"intel-pstate",
|
"intel-pstate",
|
||||||
"log",
|
"log",
|
||||||
|
"rog-aura",
|
||||||
"rusb",
|
"rusb",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"uhid-virt",
|
"uhid-virt",
|
||||||
@@ -859,9 +870,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "0.2.19"
|
version = "0.2.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c"
|
checksum = "05c1d570eb1a36f0345a5ce9c6c6e665b70b73d11236912c0b477616aeec47b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
|
|||||||
49
Cargo.toml
49
Cargo.toml
@@ -1,50 +1,5 @@
|
|||||||
[package]
|
[workspace]
|
||||||
name = "rog-daemon"
|
members = ["rog-core", "aura"]
|
||||||
version = "0.8.0"
|
|
||||||
license = "MPL-2.0"
|
|
||||||
readme = "README.md"
|
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
|
||||||
repository = "https://github.com/flukejones/rog-core"
|
|
||||||
homepage = "https://github.com/flukejones/rog-core"
|
|
||||||
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "daemon"
|
|
||||||
path = "src/lib.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "rog-core"
|
|
||||||
path = "src/main.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
rusb = "^0.5.5"
|
|
||||||
|
|
||||||
# cli and logging
|
|
||||||
gumdrop = "^0.8.0"
|
|
||||||
log = "^0.4.8"
|
|
||||||
env_logger = "^0.7.1"
|
|
||||||
|
|
||||||
# async
|
|
||||||
dbus = { version = "^0.8.2", features = ["futures"] }
|
|
||||||
dbus-tokio = "^0.5.1"
|
|
||||||
tokio = { version = "0.2.4", features = ["rt-threaded", "macros", "sync"] }
|
|
||||||
|
|
||||||
# serialisation
|
|
||||||
serde = "1.0"
|
|
||||||
serde_derive = "1.0"
|
|
||||||
toml = "0.5"
|
|
||||||
|
|
||||||
# Device control
|
|
||||||
# sysfs-class = "^0.1.2" # used for backlight control mostly
|
|
||||||
# cpu power management
|
|
||||||
intel-pstate = "^0.2.1"
|
|
||||||
# virtualisation of HID, mainly for outputting consumer key codes
|
|
||||||
uhid-virt = "^0.0.4"
|
|
||||||
#keycode = "0.3"
|
|
||||||
|
|
||||||
#
|
|
||||||
thiserror = "^1.0.15"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -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 -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
|
||||||
|
|
||||||
|
|||||||
17
aura/Cargo.toml
Normal file
17
aura/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "rog-aura"
|
||||||
|
version = "0.8.0"
|
||||||
|
license = "MPL-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
repository = "https://github.com/flukejones/rog-core"
|
||||||
|
homepage = "https://github.com/flukejones/rog-core"
|
||||||
|
description = "A small library of effect types and conversions for ROG Aura"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gumdrop = "^0.8.0"
|
||||||
|
dbus = { version = "^0.8.2" }
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
thiserror = "^1.0.15"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use daemon::aura::{AuraDbusWriter, Key, KeyColourArray};
|
use rog_aura::{AuraDbusWriter, Key, KeyColourArray};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let writer = AuraDbusWriter::new()?;
|
let writer = AuraDbusWriter::new()?;
|
||||||
81
aura/src/aura_dbus.rs
Normal file
81
aura/src/aura_dbus.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use super::*;
|
||||||
|
use dbus::{ffidisp::Connection, Message};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
|
/// Simplified way to write a effect block
|
||||||
|
pub struct AuraDbusWriter {
|
||||||
|
connection: Connection,
|
||||||
|
block_time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraDbusWriter {
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> Result<Self, Box<dyn Error>> {
|
||||||
|
Ok(AuraDbusWriter {
|
||||||
|
connection: Connection::new_system()?,
|
||||||
|
block_time: 10,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method must always be called before the very first write to initialise
|
||||||
|
/// the keyboard LED EC in the correct mode
|
||||||
|
#[inline]
|
||||||
|
pub fn init_effect(&self) -> Result<(), Box<dyn Error>> {
|
||||||
|
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
|
||||||
|
.append1(KeyColourArray::get_init_msg());
|
||||||
|
self.connection.send(msg).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write a single colour block.
|
||||||
|
///
|
||||||
|
/// Intentionally blocks for 10ms after sending to allow the block to
|
||||||
|
/// be written to the keyboard EC. This should not be async.
|
||||||
|
#[inline]
|
||||||
|
pub fn write_colour_block(
|
||||||
|
&self,
|
||||||
|
key_colour_array: &KeyColourArray,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let group = key_colour_array.get();
|
||||||
|
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")?
|
||||||
|
.append1(&group[0].to_vec())
|
||||||
|
.append1(&group[1].to_vec())
|
||||||
|
.append1(&group[2].to_vec())
|
||||||
|
.append1(&group[3].to_vec())
|
||||||
|
.append1(&group[4].to_vec())
|
||||||
|
.append1(&group[5].to_vec())
|
||||||
|
.append1(&group[6].to_vec())
|
||||||
|
.append1(&group[7].to_vec())
|
||||||
|
.append1(&group[8].to_vec())
|
||||||
|
.append1(&group[9].to_vec());
|
||||||
|
self.connection.send(msg).unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(self.block_time));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn write_bytes(&self, bytes: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
|
||||||
|
.append1(bytes.to_vec());
|
||||||
|
let r = self.connection.send_with_reply_and_block(msg, 5000)?;
|
||||||
|
if let Some(reply) = r.get1::<&str>() {
|
||||||
|
return Ok(reply.to_owned());
|
||||||
|
}
|
||||||
|
Err(Box::new(dbus::Error::new_custom("name", "message")))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn write_builtin_mode(
|
||||||
|
&self,
|
||||||
|
mode: &SetAuraBuiltin,
|
||||||
|
) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
let bytes = <[u8; LED_MSG_LEN]>::from(mode);
|
||||||
|
self.write_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
self.write_bytes(&aura_brightness_bytes(level))
|
||||||
|
}
|
||||||
|
}
|
||||||
166
aura/src/builtins.rs
Normal file
166
aura/src/builtins.rs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
use super::cli_options::*;
|
||||||
|
use super::LED_MSG_LEN;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// 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],
|
||||||
|
pub multi_static: [[u8; LED_MSG_LEN]; 4],
|
||||||
|
}
|
||||||
|
impl BuiltInModeBytes {
|
||||||
|
#[inline]
|
||||||
|
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::Single => self.stable.copy_from_slice(bytes),
|
||||||
|
BuiltInModeByte::Breathing => 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),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_field_from(&mut self, byte: u8) -> Option<&[u8]> {
|
||||||
|
let bytes = match BuiltInModeByte::from(byte) {
|
||||||
|
BuiltInModeByte::Single => &self.stable,
|
||||||
|
BuiltInModeByte::Breathing => &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(TwoColourSpeed::default())),
|
||||||
|
random: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Disco(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()),
|
||||||
|
),
|
||||||
|
multi_static: <[[u8; LED_MSG_LEN]; 4]>::from(SetAuraBuiltin::MultiStatic(
|
||||||
|
MultiColour::default(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||||
|
pub enum BuiltInModeByte {
|
||||||
|
Single = 0x00,
|
||||||
|
Breathing = 0x01,
|
||||||
|
Cycle = 0x02,
|
||||||
|
Rainbow = 0x03,
|
||||||
|
Rain = 0x04,
|
||||||
|
Random = 0x05,
|
||||||
|
Highlight = 0x06,
|
||||||
|
Laser = 0x07,
|
||||||
|
Ripple = 0x08,
|
||||||
|
Pulse = 0x0a,
|
||||||
|
ThinZoomy = 0x0b,
|
||||||
|
WideZoomy = 0x0c,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
impl Default for BuiltInModeByte {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
BuiltInModeByte::Single
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for BuiltInModeByte {
|
||||||
|
#[inline]
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0x00 => Self::Single,
|
||||||
|
0x01 => Self::Breathing,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&u8> for BuiltInModeByte {
|
||||||
|
#[inline]
|
||||||
|
fn from(byte: &u8) -> Self {
|
||||||
|
Self::from(*byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BuiltInModeByte> for u8 {
|
||||||
|
#[inline]
|
||||||
|
fn from(byte: BuiltInModeByte) -> Self {
|
||||||
|
match byte {
|
||||||
|
BuiltInModeByte::Single => 0x00,
|
||||||
|
BuiltInModeByte::Breathing => 0x01,
|
||||||
|
BuiltInModeByte::Cycle => 0x02,
|
||||||
|
BuiltInModeByte::Rainbow => 0x03,
|
||||||
|
BuiltInModeByte::Rain => 0x04,
|
||||||
|
BuiltInModeByte::Random => 0x05,
|
||||||
|
BuiltInModeByte::Highlight => 0x06,
|
||||||
|
BuiltInModeByte::Laser => 0x07,
|
||||||
|
BuiltInModeByte::Ripple => 0x08,
|
||||||
|
BuiltInModeByte::Pulse => 0x0a,
|
||||||
|
BuiltInModeByte::ThinZoomy => 0x0b,
|
||||||
|
BuiltInModeByte::WideZoomy => 0x0c,
|
||||||
|
BuiltInModeByte::None => 0xff,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,10 +15,4 @@ pub enum AuraError {
|
|||||||
PollKeyboard,
|
PollKeyboard,
|
||||||
#[error("mode not supported")]
|
#[error("mode not supported")]
|
||||||
NotSupported,
|
NotSupported,
|
||||||
#[error("USB error")]
|
|
||||||
UsbError(rusb::Error),
|
|
||||||
#[error("IO error")]
|
|
||||||
IOError(#[from] std::io::Error),
|
|
||||||
#[error("external command failed")]
|
|
||||||
CommandFailed,
|
|
||||||
}
|
}
|
||||||
265
aura/src/fancy.rs
Normal file
265
aura/src/fancy.rs
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
pub struct KeyColourArray([[u8; 64]; 10]);
|
||||||
|
impl KeyColourArray {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut set = [[0u8; 64]; 10];
|
||||||
|
for (count, row) in set.iter_mut().enumerate() {
|
||||||
|
row[0] = 0x5d; // Report ID
|
||||||
|
row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||||
|
row[2] = 0x00;
|
||||||
|
row[3] = 0x01; // ??
|
||||||
|
row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours
|
||||||
|
row[5] = 0x01; // ??
|
||||||
|
row[6] = (count as u8) << 4; // Key group
|
||||||
|
row[7] = 0x10; // 0b00010000 addressing? flips for group a0
|
||||||
|
if count == 9 {
|
||||||
|
row[7] = 0x08; // 0b00001000
|
||||||
|
}
|
||||||
|
row[8] = 0x00;
|
||||||
|
}
|
||||||
|
KeyColourArray(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialise and clear the keyboard for custom effects
|
||||||
|
#[inline]
|
||||||
|
pub fn get_init_msg() -> Vec<u8> {
|
||||||
|
let mut init = vec![0u8; 64];
|
||||||
|
init[0] = 0x5d; // Report ID
|
||||||
|
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||||
|
init
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) {
|
||||||
|
let (rr, gg, bb) = self.key(key);
|
||||||
|
*rr = r;
|
||||||
|
*gg = g;
|
||||||
|
*bb = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key(&mut self, key: Key) -> (&mut u8, &mut u8, &mut u8) {
|
||||||
|
// Tuples are indexes in to array
|
||||||
|
let (row, col) = match key {
|
||||||
|
Key::VolUp => (0, 15),
|
||||||
|
Key::VolDown => (0, 18),
|
||||||
|
Key::MicMute => (0, 21),
|
||||||
|
Key::ROG => (0, 24),
|
||||||
|
//
|
||||||
|
Key::Esc => (1, 24),
|
||||||
|
Key::F1 => (1, 30),
|
||||||
|
Key::F2 => (1, 33),
|
||||||
|
Key::F3 => (1, 36),
|
||||||
|
Key::F4 => (1, 39),
|
||||||
|
Key::F5 => (1, 45),
|
||||||
|
Key::F6 => (1, 48),
|
||||||
|
Key::F7 => (1, 51),
|
||||||
|
Key::F8 => (1, 54),
|
||||||
|
//
|
||||||
|
Key::F9 => (2, 12),
|
||||||
|
Key::F10 => (2, 15),
|
||||||
|
Key::F11 => (2, 18),
|
||||||
|
Key::F12 => (2, 21),
|
||||||
|
Key::Del => (2, 24),
|
||||||
|
Key::Tilde => (2, 39),
|
||||||
|
Key::N1 => (2, 42),
|
||||||
|
Key::N2 => (2, 45),
|
||||||
|
Key::N3 => (2, 48),
|
||||||
|
Key::N4 => (2, 51),
|
||||||
|
Key::N5 => (2, 54),
|
||||||
|
//
|
||||||
|
Key::N6 => (3, 9),
|
||||||
|
Key::N7 => (3, 12),
|
||||||
|
Key::N8 => (3, 15),
|
||||||
|
Key::N9 => (3, 18),
|
||||||
|
Key::N0 => (3, 21),
|
||||||
|
Key::Hyphen => (3, 24),
|
||||||
|
Key::Equals => (3, 27),
|
||||||
|
Key::BkSpc1 => (3, 30),
|
||||||
|
Key::BkSpc2 => (3, 33),
|
||||||
|
Key::BkSpc3 => (3, 36),
|
||||||
|
Key::Home => (3, 39),
|
||||||
|
Key::Tab => (3, 54),
|
||||||
|
//
|
||||||
|
Key::Q => (4, 9),
|
||||||
|
Key::W => (4, 12),
|
||||||
|
Key::E => (4, 15),
|
||||||
|
Key::R => (4, 18),
|
||||||
|
Key::T => (4, 21),
|
||||||
|
Key::Y => (4, 24),
|
||||||
|
Key::U => (4, 27),
|
||||||
|
Key::I => (4, 30),
|
||||||
|
Key::O => (4, 33),
|
||||||
|
Key::P => (4, 36),
|
||||||
|
Key::LBracket => (4, 39),
|
||||||
|
Key::RBracket => (4, 42),
|
||||||
|
Key::BackSlash => (4, 45),
|
||||||
|
Key::PgUp => (4, 54),
|
||||||
|
//
|
||||||
|
Key::Caps => (5, 21),
|
||||||
|
Key::A => (5, 24),
|
||||||
|
Key::S => (5, 27),
|
||||||
|
Key::D => (5, 30),
|
||||||
|
Key::F => (5, 33),
|
||||||
|
Key::G => (5, 36),
|
||||||
|
Key::H => (5, 39),
|
||||||
|
Key::J => (5, 42),
|
||||||
|
Key::K => (5, 45),
|
||||||
|
Key::L => (5, 48),
|
||||||
|
Key::SemiColon => (5, 51),
|
||||||
|
Key::Quote => (5, 54),
|
||||||
|
//
|
||||||
|
Key::Ret1 => (6, 12),
|
||||||
|
Key::Ret2 => (6, 15),
|
||||||
|
Key::Ret3 => (6, 18),
|
||||||
|
Key::PgDn => (6, 21),
|
||||||
|
Key::LShift => (6, 36),
|
||||||
|
Key::Z => (6, 42),
|
||||||
|
Key::X => (6, 45),
|
||||||
|
Key::C => (6, 48),
|
||||||
|
Key::V => (6, 51),
|
||||||
|
Key::B => (6, 54),
|
||||||
|
//
|
||||||
|
Key::N => (7, 9),
|
||||||
|
Key::M => (7, 12),
|
||||||
|
Key::Comma => (7, 15),
|
||||||
|
Key::Period => (7, 18),
|
||||||
|
Key::FwdSlash => (7, 21),
|
||||||
|
Key::Rshift1 => (7, 27),
|
||||||
|
Key::Rshift2 => (7, 30),
|
||||||
|
Key::Rshift3 => (7, 33),
|
||||||
|
Key::End => (7, 36),
|
||||||
|
Key::LCtrl => (7, 51),
|
||||||
|
Key::LFn => (7, 54),
|
||||||
|
//
|
||||||
|
Key::Meta => (8, 9),
|
||||||
|
Key::LAlt => (8, 12),
|
||||||
|
Key::Space1 => (8, 15),
|
||||||
|
Key::Space2 => (8, 18),
|
||||||
|
Key::Space3 => (8, 21),
|
||||||
|
Key::Space4 => (8, 24),
|
||||||
|
Key::RAlt => (8, 30),
|
||||||
|
Key::PrtSc => (8, 33),
|
||||||
|
Key::RCtrl => (8, 36),
|
||||||
|
Key::Up => (8, 42),
|
||||||
|
Key::RFn => (8, 51),
|
||||||
|
//
|
||||||
|
Key::Left => (9, 54),
|
||||||
|
//
|
||||||
|
Key::Down => (10, 9),
|
||||||
|
Key::Right => (10, 12),
|
||||||
|
};
|
||||||
|
// LOLOLOLOLOLOLOL! Look it's safe okay
|
||||||
|
unsafe {
|
||||||
|
(
|
||||||
|
&mut *(&mut self.0[row][col] as *mut u8),
|
||||||
|
&mut *(&mut self.0[row][col + 1] as *mut u8),
|
||||||
|
&mut *(&mut self.0[row][col + 2] as *mut u8),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get(&self) -> &[[u8; 64]; 10] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Key {
|
||||||
|
VolUp,
|
||||||
|
VolDown,
|
||||||
|
MicMute,
|
||||||
|
ROG,
|
||||||
|
Esc,
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
Del,
|
||||||
|
Tilde,
|
||||||
|
N1,
|
||||||
|
N2,
|
||||||
|
N3,
|
||||||
|
N4,
|
||||||
|
N5,
|
||||||
|
N6,
|
||||||
|
N7,
|
||||||
|
N8,
|
||||||
|
N9,
|
||||||
|
N0,
|
||||||
|
Hyphen,
|
||||||
|
Equals,
|
||||||
|
BkSpc1,
|
||||||
|
BkSpc2,
|
||||||
|
BkSpc3,
|
||||||
|
Home,
|
||||||
|
Tab,
|
||||||
|
Q,
|
||||||
|
W,
|
||||||
|
E,
|
||||||
|
R,
|
||||||
|
T,
|
||||||
|
Y,
|
||||||
|
U,
|
||||||
|
I,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
LBracket,
|
||||||
|
RBracket,
|
||||||
|
BackSlash,
|
||||||
|
PgUp,
|
||||||
|
Caps,
|
||||||
|
A,
|
||||||
|
S,
|
||||||
|
D,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
SemiColon,
|
||||||
|
Quote,
|
||||||
|
Ret1,
|
||||||
|
Ret2,
|
||||||
|
Ret3,
|
||||||
|
PgDn,
|
||||||
|
LShift,
|
||||||
|
Z,
|
||||||
|
X,
|
||||||
|
C,
|
||||||
|
V,
|
||||||
|
B,
|
||||||
|
N,
|
||||||
|
M,
|
||||||
|
Comma,
|
||||||
|
Period,
|
||||||
|
FwdSlash,
|
||||||
|
Rshift1,
|
||||||
|
Rshift2,
|
||||||
|
Rshift3,
|
||||||
|
End,
|
||||||
|
LCtrl,
|
||||||
|
LFn,
|
||||||
|
Meta,
|
||||||
|
LAlt,
|
||||||
|
Space1,
|
||||||
|
Space2,
|
||||||
|
Space3,
|
||||||
|
Space4,
|
||||||
|
RAlt,
|
||||||
|
PrtSc,
|
||||||
|
RCtrl,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
RFn,
|
||||||
|
}
|
||||||
233
aura/src/lib.rs
Normal file
233
aura/src/lib.rs
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
pub static DBUS_NAME: &'static str = "org.rogcore.Daemon";
|
||||||
|
pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon";
|
||||||
|
pub static DBUS_IFACE: &'static str = "org.rogcore.Daemon";
|
||||||
|
pub const LED_MSG_LEN: usize = 17;
|
||||||
|
|
||||||
|
mod builtins;
|
||||||
|
pub use builtins::*;
|
||||||
|
|
||||||
|
/// Contains mostly only what is required for parsing CLI options
|
||||||
|
pub mod cli_options;
|
||||||
|
mod fancy;
|
||||||
|
|
||||||
|
mod aura_dbus;
|
||||||
|
pub use aura_dbus::*;
|
||||||
|
|
||||||
|
pub use fancy::*;
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
|
use crate::cli_options::*;
|
||||||
|
|
||||||
|
/// Writes aout the correct byte string for brightness
|
||||||
|
///
|
||||||
|
/// The HID descriptor looks like:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
||||||
|
/// 0x09, 0x76, // Usage (0x76)
|
||||||
|
/// 0xA1, 0x01, // Collection (Application)
|
||||||
|
/// 0x85, 0x5A, // Report ID (90)
|
||||||
|
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||||
|
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||||
|
/// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
/// 0x75, 0x08, // Report Size (8)
|
||||||
|
/// 0x95, 0x05, // Report Count (5)
|
||||||
|
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||||
|
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||||
|
/// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
/// 0x75, 0x08, // Report Size (8)
|
||||||
|
/// 0x95, 0x3F, // Report Count (63)
|
||||||
|
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||||
|
/// 0xC0, // End Collection
|
||||||
|
/// ```
|
||||||
|
pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||||
|
// TODO: check brightness range
|
||||||
|
[
|
||||||
|
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses `SetAuraBuiltin` in to packet data
|
||||||
|
///
|
||||||
|
/// Byte structure:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
|
||||||
|
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Bytes 0 and 1 should always be 5d, b3
|
||||||
|
///
|
||||||
|
/// On multizone laptops byte 2 is the zone number, RGB in usual
|
||||||
|
/// place, byte 3 set to zero
|
||||||
|
///
|
||||||
|
/// Byte 3 sets the mode type:
|
||||||
|
/// - 00 = static
|
||||||
|
/// - 01 = breathe (can set two colours)
|
||||||
|
/// - 02 = cycle (through all colours)
|
||||||
|
/// - 03 = rainbow
|
||||||
|
/// - 04 = rain (byte 9 sets random colour)
|
||||||
|
/// - 05 = random keys, red, white, turquoise
|
||||||
|
/// - 06 = pressed keys light up and fade
|
||||||
|
/// - 07 = pressed key emits laser
|
||||||
|
/// - 08 = pressed key emits water ripple
|
||||||
|
/// - 09 = no effect/not used
|
||||||
|
/// - 0a fast pulse (no speed setting)
|
||||||
|
/// - 0b vertical line racing to right (no speed setting)
|
||||||
|
/// - 0c wider vertical line racing to right (no speed setting)
|
||||||
|
///
|
||||||
|
/// Bytes 4, 5, 6 are Red, Green, Blue
|
||||||
|
///
|
||||||
|
/// Byte 7 sets speed from
|
||||||
|
/// - 0x00 = Off
|
||||||
|
/// - 0xe1 = Slow
|
||||||
|
/// - 0xeb = Medium
|
||||||
|
/// - 0xf5 = Fast
|
||||||
|
///
|
||||||
|
/// Byte 8 sets rainbow direction:
|
||||||
|
/// - 0x00 = rightwards
|
||||||
|
/// - 0x01 = leftwards
|
||||||
|
/// - 0x02 = upwards
|
||||||
|
/// - 0x03 = downwards
|
||||||
|
///
|
||||||
|
/// Bytes 10, 11, 12 are Red, Green, Blue for second colour if mode supports it
|
||||||
|
///
|
||||||
|
/// The HID descriptor looks like:
|
||||||
|
/// ```
|
||||||
|
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
||||||
|
/// 0x09, 0x79, // Usage (0x79)
|
||||||
|
/// 0xA1, 0x01, // Collection (Application)
|
||||||
|
/// 0x85, 0x5D, // Report ID (93)
|
||||||
|
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||||
|
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||||
|
/// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
/// 0x75, 0x08, // Report Size (8)
|
||||||
|
/// 0x95, 0x1F, // Report Count (31)
|
||||||
|
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||||
|
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||||
|
/// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
/// 0x75, 0x08, // Report Size (8)
|
||||||
|
/// 0x95, 0x3F, // Report Count (63)
|
||||||
|
/// 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||||
|
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||||
|
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||||
|
/// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
/// 0x75, 0x08, // Report Size (8)
|
||||||
|
/// 0x95, 0x3F, // Report Count (63)
|
||||||
|
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||||
|
/// 0xC0, // End Collection
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This descriptor is also used for the per-key LED settings
|
||||||
|
impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] {
|
||||||
|
fn from(mode: &SetAuraBuiltin) -> Self {
|
||||||
|
let mut msg = [0u8; 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::Disco(_) => 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,
|
||||||
|
_ => panic!("Mode not convertable to array"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
SetAuraBuiltin::Rainbow(settings) => {
|
||||||
|
msg[7] = settings.speed as u8;
|
||||||
|
msg[8] = settings.direction as u8;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Rain(settings) => {
|
||||||
|
msg[4] = settings.colour.0;
|
||||||
|
msg[5] = settings.colour.1;
|
||||||
|
msg[6] = settings.colour.2;
|
||||||
|
msg[7] = settings.speed as u8;
|
||||||
|
msg[9] = settings.colour2.2;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Breathe(settings) => {
|
||||||
|
msg[4] = settings.colour.0;
|
||||||
|
msg[5] = settings.colour.1;
|
||||||
|
msg[6] = settings.colour.2;
|
||||||
|
msg[7] = settings.speed as u8;
|
||||||
|
msg[10] = settings.colour2.0;
|
||||||
|
msg[11] = settings.colour2.1;
|
||||||
|
msg[12] = settings.colour2.2;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Cycle(settings) | SetAuraBuiltin::Disco(settings) => {
|
||||||
|
msg[7] = settings.speed as u8;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Highlight(settings)
|
||||||
|
| SetAuraBuiltin::Laser(settings)
|
||||||
|
| SetAuraBuiltin::Ripple(settings) => {
|
||||||
|
msg[4] = settings.colour.0;
|
||||||
|
msg[5] = settings.colour.1;
|
||||||
|
msg[6] = settings.colour.2;
|
||||||
|
msg[7] = settings.speed as u8;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Stable(settings)
|
||||||
|
| SetAuraBuiltin::Pulse(settings)
|
||||||
|
| SetAuraBuiltin::ThinZoomy(settings)
|
||||||
|
| SetAuraBuiltin::WideZoomy(settings) => {
|
||||||
|
msg[4] = settings.colour.0;
|
||||||
|
msg[5] = settings.colour.1;
|
||||||
|
msg[6] = settings.colour.2;
|
||||||
|
}
|
||||||
|
_ => panic!("Mode not convertable to array"),
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
|
||||||
|
#[inline]
|
||||||
|
fn from(mode: SetAuraBuiltin) -> Self {
|
||||||
|
<[u8; LED_MSG_LEN]>::from(&mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SetAuraBuiltin> for [[u8; LED_MSG_LEN]; 4] {
|
||||||
|
#[inline]
|
||||||
|
fn from(mode: SetAuraBuiltin) -> Self {
|
||||||
|
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
||||||
|
for i in 0..4 {
|
||||||
|
msg[i][0] = 0x5d;
|
||||||
|
msg[i][1] = 0xb3;
|
||||||
|
msg[i][2] = i as u8 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
SetAuraBuiltin::MultiStatic(settings) => {
|
||||||
|
msg[0][4] = settings.colour1.0;
|
||||||
|
msg[0][5] = settings.colour1.1;
|
||||||
|
msg[0][6] = settings.colour1.2;
|
||||||
|
msg[1][4] = settings.colour2.0;
|
||||||
|
msg[1][5] = settings.colour2.1;
|
||||||
|
msg[1][6] = settings.colour2.2;
|
||||||
|
msg[2][4] = settings.colour3.0;
|
||||||
|
msg[2][5] = settings.colour3.1;
|
||||||
|
msg[2][6] = settings.colour3.2;
|
||||||
|
msg[3][4] = settings.colour4.0;
|
||||||
|
msg[3][5] = settings.colour4.1;
|
||||||
|
msg[3][6] = settings.colour4.2;
|
||||||
|
}
|
||||||
|
_ => panic!("Mode not convertable to array"),
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
}
|
||||||
1016
rog-core/Cargo.lock
generated
Normal file
1016
rog-core/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
rog-core/Cargo.toml
Normal file
45
rog-core/Cargo.toml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
[package]
|
||||||
|
name = "rog-daemon"
|
||||||
|
version = "0.8.0"
|
||||||
|
license = "MPL-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
repository = "https://github.com/flukejones/rog-core"
|
||||||
|
homepage = "https://github.com/flukejones/rog-core"
|
||||||
|
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "daemon"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "rog-core"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rog-aura = { path = "../aura" }
|
||||||
|
rusb = "^0.5.5"
|
||||||
|
|
||||||
|
# cli and logging
|
||||||
|
gumdrop = "^0.8.0"
|
||||||
|
log = "^0.4.8"
|
||||||
|
env_logger = "^0.7.1"
|
||||||
|
|
||||||
|
# async
|
||||||
|
dbus = { version = "^0.8.2", features = ["futures"] }
|
||||||
|
dbus-tokio = "^0.5.1"
|
||||||
|
tokio = { version = "0.2.4", features = ["rt-threaded", "macros", "sync"] }
|
||||||
|
|
||||||
|
# serialisation
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
toml = "0.5"
|
||||||
|
|
||||||
|
# Device control
|
||||||
|
# sysfs-class = "^0.1.2" # used for backlight control mostly
|
||||||
|
# cpu power management
|
||||||
|
intel-pstate = "^0.2.1"
|
||||||
|
# virtualisation of HID, mainly for outputting consumer key codes
|
||||||
|
uhid-virt = "^0.0.4"
|
||||||
|
#keycode = "0.3"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::aura::BuiltInModeBytes;
|
use rog_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};
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
// Return show-stopping errors, otherwise map error to a log level
|
// Return show-stopping errors, otherwise map error to a log level
|
||||||
|
|
||||||
use crate::{
|
use crate::{config::Config, virt_device::VirtKeys};
|
||||||
aura::{aura_brightness_bytes, BuiltInModeByte},
|
|
||||||
config::Config,
|
|
||||||
error::AuraError,
|
|
||||||
virt_device::VirtKeys,
|
|
||||||
};
|
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
|
use rog_aura::{aura_brightness_bytes, error::AuraError, BuiltInModeByte};
|
||||||
use rusb::DeviceHandle;
|
use rusb::DeviceHandle;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
@@ -48,7 +44,11 @@ pub(crate) struct RogCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RogCore {
|
impl RogCore {
|
||||||
pub(crate) fn new(vendor: u16, product: u16, led_endpoint: u8) -> Result<RogCore, AuraError> {
|
pub(crate) fn new(
|
||||||
|
vendor: u16,
|
||||||
|
product: u16,
|
||||||
|
led_endpoint: u8,
|
||||||
|
) -> Result<RogCore, Box<dyn Error>> {
|
||||||
let mut dev_handle = RogCore::get_device(vendor, product)?;
|
let mut dev_handle = RogCore::get_device(vendor, product)?;
|
||||||
dev_handle.set_active_configuration(0).unwrap_or(());
|
dev_handle.set_active_configuration(0).unwrap_or(());
|
||||||
|
|
||||||
@@ -72,9 +72,7 @@ impl RogCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev_handle.set_auto_detach_kernel_driver(true).unwrap();
|
dev_handle.set_auto_detach_kernel_driver(true).unwrap();
|
||||||
dev_handle
|
dev_handle.claim_interface(interface)?;
|
||||||
.claim_interface(interface)
|
|
||||||
.map_err(AuraError::UsbError)?;
|
|
||||||
|
|
||||||
Ok(RogCore {
|
Ok(RogCore {
|
||||||
handle: dev_handle,
|
handle: dev_handle,
|
||||||
@@ -115,14 +113,14 @@ impl RogCore {
|
|||||||
fn get_device(
|
fn get_device(
|
||||||
vendor: u16,
|
vendor: u16,
|
||||||
product: u16,
|
product: u16,
|
||||||
) -> Result<DeviceHandle<rusb::GlobalContext>, AuraError> {
|
) -> Result<DeviceHandle<rusb::GlobalContext>, rusb::Error> {
|
||||||
for device in rusb::devices().unwrap().iter() {
|
for device in rusb::devices().unwrap().iter() {
|
||||||
let device_desc = device.device_descriptor().unwrap();
|
let device_desc = device.device_descriptor().unwrap();
|
||||||
if device_desc.vendor_id() == vendor && device_desc.product_id() == product {
|
if device_desc.vendor_id() == vendor && device_desc.product_id() == product {
|
||||||
return device.open().map_err(|err| AuraError::UsbError(err));
|
return device.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(AuraError::UsbError(rusb::Error::NoDevice))
|
Err(rusb::Error::NoDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
pub(crate) fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::{aura::*, config::Config, core::*, laptops::match_laptop};
|
use crate::{config::Config, core::*, laptops::match_laptop};
|
||||||
use dbus::{
|
use dbus::{
|
||||||
nonblock::Process,
|
nonblock::Process,
|
||||||
tree::{Factory, MTSync, Method, MethodErr, Tree},
|
tree::{Factory, MTSync, Method, MethodErr, Tree},
|
||||||
};
|
};
|
||||||
use dbus_tokio::connection;
|
use dbus_tokio::connection;
|
||||||
|
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
use rog_aura::{DBUS_IFACE, DBUS_PATH};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -134,6 +134,8 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
std::thread::sleep(Duration::from_millis(200));
|
std::thread::sleep(Duration::from_millis(200));
|
||||||
} else if now.duration_since(time_mark).as_millis() > 100 {
|
} else if now.duration_since(time_mark).as_millis() > 100 {
|
||||||
std::thread::sleep(Duration::from_millis(50));
|
std::thread::sleep(Duration::from_millis(50));
|
||||||
|
} else {
|
||||||
|
std::thread::sleep(Duration::from_micros(300));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::aura::BuiltInModeByte;
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::core::{LedWriter, RogCore};
|
use crate::core::{LedWriter, RogCore};
|
||||||
use crate::error::AuraError;
|
use rog_aura::{error::AuraError, BuiltInModeByte};
|
||||||
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||||
use crate::virt_device::ConsumerKeys;
|
use crate::virt_device::ConsumerKeys;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
pub mod aura;
|
|
||||||
/// Contains mostly only what is required for parsing CLI options
|
|
||||||
pub mod cli_options;
|
|
||||||
mod config;
|
mod config;
|
||||||
/// The core module which allows writing to LEDs or polling the
|
/// The core module which allows writing to LEDs or polling the
|
||||||
/// laptop keyboard attached devices
|
/// laptop keyboard attached devices
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod daemon;
|
pub mod daemon;
|
||||||
mod error;
|
|
||||||
pub mod laptops;
|
pub mod laptops;
|
||||||
mod virt_device;
|
mod virt_device;
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
use daemon::{
|
use daemon::{core::LedBrightness, daemon::start_daemon};
|
||||||
aura::{AuraDbusWriter, LED_MSG_LEN},
|
|
||||||
cli_options::SetAuraBuiltin,
|
|
||||||
core::LedBrightness,
|
|
||||||
daemon::start_daemon,
|
|
||||||
};
|
|
||||||
use env_logger::{Builder, Target};
|
use env_logger::{Builder, Target};
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
use rog_aura::{cli_options::SetAuraBuiltin, AuraDbusWriter, LED_MSG_LEN};
|
||||||
|
|
||||||
static VERSION: &'static str = "0.8.0";
|
static VERSION: &'static str = "0.8.0";
|
||||||
|
|
||||||
714
src/aura.rs
714
src/aura.rs
@@ -1,714 +0,0 @@
|
|||||||
pub static DBUS_NAME: &'static str = "org.rogcore.Daemon";
|
|
||||||
pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon";
|
|
||||||
pub static DBUS_IFACE: &'static str = "org.rogcore.Daemon";
|
|
||||||
pub const LED_MSG_LEN: usize = 17;
|
|
||||||
|
|
||||||
use crate::cli_options::*;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Writes aout the correct byte string for brightness
|
|
||||||
///
|
|
||||||
/// The HID descriptor looks like:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
|
||||||
/// 0x09, 0x76, // Usage (0x76)
|
|
||||||
/// 0xA1, 0x01, // Collection (Application)
|
|
||||||
/// 0x85, 0x5A, // Report ID (90)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x05, // Report Count (5)
|
|
||||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0xC0, // End Collection
|
|
||||||
/// ```
|
|
||||||
pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
|
||||||
// TODO: check brightness range
|
|
||||||
[
|
|
||||||
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses `SetAuraBuiltin` in to packet data
|
|
||||||
///
|
|
||||||
/// Byte structure:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
|
|
||||||
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
||||||
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Bytes 0 and 1 should always be 5d, b3
|
|
||||||
///
|
|
||||||
/// On multizone laptops byte 2 is the zone number, RGB in usual
|
|
||||||
/// place, byte 3 set to zero
|
|
||||||
///
|
|
||||||
/// Byte 3 sets the mode type:
|
|
||||||
/// - 00 = static
|
|
||||||
/// - 01 = breathe (can set two colours)
|
|
||||||
/// - 02 = cycle (through all colours)
|
|
||||||
/// - 03 = rainbow
|
|
||||||
/// - 04 = rain (byte 9 sets random colour)
|
|
||||||
/// - 05 = random keys, red, white, turquoise
|
|
||||||
/// - 06 = pressed keys light up and fade
|
|
||||||
/// - 07 = pressed key emits laser
|
|
||||||
/// - 08 = pressed key emits water ripple
|
|
||||||
/// - 09 = no effect/not used
|
|
||||||
/// - 0a fast pulse (no speed setting)
|
|
||||||
/// - 0b vertical line racing to right (no speed setting)
|
|
||||||
/// - 0c wider vertical line racing to right (no speed setting)
|
|
||||||
///
|
|
||||||
/// Bytes 4, 5, 6 are Red, Green, Blue
|
|
||||||
///
|
|
||||||
/// Byte 7 sets speed from
|
|
||||||
/// - 0x00 = Off
|
|
||||||
/// - 0xe1 = Slow
|
|
||||||
/// - 0xeb = Medium
|
|
||||||
/// - 0xf5 = Fast
|
|
||||||
///
|
|
||||||
/// Byte 8 sets rainbow direction:
|
|
||||||
/// - 0x00 = rightwards
|
|
||||||
/// - 0x01 = leftwards
|
|
||||||
/// - 0x02 = upwards
|
|
||||||
/// - 0x03 = downwards
|
|
||||||
///
|
|
||||||
/// Bytes 10, 11, 12 are Red, Green, Blue for second colour if mode supports it
|
|
||||||
///
|
|
||||||
/// The HID descriptor looks like:
|
|
||||||
/// ```
|
|
||||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
|
||||||
/// 0x09, 0x79, // Usage (0x79)
|
|
||||||
/// 0xA1, 0x01, // Collection (Application)
|
|
||||||
/// 0x85, 0x5D, // Report ID (93)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x1F, // Report Count (31)
|
|
||||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0xC0, // End Collection
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// This descriptor is also used for the per-key LED settings
|
|
||||||
impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] {
|
|
||||||
fn from(mode: &SetAuraBuiltin) -> Self {
|
|
||||||
let mut msg = [0u8; 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::Disco(_) => 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,
|
|
||||||
_ => panic!("Mode not convertable to array"),
|
|
||||||
}
|
|
||||||
|
|
||||||
match mode {
|
|
||||||
SetAuraBuiltin::Rainbow(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[8] = settings.direction as u8;
|
|
||||||
}
|
|
||||||
SetAuraBuiltin::Rain(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[9] = settings.colour2.2;
|
|
||||||
}
|
|
||||||
SetAuraBuiltin::Breathe(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[10] = settings.colour2.0;
|
|
||||||
msg[11] = settings.colour2.1;
|
|
||||||
msg[12] = settings.colour2.2;
|
|
||||||
}
|
|
||||||
SetAuraBuiltin::Cycle(settings) | SetAuraBuiltin::Disco(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
SetAuraBuiltin::Highlight(settings)
|
|
||||||
| SetAuraBuiltin::Laser(settings)
|
|
||||||
| SetAuraBuiltin::Ripple(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
SetAuraBuiltin::Stable(settings)
|
|
||||||
| SetAuraBuiltin::Pulse(settings)
|
|
||||||
| SetAuraBuiltin::ThinZoomy(settings)
|
|
||||||
| SetAuraBuiltin::WideZoomy(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to array"),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
|
|
||||||
fn from(mode: SetAuraBuiltin) -> Self {
|
|
||||||
<[u8; LED_MSG_LEN]>::from(&mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SetAuraBuiltin> for [[u8; LED_MSG_LEN]; 4] {
|
|
||||||
fn from(mode: SetAuraBuiltin) -> Self {
|
|
||||||
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
|
||||||
for i in 0..4 {
|
|
||||||
msg[i][0] = 0x5d;
|
|
||||||
msg[i][1] = 0xb3;
|
|
||||||
msg[i][2] = i as u8 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
match mode {
|
|
||||||
SetAuraBuiltin::MultiStatic(settings) => {
|
|
||||||
msg[0][4] = settings.colour1.0;
|
|
||||||
msg[0][5] = settings.colour1.1;
|
|
||||||
msg[0][6] = settings.colour1.2;
|
|
||||||
msg[1][4] = settings.colour2.0;
|
|
||||||
msg[1][5] = settings.colour2.1;
|
|
||||||
msg[1][6] = settings.colour2.2;
|
|
||||||
msg[2][4] = settings.colour3.0;
|
|
||||||
msg[2][5] = settings.colour3.1;
|
|
||||||
msg[2][6] = settings.colour3.2;
|
|
||||||
msg[3][4] = settings.colour4.0;
|
|
||||||
msg[3][5] = settings.colour4.1;
|
|
||||||
msg[3][6] = settings.colour4.2;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to array"),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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],
|
|
||||||
pub multi_static: [[u8; LED_MSG_LEN]; 4],
|
|
||||||
}
|
|
||||||
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::Single => self.stable.copy_from_slice(bytes),
|
|
||||||
BuiltInModeByte::Breathing => 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::Single => &self.stable,
|
|
||||||
BuiltInModeByte::Breathing => &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(TwoColourSpeed::default())),
|
|
||||||
random: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Disco(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()),
|
|
||||||
),
|
|
||||||
multi_static: <[[u8; LED_MSG_LEN]; 4]>::from(SetAuraBuiltin::MultiStatic(
|
|
||||||
MultiColour::default(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
|
||||||
pub enum BuiltInModeByte {
|
|
||||||
Single = 0x00,
|
|
||||||
Breathing = 0x01,
|
|
||||||
Cycle = 0x02,
|
|
||||||
Rainbow = 0x03,
|
|
||||||
Rain = 0x04,
|
|
||||||
Random = 0x05,
|
|
||||||
Highlight = 0x06,
|
|
||||||
Laser = 0x07,
|
|
||||||
Ripple = 0x08,
|
|
||||||
Pulse = 0x0a,
|
|
||||||
ThinZoomy = 0x0b,
|
|
||||||
WideZoomy = 0x0c,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
impl Default for BuiltInModeByte {
|
|
||||||
fn default() -> Self {
|
|
||||||
BuiltInModeByte::Single
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u8> for BuiltInModeByte {
|
|
||||||
fn from(byte: u8) -> Self {
|
|
||||||
match byte {
|
|
||||||
0x00 => Self::Single,
|
|
||||||
0x01 => Self::Breathing,
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&u8> for BuiltInModeByte {
|
|
||||||
fn from(byte: &u8) -> Self {
|
|
||||||
Self::from(*byte)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BuiltInModeByte> for u8 {
|
|
||||||
fn from(byte: BuiltInModeByte) -> Self {
|
|
||||||
match byte {
|
|
||||||
BuiltInModeByte::Single => 0x00,
|
|
||||||
BuiltInModeByte::Breathing => 0x01,
|
|
||||||
BuiltInModeByte::Cycle => 0x02,
|
|
||||||
BuiltInModeByte::Rainbow => 0x03,
|
|
||||||
BuiltInModeByte::Rain => 0x04,
|
|
||||||
BuiltInModeByte::Random => 0x05,
|
|
||||||
BuiltInModeByte::Highlight => 0x06,
|
|
||||||
BuiltInModeByte::Laser => 0x07,
|
|
||||||
BuiltInModeByte::Ripple => 0x08,
|
|
||||||
BuiltInModeByte::Pulse => 0x0a,
|
|
||||||
BuiltInModeByte::ThinZoomy => 0x0b,
|
|
||||||
BuiltInModeByte::WideZoomy => 0x0c,
|
|
||||||
BuiltInModeByte::None => 0xff,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct KeyColourArray([[u8; 64]; 10]);
|
|
||||||
impl KeyColourArray {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut set = [[0u8; 64]; 10];
|
|
||||||
for (count, row) in set.iter_mut().enumerate() {
|
|
||||||
row[0] = 0x5d; // Report ID
|
|
||||||
row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
|
||||||
row[2] = 0x00;
|
|
||||||
row[3] = 0x01; // ??
|
|
||||||
row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours
|
|
||||||
row[5] = 0x01; // ??
|
|
||||||
row[6] = (count as u8) << 4; // Key group
|
|
||||||
row[7] = 0x10; // 0b00010000 addressing? flips for group a0
|
|
||||||
if count == 9 {
|
|
||||||
row[7] = 0x08; // 0b00001000
|
|
||||||
}
|
|
||||||
row[8] = 0x00;
|
|
||||||
}
|
|
||||||
KeyColourArray(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialise and clear the keyboard for custom effects
|
|
||||||
pub fn get_init_msg() -> Vec<u8> {
|
|
||||||
let mut init = vec![0u8; 64];
|
|
||||||
init[0] = 0x5d; // Report ID
|
|
||||||
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
|
||||||
init
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) {
|
|
||||||
let (rr, gg, bb) = self.key(key);
|
|
||||||
*rr = r;
|
|
||||||
*gg = g;
|
|
||||||
*bb = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn key(&mut self, key: Key) -> (&mut u8, &mut u8, &mut u8) {
|
|
||||||
// Tuples are indexes in to array
|
|
||||||
let (row, col) = match key {
|
|
||||||
Key::VolUp => (0, 15),
|
|
||||||
Key::VolDown => (0, 18),
|
|
||||||
Key::MicMute => (0, 21),
|
|
||||||
Key::ROG => (0, 24),
|
|
||||||
//
|
|
||||||
Key::Esc => (1, 24),
|
|
||||||
Key::F1 => (1, 30),
|
|
||||||
Key::F2 => (1, 33),
|
|
||||||
Key::F3 => (1, 36),
|
|
||||||
Key::F4 => (1, 39),
|
|
||||||
Key::F5 => (1, 45),
|
|
||||||
Key::F6 => (1, 48),
|
|
||||||
Key::F7 => (1, 51),
|
|
||||||
Key::F8 => (1, 54),
|
|
||||||
//
|
|
||||||
Key::F9 => (2, 12),
|
|
||||||
Key::F10 => (2, 15),
|
|
||||||
Key::F11 => (2, 18),
|
|
||||||
Key::F12 => (2, 21),
|
|
||||||
Key::Del => (2, 24),
|
|
||||||
Key::Tilde => (2, 39),
|
|
||||||
Key::N1 => (2, 42),
|
|
||||||
Key::N2 => (2, 45),
|
|
||||||
Key::N3 => (2, 48),
|
|
||||||
Key::N4 => (2, 51),
|
|
||||||
Key::N5 => (2, 54),
|
|
||||||
//
|
|
||||||
Key::N6 => (3, 9),
|
|
||||||
Key::N7 => (3, 12),
|
|
||||||
Key::N8 => (3, 15),
|
|
||||||
Key::N9 => (3, 18),
|
|
||||||
Key::N0 => (3, 21),
|
|
||||||
Key::Hyphen => (3, 24),
|
|
||||||
Key::Equals => (3, 27),
|
|
||||||
Key::BkSpc1 => (3, 30),
|
|
||||||
Key::BkSpc2 => (3, 33),
|
|
||||||
Key::BkSpc3 => (3, 36),
|
|
||||||
Key::Home => (3, 39),
|
|
||||||
Key::Tab => (3, 54),
|
|
||||||
//
|
|
||||||
Key::Q => (4, 9),
|
|
||||||
Key::W => (4, 12),
|
|
||||||
Key::E => (4, 15),
|
|
||||||
Key::R => (4, 18),
|
|
||||||
Key::T => (4, 21),
|
|
||||||
Key::Y => (4, 24),
|
|
||||||
Key::U => (4, 27),
|
|
||||||
Key::I => (4, 30),
|
|
||||||
Key::O => (4, 33),
|
|
||||||
Key::P => (4, 36),
|
|
||||||
Key::LBracket => (4, 39),
|
|
||||||
Key::RBracket => (4, 42),
|
|
||||||
Key::BackSlash => (4, 45),
|
|
||||||
Key::PgUp => (4, 54),
|
|
||||||
//
|
|
||||||
Key::Caps => (5, 21),
|
|
||||||
Key::A => (5, 24),
|
|
||||||
Key::S => (5, 27),
|
|
||||||
Key::D => (5, 30),
|
|
||||||
Key::F => (5, 33),
|
|
||||||
Key::G => (5, 36),
|
|
||||||
Key::H => (5, 39),
|
|
||||||
Key::J => (5, 42),
|
|
||||||
Key::K => (5, 45),
|
|
||||||
Key::L => (5, 48),
|
|
||||||
Key::SemiColon => (5, 51),
|
|
||||||
Key::Quote => (5, 54),
|
|
||||||
//
|
|
||||||
Key::Ret1 => (6, 12),
|
|
||||||
Key::Ret2 => (6, 15),
|
|
||||||
Key::Ret3 => (6, 18),
|
|
||||||
Key::PgDn => (6, 21),
|
|
||||||
Key::LShift => (6, 36),
|
|
||||||
Key::Z => (6, 42),
|
|
||||||
Key::X => (6, 45),
|
|
||||||
Key::C => (6, 48),
|
|
||||||
Key::V => (6, 51),
|
|
||||||
Key::B => (6, 54),
|
|
||||||
//
|
|
||||||
Key::N => (7, 9),
|
|
||||||
Key::M => (7, 12),
|
|
||||||
Key::Comma => (7, 15),
|
|
||||||
Key::Period => (7, 18),
|
|
||||||
Key::FwdSlash => (7, 21),
|
|
||||||
Key::Rshift1 => (7, 27),
|
|
||||||
Key::Rshift2 => (7, 30),
|
|
||||||
Key::Rshift3 => (7, 33),
|
|
||||||
Key::End => (7, 36),
|
|
||||||
Key::LCtrl => (7, 51),
|
|
||||||
Key::LFn => (7, 54),
|
|
||||||
//
|
|
||||||
Key::Meta => (8, 9),
|
|
||||||
Key::LAlt => (8, 12),
|
|
||||||
Key::Space1 => (8, 15),
|
|
||||||
Key::Space2 => (8, 18),
|
|
||||||
Key::Space3 => (8, 21),
|
|
||||||
Key::Space4 => (8, 24),
|
|
||||||
Key::RAlt => (8, 30),
|
|
||||||
Key::PrtSc => (8, 33),
|
|
||||||
Key::RCtrl => (8, 36),
|
|
||||||
Key::Up => (8, 42),
|
|
||||||
Key::RFn => (8, 51),
|
|
||||||
//
|
|
||||||
Key::Left => (9, 54),
|
|
||||||
//
|
|
||||||
Key::Down => (10, 9),
|
|
||||||
Key::Right => (10, 12),
|
|
||||||
};
|
|
||||||
// LOLOLOLOLOLOLOL! Look it's safe okay
|
|
||||||
unsafe {
|
|
||||||
(
|
|
||||||
&mut *(&mut self.0[row][col] as *mut u8),
|
|
||||||
&mut *(&mut self.0[row][col + 1] as *mut u8),
|
|
||||||
&mut *(&mut self.0[row][col + 2] as *mut u8),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self) -> &[[u8; 64]; 10] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Key {
|
|
||||||
VolUp,
|
|
||||||
VolDown,
|
|
||||||
MicMute,
|
|
||||||
ROG,
|
|
||||||
Esc,
|
|
||||||
F1,
|
|
||||||
F2,
|
|
||||||
F3,
|
|
||||||
F4,
|
|
||||||
F5,
|
|
||||||
F6,
|
|
||||||
F7,
|
|
||||||
F8,
|
|
||||||
F9,
|
|
||||||
F10,
|
|
||||||
F11,
|
|
||||||
F12,
|
|
||||||
Del,
|
|
||||||
Tilde,
|
|
||||||
N1,
|
|
||||||
N2,
|
|
||||||
N3,
|
|
||||||
N4,
|
|
||||||
N5,
|
|
||||||
N6,
|
|
||||||
N7,
|
|
||||||
N8,
|
|
||||||
N9,
|
|
||||||
N0,
|
|
||||||
Hyphen,
|
|
||||||
Equals,
|
|
||||||
BkSpc1,
|
|
||||||
BkSpc2,
|
|
||||||
BkSpc3,
|
|
||||||
Home,
|
|
||||||
Tab,
|
|
||||||
Q,
|
|
||||||
W,
|
|
||||||
E,
|
|
||||||
R,
|
|
||||||
T,
|
|
||||||
Y,
|
|
||||||
U,
|
|
||||||
I,
|
|
||||||
O,
|
|
||||||
P,
|
|
||||||
LBracket,
|
|
||||||
RBracket,
|
|
||||||
BackSlash,
|
|
||||||
PgUp,
|
|
||||||
Caps,
|
|
||||||
A,
|
|
||||||
S,
|
|
||||||
D,
|
|
||||||
F,
|
|
||||||
G,
|
|
||||||
H,
|
|
||||||
J,
|
|
||||||
K,
|
|
||||||
L,
|
|
||||||
SemiColon,
|
|
||||||
Quote,
|
|
||||||
Ret1,
|
|
||||||
Ret2,
|
|
||||||
Ret3,
|
|
||||||
PgDn,
|
|
||||||
LShift,
|
|
||||||
Z,
|
|
||||||
X,
|
|
||||||
C,
|
|
||||||
V,
|
|
||||||
B,
|
|
||||||
N,
|
|
||||||
M,
|
|
||||||
Comma,
|
|
||||||
Period,
|
|
||||||
FwdSlash,
|
|
||||||
Rshift1,
|
|
||||||
Rshift2,
|
|
||||||
Rshift3,
|
|
||||||
End,
|
|
||||||
LCtrl,
|
|
||||||
LFn,
|
|
||||||
Meta,
|
|
||||||
LAlt,
|
|
||||||
Space1,
|
|
||||||
Space2,
|
|
||||||
Space3,
|
|
||||||
Space4,
|
|
||||||
RAlt,
|
|
||||||
PrtSc,
|
|
||||||
RCtrl,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
RFn,
|
|
||||||
}
|
|
||||||
|
|
||||||
use dbus::{ffidisp::Connection, Message};
|
|
||||||
use std::error::Error;
|
|
||||||
use std::{thread, time::Duration};
|
|
||||||
|
|
||||||
/// Simplified way to write a effect block
|
|
||||||
pub struct AuraDbusWriter {
|
|
||||||
connection: Connection,
|
|
||||||
block_time: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuraDbusWriter {
|
|
||||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
|
||||||
Ok(AuraDbusWriter {
|
|
||||||
connection: Connection::new_system()?,
|
|
||||||
block_time: 10,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method must always be called before the very first write to initialise
|
|
||||||
/// the keyboard LED EC in the correct mode
|
|
||||||
pub fn init_effect(&self) -> Result<(), Box<dyn Error>> {
|
|
||||||
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
|
|
||||||
.append1(KeyColourArray::get_init_msg());
|
|
||||||
self.connection.send(msg).unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a single colour block.
|
|
||||||
///
|
|
||||||
/// Intentionally blocks for 10ms after sending to allow the block to
|
|
||||||
/// be written to the keyboard EC. This should not be async.
|
|
||||||
pub fn write_colour_block(
|
|
||||||
&self,
|
|
||||||
key_colour_array: &KeyColourArray,
|
|
||||||
) -> Result<(), Box<dyn Error>> {
|
|
||||||
let group = key_colour_array.get();
|
|
||||||
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")?
|
|
||||||
.append1(&group[0].to_vec())
|
|
||||||
.append1(&group[1].to_vec())
|
|
||||||
.append1(&group[2].to_vec())
|
|
||||||
.append1(&group[3].to_vec())
|
|
||||||
.append1(&group[4].to_vec())
|
|
||||||
.append1(&group[5].to_vec())
|
|
||||||
.append1(&group[6].to_vec())
|
|
||||||
.append1(&group[7].to_vec())
|
|
||||||
.append1(&group[8].to_vec())
|
|
||||||
.append1(&group[9].to_vec());
|
|
||||||
self.connection.send(msg).unwrap();
|
|
||||||
thread::sleep(Duration::from_millis(self.block_time));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_bytes(&self, bytes: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
|
|
||||||
.append1(bytes.to_vec());
|
|
||||||
let r = self.connection.send_with_reply_and_block(msg, 5000)?;
|
|
||||||
if let Some(reply) = r.get1::<&str>() {
|
|
||||||
return Ok(reply.to_owned());
|
|
||||||
}
|
|
||||||
Err(Box::new(dbus::Error::new_custom("name", "message")))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_builtin_mode(
|
|
||||||
&self,
|
|
||||||
mode: &SetAuraBuiltin,
|
|
||||||
) -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
let bytes = <[u8; LED_MSG_LEN]>::from(mode);
|
|
||||||
self.write_bytes(&bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
self.write_bytes(&aura_brightness_bytes(level))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
wireshark_data/rog-star-colour.pcapng
Executable file
BIN
wireshark_data/rog-star-colour.pcapng
Executable file
Binary file not shown.
BIN
wireshark_data/rog-star-random.pcapng
Executable file
BIN
wireshark_data/rog-star-random.pcapng
Executable file
Binary file not shown.
Reference in New Issue
Block a user