mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Merge branch 'fluke/optimising' into 'main'
Massive refactor of led control Closes #53 and #63 See merge request asus-linux/asus-nb-ctrl!36
This commit is contained in:
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Changed
|
||||||
|
- Refactor keyboard LED handling
|
||||||
|
- Added --list for profiles (Thanks @aqez)
|
||||||
|
### Broken
|
||||||
|
- Per-key LED modes, which need thinking about how to go ahead with for future
|
||||||
|
|
||||||
# [3.1.7] - 2021-03-11
|
# [3.1.7] - 2021-03-11
|
||||||
### Changed
|
### Changed
|
||||||
- Refactor many parts of daemon
|
- Refactor many parts of daemon
|
||||||
|
|||||||
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -33,7 +33,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.3"
|
version = "3.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"daemon",
|
"daemon",
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
@@ -196,7 +196,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.1.7"
|
version = "3.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"intel-pstate",
|
"intel-pstate",
|
||||||
@@ -504,9 +504,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.89"
|
version = "0.2.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6"
|
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libudev-sys"
|
name = "libudev-sys"
|
||||||
@@ -908,7 +908,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_types"
|
name = "rog_types"
|
||||||
version = "3.0.0"
|
version = "3.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
let x = do_notif(&format!(
|
let x = do_notif(&format!(
|
||||||
"Keyboard LED mode changed to {}",
|
"Keyboard LED mode changed to {}",
|
||||||
<&str>::from(&ledmode)
|
ledmode.mode_name()
|
||||||
))?;
|
))?;
|
||||||
last_led_notif = Some(x);
|
last_led_notif = Some(x);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.3"
|
version = "3.1.4"
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
use std::collections::LinkedList;
|
use std::collections::LinkedList;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{Key, KeyColourArray};
|
use rog_types::aura_perkey::{Key, KeyColourArray};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
331
asusctl/src/aura_cli.rs
Normal file
331
asusctl/src/aura_cli.rs
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
use rog_types::{
|
||||||
|
aura_modes::{Colour, Direction, Speed, AuraEffect, AuraModeNum, AuraZone},
|
||||||
|
error::AuraError,
|
||||||
|
};
|
||||||
|
use gumdrop::Options;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub struct LedBrightness {
|
||||||
|
level: Option<u8>,
|
||||||
|
}
|
||||||
|
impl LedBrightness {
|
||||||
|
pub fn new(level: Option<u8>) -> Self {
|
||||||
|
LedBrightness { level }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn level(&self) -> Option<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: Some(0x00) }),
|
||||||
|
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||||
|
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||||
|
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||||
|
_ => {
|
||||||
|
print!("Invalid argument, must be one of: off, low, med, high");
|
||||||
|
Err(AuraError::ParseBrightness)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ToString for LedBrightness {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let s = match self.level {
|
||||||
|
Some(0x00) => "low",
|
||||||
|
Some(0x01) => "med",
|
||||||
|
Some(0x02) => "high",
|
||||||
|
_ => "unknown",
|
||||||
|
};
|
||||||
|
s.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct SingleSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct SingleSpeedDirection {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
||||||
|
pub direction: Direction,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct SingleColour {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct SingleColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct TwoColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct MultiColour {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour4: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct MultiColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour4: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Byte value for setting the built-in mode.
|
||||||
|
///
|
||||||
|
/// Enum corresponds to the required integer value
|
||||||
|
#[derive(Options)]
|
||||||
|
pub enum SetAuraBuiltin {
|
||||||
|
#[options(help = "set a single static colour")]
|
||||||
|
Static(SingleColour),
|
||||||
|
#[options(help = "pulse between one or two colours")]
|
||||||
|
Breathe(TwoColourSpeed),
|
||||||
|
#[options(help = "strobe through all colours")]
|
||||||
|
Strobe(SingleSpeed),
|
||||||
|
#[options(help = "rainbow cycling in one of four directions")]
|
||||||
|
Rainbow(SingleSpeedDirection),
|
||||||
|
#[options(help = "rain pattern mimicking raindrops")]
|
||||||
|
Star(TwoColourSpeed),
|
||||||
|
#[options(help = "rain pattern of three preset colours")]
|
||||||
|
Rain(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")]
|
||||||
|
Comet(SingleColour),
|
||||||
|
#[options(help = "set a wide vertical line zooming from left")]
|
||||||
|
Flash(SingleColour),
|
||||||
|
#[options(help = "4-zone multi-colour")]
|
||||||
|
MultiStatic(MultiColour),
|
||||||
|
#[options(help = "4-zone multi-colour breathing")]
|
||||||
|
MultiBreathe(MultiColourSpeed),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SetAuraBuiltin {
|
||||||
|
fn default() -> Self {
|
||||||
|
SetAuraBuiltin::Static(SingleColour::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl From<&SingleColour> for AuraEffect {
|
||||||
|
fn from(aura: &SingleColour) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &SingleSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
speed: aura.speed,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleColourSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &SingleColourSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
speed: aura.speed,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&TwoColourSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &TwoColourSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
colour2: aura.colour2,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleSpeedDirection> for AuraEffect {
|
||||||
|
fn from(aura: &SingleSpeedDirection) -> Self {
|
||||||
|
Self {
|
||||||
|
speed: aura.speed,
|
||||||
|
direction: aura.direction,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SetAuraBuiltin> for AuraEffect {
|
||||||
|
fn from(aura: &SetAuraBuiltin) -> Self {
|
||||||
|
match aura {
|
||||||
|
SetAuraBuiltin::Static(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Static;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Breathe(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Breathe;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Strobe(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Strobe;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Rainbow(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Rainbow;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Star(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Star;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Rain(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Rain;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Highlight(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Highlight;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Laser(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Laser;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Ripple(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Ripple;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Pulse(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Pulse;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Comet(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Comet;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Flash(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Flash;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
_ => AuraEffect::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SetAuraBuiltin> for Vec<AuraEffect> {
|
||||||
|
fn from(aura: &SetAuraBuiltin) -> Vec<AuraEffect> {
|
||||||
|
let mut zones = vec![AuraEffect::default(); 4];
|
||||||
|
match aura {
|
||||||
|
SetAuraBuiltin::MultiStatic(data) => {
|
||||||
|
zones[0].mode = AuraModeNum::Static;
|
||||||
|
zones[0].zone = AuraZone::One;
|
||||||
|
zones[0].colour1 = data.colour1;
|
||||||
|
|
||||||
|
zones[1].mode = AuraModeNum::Static;
|
||||||
|
zones[1].zone = AuraZone::Two;
|
||||||
|
zones[1].colour1 = data.colour2;
|
||||||
|
|
||||||
|
zones[2].mode = AuraModeNum::Static;
|
||||||
|
zones[2].zone = AuraZone::Three;
|
||||||
|
zones[2].colour1 = data.colour3;
|
||||||
|
|
||||||
|
zones[3].mode = AuraModeNum::Static;
|
||||||
|
zones[3].zone = AuraZone::Four;
|
||||||
|
zones[3].colour1 = data.colour4;
|
||||||
|
},
|
||||||
|
SetAuraBuiltin::MultiBreathe(data) => {
|
||||||
|
zones[0].mode = AuraModeNum::Breathe;
|
||||||
|
zones[0].zone = AuraZone::One;
|
||||||
|
zones[0].colour1 = data.colour1;
|
||||||
|
zones[0].speed = data.speed;
|
||||||
|
|
||||||
|
zones[1].mode = AuraModeNum::Breathe;
|
||||||
|
zones[1].zone = AuraZone::Two;
|
||||||
|
zones[1].colour1 = data.colour2;
|
||||||
|
zones[1].speed = data.speed;
|
||||||
|
|
||||||
|
zones[2].mode = AuraModeNum::Breathe;
|
||||||
|
zones[2].zone = AuraZone::Three;
|
||||||
|
zones[2].colour1 = data.colour3;
|
||||||
|
zones[2].speed = data.speed;
|
||||||
|
|
||||||
|
zones[3].mode = AuraModeNum::Breathe;
|
||||||
|
zones[3].zone = AuraZone::Four;
|
||||||
|
zones[3].colour1 = data.colour4;
|
||||||
|
zones[3].speed = data.speed;
|
||||||
|
}
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
zones
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
mod aura_cli;
|
||||||
|
|
||||||
use daemon::{
|
use daemon::{
|
||||||
ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions,
|
ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions,
|
||||||
ctrl_rog_bios::RogBiosSupportedFunctions, ctrl_supported::SupportedFunctions,
|
ctrl_rog_bios::RogBiosSupportedFunctions, ctrl_supported::SupportedFunctions,
|
||||||
@@ -6,14 +8,15 @@ use gumdrop::{Opt, Options};
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
||||||
aura_modes::AuraModes,
|
aura_modes::{AuraEffect, AuraModeNum},
|
||||||
cli_options::{AniMeActions, AniMeStatusValue, LedBrightness, SetAuraBuiltin},
|
cli_options::{AniMeActions, AniMeStatusValue},
|
||||||
gfx_vendors::GfxVendors,
|
gfx_vendors::GfxVendors,
|
||||||
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
||||||
};
|
};
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use yansi_term::Colour::Green;
|
use yansi_term::Colour::Green;
|
||||||
use yansi_term::Colour::Red;
|
use yansi_term::Colour::Red;
|
||||||
|
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||||
|
|
||||||
#[derive(Default, Options)]
|
#[derive(Default, Options)]
|
||||||
struct CLIStart {
|
struct CLIStart {
|
||||||
@@ -199,7 +202,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let level = dbus.proxies().led().get_led_brightness()?;
|
let level = dbus.proxies().led().get_led_brightness()?;
|
||||||
println!("Current keyboard led brightness: {}", level.to_string());
|
println!("Current keyboard led brightness: {}", level.to_string());
|
||||||
}
|
}
|
||||||
Some(level) => dbus.proxies().led().set_brightness(level)?,
|
Some(level) => dbus.proxies().led().set_led_brightness(level)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,9 +328,12 @@ fn handle_led_mode(
|
|||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
for (_, command) in commands.iter().enumerate().filter(|(mode_num, _)| {
|
for command in commands.iter().filter(|mode| {
|
||||||
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
||||||
return modes.contains(&(*mode_num as u8));
|
return modes.contains(&<AuraModeNum>::from(mode.as_str()));
|
||||||
|
}
|
||||||
|
if supported.multizone_led_mode {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}) {
|
}) {
|
||||||
@@ -351,9 +357,20 @@ fn handle_led_mode(
|
|||||||
println!("{}", mode.self_usage());
|
println!("{}", mode.self_usage());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
dbus.proxies()
|
match mode {
|
||||||
.led()
|
SetAuraBuiltin::MultiStatic(_) | SetAuraBuiltin::MultiBreathe(_) => {
|
||||||
.set_led_mode(&<AuraModes>::from(mode))?;
|
let zones = <Vec<AuraEffect>>::from(mode);
|
||||||
|
for eff in zones {
|
||||||
|
dbus.proxies()
|
||||||
|
.led()
|
||||||
|
.set_led_mode(&eff)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => dbus
|
||||||
|
.proxies()
|
||||||
|
.led()
|
||||||
|
.set_led_mode(&<AuraEffect>::from(mode))?,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.1.7"
|
version = "3.2.0"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_fan_curve::Curve;
|
use rog_fan_curve::Curve;
|
||||||
use rog_types::{aura_modes::AuraModes, gfx_vendors::GfxVendors};
|
use rog_types::gfx_vendors::GfxVendors;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
@@ -10,6 +10,7 @@ use crate::config_old::*;
|
|||||||
use crate::VERSION;
|
use crate::VERSION;
|
||||||
|
|
||||||
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
||||||
|
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@@ -20,9 +21,6 @@ pub struct Config {
|
|||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub curr_fan_mode: u8,
|
pub curr_fan_mode: u8,
|
||||||
pub bat_charge_limit: u8,
|
pub bat_charge_limit: u8,
|
||||||
pub kbd_led_brightness: u8,
|
|
||||||
pub kbd_backlight_mode: u8,
|
|
||||||
pub kbd_backlight_modes: Vec<AuraModes>,
|
|
||||||
pub power_profiles: BTreeMap<String, Profile>,
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +38,6 @@ impl Default for Config {
|
|||||||
toggle_profiles: vec!["normal".into(), "boost".into(), "silent".into()],
|
toggle_profiles: vec!["normal".into(), "boost".into(), "silent".into()],
|
||||||
curr_fan_mode: 0,
|
curr_fan_mode: 0,
|
||||||
bat_charge_limit: 100,
|
bat_charge_limit: 100,
|
||||||
kbd_led_brightness: 1,
|
|
||||||
kbd_backlight_mode: 0,
|
|
||||||
kbd_backlight_modes: Vec::new(),
|
|
||||||
power_profiles: pwr,
|
power_profiles: pwr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +45,7 @@ impl Default for Config {
|
|||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// `load` will attempt to read the config, and panic if the dir is missing
|
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||||
pub fn load(supported_led_modes: &[u8]) -> Self {
|
pub fn load() -> Self {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
@@ -65,10 +60,15 @@ impl Config {
|
|||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
if read_len == 0 {
|
if read_len == 0 {
|
||||||
return Config::create_default(&mut file, &supported_led_modes);
|
return Config::create_default(&mut file);
|
||||||
} else {
|
} else {
|
||||||
if let Ok(data) = serde_json::from_str(&buf) {
|
if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
return data;
|
return data;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<ConfigV317>(&buf) {
|
||||||
|
let config = data.into_current();
|
||||||
|
config.write();
|
||||||
|
info!("Updated config version to: {}", VERSION);
|
||||||
|
return config;
|
||||||
} else if let Ok(data) = serde_json::from_str::<ConfigV301>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<ConfigV301>(&buf) {
|
||||||
let config = data.into_current();
|
let config = data.into_current();
|
||||||
config.write();
|
config.write();
|
||||||
@@ -89,17 +89,11 @@ impl Config {
|
|||||||
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Config::create_default(&mut file, &supported_led_modes)
|
Config::create_default(&mut file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self {
|
fn create_default(file: &mut File) -> Self {
|
||||||
// create a default config here
|
let config = Config::default();
|
||||||
let mut config = Config::default();
|
|
||||||
|
|
||||||
for n in supported_led_modes {
|
|
||||||
config.kbd_backlight_modes.push(AuraModes::from(*n))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should be okay to unwrap this as is since it is a Default
|
// Should be okay to unwrap this as is since it is a Default
|
||||||
let json = serde_json::to_string_pretty(&config).unwrap();
|
let json = serde_json::to_string_pretty(&config).unwrap();
|
||||||
file.write_all(json.as_bytes())
|
file.write_all(json.as_bytes())
|
||||||
@@ -141,26 +135,6 @@ impl Config {
|
|||||||
file.write_all(json.as_bytes())
|
file.write_all(json.as_bytes())
|
||||||
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mode_data(&mut self, mode: AuraModes) {
|
|
||||||
let byte: u8 = (&mode).into();
|
|
||||||
for (index, n) in self.kbd_backlight_modes.iter().enumerate() {
|
|
||||||
if byte == u8::from(n) {
|
|
||||||
// Consume it, OMNOMNOMNOM
|
|
||||||
self.kbd_backlight_modes[index] = mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_led_mode_data(&self, num: u8) -> Option<&AuraModes> {
|
|
||||||
for mode in &self.kbd_backlight_modes {
|
|
||||||
if u8::from(mode) == num {
|
|
||||||
return Some(mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
|||||||
124
daemon/src/config_aura.rs
Normal file
124
daemon/src/config_aura.rs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
use crate::laptops::LaptopLedData;
|
||||||
|
use log::{error, warn};
|
||||||
|
use rog_types::aura_modes::{AuraEffect, AuraModeNum, AuraMultiZone, AuraZone};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AuraConfig {
|
||||||
|
pub brightness: u8,
|
||||||
|
pub current_mode: AuraModeNum,
|
||||||
|
pub builtins: BTreeMap<AuraModeNum, AuraEffect>,
|
||||||
|
pub multizone: Option<AuraMultiZone>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AuraConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
AuraConfig {
|
||||||
|
brightness: 1,
|
||||||
|
current_mode: AuraModeNum::Static,
|
||||||
|
builtins: BTreeMap::new(),
|
||||||
|
multizone: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraConfig {
|
||||||
|
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||||
|
pub fn load(supported_led_modes: &LaptopLedData) -> Self {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&AURA_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"The file {} or directory /etc/asusd/ is missing",
|
||||||
|
AURA_CONFIG_PATH
|
||||||
|
)
|
||||||
|
}); // okay to cause panic here
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
|
if read_len == 0 {
|
||||||
|
return AuraConfig::create_default(&mut file, &supported_led_modes);
|
||||||
|
} else {
|
||||||
|
if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
warn!("Could not deserialise {}", AURA_CONFIG_PATH);
|
||||||
|
panic!("Please remove {} then restart asusd", AURA_CONFIG_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuraConfig::create_default(&mut file, &supported_led_modes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_default(file: &mut File, support_data: &LaptopLedData) -> Self {
|
||||||
|
// create a default config here
|
||||||
|
let mut config = AuraConfig::default();
|
||||||
|
|
||||||
|
for n in &support_data.standard {
|
||||||
|
config
|
||||||
|
.builtins
|
||||||
|
.insert(*n, AuraEffect::default_with_mode(*n));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be okay to unwrap this as is since it is a Default
|
||||||
|
let json = serde_json::to_string(&config).unwrap();
|
||||||
|
file.write_all(json.as_bytes())
|
||||||
|
.unwrap_or_else(|_| panic!("Could not write {}", AURA_CONFIG_PATH));
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self) {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(&AURA_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|err| panic!("Error reading {}: {}", AURA_CONFIG_PATH, err));
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
|
if l == 0 {
|
||||||
|
warn!("File is empty {}", AURA_CONFIG_PATH);
|
||||||
|
} else {
|
||||||
|
let x: AuraConfig = serde_json::from_str(&buf)
|
||||||
|
.unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH));
|
||||||
|
*self = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) {
|
||||||
|
let mut file = File::create(AURA_CONFIG_PATH).expect("Couldn't overwrite config");
|
||||||
|
let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed");
|
||||||
|
file.write_all(json.as_bytes())
|
||||||
|
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Multipurpose, will accecpt AuraEffect with zones and put in the correct store
|
||||||
|
pub fn set_builtin(&mut self, effect: AuraEffect) {
|
||||||
|
match effect.zone() {
|
||||||
|
AuraZone::None => {
|
||||||
|
self.builtins.insert(*effect.mode(), effect);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(multi) = self.multizone.as_mut() {
|
||||||
|
multi.set(effect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_multizone(&self, aura_type: AuraModeNum) -> Option<&[AuraEffect; 4]> {
|
||||||
|
if let Some(multi) = &self.multizone {
|
||||||
|
if aura_type == AuraModeNum::Static {
|
||||||
|
return Some(multi.static_());
|
||||||
|
} else if aura_type == AuraModeNum::Breathe {
|
||||||
|
return Some(multi.breathe());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use rog_types::{aura_modes::AuraModes, gfx_vendors::GfxVendors};
|
use rog_types::{aura_modes::AuraEffect, gfx_vendors::GfxVendors};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::config::{Config, Profile};
|
use crate::config::{Config, Profile};
|
||||||
|
|
||||||
/// for parsing old v2.1.2 config
|
/// for parsing old v2.1.2 config
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub(crate) struct ConfigV212 {
|
pub(crate) struct ConfigV212 {
|
||||||
gfx_managed: bool,
|
gfx_managed: bool,
|
||||||
@@ -15,7 +16,7 @@ pub(crate) struct ConfigV212 {
|
|||||||
power_profile: u8,
|
power_profile: u8,
|
||||||
kbd_led_brightness: u8,
|
kbd_led_brightness: u8,
|
||||||
kbd_backlight_mode: u8,
|
kbd_backlight_mode: u8,
|
||||||
kbd_backlight_modes: Vec<AuraModes>,
|
kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigV212 {
|
impl ConfigV212 {
|
||||||
@@ -27,15 +28,13 @@ impl ConfigV212 {
|
|||||||
toggle_profiles: self.toggle_profiles,
|
toggle_profiles: self.toggle_profiles,
|
||||||
curr_fan_mode: self.power_profile,
|
curr_fan_mode: self.power_profile,
|
||||||
bat_charge_limit: self.bat_charge_limit,
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
kbd_led_brightness: self.kbd_led_brightness,
|
|
||||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
|
||||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
|
||||||
power_profiles: self.power_profiles,
|
power_profiles: self.power_profiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// for parsing old v2.2.2 config
|
/// for parsing old v2.2.2 config
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub(crate) struct ConfigV222 {
|
pub(crate) struct ConfigV222 {
|
||||||
gfx_managed: bool,
|
gfx_managed: bool,
|
||||||
@@ -46,7 +45,7 @@ pub(crate) struct ConfigV222 {
|
|||||||
power_profile: u8,
|
power_profile: u8,
|
||||||
kbd_led_brightness: u8,
|
kbd_led_brightness: u8,
|
||||||
kbd_backlight_mode: u8,
|
kbd_backlight_mode: u8,
|
||||||
kbd_backlight_modes: Vec<AuraModes>,
|
kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigV222 {
|
impl ConfigV222 {
|
||||||
@@ -58,14 +57,12 @@ impl ConfigV222 {
|
|||||||
toggle_profiles: self.toggle_profiles,
|
toggle_profiles: self.toggle_profiles,
|
||||||
curr_fan_mode: self.power_profile,
|
curr_fan_mode: self.power_profile,
|
||||||
bat_charge_limit: self.bat_charge_limit,
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
kbd_led_brightness: self.kbd_led_brightness,
|
|
||||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
|
||||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
|
||||||
power_profiles: self.power_profiles,
|
power_profiles: self.power_profiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// for parsing old v3.0.1 config
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub(crate) struct ConfigV301 {
|
pub(crate) struct ConfigV301 {
|
||||||
pub gfx_managed: bool,
|
pub gfx_managed: bool,
|
||||||
@@ -78,7 +75,7 @@ pub(crate) struct ConfigV301 {
|
|||||||
pub bat_charge_limit: u8,
|
pub bat_charge_limit: u8,
|
||||||
pub kbd_led_brightness: u8,
|
pub kbd_led_brightness: u8,
|
||||||
pub kbd_backlight_mode: u8,
|
pub kbd_backlight_mode: u8,
|
||||||
pub kbd_backlight_modes: Vec<AuraModes>,
|
pub kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
pub power_profiles: BTreeMap<String, Profile>,
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +88,37 @@ impl ConfigV301 {
|
|||||||
toggle_profiles: self.toggle_profiles,
|
toggle_profiles: self.toggle_profiles,
|
||||||
curr_fan_mode: self.curr_fan_mode,
|
curr_fan_mode: self.curr_fan_mode,
|
||||||
bat_charge_limit: self.bat_charge_limit,
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
kbd_led_brightness: self.kbd_led_brightness,
|
power_profiles: self.power_profiles,
|
||||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
}
|
||||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// for parsing old v3.1.7 config
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub(crate) struct ConfigV317 {
|
||||||
|
pub gfx_mode: GfxVendors,
|
||||||
|
pub gfx_managed: bool,
|
||||||
|
pub active_profile: String,
|
||||||
|
pub toggle_profiles: Vec<String>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub curr_fan_mode: u8,
|
||||||
|
pub bat_charge_limit: u8,
|
||||||
|
pub kbd_led_brightness: u8,
|
||||||
|
pub kbd_backlight_mode: u8,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub kbd_backlight_modes: Option<bool>,
|
||||||
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV317 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
active_profile: self.active_profile,
|
||||||
|
toggle_profiles: self.toggle_profiles,
|
||||||
|
curr_fan_mode: self.curr_fan_mode,
|
||||||
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
power_profiles: self.power_profiles,
|
power_profiles: self.power_profiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ trait Dbus {
|
|||||||
impl Dbus for CtrlGraphics {
|
impl Dbus for CtrlGraphics {
|
||||||
fn vendor(&self) -> String {
|
fn vendor(&self) -> String {
|
||||||
self.get_gfx_mode()
|
self.get_gfx_mode()
|
||||||
.map(|gfx| gfx.into())
|
.map(|gfx| (<&str>::from(gfx)).into())
|
||||||
.unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
.unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ impl CtrlGraphics {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_modprobe_conf() -> Result<(), RogError> {
|
fn write_modprobe_conf(content: &[u8]) -> Result<(), RogError> {
|
||||||
info!("GFX: Writing {}", MODPROBE_PATH);
|
info!("GFX: Writing {}", MODPROBE_PATH);
|
||||||
|
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
@@ -248,7 +248,7 @@ impl CtrlGraphics {
|
|||||||
.open(MODPROBE_PATH)
|
.open(MODPROBE_PATH)
|
||||||
.map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
|
.map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
file.write_all(MODPROBE_BASE)
|
file.write_all(content)
|
||||||
.and_then(|_| file.sync_all())
|
.and_then(|_| file.sync_all())
|
||||||
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
@@ -393,7 +393,14 @@ impl CtrlGraphics {
|
|||||||
bus: &PciBus,
|
bus: &PciBus,
|
||||||
) -> Result<(), RogError> {
|
) -> Result<(), RogError> {
|
||||||
Self::write_xorg_conf(vendor)?;
|
Self::write_xorg_conf(vendor)?;
|
||||||
Self::write_modprobe_conf()?; // TODO: Not required here, should put in startup?
|
// Write different modprobe to enable boot control to work
|
||||||
|
match vendor {
|
||||||
|
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||||
|
Self::write_modprobe_conf(MODPROBE_BASE)?
|
||||||
|
}
|
||||||
|
// GfxVendors::Compute => {}
|
||||||
|
GfxVendors::Integrated => Self::write_modprobe_conf(MODPROBE_INTEGRATED)?,
|
||||||
|
}
|
||||||
|
|
||||||
// Rescan before doing remove or add drivers
|
// Rescan before doing remove or add drivers
|
||||||
bus.rescan()
|
bus.rescan()
|
||||||
@@ -408,8 +415,6 @@ impl CtrlGraphics {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: compute mode, needs different setup
|
|
||||||
// GfxVendors::Compute => {}
|
|
||||||
GfxVendors::Integrated => {
|
GfxVendors::Integrated => {
|
||||||
for driver in NVIDIA_DRIVERS.iter() {
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ options nvidia NVreg_DynamicPowerManagement=0x02
|
|||||||
options nvidia-drm modeset=1
|
options nvidia-drm modeset=1
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by asusd
|
||||||
|
blacklist i2c_nvidia_gpu
|
||||||
|
blacklist nvidia
|
||||||
|
blacklist nvidia-drm
|
||||||
|
blacklist nvidia-modeset
|
||||||
|
blacklist nouveau
|
||||||
|
alias nouveau off
|
||||||
|
"#;
|
||||||
|
|
||||||
const XORG_FILE: &str = "90-nvidia-primary.conf";
|
const XORG_FILE: &str = "90-nvidia-primary.conf";
|
||||||
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
|
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
|
||||||
|
|
||||||
@@ -29,8 +38,7 @@ Section "OutputClass"
|
|||||||
Identifier "nvidia"
|
Identifier "nvidia"
|
||||||
MatchDriver "nvidia-drm"
|
MatchDriver "nvidia-drm"
|
||||||
Driver "nvidia"
|
Driver "nvidia"
|
||||||
Option "AllowEmptyInitialConfiguration"
|
Option "AllowEmptyInitialConfiguration" "true""#;
|
||||||
Option "AllowExternalGpus""#;
|
|
||||||
|
|
||||||
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
||||||
Option "PrimaryGPU" "true""#;
|
Option "PrimaryGPU" "true""#;
|
||||||
|
|||||||
@@ -5,15 +5,13 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|||||||
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
|
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config_aura::AuraConfig,
|
||||||
error::RogError,
|
error::RogError,
|
||||||
laptops::{match_laptop, HELP_ADDRESS},
|
laptops::{match_laptop, LaptopLedData, HELP_ADDRESS},
|
||||||
};
|
};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
aura_brightness_bytes,
|
aura_modes::{AuraEffect, AuraModeNum},
|
||||||
aura_modes::{AuraModes, PER_KEY},
|
|
||||||
fancy::KeyColourArray,
|
|
||||||
LED_MSG_LEN,
|
LED_MSG_LEN,
|
||||||
};
|
};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
@@ -29,7 +27,8 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LedSupportedFunctions {
|
pub struct LedSupportedFunctions {
|
||||||
pub brightness_set: bool,
|
pub brightness_set: bool,
|
||||||
pub stock_led_modes: Option<Vec<u8>>,
|
pub stock_led_modes: Option<Vec<AuraModeNum>>,
|
||||||
|
pub multizone_led_mode: bool,
|
||||||
pub per_key_led_mode: bool,
|
pub per_key_led_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,21 +38,20 @@ impl GetSupported for CtrlKbdBacklight {
|
|||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
// let mode = <&str>::from(&<AuraModes>::from(*mode));
|
// let mode = <&str>::from(&<AuraModes>::from(*mode));
|
||||||
let mut stock_led_modes = None;
|
let mut stock_led_modes = None;
|
||||||
let mut per_key_led_mode = false;
|
let multizone_led_mode = false;
|
||||||
|
let per_key_led_mode = false;
|
||||||
if let Some(laptop) = match_laptop() {
|
if let Some(laptop) = match_laptop() {
|
||||||
let modes = laptop.supported_modes().to_vec();
|
stock_led_modes = if laptop.supported_modes().standard.is_empty() {
|
||||||
if modes.contains(&PER_KEY) {
|
None
|
||||||
per_key_led_mode = true;
|
|
||||||
let modes = modes.iter().filter(|x| **x != PER_KEY).copied().collect();
|
|
||||||
stock_led_modes = Some(modes);
|
|
||||||
} else {
|
} else {
|
||||||
stock_led_modes = Some(modes);
|
Some(laptop.supported_modes().standard.clone())
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LedSupportedFunctions {
|
LedSupportedFunctions {
|
||||||
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_ok(),
|
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_ok(),
|
||||||
stock_led_modes,
|
stock_led_modes,
|
||||||
|
multizone_led_mode,
|
||||||
per_key_led_mode,
|
per_key_led_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,9 +62,9 @@ pub struct CtrlKbdBacklight {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
kbd_node: Option<String>,
|
kbd_node: Option<String>,
|
||||||
pub bright_node: String,
|
pub bright_node: String,
|
||||||
supported_modes: Vec<u8>,
|
supported_modes: LaptopLedData,
|
||||||
flip_effect_write: bool,
|
flip_effect_write: bool,
|
||||||
config: Arc<Mutex<Config>>,
|
config: AuraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbusKbdBacklight {
|
pub struct DbusKbdBacklight {
|
||||||
@@ -96,48 +94,42 @@ impl crate::ZbusAdd for DbusKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The main interface for changing, reading, or notfying signals
|
||||||
|
///
|
||||||
|
/// LED commands are split between Brightness, Modes, Per-Key
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl DbusKbdBacklight {
|
impl DbusKbdBacklight {
|
||||||
fn set_led_mode(&mut self, data: String) {
|
fn set_brightness(&mut self, brightness: u8) {
|
||||||
if let Ok(data) = serde_json::from_str(&data) {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
ctrl.set_brightness(brightness)
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
.map_err(|err| warn!("{}", err))
|
||||||
match &data {
|
.ok();
|
||||||
AuraModes::PerKey(_) => {
|
}
|
||||||
ctrl.do_command(data, &mut cfg)
|
}
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
fn set_led_mode(&mut self, effect: AuraEffect) {
|
||||||
_ => {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(json) = serde_json::to_string(&data) {
|
let mode_name = effect.mode_name();
|
||||||
match ctrl.do_command(data, &mut cfg) {
|
match ctrl.do_command(effect) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.notify_led(&json).ok();
|
self.notify_led(&mode_name).ok();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_led_mode(&self) {
|
fn next_led_mode(&self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
ctrl.toggle_mode(false)
|
||||||
ctrl.toggle_mode(false, &mut cfg)
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
|
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
self.notify_led(&json)
|
self.notify_led(&json)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,40 +137,24 @@ impl DbusKbdBacklight {
|
|||||||
|
|
||||||
fn prev_led_mode(&self) {
|
fn prev_led_mode(&self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
ctrl.toggle_mode(true)
|
||||||
ctrl.toggle_mode(true, &mut cfg)
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
|
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
self.notify_led(&json)
|
self.notify_led(&json)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current mode data
|
/// Return the current mode data
|
||||||
|
#[dbus_interface(property)]
|
||||||
fn led_mode(&self) -> String {
|
fn led_mode(&self) -> String {
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
|
||||||
"SetKeyBacklight could not deserialise".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a list of available modes
|
|
||||||
fn led_modes(&self) -> String {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
if let Ok(json) = serde_json::to_string(&cfg.kbd_backlight_modes) {
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,14 +163,25 @@ impl DbusKbdBacklight {
|
|||||||
"SetKeyBacklight could not deserialise".to_string()
|
"SetKeyBacklight could not deserialise".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current LED brightness
|
/// Return a list of available modes
|
||||||
fn led_brightness(&self) -> i8 {
|
#[dbus_interface(property)]
|
||||||
|
fn led_modes(&self) -> String {
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
if let Ok(json) = serde_json::to_string(&ctrl.config.builtins) {
|
||||||
return cfg.kbd_led_brightness as i8;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
warn!("SetKeyBacklight could not deserialise");
|
||||||
|
"SetKeyBacklight could not serialise".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the current LED brightness
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
fn led_brightness(&self) -> i8 {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1);
|
||||||
|
}
|
||||||
|
warn!("SetKeyBacklight could not serialise");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,44 +192,40 @@ impl DbusKbdBacklight {
|
|||||||
impl crate::Reloadable for CtrlKbdBacklight {
|
impl crate::Reloadable for CtrlKbdBacklight {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
// set current mode (if any)
|
// set current mode (if any)
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if self.supported_modes.standard.len() > 1 {
|
||||||
if self.supported_modes.len() > 1 {
|
let current_mode = self.config.current_mode;
|
||||||
if self.supported_modes.contains(&config.kbd_backlight_mode) {
|
if self.supported_modes.standard.contains(&(current_mode)) {
|
||||||
let mode = config
|
let mode = self
|
||||||
.get_led_mode_data(config.kbd_backlight_mode)
|
.config
|
||||||
.ok_or(RogError::NotSupported)?
|
.builtins
|
||||||
.to_owned();
|
.get(¤t_mode)
|
||||||
self.write_mode(&mode)?;
|
.ok_or(RogError::NotSupported)?
|
||||||
info!("Reloaded last used mode");
|
.to_owned();
|
||||||
} else {
|
self.write_mode(&mode)?;
|
||||||
warn!(
|
info!("Reloaded last used mode");
|
||||||
"An unsupported mode was set: {}, reset to first mode available",
|
} else {
|
||||||
<&str>::from(&<AuraModes>::from(config.kbd_backlight_mode))
|
warn!(
|
||||||
);
|
"An unsupported mode was set: {}, reset to first mode available",
|
||||||
for (idx, mode) in config.kbd_backlight_modes.iter_mut().enumerate() {
|
<&str>::from(&self.config.current_mode)
|
||||||
if !self.supported_modes.contains(&mode.into()) {
|
);
|
||||||
config.kbd_backlight_modes.remove(idx);
|
self.config.builtins.remove(¤t_mode);
|
||||||
config.write();
|
self.config.current_mode = AuraModeNum::Static;
|
||||||
break;
|
// TODO: do a recursive call with a boxed dyn future later
|
||||||
}
|
let mode = self
|
||||||
}
|
.config
|
||||||
config.kbd_backlight_mode = self.supported_modes[0];
|
.builtins
|
||||||
// TODO: do a recursive call with a boxed dyn future later
|
.get(¤t_mode)
|
||||||
let mode = config
|
.ok_or(RogError::NotSupported)?
|
||||||
.get_led_mode_data(config.kbd_backlight_mode)
|
.to_owned();
|
||||||
.ok_or(RogError::NotSupported)?
|
self.write_mode(&mode)?;
|
||||||
.to_owned();
|
info!("Reloaded last used mode");
|
||||||
self.write_mode(&mode)?;
|
|
||||||
info!("Reloaded last used mode");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload brightness
|
|
||||||
let bright = config.kbd_led_brightness;
|
|
||||||
let bytes = aura_brightness_bytes(bright);
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
info!("Reloaded last used brightness");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload brightness
|
||||||
|
let bright = self.config.brightness;
|
||||||
|
self.set_brightness(bright)?;
|
||||||
|
info!("Reloaded last used brightness");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,12 +245,10 @@ impl crate::CtrlTask for CtrlKbdBacklight {
|
|||||||
file.read_exact(&mut buf)
|
file.read_exact(&mut buf)
|
||||||
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if self.config.brightness != num as u8 {
|
||||||
if config.kbd_led_brightness != num as u8 {
|
self.config.read();
|
||||||
config.read();
|
self.config.brightness = num as u8;
|
||||||
config.kbd_led_brightness = num as u8;
|
self.config.write();
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -280,8 +261,8 @@ impl CtrlKbdBacklight {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
id_product: &str,
|
id_product: &str,
|
||||||
condev_iface: Option<&String>,
|
condev_iface: Option<&String>,
|
||||||
supported_modes: Vec<u8>,
|
supported_modes: LaptopLedData,
|
||||||
config: Arc<Mutex<Config>>,
|
config: AuraConfig,
|
||||||
) -> Result<Self, RogError> {
|
) -> Result<Self, RogError> {
|
||||||
// TODO: return error if *all* nodes are None
|
// TODO: return error if *all* nodes are None
|
||||||
let led_node = Self::get_node_failover(id_product, None, Self::scan_led_node).map_or_else(
|
let led_node = Self::get_node_failover(id_product, None, Self::scan_led_node).map_or_else(
|
||||||
@@ -334,6 +315,37 @@ impl CtrlKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_brightness(&self) -> Result<u8, RogError> {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(&self.bright_node)
|
||||||
|
.map_err(|err| match err.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => {
|
||||||
|
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
|
||||||
|
}
|
||||||
|
_ => RogError::Path((&self.bright_node).into(), err),
|
||||||
|
})?;
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
file.read_exact(&mut buf)
|
||||||
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
|
Ok(buf[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_brightness(&self, brightness: u8) -> Result<(), RogError> {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.open(&self.bright_node)
|
||||||
|
.map_err(|err| match err.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => {
|
||||||
|
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
|
||||||
|
}
|
||||||
|
_ => RogError::Path((&self.bright_node).into(), err),
|
||||||
|
})?;
|
||||||
|
file.write_all(&[brightness])
|
||||||
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_node_failover(
|
fn get_node_failover(
|
||||||
id_product: &str,
|
id_product: &str,
|
||||||
iface: Option<&String>,
|
iface: Option<&String>,
|
||||||
@@ -432,8 +444,8 @@ impl CtrlKbdBacklight {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_command(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
|
pub(crate) fn do_command(&mut self, mode: AuraEffect) -> Result<(), RogError> {
|
||||||
self.set_and_save(mode, config)
|
self.set_and_save(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should only be used if the bytes you are writing are verified correct
|
/// Should only be used if the bytes you are writing are verified correct
|
||||||
@@ -470,100 +482,61 @@ impl CtrlKbdBacklight {
|
|||||||
///
|
///
|
||||||
/// This needs to be universal so that settings applied by dbus stick
|
/// This needs to be universal so that settings applied by dbus stick
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_and_save(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
|
fn set_and_save(&mut self, mode: AuraEffect) -> Result<(), RogError> {
|
||||||
match mode {
|
self.config.read();
|
||||||
AuraModes::LedBrightness(n) => {
|
self.write_mode(&mode)?;
|
||||||
let bytes: [u8; LED_MSG_LEN] = (&mode).into();
|
self.config.current_mode = *mode.mode();
|
||||||
self.write_bytes(&bytes)?;
|
self.config.set_builtin(mode);
|
||||||
config.read();
|
self.config.write();
|
||||||
config.kbd_led_brightness = n;
|
|
||||||
config.write();
|
|
||||||
info!("LED brightness set to {:#?}", n);
|
|
||||||
}
|
|
||||||
AuraModes::PerKey(v) => {
|
|
||||||
if v.is_empty() || v[0].is_empty() {
|
|
||||||
let bytes = KeyColourArray::get_init_msg();
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
} else {
|
|
||||||
self.write_effect(&v)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
config.read();
|
|
||||||
let mode_num: u8 = u8::from(&mode);
|
|
||||||
self.write_mode(&mode)?;
|
|
||||||
config.kbd_backlight_mode = mode_num;
|
|
||||||
config.set_mode_data(mode);
|
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn toggle_mode(&mut self, reverse: bool, config: &mut Config) -> Result<(), RogError> {
|
fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> {
|
||||||
let current = config.kbd_backlight_mode;
|
let current = self.config.current_mode;
|
||||||
if let Some(idx) = self.supported_modes.iter().position(|v| *v == current) {
|
if let Some(idx) = self
|
||||||
|
.supported_modes
|
||||||
|
.standard
|
||||||
|
.iter()
|
||||||
|
.position(|v| *v == current)
|
||||||
|
{
|
||||||
let mut idx = idx;
|
let mut idx = idx;
|
||||||
// goes past end of array
|
// goes past end of array
|
||||||
if reverse {
|
if reverse {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
idx = self.supported_modes.len() - 1;
|
idx = self.supported_modes.standard.len() - 1;
|
||||||
} else {
|
} else {
|
||||||
idx -= 1;
|
idx -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
if idx == self.supported_modes.len() {
|
if idx == self.supported_modes.standard.len() {
|
||||||
idx = 0;
|
idx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let next = self.supported_modes[idx];
|
let next = self.supported_modes.standard[idx];
|
||||||
|
|
||||||
config.read();
|
self.config.read();
|
||||||
if let Some(data) = config.get_led_mode_data(next) {
|
if let Some(data) = self.config.builtins.get(&next) {
|
||||||
self.write_mode(&data)?;
|
self.write_mode(&data)?;
|
||||||
config.kbd_backlight_mode = next;
|
self.config.current_mode = next;
|
||||||
}
|
}
|
||||||
config.write();
|
self.config.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> {
|
fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> {
|
||||||
let mode_num: u8 = u8::from(mode);
|
if !self.supported_modes.standard.contains(&mode.mode()) {
|
||||||
if !self.supported_modes.contains(&mode_num) {
|
|
||||||
return Err(RogError::NotSupported);
|
return Err(RogError::NotSupported);
|
||||||
}
|
}
|
||||||
match mode {
|
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||||
AuraModes::PerKey(v) => {
|
self.write_bytes(&bytes)?;
|
||||||
if v.is_empty() || v[0].is_empty() {
|
self.write_bytes(&LED_SET)?;
|
||||||
let bytes = KeyColourArray::get_init_msg();
|
// Changes won't persist unless apply is set
|
||||||
self.write_bytes(&bytes)?;
|
self.write_bytes(&LED_APPLY)?;
|
||||||
} else {
|
|
||||||
self.write_effect(v)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuraModes::MultiStatic(_) | AuraModes::MultiBreathe(_) => {
|
|
||||||
let bytes: [[u8; LED_MSG_LEN]; 4] = mode.into();
|
|
||||||
for array in bytes.iter() {
|
|
||||||
self.write_bytes(array)?;
|
|
||||||
}
|
|
||||||
self.write_bytes(&LED_SET)?;
|
|
||||||
// Changes won't persist unless apply is set
|
|
||||||
self.write_bytes(&LED_APPLY)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
self.write_bytes(&LED_SET)?;
|
|
||||||
// Changes won't persist unless apply is set
|
|
||||||
self.write_bytes(&LED_APPLY)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use daemon::ctrl_charge::CtrlCharge;
|
|
||||||
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
|
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
|
||||||
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
||||||
use daemon::laptops::match_laptop;
|
use daemon::laptops::match_laptop;
|
||||||
use daemon::{
|
use daemon::{
|
||||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||||
};
|
};
|
||||||
|
use daemon::{config_aura::AuraConfig, ctrl_charge::CtrlCharge};
|
||||||
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
||||||
|
|
||||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
||||||
@@ -50,12 +50,9 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
print_board_info();
|
print_board_info();
|
||||||
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
||||||
|
|
||||||
let laptop = match_laptop();
|
let config = Config::load();
|
||||||
let config = if let Some(laptop) = laptop.as_ref() {
|
let enable_gfx_switching = config.gfx_managed;
|
||||||
Config::load(laptop.supported_modes())
|
let config = Arc::new(Mutex::new(config));
|
||||||
} else {
|
|
||||||
Config::load(&[])
|
|
||||||
};
|
|
||||||
|
|
||||||
let connection = Connection::new_system()?;
|
let connection = Connection::new_system()?;
|
||||||
fdo::DBusProxy::new(&connection)?
|
fdo::DBusProxy::new(&connection)?
|
||||||
@@ -64,9 +61,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
supported.add_to_server(&mut object_server);
|
supported.add_to_server(&mut object_server);
|
||||||
|
|
||||||
let enable_gfx_switching = config.gfx_managed;
|
|
||||||
let config = Arc::new(Mutex::new(config));
|
|
||||||
|
|
||||||
match CtrlRogBios::new(config.clone()) {
|
match CtrlRogBios::new(config.clone()) {
|
||||||
Ok(mut ctrl) => {
|
Ok(mut ctrl) => {
|
||||||
// Do a reload of any settings
|
// Do a reload of any settings
|
||||||
@@ -133,7 +127,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
// Collect tasks for task thread
|
// Collect tasks for task thread
|
||||||
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
||||||
|
|
||||||
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config.clone()).map_err(|err| {
|
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config).map_err(|err| {
|
||||||
error!("Profile control: {}", err);
|
error!("Profile control: {}", err);
|
||||||
}) {
|
}) {
|
||||||
ctrl.reload()
|
ctrl.reload()
|
||||||
@@ -142,12 +136,14 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(laptop) = laptop {
|
if let Some(laptop) = match_laptop() {
|
||||||
|
let aura_config = AuraConfig::load(laptop.supported_modes());
|
||||||
|
|
||||||
if let Ok(ctrl) = CtrlKbdBacklight::new(
|
if let Ok(ctrl) = CtrlKbdBacklight::new(
|
||||||
laptop.usb_product(),
|
laptop.usb_product(),
|
||||||
laptop.condev_iface(),
|
laptop.condev_iface(),
|
||||||
laptop.supported_modes().to_owned(),
|
laptop.supported_modes().to_owned(),
|
||||||
config,
|
aura_config,
|
||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("Keyboard control: {}", err);
|
error!("Keyboard control: {}", err);
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_types::aura_modes::{AuraModes, BREATHING, STATIC};
|
use rog_types::aura_modes::AuraModeNum;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub static LEDMODE_CONFIG_PATH: &str = "/etc/asusd/asusd-ledmodes.toml";
|
pub static LEDMODE_CONFIG_PATH: &str = "/etc/asusd/asusd-ledmodes.toml";
|
||||||
|
|
||||||
pub static HELP_ADDRESS: &str = "https://gitlab.com/asus-linux/asus-nb-ctrl";
|
pub static HELP_ADDRESS: &str = "https://gitlab.com/asus-linux/asus-nb-ctrl";
|
||||||
|
|
||||||
static LAPTOP_DEVICES: [u16; 4] = [0x1866, 0x1869, 0x1854, 0x19b6];
|
static LAPTOP_DEVICES: [u16; 4] = [0x1866, 0x1869, 0x1854, 0x19b6];
|
||||||
|
|
||||||
|
/// A helper of sorts specifically for functions tied to laptop models
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LaptopBase {
|
pub struct LaptopBase {
|
||||||
usb_product: String,
|
usb_product: String,
|
||||||
condev_iface: Option<String>, // required for finding the Consumer Device interface
|
condev_iface: Option<String>, // required for finding the Consumer Device interface
|
||||||
supported_modes: Vec<u8>,
|
led_support: LaptopLedData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LaptopBase {
|
impl LaptopBase {
|
||||||
@@ -24,8 +23,8 @@ impl LaptopBase {
|
|||||||
pub fn condev_iface(&self) -> Option<&String> {
|
pub fn condev_iface(&self) -> Option<&String> {
|
||||||
self.condev_iface.as_ref()
|
self.condev_iface.as_ref()
|
||||||
}
|
}
|
||||||
pub fn supported_modes(&self) -> &[u8] {
|
pub fn supported_modes(&self) -> &LaptopLedData {
|
||||||
&self.supported_modes
|
&self.led_support
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,10 +37,7 @@ pub fn match_laptop() -> Option<LaptopBase> {
|
|||||||
let prod_str = format!("{:x?}", device_desc.product_id());
|
let prod_str = format!("{:x?}", device_desc.product_id());
|
||||||
|
|
||||||
if device_desc.product_id() == 0x1854 {
|
if device_desc.product_id() == 0x1854 {
|
||||||
let mut laptop = laptop(prod_str, None);
|
let laptop = laptop(prod_str, None);
|
||||||
if laptop.supported_modes.is_empty() {
|
|
||||||
laptop.supported_modes = vec![STATIC, BREATHING];
|
|
||||||
}
|
|
||||||
return Some(laptop);
|
return Some(laptop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +61,18 @@ fn laptop(prod: String, condev_iface: Option<String>) -> LaptopBase {
|
|||||||
let mut laptop = LaptopBase {
|
let mut laptop = LaptopBase {
|
||||||
usb_product: prod,
|
usb_product: prod,
|
||||||
condev_iface,
|
condev_iface,
|
||||||
supported_modes: vec![],
|
led_support: LaptopLedData {
|
||||||
|
board_names: vec![],
|
||||||
|
prod_family: String::new(),
|
||||||
|
standard: vec![],
|
||||||
|
multizone: false,
|
||||||
|
per_key: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(modes) = LEDModeGroup::load_from_config() {
|
if let Some(modes) = LedSupportFile::load_from_config() {
|
||||||
if let Some(led_modes) = modes.matcher(&prod_family, &board_name) {
|
if let Some(led_modes) = modes.matcher(&prod_family, &board_name) {
|
||||||
laptop.supported_modes = led_modes;
|
laptop.led_support = led_modes;
|
||||||
return laptop;
|
return laptop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +94,7 @@ pub fn print_modes(supported_modes: &[u8]) {
|
|||||||
if !supported_modes.is_empty() {
|
if !supported_modes.is_empty() {
|
||||||
info!("Supported Keyboard LED modes are:");
|
info!("Supported Keyboard LED modes are:");
|
||||||
for mode in supported_modes {
|
for mode in supported_modes {
|
||||||
let mode = <&str>::from(&<AuraModes>::from(*mode));
|
let mode = <&str>::from(&<AuraModeNum>::from(*mode));
|
||||||
info!("- {}", mode);
|
info!("- {}", mode);
|
||||||
}
|
}
|
||||||
info!(
|
info!(
|
||||||
@@ -105,19 +107,28 @@ pub fn print_modes(supported_modes: &[u8]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct LEDModeGroup {
|
struct LedSupportFile {
|
||||||
led_modes: Vec<LEDModes>,
|
led_data: Vec<LaptopLedData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LEDModeGroup {
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct LaptopLedData {
|
||||||
|
pub prod_family: String,
|
||||||
|
pub board_names: Vec<String>,
|
||||||
|
pub standard: Vec<AuraModeNum>,
|
||||||
|
pub multizone: bool,
|
||||||
|
pub per_key: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LedSupportFile {
|
||||||
/// Consumes the LEDModes
|
/// Consumes the LEDModes
|
||||||
fn matcher(self, prod_family: &str, board_name: &str) -> Option<Vec<u8>> {
|
fn matcher(self, prod_family: &str, board_name: &str) -> Option<LaptopLedData> {
|
||||||
for led_modes in self.led_modes {
|
for config in self.led_data {
|
||||||
if prod_family.contains(&led_modes.prod_family) {
|
if prod_family.contains(&config.prod_family) {
|
||||||
for board in led_modes.board_names {
|
for board in &config.board_names {
|
||||||
if board_name.contains(&board) {
|
if board_name.contains(board) {
|
||||||
info!("Matched to {} {}", led_modes.prod_family, board);
|
info!("Matched to {} {}", config.prod_family, board);
|
||||||
return Some(led_modes.led_modes);
|
return Some(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,10 +153,3 @@ impl LEDModeGroup {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
struct LEDModes {
|
|
||||||
prod_family: String,
|
|
||||||
board_names: Vec<String>,
|
|
||||||
led_modes: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
/// Configuration loading, saving
|
/// Configuration loading, saving
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod config_aura;
|
||||||
pub(crate) mod config_old;
|
pub(crate) mod config_old;
|
||||||
/// Control of AniMe matrix display
|
/// Control of AniMe matrix display
|
||||||
pub mod ctrl_anime;
|
pub mod ctrl_anime;
|
||||||
|
|||||||
@@ -1,59 +1,83 @@
|
|||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus S"
|
prod_family = "Zephyrus S"
|
||||||
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus M"
|
prod_family = "Zephyrus M"
|
||||||
board_names = ["GU502GV"]
|
board_names = ["GU502GV"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus M15"
|
prod_family = "ROG Zephyrus M15"
|
||||||
board_names = ["GU502LW"]
|
board_names = ["GU502LW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus M15"
|
prod_family = "ROG Zephyrus M15"
|
||||||
board_names = ["GU502LU"]
|
board_names = ["GU502LU"]
|
||||||
led_modes = [0, 1, 2, 10]
|
standard = ["Static", "Breathe", "Strobe", "Pulse"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus"
|
prod_family = "Zephyrus"
|
||||||
board_names = ["GM501GM", "GX531"]
|
board_names = ["GM501GM", "GX531"]
|
||||||
led_modes = [0, 1, 2, 3, 10, 13]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G531GW"]
|
board_names = ["G531GW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["GX531", "G512LV", "G712LV"]
|
board_names = ["GX531", "G512LV", "G712LV"]
|
||||||
led_modes = [0, 1, 2, 3, 10, 13, 14]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G512LI", "G712LI", "G531GD"]
|
board_names = ["G512LI", "G712LI", "G531GD"]
|
||||||
led_modes = [0, 1, 2, 3, 10]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix"
|
prod_family = "Strix"
|
||||||
board_names = ["G731GV", "G731GW", "G531GV"]
|
board_names = ["G731GV", "G731GW", "G531GV"]
|
||||||
led_modes = [0, 1, 2, 3, 13, 14]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix"
|
prod_family = "Strix"
|
||||||
board_names = ["G731GT", "G731GU", "G531GT", "G531GU"]
|
board_names = ["G731GT", "G731GU", "G531GT", "G531GU"]
|
||||||
led_modes = [0, 1, 2, 3]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix Scar"
|
prod_family = "Strix Scar"
|
||||||
board_names = ["G531", "G731"]
|
board_names = ["G531", "G731"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = true
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG"
|
prod_family = "ROG"
|
||||||
board_names = ["GL553VE"]
|
board_names = ["GL553VE"]
|
||||||
led_modes = [0, 1, 2, 13, 14]
|
standard = ["Static", "Breathe", "Strobe"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
@@ -11,7 +11,7 @@ pub mod zbus_profile;
|
|||||||
pub mod zbus_rogbios;
|
pub mod zbus_rogbios;
|
||||||
pub mod zbus_supported;
|
pub mod zbus_supported;
|
||||||
|
|
||||||
use rog_types::aura_modes::AuraModes;
|
use rog_types::aura_modes::AuraEffect;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use zbus::{Connection, Result, SignalReceiver};
|
use zbus::{Connection, Result, SignalReceiver};
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ pub struct Signals {
|
|||||||
pub gfx_vendor: Arc<Mutex<Option<String>>>,
|
pub gfx_vendor: Arc<Mutex<Option<String>>>,
|
||||||
pub gfx_action: Arc<Mutex<Option<String>>>,
|
pub gfx_action: Arc<Mutex<Option<String>>>,
|
||||||
pub profile: Arc<Mutex<Option<String>>>,
|
pub profile: Arc<Mutex<Option<String>>>,
|
||||||
pub led_mode: Arc<Mutex<Option<AuraModes>>>,
|
pub led_mode: Arc<Mutex<Option<AuraEffect>>>,
|
||||||
pub charge: Arc<Mutex<Option<u8>>>,
|
pub charge: Arc<Mutex<Option<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use zbus::{dbus_proxy, Connection, Result};
|
use zbus::{dbus_proxy, Connection, Result};
|
||||||
|
|
||||||
use rog_types::{aura_modes::AuraModes, cli_options::LedBrightness, fancy::KeyColourArray};
|
use rog_types::{aura_modes::AuraEffect, aura_perkey::KeyColourArray};
|
||||||
|
|
||||||
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
||||||
|
|
||||||
@@ -32,27 +32,34 @@ const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 F
|
|||||||
default_path = "/org/asuslinux/Led"
|
default_path = "/org/asuslinux/Led"
|
||||||
)]
|
)]
|
||||||
trait Daemon {
|
trait Daemon {
|
||||||
/// LedBrightness method
|
|
||||||
fn led_brightness(&self) -> zbus::Result<i16>;
|
|
||||||
|
|
||||||
/// LedMode method
|
|
||||||
fn led_mode(&self) -> zbus::Result<String>;
|
|
||||||
|
|
||||||
/// LedModes method
|
|
||||||
fn led_modes(&self) -> zbus::Result<String>;
|
|
||||||
|
|
||||||
/// NextLedMode method
|
/// NextLedMode method
|
||||||
fn next_led_mode(&self) -> zbus::Result<()>;
|
fn next_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// PrevLedMode method
|
/// PrevLedMode method
|
||||||
fn prev_led_mode(&self) -> zbus::Result<()>;
|
fn prev_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetBrightness method
|
||||||
|
fn set_brightness(&self, brightness: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetLedMode method
|
/// SetLedMode method
|
||||||
fn set_led_mode(&self, data: &str) -> zbus::Result<()>;
|
fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyLed signal
|
/// NotifyLed signal
|
||||||
|
/// NotifyLed signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// LedBrightness property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_brightness(&self) -> zbus::Result<i16>;
|
||||||
|
|
||||||
|
/// LedMode property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_mode(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// LedModes property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_modes(&self) -> zbus::Result<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LedProxy<'a>(DaemonProxy<'a>);
|
pub struct LedProxy<'a>(DaemonProxy<'a>);
|
||||||
@@ -68,16 +75,13 @@ impl<'a> LedProxy<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_led_brightness(&self) -> Result<LedBrightness> {
|
pub fn get_led_brightness(&self) -> Result<i16> {
|
||||||
match self.0.led_brightness()? {
|
self.0.led_brightness()
|
||||||
-1 => Ok(LedBrightness::new(None)),
|
|
||||||
level => Ok(LedBrightness::new(Some(level as u8))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_brightness(&self, level: u8) -> Result<()> {
|
pub fn set_led_brightness(&self, level: u8) -> Result<()> {
|
||||||
self.set_led_mode(&AuraModes::LedBrightness(level))?;
|
self.0.set_brightness(level)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +96,8 @@ impl<'a> LedProxy<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_led_mode(&self, mode: &AuraModes) -> Result<()> {
|
pub fn set_led_mode(&self, mode: &AuraEffect) -> Result<()> {
|
||||||
self.0.set_led_mode(&serde_json::to_string(mode).unwrap())
|
self.0.set_led_mode(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a single colour block.
|
/// Write a single colour block.
|
||||||
@@ -107,9 +111,8 @@ impl<'a> LedProxy<'a> {
|
|||||||
for v in group {
|
for v in group {
|
||||||
vecs.push(v.to_vec());
|
vecs.push(v.to_vec());
|
||||||
}
|
}
|
||||||
let mode = AuraModes::PerKey(vecs);
|
// TODO: let mode = AuraModes::PerKey(vecs);
|
||||||
|
// self.set_led_mode(&mode)?;
|
||||||
self.set_led_mode(&mode)?;
|
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME));
|
std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME));
|
||||||
|
|
||||||
@@ -124,12 +127,13 @@ impl<'a> LedProxy<'a> {
|
|||||||
/// the keyboard LED EC in the correct mode
|
/// the keyboard LED EC in the correct mode
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn init_effect(&self) -> Result<()> {
|
pub fn init_effect(&self) -> Result<()> {
|
||||||
let mode = AuraModes::PerKey(vec![vec![]]);
|
// TODO: let mode = AuraModes::PerKey(vec![vec![]]);
|
||||||
self.0.set_led_mode(&serde_json::to_string(&mode).unwrap())
|
// self.0.set_led_mode(&serde_json::to_string(&mode).unwrap())
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connect_notify_led(&self, led: Arc<Mutex<Option<AuraModes>>>) -> zbus::fdo::Result<()> {
|
pub fn connect_notify_led(&self, led: Arc<Mutex<Option<AuraEffect>>>) -> zbus::fdo::Result<()> {
|
||||||
self.0.connect_notify_led(move |data| {
|
self.0.connect_notify_led(move |data| {
|
||||||
if let Ok(mut lock) = led.lock() {
|
if let Ok(mut lock) = led.lock() {
|
||||||
if let Ok(dat) = serde_json::from_str(&data) {
|
if let Ok(dat) = serde_json::from_str(&data) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_types"
|
name = "rog_types"
|
||||||
version = "3.0.0"
|
version = "3.1.0"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
|||||||
@@ -1,31 +1,21 @@
|
|||||||
use crate::cli_options::SetAuraBuiltin;
|
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
||||||
|
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
||||||
|
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
||||||
|
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
||||||
|
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
||||||
|
|
||||||
|
use crate::LED_MSG_LEN;
|
||||||
use crate::error::AuraError;
|
use crate::error::AuraError;
|
||||||
use gumdrop::Options;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use zvariant_derive::Type;
|
||||||
|
|
||||||
pub const STATIC: u8 = 0x00;
|
#[derive(Debug, Clone, PartialEq, Copy, Deserialize, Serialize, Type)]
|
||||||
pub const BREATHING: u8 = 0x01;
|
|
||||||
pub const STROBE: u8 = 0x02;
|
|
||||||
pub const RAINBOW: u8 = 0x03;
|
|
||||||
pub const STAR: u8 = 0x04;
|
|
||||||
pub const RAIN: u8 = 0x05;
|
|
||||||
pub const HIGHLIGHT: u8 = 0x06;
|
|
||||||
pub const LASER: u8 = 0x07;
|
|
||||||
pub const RIPPLE: u8 = 0x08;
|
|
||||||
pub const PULSE: u8 = 0x0a;
|
|
||||||
pub const COMET: u8 = 0x0b;
|
|
||||||
pub const FLASH: u8 = 0x0c;
|
|
||||||
pub const MULTISTATIC: u8 = 0x0d;
|
|
||||||
pub const MULTIBREATHE: u8 = 0x0e;
|
|
||||||
pub const PER_KEY: u8 = 0xff;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct Colour(pub u8, pub u8, pub u8);
|
pub struct Colour(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
impl Default for Colour {
|
impl Default for Colour {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Colour(128, 0, 0)
|
Colour(166, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +33,7 @@ impl FromStr for Colour {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize, Type)]
|
||||||
pub enum Speed {
|
pub enum Speed {
|
||||||
Low = 0xe1,
|
Low = 0xe1,
|
||||||
Med = 0xeb,
|
Med = 0xeb,
|
||||||
@@ -71,7 +61,7 @@ impl FromStr for Speed {
|
|||||||
/// Used for Rainbow mode.
|
/// Used for Rainbow mode.
|
||||||
///
|
///
|
||||||
/// Enum corresponds to the required integer value
|
/// Enum corresponds to the required integer value
|
||||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize, Type)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Right,
|
Right,
|
||||||
Left,
|
Left,
|
||||||
@@ -98,219 +88,265 @@ impl FromStr for Direction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
/// Writes out the correct byte string for brightness
|
||||||
pub struct SingleSpeed {
|
pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||||
#[serde(skip)]
|
[
|
||||||
#[options(help = "print help message")]
|
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
help: bool,
|
]
|
||||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
|
||||||
pub struct SingleSpeedDirection {
|
#[derive(
|
||||||
#[serde(skip)]
|
Debug, Type, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize,
|
||||||
#[options(help = "print help message")]
|
)]
|
||||||
help: bool,
|
pub enum AuraModeNum {
|
||||||
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
Static = 0,
|
||||||
|
Breathe = 1,
|
||||||
|
Strobe = 2,
|
||||||
|
Rainbow = 3,
|
||||||
|
Star = 4,
|
||||||
|
Rain = 5,
|
||||||
|
Highlight = 6,
|
||||||
|
Laser = 7,
|
||||||
|
Ripple = 8,
|
||||||
|
Pulse = 10,
|
||||||
|
Comet = 11,
|
||||||
|
Flash = 12,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&AuraModeNum> for &str {
|
||||||
|
fn from(mode: &AuraModeNum) -> Self {
|
||||||
|
match mode {
|
||||||
|
AuraModeNum::Static => "Static",
|
||||||
|
AuraModeNum::Breathe => "Breathing",
|
||||||
|
AuraModeNum::Strobe => "Strobing",
|
||||||
|
AuraModeNum::Rainbow => "Rainbow",
|
||||||
|
AuraModeNum::Star => "Stars",
|
||||||
|
AuraModeNum::Rain => "Rain",
|
||||||
|
AuraModeNum::Highlight => "Keypress Highlight",
|
||||||
|
AuraModeNum::Laser => "Keypress Laser",
|
||||||
|
AuraModeNum::Ripple => "Keypress Ripple",
|
||||||
|
AuraModeNum::Pulse => "Pulse",
|
||||||
|
AuraModeNum::Comet => "Comet",
|
||||||
|
AuraModeNum::Flash => "Flash",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&str> for AuraModeNum {
|
||||||
|
fn from(mode: &str) -> Self {
|
||||||
|
match mode {
|
||||||
|
"Static" => AuraModeNum::Static,
|
||||||
|
"Breathing" => AuraModeNum::Breathe,
|
||||||
|
"Strobing" => AuraModeNum::Strobe,
|
||||||
|
"Rainbow" => AuraModeNum::Rainbow,
|
||||||
|
"Stars" => AuraModeNum::Star,
|
||||||
|
"Rain" => AuraModeNum::Rain,
|
||||||
|
"Keypress Highlight" => AuraModeNum::Highlight,
|
||||||
|
"Keypress Laser" => AuraModeNum::Laser,
|
||||||
|
"Keypress Ripple" => AuraModeNum::Ripple,
|
||||||
|
"Pulse" => AuraModeNum::Pulse,
|
||||||
|
"Comet" => AuraModeNum::Comet,
|
||||||
|
"Flash" => AuraModeNum::Flash,
|
||||||
|
_ => AuraModeNum::Static,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for AuraModeNum {
|
||||||
|
fn from(mode: u8) -> Self {
|
||||||
|
match mode {
|
||||||
|
0 => AuraModeNum::Static,
|
||||||
|
1 => AuraModeNum::Breathe,
|
||||||
|
2 => AuraModeNum::Strobe,
|
||||||
|
3 => AuraModeNum::Rainbow,
|
||||||
|
4 => AuraModeNum::Star,
|
||||||
|
5 => AuraModeNum::Rain,
|
||||||
|
6 => AuraModeNum::Highlight,
|
||||||
|
7 => AuraModeNum::Laser,
|
||||||
|
8 => AuraModeNum::Ripple,
|
||||||
|
10 => AuraModeNum::Pulse,
|
||||||
|
11 => AuraModeNum::Comet,
|
||||||
|
12 => AuraModeNum::Flash,
|
||||||
|
_ => AuraModeNum::Static,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AuraMultiZone {
|
||||||
|
static_: [AuraEffect; 4],
|
||||||
|
breathe: [AuraEffect; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraMultiZone {
|
||||||
|
pub fn set(&mut self, effect: AuraEffect) {
|
||||||
|
if effect.mode == AuraModeNum::Static {
|
||||||
|
match effect.zone {
|
||||||
|
AuraZone::None => {}
|
||||||
|
AuraZone::One => self.static_[0] = effect,
|
||||||
|
AuraZone::Two => self.static_[1] = effect,
|
||||||
|
AuraZone::Three => self.static_[2] = effect,
|
||||||
|
AuraZone::Four => self.static_[3] = effect,
|
||||||
|
}
|
||||||
|
} else if effect.mode == AuraModeNum::Breathe {
|
||||||
|
match effect.zone {
|
||||||
|
AuraZone::None => {}
|
||||||
|
AuraZone::One => self.breathe[0] = effect,
|
||||||
|
AuraZone::Two => self.breathe[1] = effect,
|
||||||
|
AuraZone::Three => self.breathe[2] = effect,
|
||||||
|
AuraZone::Four => self.breathe[3] = effect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn static_(&self) -> &[AuraEffect; 4] {
|
||||||
|
&self.static_
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn breathe(&self) -> &[AuraEffect; 4] {
|
||||||
|
&self.breathe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AuraMultiZone {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
static_: [
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::One,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Two,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Three,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Four,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
breathe: [
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::One,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Two,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Three,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Four,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Base effects have no zoning, while multizone is 1-4
|
||||||
|
#[derive(Debug, Type, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub enum AuraZone {
|
||||||
|
None,
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default factory modes structure
|
||||||
|
#[derive(Debug, Type, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct AuraEffect {
|
||||||
|
/// The effect type
|
||||||
|
pub mode: AuraModeNum,
|
||||||
|
/// `AuraZone::None` for no zone or zoneless keyboards
|
||||||
|
pub zone: AuraZone,
|
||||||
|
/// Primary colour for all modes
|
||||||
|
pub colour1: Colour,
|
||||||
|
/// Secondary colour in some modes like Breathing or Stars
|
||||||
|
pub colour2: Colour,
|
||||||
|
/// One of three speeds for modes that support speed (most that animate)
|
||||||
|
pub speed: Speed,
|
||||||
|
/// Up, down, left, right. Only Rainbow mode seems to use this
|
||||||
pub direction: Direction,
|
pub direction: Direction,
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
impl AuraEffect {
|
||||||
pub struct SingleColour {
|
pub fn mode(&self) -> &AuraModeNum {
|
||||||
#[serde(skip)]
|
&self.mode
|
||||||
#[options(help = "print help message")]
|
}
|
||||||
help: bool,
|
|
||||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
pub fn mode_name(&self) -> String {
|
||||||
pub struct SingleColourSpeed {
|
(<&str>::from(&self.mode)).to_string()
|
||||||
#[serde(skip)]
|
}
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
pub fn mode_num(&self) -> u8 {
|
||||||
pub struct TwoColourSpeed {
|
self.mode as u8
|
||||||
#[serde(skip)]
|
}
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
pub fn default_with_mode(mode: AuraModeNum) -> Self {
|
||||||
pub struct MultiColour {
|
Self {
|
||||||
#[serde(skip)]
|
mode,
|
||||||
#[options(help = "print help message")]
|
..Default::default()
|
||||||
help: bool,
|
}
|
||||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
}
|
||||||
pub colour1: Colour,
|
|
||||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour3: Colour,
|
|
||||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour4: Colour,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
pub fn zone(&self) -> AuraZone {
|
||||||
pub struct MultiColourSpeed {
|
self.zone
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour1: Colour,
|
|
||||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour3: Colour,
|
|
||||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour4: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub enum AuraModes {
|
|
||||||
Static(SingleColour),
|
|
||||||
Breathe(TwoColourSpeed),
|
|
||||||
Strobe(SingleSpeed),
|
|
||||||
Rainbow(SingleSpeedDirection),
|
|
||||||
Star(TwoColourSpeed),
|
|
||||||
Rain(SingleSpeed),
|
|
||||||
Highlight(SingleColourSpeed),
|
|
||||||
Laser(SingleColourSpeed),
|
|
||||||
Ripple(SingleColourSpeed),
|
|
||||||
Pulse(SingleColour),
|
|
||||||
Comet(SingleColour),
|
|
||||||
Flash(SingleColour),
|
|
||||||
MultiStatic(MultiColour),
|
|
||||||
MultiBreathe(MultiColourSpeed),
|
|
||||||
LedBrightness(u8),
|
|
||||||
// TODO: use a serializable structure for this (KeyColourArray)
|
|
||||||
PerKey(Vec<Vec<u8>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SetAuraBuiltin> for AuraModes {
|
|
||||||
fn from(mode: SetAuraBuiltin) -> Self {
|
|
||||||
(&mode).into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&SetAuraBuiltin> for AuraModes {
|
impl Default for AuraEffect {
|
||||||
fn from(mode: &SetAuraBuiltin) -> Self {
|
fn default() -> Self {
|
||||||
match mode {
|
Self {
|
||||||
SetAuraBuiltin::Static(x) => AuraModes::Static(x.clone()),
|
mode: AuraModeNum::Static,
|
||||||
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x.clone()),
|
zone: AuraZone::None,
|
||||||
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x.clone()),
|
colour1: Colour(166, 0, 0),
|
||||||
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x.clone()),
|
colour2: Colour(0, 0, 0),
|
||||||
SetAuraBuiltin::Star(x) => AuraModes::Star(x.clone()),
|
speed: Speed::Med,
|
||||||
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x.clone()),
|
direction: Direction::Right,
|
||||||
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x.clone()),
|
|
||||||
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x.clone()),
|
|
||||||
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x.clone()),
|
|
||||||
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x.clone()),
|
|
||||||
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x.clone()),
|
|
||||||
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x.clone()),
|
|
||||||
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x.clone()),
|
|
||||||
SetAuraBuiltin::MultiBreathe(x) => AuraModes::MultiBreathe(x.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
/// Parses `AuraEffect` in to packet data for writing to the USB interface
|
||||||
impl From<AuraModes> for u8 {
|
///
|
||||||
fn from(mode: AuraModes) -> Self {
|
/// Byte structure:
|
||||||
u8::from(&mode)
|
/// ```ignore
|
||||||
}
|
/// | 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 |
|
||||||
|
/// ```
|
||||||
|
impl From<&AuraEffect> for [u8; LED_MSG_LEN] {
|
||||||
|
fn from(aura: &AuraEffect) -> Self {
|
||||||
|
let mut msg = [0u8; LED_MSG_LEN];
|
||||||
|
msg[0] = 0x5d;
|
||||||
|
msg[1] = 0xb3;
|
||||||
|
msg[2] = aura.zone as u8;
|
||||||
|
msg[3] = aura.mode as u8;
|
||||||
|
msg[4] = aura.colour1.0;
|
||||||
|
msg[5] = aura.colour1.1;
|
||||||
|
msg[6] = aura.colour1.2;
|
||||||
|
msg[7] = aura.speed as u8;
|
||||||
|
msg[8] = aura.direction as u8;
|
||||||
|
msg[10] = aura.colour2.0;
|
||||||
|
msg[11] = aura.colour2.1;
|
||||||
|
msg[12] = aura.colour2.2;
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
msg
|
||||||
impl From<&mut AuraModes> for u8 {
|
|
||||||
fn from(mode: &mut AuraModes) -> Self {
|
|
||||||
u8::from(&*mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
|
||||||
impl From<&AuraModes> for u8 {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
match mode {
|
|
||||||
AuraModes::Static(_) => STATIC,
|
|
||||||
AuraModes::Breathe(_) => BREATHING,
|
|
||||||
AuraModes::Strobe(_) => STROBE,
|
|
||||||
AuraModes::Rainbow(_) => RAINBOW,
|
|
||||||
AuraModes::Star(_) => STAR,
|
|
||||||
AuraModes::Rain(_) => RAIN,
|
|
||||||
AuraModes::Highlight(_) => HIGHLIGHT,
|
|
||||||
AuraModes::Laser(_) => LASER,
|
|
||||||
AuraModes::Ripple(_) => RIPPLE,
|
|
||||||
AuraModes::Pulse(_) => PULSE,
|
|
||||||
AuraModes::Comet(_) => COMET,
|
|
||||||
AuraModes::Flash(_) => FLASH,
|
|
||||||
AuraModes::MultiStatic(_) => MULTISTATIC,
|
|
||||||
AuraModes::MultiBreathe(_) => MULTIBREATHE,
|
|
||||||
AuraModes::PerKey(_) => PER_KEY,
|
|
||||||
_ => panic!("Invalid mode"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&AuraModes> for &str {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
match mode {
|
|
||||||
AuraModes::Static(_) => "Static",
|
|
||||||
AuraModes::Breathe(_) => "Breathing",
|
|
||||||
AuraModes::Strobe(_) => "Strobing",
|
|
||||||
AuraModes::Rainbow(_) => "Rainbow",
|
|
||||||
AuraModes::Star(_) => "Stars",
|
|
||||||
AuraModes::Rain(_) => "Rain",
|
|
||||||
AuraModes::Highlight(_) => "Keypress Highlight",
|
|
||||||
AuraModes::Laser(_) => "Keypress Laser",
|
|
||||||
AuraModes::Ripple(_) => "Keypress Ripple",
|
|
||||||
AuraModes::Pulse(_) => "Pulse",
|
|
||||||
AuraModes::Comet(_) => "Comet",
|
|
||||||
AuraModes::Flash(_) => "Flash",
|
|
||||||
AuraModes::MultiStatic(_) => "4-Zone Static Colours",
|
|
||||||
AuraModes::MultiBreathe(_) => "4-Zone Breathing Colours",
|
|
||||||
AuraModes::PerKey(_) => "RGB per-key",
|
|
||||||
_ => panic!("Invalid mode"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exists to convert back from correct bytes. PER_KEY byte intentionally left off as it
|
|
||||||
/// does not correspond to an actual pre-set mode, nor does brightness.
|
|
||||||
impl From<u8> for AuraModes {
|
|
||||||
fn from(byte: u8) -> Self {
|
|
||||||
match byte {
|
|
||||||
STATIC => AuraModes::Static(SingleColour::default()),
|
|
||||||
BREATHING => AuraModes::Breathe(TwoColourSpeed::default()),
|
|
||||||
STROBE => AuraModes::Strobe(SingleSpeed::default()),
|
|
||||||
RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()),
|
|
||||||
STAR => AuraModes::Star(TwoColourSpeed::default()),
|
|
||||||
RAIN => AuraModes::Rain(SingleSpeed::default()),
|
|
||||||
HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()),
|
|
||||||
LASER => AuraModes::Laser(SingleColourSpeed::default()),
|
|
||||||
RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()),
|
|
||||||
PULSE => AuraModes::Pulse(SingleColour::default()),
|
|
||||||
COMET => AuraModes::Comet(SingleColour::default()),
|
|
||||||
FLASH => AuraModes::Flash(SingleColour::default()),
|
|
||||||
MULTISTATIC => AuraModes::MultiStatic(MultiColour::default()),
|
|
||||||
MULTIBREATHE => AuraModes::MultiBreathe(MultiColourSpeed::default()),
|
|
||||||
PER_KEY => AuraModes::PerKey(vec![]),
|
|
||||||
_ => panic!("Invalid mode byte"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ impl KeyColourArray {
|
|||||||
|
|
||||||
/// Initialise and clear the keyboard for custom effects
|
/// Initialise and clear the keyboard for custom effects
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_init_msg() -> Vec<u8> {
|
pub const fn get_init_msg() -> [u8; 64] {
|
||||||
let mut init = vec![0u8; 64];
|
let mut init = [0u8; 64];
|
||||||
init[0] = 0x5d; // Report ID
|
init[0] = 0x5d; // Report ID
|
||||||
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||||
init
|
init
|
||||||
@@ -1,97 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
aura_modes::{
|
|
||||||
MultiColour, MultiColourSpeed, SingleColour, SingleColourSpeed, SingleSpeed,
|
|
||||||
SingleSpeedDirection, TwoColourSpeed,
|
|
||||||
},
|
|
||||||
error::AuraError,
|
error::AuraError,
|
||||||
};
|
};
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Options)]
|
|
||||||
pub struct LedBrightness {
|
|
||||||
level: Option<u8>,
|
|
||||||
}
|
|
||||||
impl LedBrightness {
|
|
||||||
pub fn new(level: Option<u8>) -> Self {
|
|
||||||
LedBrightness { level }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn level(&self) -> Option<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: Some(0x00) }),
|
|
||||||
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
|
||||||
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
|
||||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
|
||||||
_ => {
|
|
||||||
print!("Invalid argument, must be one of: off, low, med, high");
|
|
||||||
Err(AuraError::ParseBrightness)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl ToString for LedBrightness {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
let s = match self.level {
|
|
||||||
Some(0x00) => "low",
|
|
||||||
Some(0x01) => "med",
|
|
||||||
Some(0x02) => "high",
|
|
||||||
_ => "unknown",
|
|
||||||
};
|
|
||||||
s.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Byte value for setting the built-in mode.
|
|
||||||
///
|
|
||||||
/// Enum corresponds to the required integer value
|
|
||||||
#[derive(Options, Deserialize, Serialize)]
|
|
||||||
pub enum SetAuraBuiltin {
|
|
||||||
#[options(help = "set a single static colour")]
|
|
||||||
Static(SingleColour),
|
|
||||||
#[options(help = "pulse between one or two colours")]
|
|
||||||
Breathe(TwoColourSpeed),
|
|
||||||
#[options(help = "strobe through all colours")]
|
|
||||||
Strobe(SingleSpeed),
|
|
||||||
#[options(help = "rainbow cycling in one of four directions")]
|
|
||||||
Rainbow(SingleSpeedDirection),
|
|
||||||
#[options(help = "rain pattern mimicking raindrops")]
|
|
||||||
Star(TwoColourSpeed),
|
|
||||||
#[options(help = "rain pattern of three preset colours")]
|
|
||||||
Rain(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")]
|
|
||||||
Comet(SingleColour),
|
|
||||||
#[options(help = "set a wide vertical line zooming from left")]
|
|
||||||
Flash(SingleColour),
|
|
||||||
#[options(help = "4-zone multi-colour")]
|
|
||||||
MultiStatic(MultiColour),
|
|
||||||
#[options(help = "4-zone multi-colour breathing")]
|
|
||||||
MultiBreathe(MultiColourSpeed),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SetAuraBuiltin {
|
|
||||||
fn default() -> Self {
|
|
||||||
SetAuraBuiltin::Static(SingleColour::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum AniMeStatusValue {
|
pub enum AniMeStatusValue {
|
||||||
On,
|
On,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
use crate::error::GraphicsError;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||||
pub enum GfxVendors {
|
pub enum GfxVendors {
|
||||||
@@ -8,10 +10,6 @@ pub enum GfxVendors {
|
|||||||
Hybrid,
|
Hybrid,
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use crate::error::GraphicsError;
|
|
||||||
|
|
||||||
impl FromStr for GfxVendors {
|
impl FromStr for GfxVendors {
|
||||||
type Err = GraphicsError;
|
type Err = GraphicsError;
|
||||||
|
|
||||||
@@ -30,9 +28,9 @@ impl FromStr for GfxVendors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<&str> for GfxVendors {
|
impl From<&GfxVendors> for &str {
|
||||||
fn into(self) -> &'static str {
|
fn from(gfx: &GfxVendors) -> &'static str {
|
||||||
match self {
|
match gfx {
|
||||||
GfxVendors::Nvidia => "nvidia",
|
GfxVendors::Nvidia => "nvidia",
|
||||||
GfxVendors::Hybrid => "hybrid",
|
GfxVendors::Hybrid => "hybrid",
|
||||||
GfxVendors::Compute => "compute",
|
GfxVendors::Compute => "compute",
|
||||||
@@ -41,14 +39,9 @@ impl Into<&str> for GfxVendors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<String> for GfxVendors {
|
impl From<GfxVendors> for &str {
|
||||||
fn into(self) -> String {
|
fn from(gfx: GfxVendors) -> &'static str {
|
||||||
match self {
|
(&gfx).into()
|
||||||
GfxVendors::Nvidia => "nvidia".to_string(),
|
|
||||||
GfxVendors::Hybrid => "hybrid".to_string(),
|
|
||||||
GfxVendors::Compute => "compute".to_string(),
|
|
||||||
GfxVendors::Integrated => "integrated".to_string(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,17 +75,7 @@ impl From<&GfxCtrlAction> for &str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GfxCtrlAction> for String {
|
impl From<GfxCtrlAction> for &str {
|
||||||
fn from(mode: &GfxCtrlAction) -> Self {
|
|
||||||
match mode {
|
|
||||||
GfxCtrlAction::Reboot => "reboot".into(),
|
|
||||||
GfxCtrlAction::RestartX => "restartx".into(),
|
|
||||||
GfxCtrlAction::None => "none".into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<GfxCtrlAction> for String {
|
|
||||||
fn from(mode: GfxCtrlAction) -> Self {
|
fn from(mode: GfxCtrlAction) -> Self {
|
||||||
(&mode).into()
|
(&mode).into()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
//! This crate is intended for shared types (eg, between daemon and CLI), or
|
||||||
|
//! for types that might be useful in third-party crates perhaps for
|
||||||
|
//! sending messages over dbus wire
|
||||||
|
|
||||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||||
pub const LED_MSG_LEN: usize = 17;
|
pub const LED_MSG_LEN: usize = 17;
|
||||||
|
|
||||||
pub mod aura_modes;
|
pub mod aura_modes;
|
||||||
use aura_modes::AuraModes;
|
|
||||||
|
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
|
|
||||||
@@ -12,7 +15,7 @@ pub mod profile;
|
|||||||
pub mod cli_options;
|
pub mod cli_options;
|
||||||
|
|
||||||
/// Enables you to create fancy RGB effects
|
/// Enables you to create fancy RGB effects
|
||||||
pub mod fancy;
|
pub mod aura_perkey;
|
||||||
|
|
||||||
/// Helper functions for the AniMe display
|
/// Helper functions for the AniMe display
|
||||||
pub mod anime_matrix;
|
pub mod anime_matrix;
|
||||||
@@ -22,262 +25,3 @@ pub mod gfx_vendors;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
|
||||||
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
|
||||||
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
|
||||||
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
|
||||||
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
|
||||||
|
|
||||||
/// Writes aout the correct byte string for brightness
|
|
||||||
///
|
|
||||||
/// The HID descriptor looks like:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// 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 `AuraCommands` in to packet data
|
|
||||||
///
|
|
||||||
/// Byte structure:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// | 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 = strobe (through all colours)
|
|
||||||
/// - 03 = rainbow
|
|
||||||
/// - 04 = star (byte 9 sets rain colour)
|
|
||||||
/// - 05 = rain 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:
|
|
||||||
/// ```ignore
|
|
||||||
/// 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<&AuraModes> for [u8; LED_MSG_LEN] {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
let mut msg = [0u8; LED_MSG_LEN];
|
|
||||||
msg[0] = 0x5d;
|
|
||||||
msg[1] = 0xb3;
|
|
||||||
msg[7] = 0xeb;
|
|
||||||
match mode {
|
|
||||||
AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
|
|
||||||
AuraModes::Static(_) => msg[3] = 0x00,
|
|
||||||
AuraModes::Breathe(_) => msg[3] = 0x01,
|
|
||||||
AuraModes::Strobe(_) => msg[3] = 0x02,
|
|
||||||
AuraModes::Rainbow(_) => msg[3] = 0x03,
|
|
||||||
AuraModes::Star(_) => msg[3] = 0x04,
|
|
||||||
AuraModes::Rain(_) => msg[3] = 0x05,
|
|
||||||
AuraModes::Highlight(_) => msg[3] = 0x06,
|
|
||||||
AuraModes::Laser(_) => msg[3] = 0x07,
|
|
||||||
AuraModes::Ripple(_) => msg[3] = 0x08,
|
|
||||||
AuraModes::Pulse(_) => msg[3] = 0x0a,
|
|
||||||
AuraModes::Comet(_) => msg[3] = 0x0b,
|
|
||||||
AuraModes::Flash(_) => msg[3] = 0x0c,
|
|
||||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
|
|
||||||
match mode {
|
|
||||||
AuraModes::Rainbow(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[8] = settings.direction as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Star(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;
|
|
||||||
}
|
|
||||||
AuraModes::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;
|
|
||||||
}
|
|
||||||
AuraModes::Strobe(settings) | AuraModes::Rain(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Highlight(settings)
|
|
||||||
| AuraModes::Laser(settings)
|
|
||||||
| AuraModes::Ripple(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Static(settings)
|
|
||||||
| AuraModes::Pulse(settings)
|
|
||||||
| AuraModes::Comet(settings)
|
|
||||||
| AuraModes::Flash(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AuraModes> for [u8; LED_MSG_LEN] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: AuraModes) -> Self {
|
|
||||||
<[u8; LED_MSG_LEN]>::from(&mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: AuraModes) -> Self {
|
|
||||||
<[[u8; LED_MSG_LEN]; 4]>::from(&mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
|
||||||
match mode {
|
|
||||||
AuraModes::MultiStatic(settings) => {
|
|
||||||
for (i, row) in msg.iter_mut().enumerate() {
|
|
||||||
row[0] = 0x5d;
|
|
||||||
row[1] = 0xb3;
|
|
||||||
row[2] = i as u8 + 1; // zone
|
|
||||||
row[3] = 0x00; // mode
|
|
||||||
row[7] = 0xeb; // static needs speed?
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
AuraModes::MultiBreathe(settings) => {
|
|
||||||
for (i, row) in msg.iter_mut().enumerate() {
|
|
||||||
row[0] = 0x5d;
|
|
||||||
row[1] = 0xb3;
|
|
||||||
row[2] = i as u8 + 1; // zone
|
|
||||||
row[3] = 0x01; // mode
|
|
||||||
}
|
|
||||||
let speed = match settings.speed {
|
|
||||||
aura_modes::Speed::Low => 0xfd,
|
|
||||||
aura_modes::Speed::Med => 0xfe,
|
|
||||||
aura_modes::Speed::High => 0xff,
|
|
||||||
};
|
|
||||||
msg[0][4] = settings.colour1.0;
|
|
||||||
msg[0][5] = settings.colour1.1;
|
|
||||||
msg[0][6] = settings.colour1.2;
|
|
||||||
msg[0][7] = speed; // fd, fe, ff
|
|
||||||
msg[1][4] = settings.colour2.0;
|
|
||||||
msg[1][5] = settings.colour2.1;
|
|
||||||
msg[1][6] = settings.colour2.2;
|
|
||||||
msg[1][7] = speed;
|
|
||||||
msg[2][4] = settings.colour3.0;
|
|
||||||
msg[2][5] = settings.colour3.1;
|
|
||||||
msg[2][6] = settings.colour3.2;
|
|
||||||
msg[2][7] = speed;
|
|
||||||
msg[3][4] = settings.colour4.0;
|
|
||||||
msg[3][5] = settings.colour4.1;
|
|
||||||
msg[3][6] = settings.colour4.2;
|
|
||||||
msg[3][7] = speed;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to 2D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user