mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19370215c0 | |||
| 030dd661b8 | |||
| 1fc12d9855 | |||
| 6c1b2b70ea | |||
| 23f9af35bf | |||
| 526626b80c | |||
| 10eaaac54b | |||
| 901a3ddcc9 | |||
| e6ebf72a11 | |||
| cd7e748c88 | |||
| a313359ef6 | |||
| f222eef6b7 | |||
| e6f3aeb851 | |||
| 22605e57cc | |||
| 02fb7addf4 | |||
| bdbb403a0e | |||
| 7a8bede92f | |||
| a71a40b509 | |||
| 42fc5a5392 |
@@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased ]
|
||||
|
||||
## [4.3.0] - 2022-07-21
|
||||
### Added
|
||||
- Clear command for anime `asusctl anime --clear` will clear the display
|
||||
- Re-added support for LED power states on `0x1866` type keyboards
|
||||
### Changed
|
||||
- Make rog-anime more error tolerent. Remove various asserts and return errors instead
|
||||
- Return error if a pixel-gif is larger than the anime-display dimensions
|
||||
- Both Anime and Aura dbus interfaces are changed a little
|
||||
- Aura power has changed, all power related settings are now in one method
|
||||
- Anime methods will now return an error (if errored)
|
||||
- /org/asuslinux/Led renamed to /org/asuslinux/Aura
|
||||
|
||||
## [4.2.1] - 2022-07-18
|
||||
### Added
|
||||
- Add panel overdrive support (autodetects if supported)
|
||||
|
||||
Generated
+5
-4
@@ -33,7 +33,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "asusctl"
|
||||
version = "4.2.1"
|
||||
version = "4.3.0"
|
||||
dependencies = [
|
||||
"daemon",
|
||||
"gif",
|
||||
@@ -278,7 +278,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "daemon"
|
||||
version = "4.2.1"
|
||||
version = "4.3.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"env_logger",
|
||||
@@ -1018,7 +1018,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rog_anime"
|
||||
version = "1.3.4"
|
||||
version = "1.3.5"
|
||||
dependencies = [
|
||||
"gif",
|
||||
"glam",
|
||||
@@ -1029,12 +1029,13 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"sysfs-class",
|
||||
"udev",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rog_aura"
|
||||
version = "1.1.3"
|
||||
version = "1.2.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
||||
@@ -90,7 +90,7 @@ where the number is a percentage.
|
||||
|
||||
Some options that you find in Armory Crate are available under this controller, so far there is:
|
||||
|
||||
- POST sound: this is the sound you here on bios boot post
|
||||
- POST sound: this is the sound you hear on bios boot post
|
||||
- G-Sync: this controls if the dGPU (Nvidia) is the *only* GPU, making it the main GPU and disabling the iGPU
|
||||
|
||||
These options are not written to the config file as they are stored in efivars. The only way to change these is to use the exposed safe dbus methods, or use the `asusctl` CLI tool.
|
||||
@@ -293,7 +293,7 @@ A plain non-float integer.
|
||||
|
||||
## asusctl
|
||||
|
||||
`asusctl` is a commandline interface which intends to be the main method of interacting with `asusd`. I can be used in any place a terminal app can be used.
|
||||
`asusctl` is a commandline interface which intends to be the main method of interacting with `asusd`. It can be used in any place a terminal app can be used.
|
||||
|
||||
This program will query `asusd` for the `Support` level of the laptop and show or hide options according to this support level.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asusctl"
|
||||
version = "4.2.1"
|
||||
version = "4.3.0"
|
||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(matrix.into_data_buffer(anime_type))
|
||||
.write(matrix.into_data_buffer(anime_type)?)
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -29,7 +29,7 @@ fn main() {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(matrix.into_data_buffer(anime_type))
|
||||
.write(matrix.into_data_buffer(anime_type).unwrap())
|
||||
.unwrap();
|
||||
sleep(Duration::from_millis(300));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use rog_anime::{usb::get_anime_type, AnimeDataBuffer, AnimeGrid};
|
||||
use rog_dbus::RogDbusClientBlocking;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
// In usable data:
|
||||
// Top row start at 1, ends at 32
|
||||
@@ -39,7 +40,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = <AnimeDataBuffer>::from(matrix);
|
||||
let matrix = <AnimeDataBuffer>::try_from(matrix).unwrap();
|
||||
|
||||
client.proxies().anime().write(matrix).unwrap();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::{env, error::Error, path::Path, process::exit};
|
||||
|
||||
use rog_anime::{
|
||||
@@ -32,7 +33,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::try_from(&matrix)?)
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::{
|
||||
env, error::Error, f32::consts::PI, path::Path, process::exit, thread::sleep, time::Duration,
|
||||
};
|
||||
@@ -41,7 +42,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::try_from(&matrix)?)
|
||||
.unwrap();
|
||||
sleep(Duration::from_micros(500));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ pub struct AnimeCommand {
|
||||
pub boot_enable: Option<bool>,
|
||||
#[options(meta = "", help = "set global AniMe brightness value")]
|
||||
pub brightness: Option<f32>,
|
||||
#[options(help = "clear the display")]
|
||||
pub clear: bool,
|
||||
#[options(command)]
|
||||
pub command: Option<AnimeActions>,
|
||||
}
|
||||
|
||||
+20
-3
@@ -3,7 +3,23 @@ use rog_aura::{error::Error, AuraEffect, AuraModeNum, AuraZone, Colour, Directio
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedPowerCommand {
|
||||
pub struct LedPowerCommand1 {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "Control if LEDs enabled while awake <true/false>")]
|
||||
pub awake: Option<bool>,
|
||||
#[options(meta = "", help = "Use with awake option <true/false>")]
|
||||
pub keyboard: Option<bool>,
|
||||
#[options(meta = "", help = "Use with awake option <true/false>")]
|
||||
pub lightbar: Option<bool>,
|
||||
#[options(meta = "", help = "Control boot animations <true/false>")]
|
||||
pub boot: Option<bool>,
|
||||
#[options(meta = "", help = "Control suspend animations <true/false>")]
|
||||
pub sleep: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedPowerCommand2 {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(command)]
|
||||
@@ -12,12 +28,13 @@ pub struct LedPowerCommand {
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum SetAuraEnabled {
|
||||
/// Applies to both old and new models
|
||||
#[options(help = "set <keyboard, logo, lightbar> to enabled while device is awake")]
|
||||
Awake(AuraEnabled),
|
||||
#[options(help = "set <keyboard, logo, lightbar> to enabled while the device is booting")]
|
||||
Boot(AuraEnabled),
|
||||
#[options(help = "set <keyboard, logo, lightbar> to animate while the device is suspended")]
|
||||
Sleep(AuraEnabled),
|
||||
#[options(help = "set <keyboard, logo, lightbar> to enabled while device is awake")]
|
||||
Awake(AuraEnabled),
|
||||
#[options(help = "set <keyboard, logo, lightbar> to animate while the device is shutdown")]
|
||||
Shutdown(AuraEnabled),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
anime_cli::AnimeCommand,
|
||||
aura_cli::{LedBrightness, LedPowerCommand, SetAuraBuiltin},
|
||||
aura_cli::{LedBrightness, LedPowerCommand1, LedPowerCommand2, SetAuraBuiltin},
|
||||
profiles_cli::{FanCurveCommand, ProfileCommand},
|
||||
};
|
||||
use gumdrop::Options;
|
||||
@@ -29,8 +29,10 @@ pub struct CliStart {
|
||||
pub enum CliCommand {
|
||||
#[options(help = "Set the keyboard lighting from built-in modes")]
|
||||
LedMode(LedModeCommand),
|
||||
#[options(help = "Set the keyboard lighting from built-in modes")]
|
||||
LedPower(LedPowerCommand),
|
||||
#[options(help = "Set the LED power states")]
|
||||
LedPow1(LedPowerCommand1),
|
||||
#[options(help = "Set the LED power states")]
|
||||
LedPow2(LedPowerCommand2),
|
||||
#[options(help = "Set or select platform_profile")]
|
||||
Profile(ProfileCommand),
|
||||
#[options(help = "Set, select, or modify fan curves if supported")]
|
||||
|
||||
+143
-145
@@ -1,15 +1,16 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::process::Command;
|
||||
use std::thread::sleep;
|
||||
use std::{env::args, path::Path};
|
||||
|
||||
use aura_cli::LedPowerCommand;
|
||||
use aura_cli::{LedPowerCommand1, LedPowerCommand2};
|
||||
use gumdrop::{Opt, Options};
|
||||
|
||||
use anime_cli::{AnimeActions, AnimeCommand};
|
||||
use profiles_cli::{FanCurveCommand, ProfileCommand};
|
||||
use rog_anime::usb::get_anime_type;
|
||||
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
|
||||
use rog_aura::usb::AuraControl;
|
||||
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraPowerDev};
|
||||
use rog_aura::{self, AuraEffect};
|
||||
use rog_dbus::RogDbusClientBlocking;
|
||||
use rog_profiles::error::ProfileError;
|
||||
@@ -27,8 +28,6 @@ mod aura_cli;
|
||||
mod cli_opts;
|
||||
mod profiles_cli;
|
||||
|
||||
const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated";
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args: Vec<String> = args().skip(1).collect();
|
||||
|
||||
@@ -82,15 +81,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
fn print_error_help(err: Box<dyn std::error::Error>, supported: Option<&SupportedFunctions>) {
|
||||
if do_diagnose("asusd") {
|
||||
println!("\nError: {}\n", err);
|
||||
print_versions();
|
||||
check_service("asusd");
|
||||
println!("\nError: {}\n", err);
|
||||
print_versions();
|
||||
println!();
|
||||
print_laptop_info();
|
||||
if let Some(supported) = supported {
|
||||
println!();
|
||||
print_laptop_info();
|
||||
if let Some(supported) = supported {
|
||||
println!();
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
}
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +113,7 @@ fn print_laptop_info() {
|
||||
println!("Board name: {}", board_name.trim());
|
||||
}
|
||||
|
||||
fn do_diagnose(name: &str) -> bool {
|
||||
fn check_service(name: &str) -> bool {
|
||||
if name != "asusd" && !check_systemd_unit_enabled(name) {
|
||||
println!(
|
||||
"\n\x1b[0;31m{} is not enabled, enable it with `systemctl enable {}\x1b[0m",
|
||||
@@ -128,13 +126,6 @@ fn do_diagnose(name: &str) -> bool {
|
||||
name, name
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
println!("\nSome error happened (sorry)");
|
||||
println!(
|
||||
"Please use `systemctl status {}` and `journalctl -b -u {}` for more information",
|
||||
name, name
|
||||
);
|
||||
println!("{}", CONFIG_ADVICE);
|
||||
}
|
||||
false
|
||||
}
|
||||
@@ -146,7 +137,8 @@ fn do_parsed(
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
match &parsed.command {
|
||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?,
|
||||
Some(CliCommand::LedPower(pow)) => handle_led_power(dbus, &supported.keyboard_led, pow)?,
|
||||
Some(CliCommand::LedPow1(pow)) => handle_led_power1(dbus, &supported.keyboard_led, pow)?,
|
||||
Some(CliCommand::LedPow2(pow)) => handle_led_power2(dbus, &supported.keyboard_led, pow)?,
|
||||
Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?,
|
||||
Some(CliCommand::FanCurve(cmd)) => {
|
||||
handle_fan_curve(dbus, &supported.platform_profile, cmd)?
|
||||
@@ -165,7 +157,22 @@ fn do_parsed(
|
||||
println!("{}", CliStart::usage());
|
||||
println!();
|
||||
if let Some(cmdlist) = CliStart::command_list() {
|
||||
println!("{}", cmdlist);
|
||||
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_string()).collect();
|
||||
for command in commands.iter().filter(|command| {
|
||||
if supported.keyboard_led.prod_id != "1866"
|
||||
&& command.trim().starts_with("led-pow-1")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if supported.keyboard_led.prod_id != "19b6"
|
||||
&& command.trim().starts_with("led-pow-2")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}) {
|
||||
println!("{}", command);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nExtra help can be requested on any command or subcommand:");
|
||||
@@ -239,6 +246,13 @@ fn handle_anime(
|
||||
verify_brightness(bright);
|
||||
dbus.proxies().anime().set_brightness(bright)?
|
||||
}
|
||||
if cmd.clear {
|
||||
let anime_type = get_anime_type()?;
|
||||
let data = vec![0u8; anime_type.data_length()];
|
||||
let tmp = AnimeDataBuffer::from_vec(anime_type, data)?;
|
||||
dbus.proxies().anime().write(tmp)?;
|
||||
}
|
||||
|
||||
if let Some(action) = cmd.command.as_ref() {
|
||||
let anime_type = get_anime_type()?;
|
||||
match action {
|
||||
@@ -263,7 +277,7 @@ fn handle_anime(
|
||||
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.write(<AnimeDataBuffer>::from(&matrix))?;
|
||||
.write(<AnimeDataBuffer>::try_from(&matrix)?)?;
|
||||
}
|
||||
AnimeActions::PixelImage(image) => {
|
||||
if image.help_requested() || image.path.is_empty() {
|
||||
@@ -284,7 +298,7 @@ fn handle_anime(
|
||||
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.write(matrix.into_data_buffer(anime_type))?;
|
||||
.write(matrix.into_data_buffer(anime_type)?)?;
|
||||
}
|
||||
AnimeActions::Gif(gif) => {
|
||||
if gif.help_requested() || gif.path.is_empty() {
|
||||
@@ -423,10 +437,67 @@ fn handle_led_mode(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_led_power(
|
||||
fn handle_led_power1(
|
||||
dbus: &RogDbusClientBlocking,
|
||||
_supported: &LedSupportedFunctions,
|
||||
power: &LedPowerCommand,
|
||||
supported: &LedSupportedFunctions,
|
||||
power: &LedPowerCommand1,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if power.awake.is_none()
|
||||
&& power.sleep.is_none()
|
||||
&& power.boot.is_none()
|
||||
&& power.keyboard.is_none()
|
||||
&& power.lightbar.is_none()
|
||||
{
|
||||
if !power.help {
|
||||
println!("Missing arg or command\n");
|
||||
}
|
||||
println!("{}\n", power.self_usage());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if supported.prod_id != "1866" {
|
||||
println!("These options are for keyboards of product ID 0x1866 only");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut enabled: Vec<AuraDev1866> = Vec::new();
|
||||
let mut disabled: Vec<AuraDev1866> = Vec::new();
|
||||
|
||||
let mut check = |e: Option<bool>, a: AuraDev1866| {
|
||||
if let Some(arg) = e {
|
||||
if arg {
|
||||
enabled.push(a);
|
||||
} else {
|
||||
disabled.push(a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
check(power.awake, AuraDev1866::Awake);
|
||||
check(power.boot, AuraDev1866::Boot);
|
||||
check(power.sleep, AuraDev1866::Sleep);
|
||||
check(power.keyboard, AuraDev1866::Keyboard);
|
||||
check(power.lightbar, AuraDev1866::Lightbar);
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: enabled,
|
||||
x19b6: vec![],
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, true)?;
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: disabled,
|
||||
x19b6: vec![],
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, false)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_led_power2(
|
||||
dbus: &RogDbusClientBlocking,
|
||||
supported: &LedSupportedFunctions,
|
||||
power: &LedPowerCommand2,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if power.command().is_none() {
|
||||
if !power.help {
|
||||
@@ -435,7 +506,7 @@ fn handle_led_power(
|
||||
println!("{}\n", power.self_usage());
|
||||
println!("Commands available");
|
||||
|
||||
if let Some(cmdlist) = LedPowerCommand::command_list() {
|
||||
if let Some(cmdlist) = LedPowerCommand2::command_list() {
|
||||
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_string()).collect();
|
||||
for command in commands.iter() {
|
||||
println!("{}", command);
|
||||
@@ -452,133 +523,60 @@ fn handle_led_power(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if supported.prod_id == "1866" {
|
||||
println!("This option does not apply to keyboards with product ID 0x1866")
|
||||
}
|
||||
|
||||
let mut enabled: Vec<AuraDev19b6> = Vec::new();
|
||||
let mut disabled: Vec<AuraDev19b6> = Vec::new();
|
||||
let mut check = |e: Option<bool>, a: AuraDev19b6| {
|
||||
if let Some(arg) = e {
|
||||
if arg {
|
||||
enabled.push(a);
|
||||
} else {
|
||||
disabled.push(a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match pow {
|
||||
// TODO: make this a macro or something
|
||||
aura_cli::SetAuraEnabled::Boot(arg) => {
|
||||
let mut enabled: Vec<AuraControl> = Vec::new();
|
||||
let mut disabled: Vec<AuraControl> = Vec::new();
|
||||
arg.keyboard.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::BootKeyb)
|
||||
} else {
|
||||
disabled.push(AuraControl::BootKeyb)
|
||||
}
|
||||
});
|
||||
arg.logo.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::BootLogo)
|
||||
} else {
|
||||
disabled.push(AuraControl::BootLogo)
|
||||
}
|
||||
});
|
||||
arg.lightbar.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::BootBar)
|
||||
} else {
|
||||
disabled.push(AuraControl::BootBar)
|
||||
}
|
||||
});
|
||||
if !enabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_enabled(enabled)?;
|
||||
}
|
||||
if !disabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_disabled(disabled)?;
|
||||
}
|
||||
check(arg.keyboard, AuraDev19b6::BootKeyb);
|
||||
check(arg.logo, AuraDev19b6::BootLogo);
|
||||
check(arg.lightbar, AuraDev19b6::BootBar);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Sleep(arg) => {
|
||||
let mut enabled: Vec<AuraControl> = Vec::new();
|
||||
let mut disabled: Vec<AuraControl> = Vec::new();
|
||||
arg.keyboard.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::SleepKeyb)
|
||||
} else {
|
||||
disabled.push(AuraControl::SleepKeyb)
|
||||
}
|
||||
});
|
||||
arg.logo.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::SleepLogo)
|
||||
} else {
|
||||
disabled.push(AuraControl::SleepLogo)
|
||||
}
|
||||
});
|
||||
arg.lightbar.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::SleepBar)
|
||||
} else {
|
||||
disabled.push(AuraControl::SleepBar)
|
||||
}
|
||||
});
|
||||
if !enabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_enabled(enabled)?;
|
||||
}
|
||||
if !disabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_disabled(disabled)?;
|
||||
}
|
||||
check(arg.keyboard, AuraDev19b6::SleepKeyb);
|
||||
check(arg.logo, AuraDev19b6::SleepLogo);
|
||||
check(arg.lightbar, AuraDev19b6::SleepBar);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Awake(arg) => {
|
||||
let mut enabled: Vec<AuraControl> = Vec::new();
|
||||
let mut disabled: Vec<AuraControl> = Vec::new();
|
||||
arg.keyboard.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::AwakeKeyb)
|
||||
} else {
|
||||
disabled.push(AuraControl::AwakeKeyb)
|
||||
}
|
||||
});
|
||||
arg.logo.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::AwakeLogo)
|
||||
} else {
|
||||
disabled.push(AuraControl::AwakeLogo)
|
||||
}
|
||||
});
|
||||
arg.lightbar.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::AwakeBar)
|
||||
} else {
|
||||
disabled.push(AuraControl::AwakeBar)
|
||||
}
|
||||
});
|
||||
if !enabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_enabled(enabled)?;
|
||||
}
|
||||
if !disabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_disabled(disabled)?;
|
||||
}
|
||||
check(arg.keyboard, AuraDev19b6::AwakeKeyb);
|
||||
check(arg.logo, AuraDev19b6::AwakeLogo);
|
||||
check(arg.lightbar, AuraDev19b6::AwakeBar);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Shutdown(arg) => {
|
||||
let mut enabled: Vec<AuraControl> = Vec::new();
|
||||
let mut disabled: Vec<AuraControl> = Vec::new();
|
||||
arg.keyboard.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::ShutdownKeyb)
|
||||
} else {
|
||||
disabled.push(AuraControl::ShutdownKeyb)
|
||||
}
|
||||
});
|
||||
arg.logo.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::ShutdownLogo)
|
||||
} else {
|
||||
disabled.push(AuraControl::ShutdownLogo)
|
||||
}
|
||||
});
|
||||
arg.lightbar.map(|v| {
|
||||
if v {
|
||||
enabled.push(AuraControl::ShutdownBar)
|
||||
} else {
|
||||
disabled.push(AuraControl::ShutdownBar)
|
||||
}
|
||||
});
|
||||
if !enabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_enabled(enabled)?;
|
||||
}
|
||||
if !disabled.is_empty() {
|
||||
dbus.proxies().led().set_leds_disabled(disabled)?;
|
||||
}
|
||||
check(arg.keyboard, AuraDev19b6::ShutdownKeyb);
|
||||
check(arg.logo, AuraDev19b6::ShutdownLogo);
|
||||
check(arg.lightbar, AuraDev19b6::ShutdownBar);
|
||||
}
|
||||
}
|
||||
|
||||
if !enabled.is_empty() {
|
||||
let data = AuraPowerDev {
|
||||
x1866: vec![],
|
||||
x19b6: enabled,
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, true)?;
|
||||
}
|
||||
|
||||
if !disabled.is_empty() {
|
||||
let data = AuraPowerDev {
|
||||
x1866: vec![],
|
||||
x19b6: disabled,
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, false)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "daemon"
|
||||
version = "4.2.1"
|
||||
version = "4.3.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
@@ -18,6 +18,7 @@ use rusb::{Device, DeviceHandle};
|
||||
use smol::{stream::StreamExt, Executor};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
convert::TryFrom,
|
||||
error::Error,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
thread::sleep,
|
||||
@@ -167,7 +168,14 @@ impl CtrlAnime {
|
||||
inner
|
||||
.try_lock()
|
||||
.map(|lock| {
|
||||
lock.write_data_buffer(frame);
|
||||
lock.write_data_buffer(frame)
|
||||
.map_err(|err| {
|
||||
warn!(
|
||||
"rog_anime::run_animation:callback {}",
|
||||
err
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
false // Don't exit yet
|
||||
})
|
||||
.map_err(|err| {
|
||||
@@ -183,6 +191,8 @@ impl CtrlAnime {
|
||||
once = false;
|
||||
if let Ok(lock) = inner.try_lock() {
|
||||
lock.write_data_buffer(image.as_ref().clone())
|
||||
.map_err(|e| error!("{}", e))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
ActionData::Pause(duration) => sleep(*duration),
|
||||
@@ -201,9 +211,16 @@ impl CtrlAnime {
|
||||
}
|
||||
// Clear the display on exit
|
||||
if let Ok(lock) = inner.try_lock() {
|
||||
let data =
|
||||
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()]);
|
||||
lock.write_data_buffer(data);
|
||||
if let Ok(data) =
|
||||
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()])
|
||||
.map_err(|e| error!("{}", e))
|
||||
{
|
||||
lock.write_data_buffer(data)
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
// Loop ended, set the atmonics
|
||||
thread_running.store(false, Ordering::SeqCst);
|
||||
@@ -254,7 +271,7 @@ impl CtrlAnime {
|
||||
|
||||
/// Write only a data packet. This will modify the leds brightness using the
|
||||
/// global brightness set in config.
|
||||
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) {
|
||||
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> {
|
||||
for led in buffer.data_mut()[7..].iter_mut() {
|
||||
let mut bright = *led as f32 * self.config.brightness;
|
||||
if bright > 254.0 {
|
||||
@@ -262,11 +279,12 @@ impl CtrlAnime {
|
||||
}
|
||||
*led = bright as u8;
|
||||
}
|
||||
let data = AnimePacketType::from(buffer);
|
||||
let data = AnimePacketType::try_from(buffer)?;
|
||||
for row in data.iter() {
|
||||
self.write_bytes(row);
|
||||
}
|
||||
self.write_bytes(&pkt_for_flush());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_initialization(&self) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::warn;
|
||||
use rog_anime::{
|
||||
usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on},
|
||||
AnimeDataBuffer, AnimePowerStates,
|
||||
@@ -27,14 +28,18 @@ impl crate::ZbusAdd for CtrlAnimeZbus {
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlAnimeZbus {
|
||||
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
||||
fn write(&self, input: AnimeDataBuffer) {
|
||||
fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
|
||||
'outer: loop {
|
||||
if let Ok(lock) = self.0.try_lock() {
|
||||
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||
lock.write_data_buffer(input);
|
||||
lock.write_data_buffer(input).map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
err
|
||||
})?;
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the global AniMe brightness
|
||||
|
||||
@@ -1,14 +1,75 @@
|
||||
use crate::laptops::LaptopLedData;
|
||||
use crate::laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
|
||||
use log::{error, warn};
|
||||
use rog_aura::usb::AuraControl;
|
||||
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraPowerDev};
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use super::controller::CtrlKbdLed;
|
||||
|
||||
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
|
||||
|
||||
/// Enable/disable LED control in various states such as
|
||||
/// when the device is awake, suspended, shutting down or
|
||||
/// booting.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum AuraPowerConfig {
|
||||
AuraDev1866(HashSet<AuraDev1866>),
|
||||
AuraDev19b6(HashSet<AuraDev19b6>),
|
||||
}
|
||||
|
||||
impl AuraPowerConfig {
|
||||
pub fn to_bytes(control: &Self) -> [u8; 3] {
|
||||
match control {
|
||||
AuraPowerConfig::AuraDev1866(c) => {
|
||||
let c: Vec<AuraDev1866> = c.iter().map(|v| *v).collect();
|
||||
AuraDev1866::to_bytes(&c)
|
||||
}
|
||||
AuraPowerConfig::AuraDev19b6(c) => {
|
||||
let c: Vec<AuraDev19b6> = c.iter().map(|v| *v).collect();
|
||||
AuraDev19b6::to_bytes(&c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_0x1866(&mut self, power: AuraDev1866, on: bool) {
|
||||
if let Self::AuraDev1866(p) = self {
|
||||
if on {
|
||||
p.insert(power);
|
||||
} else {
|
||||
p.remove(&power);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_0x19b6(&mut self, power: AuraDev19b6, on: bool) {
|
||||
if let Self::AuraDev19b6(p) = self {
|
||||
if on {
|
||||
p.insert(power);
|
||||
} else {
|
||||
p.remove(&power);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AuraPowerConfig> for AuraPowerDev {
|
||||
fn from(config: &AuraPowerConfig) -> Self {
|
||||
match config {
|
||||
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev {
|
||||
x1866: d.iter().map(|o| *o).collect(),
|
||||
x19b6: vec![],
|
||||
},
|
||||
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev {
|
||||
x1866: vec![],
|
||||
x19b6: d.iter().map(|o| *o).collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct AuraConfig {
|
||||
@@ -17,31 +78,51 @@ pub struct AuraConfig {
|
||||
pub builtins: BTreeMap<AuraModeNum, AuraEffect>,
|
||||
pub multizone: Option<BTreeMap<AuraModeNum, Vec<AuraEffect>>>,
|
||||
pub multizone_on: bool,
|
||||
pub enabled: HashSet<AuraControl>,
|
||||
pub enabled: AuraPowerConfig,
|
||||
}
|
||||
|
||||
impl Default for AuraConfig {
|
||||
fn default() -> Self {
|
||||
let mut prod_id = String::new();
|
||||
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||
if let Ok(_) = CtrlKbdLed::find_led_node(prod) {
|
||||
prod_id = prod.to_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let enabled = if prod_id == "19b6" {
|
||||
AuraPowerConfig::AuraDev19b6(HashSet::from([
|
||||
AuraDev19b6::BootLogo,
|
||||
AuraDev19b6::BootKeyb,
|
||||
AuraDev19b6::SleepLogo,
|
||||
AuraDev19b6::SleepKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
AuraDev19b6::AwakeBar,
|
||||
AuraDev19b6::BootBar,
|
||||
AuraDev19b6::SleepBar,
|
||||
AuraDev19b6::ShutdownBar,
|
||||
]))
|
||||
} else {
|
||||
AuraPowerConfig::AuraDev1866(HashSet::from([
|
||||
AuraDev1866::Awake,
|
||||
AuraDev1866::Boot,
|
||||
AuraDev1866::Sleep,
|
||||
AuraDev1866::Keyboard,
|
||||
AuraDev1866::Lightbar,
|
||||
]))
|
||||
};
|
||||
|
||||
AuraConfig {
|
||||
brightness: LedBrightness::Med,
|
||||
current_mode: AuraModeNum::Static,
|
||||
builtins: BTreeMap::new(),
|
||||
multizone: None,
|
||||
multizone_on: false,
|
||||
enabled: HashSet::from([
|
||||
AuraControl::BootLogo,
|
||||
AuraControl::BootKeyb,
|
||||
AuraControl::SleepLogo,
|
||||
AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraControl::AwakeBar,
|
||||
AuraControl::BootBar,
|
||||
AuraControl::SleepBar,
|
||||
AuraControl::ShutdownBar,
|
||||
]),
|
||||
enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ use crate::{
|
||||
use async_trait::async_trait;
|
||||
use log::{error, info, warn};
|
||||
use logind_zbus::manager::ManagerProxy;
|
||||
use rog_aura::{usb::AuraControl, AuraZone, Direction, Speed, GRADIENT};
|
||||
use rog_aura::{
|
||||
usb::{LED_APPLY, LED_SET},
|
||||
AuraEffect, LedBrightness, LED_MSG_LEN,
|
||||
};
|
||||
use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
|
||||
use rog_supported::LedSupportedFunctions;
|
||||
use smol::{stream::StreamExt, Executor};
|
||||
use std::path::Path;
|
||||
@@ -28,7 +28,7 @@ use zbus::Connection;
|
||||
|
||||
use crate::GetSupported;
|
||||
|
||||
use super::config::AuraConfig;
|
||||
use super::config::{AuraConfig, AuraPowerConfig};
|
||||
|
||||
impl GetSupported for CtrlKbdLed {
|
||||
type A = LedSupportedFunctions;
|
||||
@@ -40,7 +40,16 @@ impl GetSupported for CtrlKbdLed {
|
||||
let multizone_led_mode = laptop.multizone;
|
||||
let per_key_led_mode = laptop.per_key;
|
||||
|
||||
let mut prod_id = String::new();
|
||||
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||
if let Ok(_) = Self::find_led_node(prod) {
|
||||
prod_id = prod.to_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LedSupportedFunctions {
|
||||
prod_id,
|
||||
brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(),
|
||||
stock_led_modes,
|
||||
multizone_led_mode,
|
||||
@@ -50,6 +59,8 @@ impl GetSupported for CtrlKbdLed {
|
||||
}
|
||||
|
||||
pub struct CtrlKbdLed {
|
||||
// TODO: config stores the keyboard type as an AuraPower, use or update this
|
||||
pub led_prod: Option<String>,
|
||||
pub led_node: Option<String>,
|
||||
pub bright_node: String,
|
||||
pub supported_modes: LaptopLedData,
|
||||
@@ -184,10 +195,12 @@ impl CtrlKbdLedZbus {
|
||||
impl CtrlKbdLed {
|
||||
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
||||
// TODO: return error if *all* nodes are None
|
||||
let mut led_prod = None;
|
||||
let mut led_node = None;
|
||||
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||
match Self::find_led_node(prod) {
|
||||
Ok(node) => {
|
||||
led_prod = Some(prod.to_string());
|
||||
led_node = Some(node);
|
||||
info!("Looked for keyboard controller 0x{prod}: Found");
|
||||
break;
|
||||
@@ -209,6 +222,7 @@ impl CtrlKbdLed {
|
||||
}
|
||||
|
||||
let ctrl = CtrlKbdLed {
|
||||
led_prod,
|
||||
led_node,
|
||||
bright_node: bright_node.unwrap(), // If was none then we already returned above
|
||||
supported_modes,
|
||||
@@ -282,12 +296,8 @@ impl CtrlKbdLed {
|
||||
|
||||
/// Set combination state for boot animation/sleep animation/all leds/keys leds/side leds LED active
|
||||
pub(super) fn set_power_states(&self, config: &AuraConfig) -> Result<(), RogError> {
|
||||
let set: Vec<AuraControl> = config.enabled.iter().map(|v| *v).collect();
|
||||
let bytes = AuraControl::to_bytes(&set);
|
||||
|
||||
let message = [
|
||||
0x5d, 0xbd, 0x01, bytes[0], bytes[1], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
let bytes = AuraPowerConfig::to_bytes(&config.enabled);
|
||||
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
|
||||
|
||||
self.write_bytes(&message)?;
|
||||
self.write_bytes(&LED_SET)?;
|
||||
@@ -296,7 +306,7 @@ impl CtrlKbdLed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_led_node(id_product: &str) -> Result<String, RogError> {
|
||||
pub(crate) fn find_led_node(id_product: &str) -> Result<String, RogError> {
|
||||
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
||||
warn!("{}", err);
|
||||
RogError::Udev("enumerator failed".into(), err)
|
||||
@@ -407,10 +417,10 @@ impl CtrlKbdLed {
|
||||
let next = self.supported_modes.standard[idx];
|
||||
|
||||
self.config.read();
|
||||
if self.config.builtins.contains_key(&next) {
|
||||
// if self.config.builtins.contains_key(&next) {
|
||||
self.config.current_mode = next;
|
||||
self.write_current_config_mode()?;
|
||||
}
|
||||
// }
|
||||
self.config.write();
|
||||
}
|
||||
|
||||
@@ -511,6 +521,7 @@ mod tests {
|
||||
per_key: false,
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: None,
|
||||
led_node: None,
|
||||
bright_node: String::new(),
|
||||
supported_modes,
|
||||
@@ -572,6 +583,7 @@ mod tests {
|
||||
per_key: false,
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: None,
|
||||
led_node: None,
|
||||
bright_node: String::new(),
|
||||
supported_modes,
|
||||
@@ -608,6 +620,7 @@ mod tests {
|
||||
per_key: false,
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: None,
|
||||
led_node: None,
|
||||
bright_node: String::new(),
|
||||
supported_modes,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use async_trait::async_trait;
|
||||
use log::warn;
|
||||
use rog_aura::{usb::AuraControl, AuraEffect, LedBrightness};
|
||||
use rog_aura::{usb::AuraPowerDev, AuraEffect, LedBrightness, AuraModeNum};
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
|
||||
use super::controller::CtrlKbdLedZbus;
|
||||
@@ -8,7 +8,7 @@ use super::controller::CtrlKbdLedZbus;
|
||||
#[async_trait]
|
||||
impl crate::ZbusAdd for CtrlKbdLedZbus {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, "/org/asuslinux/Led", server).await;
|
||||
Self::add_to_server_helper(self, "/org/asuslinux/Aura", server).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,16 +42,21 @@ impl CtrlKbdLedZbus {
|
||||
/// SleepBar,
|
||||
/// ShutdownBar,
|
||||
/// }
|
||||
async fn set_leds_enabled(
|
||||
async fn set_leds_power(
|
||||
&mut self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
enabled: Vec<AuraControl>,
|
||||
options: AuraPowerDev,
|
||||
enabled: bool,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut states = None;
|
||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
||||
for s in enabled {
|
||||
ctrl.config.enabled.insert(s);
|
||||
for p in options.x1866 {
|
||||
ctrl.config.enabled.set_0x1866(p, enabled);
|
||||
}
|
||||
for p in options.x19b6 {
|
||||
ctrl.config.enabled.set_0x19b6(p, enabled);
|
||||
}
|
||||
|
||||
ctrl.config.write();
|
||||
|
||||
ctrl.set_power_states(&ctrl.config).map_err(|e| {
|
||||
@@ -59,37 +64,7 @@ impl CtrlKbdLedZbus {
|
||||
e
|
||||
})?;
|
||||
|
||||
let set: Vec<AuraControl> = ctrl.config.enabled.iter().map(|v| *v).collect();
|
||||
states = Some(set);
|
||||
}
|
||||
// Need to pull state out like this due to MutexGuard
|
||||
if let Some(states) = states {
|
||||
Self::notify_power_states(&ctxt, &states)
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_leds_disabled(
|
||||
&mut self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
disabled: Vec<AuraControl>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut states = None;
|
||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
||||
for s in disabled {
|
||||
ctrl.config.enabled.remove(&s);
|
||||
}
|
||||
ctrl.config.write();
|
||||
|
||||
ctrl.set_power_states(&ctrl.config).map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let set: Vec<AuraControl> = ctrl.config.enabled.iter().map(|v| *v).collect();
|
||||
states = Some(set);
|
||||
states = Some(AuraPowerDev::from(&ctrl.config.enabled));
|
||||
}
|
||||
// Need to pull state out like this due to MutexGuard
|
||||
if let Some(states) = states {
|
||||
@@ -189,27 +164,22 @@ impl CtrlKbdLedZbus {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[dbus_interface(property)]
|
||||
async fn leds_enabled(&self) -> Vec<u8> {
|
||||
if let Ok(ctrl) = self.0.try_lock() {
|
||||
let set: Vec<AuraControl> = ctrl.config.enabled.iter().map(|v| *v).collect();
|
||||
return AuraControl::to_bytes(&set).to_vec();
|
||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||
// #[dbus_interface(property)]
|
||||
async fn leds_power(&self) -> AuraPowerDev {
|
||||
loop {
|
||||
if let Ok(ctrl) = self.0.try_lock() {
|
||||
return AuraPowerDev::from(&ctrl.config.enabled);
|
||||
}
|
||||
}
|
||||
vec![0, 0]
|
||||
}
|
||||
|
||||
/// Return the current mode data
|
||||
#[dbus_interface(property)]
|
||||
async fn led_mode(&self) -> String {
|
||||
async fn led_mode(&self) -> AuraModeNum {
|
||||
if let Ok(ctrl) = self.0.try_lock() {
|
||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||
if let Ok(json) = serde_json::to_string(&mode) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
return ctrl.config.current_mode;
|
||||
}
|
||||
warn!("SetKeyBacklight could not deserialise");
|
||||
"SetKeyBacklight could not deserialise".to_string()
|
||||
AuraModeNum::Static
|
||||
}
|
||||
|
||||
/// Return a list of available modes
|
||||
@@ -240,6 +210,6 @@ impl CtrlKbdLedZbus {
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_power_states(
|
||||
signal_ctxt: &SignalContext<'_>,
|
||||
data: &[AuraControl],
|
||||
data: &AuraPowerDev,
|
||||
) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use rog_anime::error::AnimeError;
|
||||
use rog_profiles::error::ProfileError;
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
@@ -26,6 +27,7 @@ pub enum RogError {
|
||||
AuraEffectNotSupported,
|
||||
NoAuraKeyboard,
|
||||
NoAuraNode,
|
||||
Anime(AnimeError),
|
||||
}
|
||||
|
||||
impl fmt::Display for RogError {
|
||||
@@ -54,6 +56,7 @@ impl fmt::Display for RogError {
|
||||
RogError::AuraEffectNotSupported => write!(f, "Aura effect not supported"),
|
||||
RogError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
|
||||
RogError::NoAuraNode => write!(f, "No Aura keyboard node found"),
|
||||
RogError::Anime(deets) => write!(f, "AniMe Matrix error: {}", deets),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +69,12 @@ impl From<ProfileError> for RogError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnimeError> for RogError {
|
||||
fn from(err: AnimeError) -> Self {
|
||||
RogError::Anime(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<zbus::Error> for RogError {
|
||||
fn from(err: zbus::Error) -> Self {
|
||||
RogError::Zbus(err)
|
||||
|
||||
@@ -50,7 +50,7 @@ per_key = false
|
||||
|
||||
[[led_data]]
|
||||
prod_family = "ROG Strix"
|
||||
board_names = ["G531GW", "G533QR", "G533QS", "G733QS", "G733QR", "G513QR", "G713QR", "G513QM"]
|
||||
board_names = ["G531GW", "G533QR", "G533QS", "G733QS", "G733QR", "G513QR", "G713QR", "G513QM", "G713IC"]
|
||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||
multizone = []
|
||||
per_key = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog_anime"
|
||||
version = "1.3.4"
|
||||
version = "1.3.5"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
@@ -14,7 +14,7 @@ exclude = ["data"]
|
||||
|
||||
[features]
|
||||
default = ["dbus", "detect"]
|
||||
dbus = ["zvariant"]
|
||||
dbus = ["zvariant", "zbus"]
|
||||
detect = ["udev", "sysfs-class"]
|
||||
|
||||
[dependencies]
|
||||
@@ -29,6 +29,7 @@ serde_derive = "^1.0"
|
||||
glam = { version = "0.20.5", features = ["serde"] }
|
||||
|
||||
zvariant = { version = "^3.0", optional = true }
|
||||
zbus = { version = "^2.2", optional = true }
|
||||
|
||||
udev = { version = "^0.6", optional = true }
|
||||
sysfs-class = { version = "^0.1", optional = true }
|
||||
+20
-11
@@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
@@ -8,7 +9,10 @@ use serde_derive::{Deserialize, Serialize};
|
||||
#[cfg(feature = "dbus")]
|
||||
use zvariant::Type;
|
||||
|
||||
use crate::{error::AnimeError, AnimTime, AnimeGif};
|
||||
use crate::{
|
||||
error::{AnimeError, Result},
|
||||
AnimTime, AnimeGif,
|
||||
};
|
||||
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
|
||||
const BLOCK_START: usize = 7;
|
||||
@@ -102,20 +106,25 @@ impl AnimeDataBuffer {
|
||||
/// # Panics
|
||||
/// Will panic if the vector length is not `ANIME_DATA_LEN`
|
||||
#[inline]
|
||||
pub fn from_vec(anime: AnimeType, data: Vec<u8>) -> Self {
|
||||
assert_eq!(data.len(), anime.data_length());
|
||||
pub fn from_vec(anime: AnimeType, data: Vec<u8>) -> Result<Self> {
|
||||
if data.len() != anime.data_length() {
|
||||
return Err(AnimeError::DataBufferLength);
|
||||
}
|
||||
|
||||
Self { data, anime }
|
||||
Ok(Self { data, anime })
|
||||
}
|
||||
}
|
||||
|
||||
/// The two packets to be written to USB
|
||||
pub type AnimePacketType = Vec<[u8; 640]>;
|
||||
|
||||
impl From<AnimeDataBuffer> for AnimePacketType {
|
||||
#[inline]
|
||||
fn from(anime: AnimeDataBuffer) -> Self {
|
||||
assert_eq!(anime.data.len(), anime.anime.data_length());
|
||||
impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
||||
type Error = AnimeError;
|
||||
|
||||
fn try_from(anime: AnimeDataBuffer) -> std::result::Result<Self, Self::Error> {
|
||||
if anime.data.len() != anime.anime.data_length() {
|
||||
return Err(AnimeError::DataBufferLength);
|
||||
}
|
||||
|
||||
let mut buffers = match anime.anime {
|
||||
AnimeType::GA401 => vec![[0; 640]; 2],
|
||||
@@ -131,7 +140,7 @@ impl From<AnimeDataBuffer> for AnimePacketType {
|
||||
if matches!(anime.anime, AnimeType::GA402) {
|
||||
buffers[2][..7].copy_from_slice(&USB_PREFIX3);
|
||||
}
|
||||
buffers
|
||||
Ok(buffers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,8 +149,8 @@ impl From<AnimeDataBuffer> for AnimePacketType {
|
||||
/// If `callback` is `Ok(true)` then `run_animation` will exit the animation loop early.
|
||||
pub fn run_animation(
|
||||
frames: &AnimeGif,
|
||||
callback: &dyn Fn(AnimeDataBuffer) -> Result<bool, AnimeError>,
|
||||
) -> Result<(), AnimeError> {
|
||||
callback: &dyn Fn(AnimeDataBuffer) -> Result<bool>,
|
||||
) -> Result<()> {
|
||||
let mut count = 0;
|
||||
let start = Instant::now();
|
||||
|
||||
|
||||
+16
-12
@@ -1,6 +1,10 @@
|
||||
use std::{path::Path, time::Duration};
|
||||
|
||||
use crate::{data::AnimeDataBuffer, error::AnimeError, AnimeType};
|
||||
use crate::{
|
||||
data::AnimeDataBuffer,
|
||||
error::{AnimeError, Result},
|
||||
AnimeType,
|
||||
};
|
||||
|
||||
/// Mostly intended to be used with ASUS gifs, but can be used for other purposes (like images)
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -40,7 +44,7 @@ impl AnimeDiagonal {
|
||||
duration: Option<Duration>,
|
||||
bright: f32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let data = std::fs::read(path)?;
|
||||
let data = std::io::Cursor::new(data);
|
||||
let decoder = png_pong::Decoder::new(data)?.into_steps();
|
||||
@@ -125,7 +129,7 @@ impl AnimeDiagonal {
|
||||
|
||||
/// Convert to a data buffer that can be sent over dbus
|
||||
#[inline]
|
||||
pub fn into_data_buffer(&self, anime_type: AnimeType) -> AnimeDataBuffer {
|
||||
pub fn into_data_buffer(&self, anime_type: AnimeType) -> Result<AnimeDataBuffer> {
|
||||
match anime_type {
|
||||
AnimeType::GA401 => self.into_ga401_packets(),
|
||||
AnimeType::GA402 => self.into_ga402_packets(),
|
||||
@@ -134,7 +138,7 @@ impl AnimeDiagonal {
|
||||
|
||||
/// Do conversion from the nested Vec in AnimeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
fn into_ga401_packets(&self) -> AnimeDataBuffer {
|
||||
fn into_ga401_packets(&self) -> Result<AnimeDataBuffer> {
|
||||
let mut buf = vec![0u8; AnimeType::GA401.data_length()];
|
||||
|
||||
buf[1..=32].copy_from_slice(&self.get_row(0, 3, 32));
|
||||
@@ -196,7 +200,7 @@ impl AnimeDiagonal {
|
||||
AnimeDataBuffer::from_vec(crate::AnimeType::GA401, buf)
|
||||
}
|
||||
|
||||
fn into_ga402_packets(&self) -> AnimeDataBuffer {
|
||||
fn into_ga402_packets(&self) -> Result<AnimeDataBuffer> {
|
||||
let mut buf = vec![0u8; AnimeType::GA402.data_length()];
|
||||
let mut start_index: usize = 0;
|
||||
|
||||
@@ -282,7 +286,7 @@ impl AnimeDiagonal {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
use std::{convert::TryFrom, path::PathBuf};
|
||||
|
||||
use crate::{AnimeDiagonal, AnimePacketType, AnimeType};
|
||||
|
||||
@@ -374,8 +378,8 @@ mod tests {
|
||||
path.push("test/ga401-diagonal.png");
|
||||
|
||||
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA401).unwrap();
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA401);
|
||||
let pkt = AnimePacketType::from(data);
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA401).unwrap();
|
||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
||||
|
||||
assert_eq!(pkt[0], pkt0_check);
|
||||
assert_eq!(pkt[1], pkt1_check);
|
||||
@@ -509,8 +513,8 @@ mod tests {
|
||||
path.push("test/ga402-diagonal.png");
|
||||
|
||||
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA402);
|
||||
let pkt = AnimePacketType::from(data);
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA402).unwrap();
|
||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
||||
|
||||
assert_eq!(pkt[0], pkt0_check);
|
||||
assert_eq!(pkt[1], pkt1_check);
|
||||
@@ -654,8 +658,8 @@ mod tests {
|
||||
path.push("test/ga402-diagonal-fullbright.png");
|
||||
|
||||
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA402);
|
||||
let pkt = AnimePacketType::from(data);
|
||||
let data = matrix.into_data_buffer(crate::AnimeType::GA402).unwrap();
|
||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
||||
|
||||
assert_eq!(pkt[0], pkt0_check);
|
||||
assert_eq!(pkt[1], pkt1_check);
|
||||
|
||||
@@ -3,6 +3,8 @@ use png_pong::decode::Error as PngError;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, AnimeError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AnimeError {
|
||||
NoFrames,
|
||||
@@ -17,6 +19,9 @@ pub enum AnimeError {
|
||||
NoDevice,
|
||||
UnsupportedDevice,
|
||||
InvalidBrightness(f32),
|
||||
DataBufferLength,
|
||||
PixelGifWidth(usize),
|
||||
PixelGifHeight(usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for AnimeError {
|
||||
@@ -36,12 +41,23 @@ impl fmt::Display for AnimeError {
|
||||
AnimeError::Dbus(detail) => write!(f, "{}", detail),
|
||||
AnimeError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
|
||||
AnimeError::NoDevice => write!(f, "No AniMe Matrix device found"),
|
||||
AnimeError::DataBufferLength => write!(
|
||||
f,
|
||||
"The data buffer was incorrect length for generating USB packets"
|
||||
),
|
||||
AnimeError::UnsupportedDevice => write!(f, "Unsupported AniMe Matrix device found"),
|
||||
AnimeError::InvalidBrightness(bright) => write!(
|
||||
f,
|
||||
"Image brightness must be between 0.0 and 1.0 (inclusive), was {}",
|
||||
bright
|
||||
),
|
||||
AnimeError::PixelGifWidth(n) => {
|
||||
write!(f, "The gif used for pixel-perfect gif is is wider than {n}")
|
||||
}
|
||||
AnimeError::PixelGifHeight(n) => write!(
|
||||
f,
|
||||
"The gif used for pixel-perfect gif is is taller than {n}"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,3 +84,10 @@ impl From<DecodingError> for AnimeError {
|
||||
AnimeError::Gif(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnimeError> for zbus::fdo::Error {
|
||||
#[inline]
|
||||
fn from(err: AnimeError) -> Self {
|
||||
zbus::fdo::Error::Failed(format!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
+22
-11
@@ -1,8 +1,10 @@
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::{fs::File, path::Path, time::Duration};
|
||||
|
||||
use crate::{error::AnimeError, AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel};
|
||||
use crate::error::AnimeError;
|
||||
use crate::{error::Result, AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AnimeFrame {
|
||||
@@ -93,7 +95,7 @@ impl AnimeGif {
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let mut matrix = AnimeDiagonal::new(anime_type, None);
|
||||
|
||||
let mut decoder = gif::DecodeOptions::new();
|
||||
@@ -116,13 +118,22 @@ impl AnimeGif {
|
||||
// should be t but not in some gifs? What, ASUS, what?
|
||||
continue;
|
||||
}
|
||||
matrix.get_mut()[y + frame.top as usize][x + frame.left as usize] =
|
||||
(px[0] as f32 * brightness) as u8;
|
||||
let tmp = matrix.get_mut();
|
||||
let y = y + frame.top as usize;
|
||||
if y >= tmp.len() {
|
||||
return Err(AnimeError::PixelGifHeight(tmp.len()));
|
||||
}
|
||||
let x = x + frame.left as usize;
|
||||
if x >= tmp[y].len() {
|
||||
return Err(AnimeError::PixelGifWidth(tmp[y].len()));
|
||||
}
|
||||
|
||||
matrix.get_mut()[y][x] = (px[0] as f32 * brightness) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
frames.push(AnimeFrame {
|
||||
data: matrix.into_data_buffer(anime_type),
|
||||
data: matrix.into_data_buffer(anime_type)?,
|
||||
delay: Duration::from_millis(wait as u64),
|
||||
});
|
||||
}
|
||||
@@ -136,7 +147,7 @@ impl AnimeGif {
|
||||
anime_type: AnimeType,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let image = AnimeDiagonal::from_png(file_name, None, brightness, anime_type)?;
|
||||
|
||||
let mut total = Duration::from_millis(1000);
|
||||
@@ -150,7 +161,7 @@ impl AnimeGif {
|
||||
let frame_count = total.as_millis() / 30;
|
||||
|
||||
let single = AnimeFrame {
|
||||
data: image.into_data_buffer(anime_type),
|
||||
data: image.into_data_buffer(anime_type)?,
|
||||
delay: Duration::from_millis(30),
|
||||
};
|
||||
let frames = vec![single; frame_count as usize];
|
||||
@@ -169,7 +180,7 @@ impl AnimeGif {
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let mut frames = Vec::new();
|
||||
|
||||
let mut decoder = gif::DecodeOptions::new();
|
||||
@@ -225,7 +236,7 @@ impl AnimeGif {
|
||||
image.update();
|
||||
|
||||
frames.push(AnimeFrame {
|
||||
data: <AnimeDataBuffer>::from(&image),
|
||||
data: <AnimeDataBuffer>::try_from(&image)?,
|
||||
delay: Duration::from_millis(wait as u64),
|
||||
});
|
||||
}
|
||||
@@ -244,7 +255,7 @@ impl AnimeGif {
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let image =
|
||||
AnimeImage::from_png(file_name, scale, angle, translation, brightness, anime_type)?;
|
||||
|
||||
@@ -259,7 +270,7 @@ impl AnimeGif {
|
||||
let frame_count = total.as_millis() / 30;
|
||||
|
||||
let single = AnimeFrame {
|
||||
data: <AnimeDataBuffer>::from(&image),
|
||||
data: <AnimeDataBuffer>::try_from(&image)?,
|
||||
delay: Duration::from_millis(30),
|
||||
};
|
||||
let frames = vec![single; frame_count as usize];
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::data::AnimeDataBuffer;
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::{AnimeImage, AnimeType};
|
||||
|
||||
// TODO: Adjust these sizes as WIDTH_GA401 WIDTH_GA402
|
||||
@@ -87,11 +90,12 @@ impl AnimeGrid {
|
||||
// }
|
||||
}
|
||||
|
||||
impl From<AnimeGrid> for AnimeDataBuffer {
|
||||
impl TryFrom<AnimeGrid> for AnimeDataBuffer {
|
||||
type Error = AnimeError;
|
||||
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(anime: AnimeGrid) -> Self {
|
||||
fn try_from(anime: AnimeGrid) -> Result<Self> {
|
||||
let mut buf = vec![0u8; anime.anime_type.data_length()];
|
||||
|
||||
for (idx, pos) in AnimeImage::generate_image_positioning(anime.anime_type)
|
||||
@@ -123,7 +127,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = <AnimeDataBuffer>::from(matrix);
|
||||
let matrix = <AnimeDataBuffer>::try_from(matrix).unwrap();
|
||||
|
||||
let data_cmp = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
+16
-11
@@ -1,9 +1,13 @@
|
||||
use std::path::Path;
|
||||
use std::{convert::TryFrom, path::Path};
|
||||
|
||||
pub use glam::Vec2;
|
||||
use glam::{Mat3, Vec3};
|
||||
|
||||
use crate::{data::AnimeDataBuffer, error::AnimeError, AnimeType};
|
||||
use crate::{
|
||||
data::AnimeDataBuffer,
|
||||
error::{AnimeError, Result},
|
||||
AnimeType,
|
||||
};
|
||||
|
||||
/// A single greyscale + alpha pixel in the image
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@@ -83,7 +87,7 @@ impl AnimeImage {
|
||||
pixels: Vec<Pixel>,
|
||||
width: u32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
if bright < 0.0 || bright > 1.0 {
|
||||
return Err(AnimeError::InvalidBrightness(bright));
|
||||
}
|
||||
@@ -388,7 +392,7 @@ impl AnimeImage {
|
||||
translation: Vec2,
|
||||
bright: f32,
|
||||
anime_type: AnimeType,
|
||||
) -> Result<Self, AnimeError> {
|
||||
) -> Result<Self> {
|
||||
let data = std::fs::read(path)?;
|
||||
let data = std::io::Cursor::new(data);
|
||||
let decoder = png_pong::Decoder::new(data)?.into_steps();
|
||||
@@ -484,11 +488,12 @@ impl AnimeImage {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AnimeImage> for AnimeDataBuffer {
|
||||
impl TryFrom<&AnimeImage> for AnimeDataBuffer {
|
||||
type Error = AnimeError;
|
||||
|
||||
/// Do conversion from the nested Vec in AnimeDataBuffer to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(leds: &AnimeImage) -> Self {
|
||||
fn try_from(leds: &AnimeImage) -> Result<Self> {
|
||||
let mut l: Vec<u8> = leds
|
||||
.led_pos
|
||||
.iter()
|
||||
@@ -506,7 +511,7 @@ impl From<&AnimeImage> for AnimeDataBuffer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
use std::{convert::TryFrom, path::PathBuf};
|
||||
|
||||
use crate::{image::*, AnimTime, AnimeGif, AnimePacketType};
|
||||
|
||||
@@ -734,8 +739,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
matrix._edge_outline();
|
||||
let data = AnimeDataBuffer::from(&matrix);
|
||||
let pkt = AnimePacketType::from(data);
|
||||
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
|
||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
||||
|
||||
assert_eq!(pkt[0], pkt0_check);
|
||||
assert_eq!(pkt[1], pkt1_check);
|
||||
@@ -759,6 +764,6 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
matrix.frames()[0].frame();
|
||||
let _pkt = AnimePacketType::from(matrix.frames()[0].frame().clone());
|
||||
let _pkt = AnimePacketType::try_from(matrix.frames()[0].frame().clone()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use crate::{
|
||||
error::AnimeError, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType,
|
||||
error::Result, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType,
|
||||
};
|
||||
|
||||
/// All the possible AniMe actions that can be used. This enum is intended to be
|
||||
@@ -65,10 +65,7 @@ pub enum ActionData {
|
||||
}
|
||||
|
||||
impl ActionData {
|
||||
pub fn from_anime_action(
|
||||
anime_type: AnimeType,
|
||||
action: &ActionLoader,
|
||||
) -> Result<ActionData, AnimeError> {
|
||||
pub fn from_anime_action(anime_type: AnimeType, action: &ActionLoader) -> Result<ActionData> {
|
||||
let a = match action {
|
||||
ActionLoader::AsusAnimation {
|
||||
file,
|
||||
@@ -87,7 +84,7 @@ impl ActionData {
|
||||
} => match time {
|
||||
AnimTime::Infinite => {
|
||||
let image = AnimeDiagonal::from_png(file, None, *brightness, anime_type)?;
|
||||
let data = image.into_data_buffer(anime_type);
|
||||
let data = image.into_data_buffer(anime_type)?;
|
||||
ActionData::Image(Box::new(data))
|
||||
}
|
||||
_ => ActionData::Animation(AnimeGif::from_diagonal_png(
|
||||
@@ -147,7 +144,7 @@ impl ActionData {
|
||||
*brightness,
|
||||
anime_type,
|
||||
)?;
|
||||
let data = <AnimeDataBuffer>::from(&image);
|
||||
let data = <AnimeDataBuffer>::try_from(&image)?;
|
||||
ActionData::Image(Box::new(data))
|
||||
}
|
||||
_ => ActionData::Animation(AnimeGif::from_png(
|
||||
@@ -180,7 +177,7 @@ impl Sequences {
|
||||
/// Use a base `AnimeAction` to generate the precomputed data and insert in to
|
||||
/// the run buffer
|
||||
#[inline]
|
||||
pub fn insert(&mut self, index: usize, action: &ActionLoader) -> Result<(), AnimeError> {
|
||||
pub fn insert(&mut self, index: usize, action: &ActionLoader) -> Result<()> {
|
||||
self.0
|
||||
.insert(index, ActionData::from_anime_action(self.1, action)?);
|
||||
Ok(())
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog_aura"
|
||||
version = "1.1.3"
|
||||
version = "1.2.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
+177
-77
@@ -20,16 +20,85 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||
]
|
||||
}
|
||||
|
||||
/// Enable/disable LED control in various states such as
|
||||
/// when the device is awake, suspended, shutting down or
|
||||
/// booting.
|
||||
/// This struct is intended as a helper to pass args to generic dbus interface
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuraPowerDev {
|
||||
pub x1866: Vec<AuraDev1866>,
|
||||
pub x19b6: Vec<AuraDev19b6>,
|
||||
}
|
||||
|
||||
/// # Bits for older 0x1866 keyboard model
|
||||
///
|
||||
/// Keybord and Lightbar require Awake, Boot and Sleep apply to both
|
||||
/// Keybord and Lightbar regardless of if either are enabled (or Awake is enabled)
|
||||
///
|
||||
/// | Byte 1 | Byte 2 | Byte 3 | function | hex |
|
||||
/// |------------|------------|------------|----------|----------|
|
||||
/// | 0000, 0000 | 0000, 0000 | 0000, 0010 | Awake | 00,00,02 |
|
||||
/// | 0000, 1000 | 0000, 0000 | 0000, 0000 | Keyboard | 08,00,00 |
|
||||
/// | 0000, 0100 | 0000, 0101 | 0000, 0000 | Lightbar | 04,05,00 |
|
||||
/// | 1100, 0011 | 0001, 0010 | 0000, 1001 | Boot/Sht | c3,12,09 |
|
||||
/// | 0011, 0000 | 0000, 1000 | 0000, 0100 | Sleep | 30,08,04 |
|
||||
/// | 1111, 1111 | 0001, 1111 | 0000, 1111 | all on | |
|
||||
///
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum AuraDev1866 {
|
||||
Awake = 0x000002,
|
||||
Keyboard = 0x080000,
|
||||
Lightbar = 0x040500,
|
||||
Boot = 0xc31209,
|
||||
Sleep = 0x300804,
|
||||
}
|
||||
|
||||
impl From<AuraDev1866> for u32 {
|
||||
fn from(a: AuraDev1866) -> Self {
|
||||
a as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl AuraDev1866 {
|
||||
pub fn to_bytes(control: &[Self]) -> [u8; 3] {
|
||||
let mut a: u32 = 0;
|
||||
control.iter().for_each(|n| {
|
||||
a |= *n as u32;
|
||||
});
|
||||
[
|
||||
((a & 0xff0000) >> 16) as u8,
|
||||
((a & 0xff00) >> 8) as u8,
|
||||
(a & 0xff) as u8,
|
||||
]
|
||||
}
|
||||
|
||||
pub const fn dev_id() -> &'static str {
|
||||
"0x1866"
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<AuraDev1866> for AuraDev1866 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitor(self, rhs: AuraDev1866) -> Self::Output {
|
||||
return self as u32 | rhs as u32;
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd<AuraDev1866> for AuraDev1866 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitand(self, rhs: AuraDev1866) -> Self::Output {
|
||||
return self as u32 & rhs as u32;
|
||||
}
|
||||
}
|
||||
|
||||
/// # Bits for 0x19b6 keyboard model
|
||||
///
|
||||
/// ```text
|
||||
/// byte 4 in the USB packet is for keyboard + logo power states
|
||||
/// default is on, `ff`
|
||||
/// Keyboard and logo use the full range of bits (almost)
|
||||
///
|
||||
/// | n1 | n2 | hex | action | bit |
|
||||
/// |------|------|-----|-----------------------|-------|
|
||||
/// | 0000 | 0000 | 00 | all off | |
|
||||
@@ -43,6 +112,7 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||
/// | 1000 | 0000 | 80 | keyboard shutdown off | bit 8 |
|
||||
///
|
||||
/// byte 5 = lightbar
|
||||
///
|
||||
/// | 1 | 2 | hex | action | bit |
|
||||
/// |------|------|-----|----------------------|-------|
|
||||
/// | 0000 | 0010 | 02 | lightbar off boot | bit 2 |
|
||||
@@ -50,21 +120,10 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||
/// | 0000 | 1000 | 08 | lightbar off sleep | bit 4 |
|
||||
/// | 0001 | 0000 | 10 | lightbar shtdn off | bit 5 |
|
||||
///
|
||||
/// # Bits for older 0x1866 keyboard model
|
||||
///
|
||||
/// Keybord and Light zone require Awake
|
||||
/// | byte 1 | byte 2 | byte 3 | | |
|
||||
/// | 1 | 2 | 3 | 4 | 5 | 6 | function | hex |
|
||||
/// |------|------|------|------|------|------|----------|----------|
|
||||
/// | 0000 | 0000 | 0000 | 0000 | 0000 | 0010 | Awake | 00,00,02 |
|
||||
/// | 1000 | 0000 | 0000 | 0000 | 0000 | 0010 | Keyboard | 80,00,02 |
|
||||
/// | 0000 | 0100 | 0000 | 0101 | 0000 | 0010 | Lightbar | 04,05,02 |
|
||||
/// | 1100 | 0011 | 0001 | 0010 | 0000 | 1001 | Boot/Sht | c3,12,09 |
|
||||
/// | 0011 | 0000 | 0000 | 1000 | 0000 | 0100 | Sleep | 30,08,04 |
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u16)]
|
||||
pub enum AuraControl {
|
||||
pub enum AuraDev19b6 {
|
||||
BootLogo = 1,
|
||||
BootKeyb = 1 << 1,
|
||||
AwakeLogo = 1 << 2,
|
||||
@@ -79,133 +138,174 @@ pub enum AuraControl {
|
||||
ShutdownBar = 1 << 7 + 5,
|
||||
}
|
||||
|
||||
impl From<AuraControl> for u16 {
|
||||
fn from(a: AuraControl) -> Self {
|
||||
impl From<AuraDev19b6> for u16 {
|
||||
fn from(a: AuraDev19b6) -> Self {
|
||||
a as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl AuraControl {
|
||||
pub fn to_bytes(control: &[Self]) -> [u8; 2] {
|
||||
impl AuraDev19b6 {
|
||||
pub fn to_bytes(control: &[Self]) -> [u8; 3] {
|
||||
let mut a: u16 = 0;
|
||||
control.iter().for_each(|n| {
|
||||
a |= *n as u16;
|
||||
});
|
||||
[(a & 0xff) as u8, ((a & 0xff00) >> 8) as u8]
|
||||
[(a & 0xff) as u8, ((a & 0xff00) >> 8) as u8, 0x00]
|
||||
}
|
||||
|
||||
pub const fn dev_id() -> &'static str {
|
||||
"0x196b"
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<AuraControl> for AuraControl {
|
||||
impl BitOr<AuraDev19b6> for AuraDev19b6 {
|
||||
type Output = u16;
|
||||
|
||||
fn bitor(self, rhs: AuraControl) -> Self::Output {
|
||||
fn bitor(self, rhs: AuraDev19b6) -> Self::Output {
|
||||
return self as u16 | rhs as u16;
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd<AuraControl> for AuraControl {
|
||||
impl BitAnd<AuraDev19b6> for AuraDev19b6 {
|
||||
type Output = u16;
|
||||
|
||||
fn bitand(self, rhs: AuraControl) -> Self::Output {
|
||||
fn bitand(self, rhs: AuraDev19b6) -> Self::Output {
|
||||
return self as u16 & rhs as u16;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::usb::AuraControl;
|
||||
use crate::usb::AuraDev19b6;
|
||||
|
||||
use super::AuraDev1866;
|
||||
|
||||
#[test]
|
||||
fn check_led_control_bytes() {
|
||||
fn check_0x1866_control_bytes() {
|
||||
let bytes = [AuraDev1866::Keyboard, AuraDev1866::Awake];
|
||||
let bytes = AuraDev1866::to_bytes(&bytes);
|
||||
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
|
||||
assert_eq!(bytes, [0x08, 0x00, 0x02]);
|
||||
|
||||
let bytes = [AuraDev1866::Lightbar, AuraDev1866::Awake];
|
||||
let bytes = AuraDev1866::to_bytes(&bytes);
|
||||
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
|
||||
assert_eq!(bytes, [0x04, 0x05, 0x02]);
|
||||
|
||||
let bytes = [AuraDev1866::Sleep];
|
||||
let bytes = AuraDev1866::to_bytes(&bytes);
|
||||
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
|
||||
assert_eq!(bytes, [0x30, 0x08, 0x04]);
|
||||
|
||||
let bytes = [AuraDev1866::Boot];
|
||||
let bytes = AuraDev1866::to_bytes(&bytes);
|
||||
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
|
||||
assert_eq!(bytes, [0xc3, 0x12, 0x09]);
|
||||
|
||||
let bytes = [
|
||||
AuraDev1866::Keyboard,
|
||||
AuraDev1866::Lightbar,
|
||||
AuraDev1866::Awake,
|
||||
AuraDev1866::Sleep,
|
||||
AuraDev1866::Boot,
|
||||
];
|
||||
|
||||
let bytes = AuraDev1866::to_bytes(&bytes);
|
||||
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
|
||||
assert_eq!(bytes, [0xff, 0x1f, 0x000f]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_0x19b6_control_bytes() {
|
||||
// All on
|
||||
let byte1 = [
|
||||
AuraControl::BootLogo,
|
||||
AuraControl::BootKeyb,
|
||||
AuraControl::SleepLogo,
|
||||
AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraDev19b6::BootLogo,
|
||||
AuraDev19b6::BootKeyb,
|
||||
AuraDev19b6::SleepLogo,
|
||||
AuraDev19b6::SleepKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte1);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte1);
|
||||
println!("{:08b}", bytes[0]);
|
||||
assert_eq!(bytes[0], 0xff);
|
||||
|
||||
//
|
||||
let byte1 = [
|
||||
// AuraControl::BootLogo,
|
||||
AuraControl::BootKeyb,
|
||||
AuraControl::SleepLogo,
|
||||
AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraDev19b6::BootKeyb,
|
||||
AuraDev19b6::SleepLogo,
|
||||
AuraDev19b6::SleepKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte1);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte1);
|
||||
println!("{:08b}", bytes[0]);
|
||||
assert_eq!(bytes[0], 0xfe);
|
||||
|
||||
let byte1 = [
|
||||
AuraControl::BootLogo,
|
||||
AuraDev19b6::BootLogo,
|
||||
// AuraControl::BootKeyb,
|
||||
AuraControl::SleepLogo,
|
||||
AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraDev19b6::SleepLogo,
|
||||
AuraDev19b6::SleepKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte1);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte1);
|
||||
println!("{:08b}", bytes[0]);
|
||||
assert_eq!(bytes[0], 0xfd);
|
||||
|
||||
let byte1 = [
|
||||
AuraControl::BootLogo,
|
||||
AuraControl::BootKeyb,
|
||||
AuraDev19b6::BootLogo,
|
||||
AuraDev19b6::BootKeyb,
|
||||
// AuraControl::SleepLogo,
|
||||
AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraDev19b6::SleepKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte1);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte1);
|
||||
println!("{:08b}", bytes[0]);
|
||||
assert_eq!(bytes[0], 0xef);
|
||||
|
||||
let byte1 = [
|
||||
AuraControl::BootLogo,
|
||||
AuraControl::BootKeyb,
|
||||
AuraControl::SleepLogo,
|
||||
AuraDev19b6::BootLogo,
|
||||
AuraDev19b6::BootKeyb,
|
||||
AuraDev19b6::SleepLogo,
|
||||
// AuraControl::SleepKeyb,
|
||||
AuraControl::AwakeLogo,
|
||||
AuraControl::AwakeKeyb,
|
||||
AuraControl::ShutdownLogo,
|
||||
AuraControl::ShutdownKeyb,
|
||||
AuraDev19b6::AwakeLogo,
|
||||
AuraDev19b6::AwakeKeyb,
|
||||
AuraDev19b6::ShutdownLogo,
|
||||
AuraDev19b6::ShutdownKeyb,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte1);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte1);
|
||||
println!("{:08b}", bytes[0]);
|
||||
assert_eq!(bytes[0], 0xdf);
|
||||
|
||||
let byte2 = [
|
||||
AuraControl::AwakeBar,
|
||||
AuraControl::BootBar,
|
||||
AuraControl::SleepBar,
|
||||
AuraControl::ShutdownBar,
|
||||
AuraDev19b6::AwakeBar,
|
||||
AuraDev19b6::BootBar,
|
||||
AuraDev19b6::SleepBar,
|
||||
AuraDev19b6::ShutdownBar,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte2);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte2);
|
||||
println!("{:08b}", bytes[1]);
|
||||
assert_eq!(bytes[1], 0x1e);
|
||||
|
||||
let byte2 = [
|
||||
AuraControl::AwakeBar,
|
||||
AuraControl::BootBar,
|
||||
AuraDev19b6::AwakeBar,
|
||||
AuraDev19b6::BootBar,
|
||||
// AuraControl::SleepBar,
|
||||
AuraControl::ShutdownBar,
|
||||
AuraDev19b6::ShutdownBar,
|
||||
];
|
||||
let bytes = AuraControl::to_bytes(&byte2);
|
||||
let bytes = AuraDev19b6::to_bytes(&byte2);
|
||||
println!("{:08b}", bytes[1]);
|
||||
assert_eq!(bytes[1], 0x16);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! # DBus interface proxy for: `org.asuslinux.Daemon`
|
||||
//!
|
||||
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data.
|
||||
//! Source: `Interface '/org/asuslinux/Led' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//! Source: `Interface '/org/asuslinux/Aura' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
@@ -22,13 +22,13 @@
|
||||
use zbus::{blocking::Connection, Result};
|
||||
use zbus_macros::dbus_proxy;
|
||||
|
||||
use rog_aura::{usb::AuraControl, AuraEffect, KeyColourArray, LedBrightness};
|
||||
use rog_aura::{usb::AuraPowerDev, AuraEffect, KeyColourArray, LedBrightness, AuraModeNum};
|
||||
|
||||
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Led"
|
||||
default_path = "/org/asuslinux/Aura"
|
||||
)]
|
||||
trait Led {
|
||||
/// NextLedMode method
|
||||
@@ -49,31 +49,29 @@ trait Led {
|
||||
/// SetLedMode method
|
||||
fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>;
|
||||
|
||||
fn set_leds_enabled(&self, enabled: Vec<AuraControl>) -> zbus::Result<()>;
|
||||
|
||||
fn set_leds_disabled(&self, disabled: Vec<AuraControl>) -> zbus::Result<()>;
|
||||
fn set_leds_power(&self, options: AuraPowerDev, enabled: bool) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyLed signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>;
|
||||
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_power_states(&self, data: Vec<AuraControl>) -> zbus::Result<()>;
|
||||
fn notify_power_states(&self, data: AuraPowerDev) -> 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>;
|
||||
fn led_mode(&self) -> zbus::Result<AuraModeNum>;
|
||||
|
||||
/// LedModes property
|
||||
#[dbus_proxy(property)]
|
||||
fn led_modes(&self) -> zbus::Result<String>;
|
||||
|
||||
#[dbus_proxy(property)]
|
||||
fn leds_enabled(&self) -> zbus::Result<Vec<u8>>;
|
||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||
// #[dbus_proxy(property)]
|
||||
fn leds_enabled(&self) -> zbus::Result<AuraPowerDev>;
|
||||
}
|
||||
|
||||
pub struct LedProxyPerkey<'a>(LedProxyBlocking<'a>);
|
||||
|
||||
@@ -29,9 +29,9 @@ pub(crate) fn temp_str(fan: char, index: usize) -> String {
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
|
||||
pub struct CurveData {
|
||||
pub(crate) fan: FanCurvePU,
|
||||
pub(crate) pwm: [u8; 8],
|
||||
pub(crate) temp: [u8; 8],
|
||||
pub fan: FanCurvePU,
|
||||
pub pwm: [u8; 8],
|
||||
pub temp: [u8; 8],
|
||||
}
|
||||
|
||||
impl std::str::FromStr for CurveData {
|
||||
@@ -166,9 +166,9 @@ impl CurveData {
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct FanCurveSet {
|
||||
pub(crate) enabled: bool,
|
||||
pub(crate) cpu: CurveData,
|
||||
pub(crate) gpu: CurveData,
|
||||
pub enabled: bool,
|
||||
pub cpu: CurveData,
|
||||
pub gpu: CurveData,
|
||||
}
|
||||
|
||||
impl Default for FanCurveSet {
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn find_fan_curve_node() -> Result<Option<Device>, ProfileError> {
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
pub enum Profile {
|
||||
Balanced,
|
||||
Performance,
|
||||
|
||||
@@ -30,6 +30,7 @@ pub struct PlatformProfileFunctions {
|
||||
|
||||
#[derive(Serialize, Deserialize, Type, Debug)]
|
||||
pub struct LedSupportedFunctions {
|
||||
pub prod_id: String,
|
||||
pub brightness_set: bool,
|
||||
pub stock_led_modes: Vec<AuraModeNum>,
|
||||
pub multizone_led_mode: Vec<AuraZone>,
|
||||
|
||||
Reference in New Issue
Block a user