mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Polling keyboard in daemon. Split into app/lib
This commit is contained in:
283
rog-lib/Cargo.lock
generated
Normal file
283
rog-lib/Cargo.lock
generated
Normal file
@@ -0,0 +1,283 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "add8dd36d6d34a084220eb9fe216d3e230d52b37c31702e1ffda4fb2d4ef950e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libdbus-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gumdrop"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46571f5d540478cf70d2a42dd0d6d8e9f4b9cc7531544b93311e657b86568a0b"
|
||||
dependencies = [
|
||||
"gumdrop_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gumdrop_derive"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9135df43b1f5d0e333385cb6e7897ecd1a43d7d11b91ac003f4d2c2d2401fdd"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"crc32fast",
|
||||
"rle-decode-fast",
|
||||
"take_mut",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libusb1-sys"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0318f131edc8211a9a3e40133be6fc93f0b686e14f59c6115eab4e7bd794b34"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libflate",
|
||||
"pkg-config",
|
||||
"tar",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||
|
||||
[[package]]
|
||||
name = "rog-core"
|
||||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"dbus",
|
||||
"gumdrop",
|
||||
"rusb",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusb"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d10caa3e5fc7ad1879a679bf16d3304ea10614b8f2f1a1386be4ec942d44062a"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"libc",
|
||||
"libusb1-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "take_mut"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
11
rog-lib/Cargo.toml
Normal file
11
rog-lib/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "rog-lib"
|
||||
version = "0.3.1"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rusb = "0.5"
|
||||
gumdrop = "0.8"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
296
rog-lib/src/aura.rs
Normal file
296
rog-lib/src/aura.rs
Normal file
@@ -0,0 +1,296 @@
|
||||
use crate::core::LED_MSG_LEN;
|
||||
use crate::error::AuraError;
|
||||
use gumdrop::Options;
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Colour(u8, u8, u8);
|
||||
impl Default for Colour {
|
||||
fn default() -> Self {
|
||||
Colour(255, 0, 0)
|
||||
}
|
||||
}
|
||||
impl FromStr for Colour {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() < 6 {
|
||||
return Err(AuraError::ParseColour);
|
||||
}
|
||||
let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?;
|
||||
Ok(Colour(r, g, b))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Speed {
|
||||
Low = 0xe1,
|
||||
Med = 0xeb,
|
||||
High = 0xf5,
|
||||
}
|
||||
impl Default for Speed {
|
||||
fn default() -> Self {
|
||||
Speed::Med
|
||||
}
|
||||
}
|
||||
impl FromStr for Speed {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"low" => Ok(Speed::Low),
|
||||
"med" => Ok(Speed::Med),
|
||||
"high" => Ok(Speed::High),
|
||||
_ => Err(AuraError::ParseSpeed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Direction {
|
||||
Right,
|
||||
Left,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl Default for Direction {
|
||||
fn default() -> Self {
|
||||
Direction::Right
|
||||
}
|
||||
}
|
||||
impl FromStr for Direction {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"right" => Ok(Direction::Right),
|
||||
"up" => Ok(Direction::Up),
|
||||
"down" => Ok(Direction::Down),
|
||||
"left" => Ok(Direction::Left),
|
||||
_ => Err(AuraError::ParseDirection),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Options)]
|
||||
pub struct TwoColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the first RGB value e.g, ff00ff")]
|
||||
colour: Colour,
|
||||
#[options(no_long, meta = "HEX", help = "set the second RGB value e.g, ff00ff")]
|
||||
colour2: Colour,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Options)]
|
||||
pub struct SingleSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||
speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Options)]
|
||||
pub struct SingleColour {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
colour: Colour,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Options)]
|
||||
pub struct SingleSpeedDirection {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(
|
||||
no_long,
|
||||
meta = "DIR",
|
||||
help = "set the direction: up, down, left, right"
|
||||
)]
|
||||
direction: Direction,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Options)]
|
||||
pub struct SingleColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
colour: Colour,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
speed: Speed,
|
||||
}
|
||||
|
||||
/// Byte value for setting the built-in mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Debug, Options)]
|
||||
pub enum SetAuraBuiltin {
|
||||
#[options(help = "set a single static colour")]
|
||||
Stable(SingleColour),
|
||||
#[options(help = "pulse between one or two colours")]
|
||||
Breathe(TwoColourSpeed),
|
||||
#[options(help = "cycle through all colours")]
|
||||
Cycle(SingleSpeed),
|
||||
#[options(help = "rainbow cycling in one of four directions")]
|
||||
Rainbow(SingleSpeedDirection),
|
||||
#[options(help = "random pattern mimicking raindrops")]
|
||||
Rain(SingleColourSpeed),
|
||||
#[options(help = "random pattern of three preset colours")]
|
||||
Random(SingleSpeed),
|
||||
#[options(help = "pressed keys are highlighted to fade")]
|
||||
Highlight(SingleColourSpeed),
|
||||
#[options(help = "pressed keys generate horizontal laser")]
|
||||
Laser(SingleColourSpeed),
|
||||
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||
Ripple(SingleColourSpeed),
|
||||
#[options(help = "set a rapid pulse")]
|
||||
Pulse(SingleColour),
|
||||
#[options(help = "set a vertical line zooming from left")]
|
||||
ThinZoomy(SingleColour),
|
||||
#[options(help = "set a wide vertical line zooming from left")]
|
||||
WideZoomy(SingleColour),
|
||||
}
|
||||
|
||||
impl Default for SetAuraBuiltin {
|
||||
fn default() -> Self {
|
||||
SetAuraBuiltin::Stable(SingleColour {
|
||||
help: false,
|
||||
colour: Colour(255, 0, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses `SetAuraBuiltin` in to packet data
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// Byte 3 sets the mode type:
|
||||
/// - 00 = static
|
||||
/// - 01 = breathe (can set two colours)
|
||||
/// - 02 = cycle (through all colours)
|
||||
/// - 03 = rainbow
|
||||
/// - 04 = rain
|
||||
/// - 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
|
||||
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::Cycle(_) => {
|
||||
msg[3] = 0x02;
|
||||
}
|
||||
SetAuraBuiltin::Rainbow(_) => {
|
||||
msg[3] = 0x03;
|
||||
}
|
||||
SetAuraBuiltin::Rain(_) => {
|
||||
msg[3] = 0x04;
|
||||
}
|
||||
SetAuraBuiltin::Random(_) => {
|
||||
msg[3] = 0x05;
|
||||
}
|
||||
SetAuraBuiltin::Highlight(_) => {
|
||||
msg[3] = 0x06;
|
||||
}
|
||||
SetAuraBuiltin::Laser(_) => {
|
||||
msg[3] = 0x07;
|
||||
}
|
||||
SetAuraBuiltin::Ripple(_) => {
|
||||
msg[3] = 0x08;
|
||||
}
|
||||
SetAuraBuiltin::Pulse(_) => {
|
||||
msg[3] = 0x0a;
|
||||
}
|
||||
SetAuraBuiltin::ThinZoomy(_) => {
|
||||
msg[3] = 0x0b;
|
||||
}
|
||||
SetAuraBuiltin::WideZoomy(_) => {
|
||||
msg[3] = 0x0c;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match mode {
|
||||
SetAuraBuiltin::Rainbow(settings) => {
|
||||
msg[7] = settings.speed as u8;
|
||||
msg[8] = settings.direction as u8;
|
||||
}
|
||||
SetAuraBuiltin::Breathe(settings) => {
|
||||
msg[3] = 0x01;
|
||||
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::Random(settings) => {
|
||||
msg[7] = settings.speed as u8;
|
||||
}
|
||||
SetAuraBuiltin::Rain(settings)
|
||||
| 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;
|
||||
}
|
||||
}
|
||||
msg
|
||||
}
|
||||
}
|
||||
165
rog-lib/src/core.rs
Normal file
165
rog-lib/src/core.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use crate::error::AuraError;
|
||||
use gumdrop::Options;
|
||||
use rusb::{DeviceHandle, Error};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
pub const LED_MSG_LEN: usize = 17;
|
||||
static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
||||
static LED_INIT2: &'static str = "]ASUS Tech.Inc."; // ] == 0x5d
|
||||
static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
||||
static LED_INIT4: &'static str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
||||
static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
||||
|
||||
// Only these two packets must be 17 bytes
|
||||
static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
pub struct LedBrightness {
|
||||
level: u8,
|
||||
}
|
||||
impl LedBrightness {
|
||||
pub fn level(&self) -> u8 {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
impl FromStr for LedBrightness {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"off" => Ok(LedBrightness { level: 0x00 }),
|
||||
"low" => Ok(LedBrightness { level: 0x01 }),
|
||||
"med" => Ok(LedBrightness { level: 0x02 }),
|
||||
"high" => Ok(LedBrightness { level: 0x03 }),
|
||||
_ => {
|
||||
println!("Missing required argument, must be one of:\noff,low,med,high\n");
|
||||
Err(AuraError::ParseBrightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ROG device controller
|
||||
///
|
||||
/// For the GX502GW the LED setup sequence looks like:
|
||||
///
|
||||
/// -` LED_INIT1`
|
||||
/// - `LED_INIT3`
|
||||
/// - `LED_INIT4`
|
||||
/// - `LED_INIT2`
|
||||
/// - `LED_INIT4`
|
||||
pub struct RogCore {
|
||||
handle: DeviceHandle<rusb::GlobalContext>,
|
||||
initialised: bool,
|
||||
led_interface_num: u8,
|
||||
keys_interface_num: u8,
|
||||
}
|
||||
|
||||
impl RogCore {
|
||||
pub fn new() -> Result<RogCore, Error> {
|
||||
let mut handle = RogCore::get_device(0x0B05, 0x1866)?;
|
||||
handle.set_active_configuration(0).unwrap_or(());
|
||||
|
||||
let config = handle.device().config_descriptor(0).unwrap();
|
||||
// Interface with outputs
|
||||
let mut keys_interface_num = 0;
|
||||
let mut led_interface_num = 0;
|
||||
for iface in config.interfaces() {
|
||||
for desc in iface.descriptors() {
|
||||
for endpoint in desc.endpoint_descriptors() {
|
||||
if endpoint.address() == 0x83 {
|
||||
keys_interface_num = desc.interface_number();
|
||||
} else if endpoint.address() == 0x81 {
|
||||
led_interface_num = desc.interface_number();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle.set_auto_detach_kernel_driver(true).unwrap();
|
||||
handle.set_auto_detach_kernel_driver(true).unwrap();
|
||||
|
||||
Ok(RogCore {
|
||||
handle,
|
||||
initialised: false,
|
||||
led_interface_num,
|
||||
keys_interface_num,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_device(vendor: u16, product: u16) -> Result<DeviceHandle<rusb::GlobalContext>, Error> {
|
||||
for device in rusb::devices().unwrap().iter() {
|
||||
let device_desc = device.device_descriptor().unwrap();
|
||||
if device_desc.vendor_id() == vendor && device_desc.product_id() == product {
|
||||
return device.open();
|
||||
}
|
||||
}
|
||||
Err(Error::NoDevice)
|
||||
}
|
||||
|
||||
fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), Error> {
|
||||
self.handle.claim_interface(self.led_interface_num)?;
|
||||
// Declared as a zoomy so that it is hidden
|
||||
let write = |message: &[u8]| {
|
||||
self.handle
|
||||
.write_control(0x21, 0x09, 0x035D, 0, message, Duration::new(0, 5))
|
||||
};
|
||||
|
||||
if !self.initialised {
|
||||
write(&LED_INIT1)?;
|
||||
write(LED_INIT2.as_bytes())?;
|
||||
write(&LED_INIT3)?;
|
||||
write(LED_INIT4.as_bytes())?;
|
||||
write(&LED_INIT5)?;
|
||||
}
|
||||
|
||||
for message in messages {
|
||||
println!("{:x?}", &message);
|
||||
write(*message)?;
|
||||
write(&LED_SET)?;
|
||||
}
|
||||
// Changes won't persist unless apply is set
|
||||
write(&LED_APPLY)?;
|
||||
|
||||
self.handle.release_interface(self.led_interface_num)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn aura_brightness_bytes(brightness: u8) -> Result<[u8; 17], Error> {
|
||||
// TODO: check brightness range
|
||||
let mut bright = [0u8; LED_MSG_LEN];
|
||||
bright[0] = 0x5a;
|
||||
bright[1] = 0xba;
|
||||
bright[2] = 0xc5;
|
||||
bright[3] = 0xc4;
|
||||
bright[4] = brightness;
|
||||
Ok(bright)
|
||||
}
|
||||
|
||||
pub fn aura_set_mode(&mut self, mode: &[u8]) -> Result<(), Error> {
|
||||
let messages = [mode];
|
||||
self.aura_write_messages(&messages)
|
||||
}
|
||||
|
||||
pub fn poll_keyboard(&mut self) -> Result<[u8; 32], Error> {
|
||||
self.handle.claim_interface(self.keys_interface_num)?;
|
||||
|
||||
let mut buf = [0; 32];
|
||||
match self
|
||||
.handle
|
||||
.read_interrupt(0x83, &mut buf, Duration::from_micros(10))
|
||||
{
|
||||
Ok(_) => {
|
||||
self.handle.release_interface(self.keys_interface_num)?;
|
||||
Ok(buf)
|
||||
}
|
||||
Err(err) => match err {
|
||||
//Error::Timeout => {}
|
||||
_ => return Err(err),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
38
rog-lib/src/error.rs
Normal file
38
rog-lib/src/error.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum AuraError {
|
||||
ParseColour,
|
||||
ParseSpeed,
|
||||
ParseDirection,
|
||||
ParseBrightness,
|
||||
PollKeyboard,
|
||||
}
|
||||
|
||||
impl Debug for AuraError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(self.description(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AuraError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(self.description(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for AuraError {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
AuraError::ParseColour => "could not parse colour",
|
||||
AuraError::ParseSpeed => "could not parse speed",
|
||||
AuraError::ParseDirection => "could not parse direction",
|
||||
AuraError::ParseBrightness => "could not parse brightness",
|
||||
AuraError::PollKeyboard => "failed to poll keyboard",
|
||||
}
|
||||
}
|
||||
}
|
||||
3
rog-lib/src/lib.rs
Normal file
3
rog-lib/src/lib.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod aura;
|
||||
pub mod core;
|
||||
mod error;
|
||||
Reference in New Issue
Block a user