Compare commits

...

44 Commits

Author SHA1 Message Date
Luke D. Jones 7ae0f896cf Update deps 2023-04-27 16:08:52 +12:00
Luke D. Jones fb0374512d Fix rog-control-center not reopening if is set 2023-04-27 16:01:07 +12:00
Luke D. Jones 14f031ad34 Better update of aura modes if supported list changed 2023-04-27 10:57:45 +12:00
Luke D. Jones bee5508099 Prep new release 2023-04-26 22:00:22 +12:00
Luke D. Jones c741204200 Prep new release 2023-04-26 21:59:13 +12:00
Luke D. Jones 858c9841a7 Update deps 2023-04-26 21:35:48 +12:00
Luke D. Jones fdc7d88a70 More tweaks to notifications 2023-04-26 12:49:29 +12:00
Luke D. Jones da3017bb89 Update supergfx dep 2023-04-26 12:32:26 +12:00
Luke D. Jones 641e762e80 Update deps 2023-04-26 11:24:50 +12:00
Luke D. Jones 25ecfda095 Various tray and notification improvements 2023-04-26 10:57:13 +12:00
Luke D. Jones 31af8f9511 Use egui without wayland feature due to segfault 2023-04-25 14:44:31 +12:00
Luke D. Jones 8db783d9b4 Better handling of supergfx version check, aura config updates 2023-04-25 13:57:07 +12:00
Luke D. Jones 45a354880a Add support for GV604 LEDs 2023-04-25 12:13:20 +12:00
Luke D. Jones ca1c67e803 Begin fixing up support of basic modes + supergfx 2023-04-25 10:27:09 +12:00
Luke D. Jones c819fa458a Optimise keyboard detection 2023-04-24 22:23:42 +12:00
Luke D. Jones 869ab90299 Add 0x18c6 keyboard 2023-04-24 20:54:51 +12:00
Luke D. Jones c40029f5e7 Merge branch 'fluke/18c6-keyboard' 2023-04-24 20:15:11 +12:00
Luke Jones e864dfb0e7 Merge branch 'feature/persistent-theme' into 'main'
Persistent dark / light mode

See merge request asus-linux/asusctl!160
2023-04-22 21:29:36 +00:00
Filip 476b394add Persistent dark / light mode 2023-04-22 21:29:36 +00:00
Luke D. Jones 4ea5480e66 Add support for GX650P LED modes 2023-04-21 11:01:54 +12:00
Luke Jones cfc46a2b70 Merge branch 'guv604vi-support' into 'main'
Add led modes for GU604VI

See merge request asus-linux/asusctl!159
2023-04-20 22:32:50 +00:00
bno1 235763a615 Add led modes for GU604V 2023-04-21 00:36:00 +03:00
Luke D. Jones 6e19c16e70 Begin adding 18c6 keyboard support
This keyboard is found in ROG Flow Z13 machines. A kernel patch is also
required for full support.

Addresses #344.
2023-04-19 12:08:30 +12:00
Luke D. Jones 6ea550b6ff Update egui and supergfxctl deps
Requires running with supergfxctl v5.1.0-RC5 if installed
2023-04-19 10:12:14 +12:00
Luke Jones dd30c8092b Merge branch 'pr-makefile-split' into 'main'
Makefile: split install into install-{program,data}

See merge request asus-linux/asusctl!158
2023-04-10 08:04:40 +00:00
Cole Mickens 2bd751f841 Makefile: split install into install-{program,data} 2023-04-09 18:44:55 -05:00
Luke Jones 7a6aafded7 Merge branch 'fluke/fix-anime-loops' into 'main'
Bugfix: Adjust how sub-llops and part of anime animation handle

See merge request asus-linux/asusctl!157
2023-04-08 03:40:32 +00:00
Luke Jones 940b93a75f Merge branch 'zpl/fix-anime-loops_fix' into 'fluke/fix-anime-loops'
fix: sleep-animation

See merge request asus-linux/asusctl!156
2023-04-04 21:36:48 +00:00
Armas Spann 5c70fec29a fix: sleep-animation 2023-04-04 01:20:25 +02:00
Luke Jones 8ac505e0dd Merge branch 'main' into 'main'
Add support for FX506LH keyboard layout

See merge request asus-linux/asusctl!155
2023-04-03 08:13:07 +00:00
Luke D. Jones 3bdb03b1d8 Bugfix: Adjust how sub-llops and part of anime animation handle
Attempts to address #332
2023-04-03 20:01:06 +12:00
Winfried 4ac4909881 Add support for FX506LH keyboard layout 2023-03-29 15:12:03 +03:00
Luke D. Jones ec5e6d2e7c Add support for G533Z keyboard and modes
Closes #327
2023-03-20 08:52:23 +01:00
Luke D. Jones 5600c51ba0 Fix remove the leftover initial config writes on new() for some controllers
Closes #320
2023-01-25 09:27:12 +13:00
Luke D. Jones cb5856c4dc Update fedora build instruction 2023-01-18 20:40:25 +13:00
Luke Jones aad6f6350b Update README.md 2023-01-17 20:54:46 +00:00
Luke D. Jones 1ec45a6449 Update gitlab CI 2023-01-16 15:17:37 +13:00
Luke Jones bb612283fe Update .gitlab-ci.yml file 2023-01-16 02:00:34 +00:00
Luke Jones bcba11d4ec Update .gitlab-ci.yml file 2023-01-16 01:59:50 +00:00
Luke Jones 7eab94bc7f Update .gitlab-ci.yml file 2023-01-16 01:57:55 +00:00
Luke D. Jones e73bbedb41 Properly enable pipeline cache? 2023-01-16 14:50:50 +13:00
Luke D. Jones a83ccbd33d Add git hooks via cargo-husky. Many many cleanups. 2023-01-16 13:23:30 +13:00
Luke Jones b5b7799018 Merge branch 'readme-popos-instructions-typo-fix' into 'main'
Fixed typo in the instructions for Pop_OS installation commands

See merge request asus-linux/asusctl!152
2023-01-15 21:04:36 +00:00
Andres Sanchez 24ecb92621 Fixed typo in the instructions for Pop_OS installation commands 2023-01-15 11:41:10 -05:00
65 changed files with 2128 additions and 1840 deletions
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
set -e
echo '+cargo +nightly fmt --all -- --check'
cargo +nightly fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo test --all'
cargo test --all
echo '+cargo cranky'
cargo cranky
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
set -e
echo '+cargo +nightly fmt --all -- --check'
cargo +nightly fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo cranky'
cargo cranky
+29 -8
View File
@@ -1,15 +1,15 @@
image: rust:latest image: rust:latest
cache: .rust_cache: &rust_cache
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" cache:
paths: # key: $CI_COMMIT_REF_SLUG
paths:
# Don't include `incremental` to save space # Don't include `incremental` to save space
# Debug # Debug
- target/debug/build/ - target/debug/build/
- target/debug/deps/ - target/debug/deps/
- target/debug/.fingerprint/ - target/debug/.fingerprint/
- target/debug/.cargo-lock - target/debug/.cargo-lock
- target/debug/df_storyteller
# Release # Release
- target/release/build/ - target/release/build/
- target/release/deps/ - target/release/deps/
@@ -20,14 +20,16 @@ before_script:
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev - apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev
stages: stages:
- format - format
- check - check
- test - test
- release - release
- deploy
format: format:
except: except:
- tags - tags
<<: *rust_cache
script: script:
- echo "nightly" > rust-toolchain - echo "nightly" > rust-toolchain
- rustup component add rustfmt - rustup component add rustfmt
@@ -36,6 +38,7 @@ format:
check: check:
except: except:
- tags - tags
<<: *rust_cache
script: script:
- rustup component add clippy - rustup component add clippy
- cargo check - cargo check
@@ -46,12 +49,15 @@ check:
test: test:
except: except:
- tags - tags
<<: *rust_cache
script: script:
- mkdir -p .git/hooks > /dev/null
- cargo test - cargo test
release: release:
only: only:
- tags - tags
<<: *rust_cache
script: script:
- make && make vendor - make && make vendor
artifacts: artifacts:
@@ -59,5 +65,20 @@ release:
- vendor_asusctl_*.tar.xz - vendor_asusctl_*.tar.xz
- cargo-config - cargo-config
pages:
stage: deploy
only:
- tags
<<: *rust_cache
script:
- cargo doc --document-private-items --no-deps --workspace
- rm -rf public
- mkdir public
- cp -R target/doc/* public
- cp misc/index.html public
artifacts:
paths:
- public
variables: variables:
GIT_SUBMODULE_STRATEGY: normal GIT_SUBMODULE_STRATEGY: normal
+29
View File
@@ -5,8 +5,35 @@ 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]
## [v4.6.2]
- Fix rog-control-center not reopening if `startup_in_background` is set
## [v4.6.1]
### Added
- Support for G733Z LED modes
- Support for GU604V LED modes
- Support for GX650P LED modes
- Support for GV604I LED modes
- Support for FX516P LED modes (this laptop still has further issues, will require a patched kernel when patch is ready)
- Add device code for the Z13 ACRNM keyboard (requires kernel patch, in progress)
- Support for GV301VIC LED modes
- Add device code for the plain Z13 keyboard (requires kernel patch, in progress)
- Support for GV301V LED modes
### Changed
- Adjustments to Anime system events thread
- Add "sleep" animetion config options to anime config
- rog-control-center dark/light mode persistency
- Adjustments to keyboard detection
- Better support of using supergfxctl when available (tray icon and menu)
- Check supergfx version before enabling use in tray (require 5.1.0+)
- Update allowed Aura modes on asusd restart if changed
- Set tray icon for dgpu to "On" if in Vfio mode to prevent confusion
- Add support for Logout/Reboot in notification for KDE
## [v4.6.0]
### Added ### Added
- Support for GL703GE keyboard layout - Support for GL703GE keyboard layout
- Support for G533Z modes and keyboard layout
### Changed ### Changed
- Better handling of `/etc/asusd` not existing - Better handling of `/etc/asusd` not existing
- Better handling of non-existant config files - Better handling of non-existant config files
@@ -20,6 +47,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ROGCC: Add CLI opt for viewing all layout files + filenames to help find a layout matching your laptop - ROGCC: Add CLI opt for viewing all layout files + filenames to help find a layout matching your laptop
+ Both of these options would hopefully be temporary and replaced with a "wizard" GUI helper + Both of these options would hopefully be temporary and replaced with a "wizard" GUI helper
- Fix profile controller not detecting if platform_profile is changed - Fix profile controller not detecting if platform_profile is changed
- Fix remove the leftover initial config writes on `new()` for some controllers to prevent resetting settings on startup
+ refactor the loading of systemd curve defaults and config file
### BREAKING ### BREAKING
- Rename aura dbus method from `per_key_raw` to `direct_addressing_raw` and add doc comment - Rename aura dbus method from `per_key_raw` to `direct_addressing_raw` and add doc comment
- Changes to aura.conf: - Changes to aura.conf:
Generated
+880 -968
View File
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -2,7 +2,7 @@
members = ["asusctl", "config-traits", "daemon", "daemon-user", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"] members = ["asusctl", "config-traits", "daemon", "daemon-user", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"]
[workspace.package] [workspace.package]
version = "4.6.0-rc1" version = "4.6.2"
[workspace.dependencies] [workspace.dependencies]
async-trait = "^0.1" async-trait = "^0.1"
@@ -35,6 +35,8 @@ pix = "^0.13"
tinybmp = "^0.4.0" tinybmp = "^0.4.0"
gif = "^0.12.0" gif = "^0.12.0"
versions = "4.1"
notify-rust = { git = "https://github.com/flukejones/notify-rust.git", default-features = false, features = ["z"] } notify-rust = { git = "https://github.com/flukejones/notify-rust.git", default-features = false, features = ["z"] }
[profile.release] [profile.release]
@@ -52,3 +54,8 @@ opt-level = 1
[profile.bench] [profile.bench]
debug = false debug = false
opt-level = 3 opt-level = 3
[workspace.dependencies.cargo-husky]
version = "1"
default-features = false
features = ["user-hooks"]
+1 -1
View File
@@ -1,7 +1,7 @@
# https://github.com/ericseppanen/cargo-cranky # https://github.com/ericseppanen/cargo-cranky
# cargo install cargo-cranky && cargo cranky # cargo install cargo-cranky && cargo cranky
warn = [ error = [
"clippy::all", "clippy::all",
"clippy::await_holding_lock", "clippy::await_holding_lock",
"clippy::bool_to_int_with_if", "clippy::bool_to_int_with_if",
+8 -4
View File
@@ -38,16 +38,18 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
install: install-program:
$(INSTALL_PROGRAM) "./target/release/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)" $(INSTALL_PROGRAM) "./target/release/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)"
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).desktop" "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png"
cd rog-aura/data/layouts && find . -type f -name "*.ron" -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/rog-gui/layouts/{}" \;
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" $(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)" $(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
install-data:
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).desktop" "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png"
cd rog-aura/data/layouts && find . -type f -name "*.ron" -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/rog-gui/layouts/{}" \;
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules" $(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
$(INSTALL_DATA) "./rog-aura/data/$(LEDCFG)" "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)" $(INSTALL_DATA) "./rog-aura/data/$(LEDCFG)" "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)"
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf" $(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
@@ -71,6 +73,8 @@ install:
cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \; cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \;
install: install-program install-data
uninstall: uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)" rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)"
rm -r "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop" rm -r "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
+7 -3
View File
@@ -82,7 +82,7 @@ Requirements are rust >= 1.57 installed from rustup.io if the distro provided ve
**popos (unsuported):** **popos (unsuported):**
sudo apt install cmake libclang-dev libudev-dev libgtk-3-dev ibclang-dev libglib2.0-dev libatkmm-1.6-dev libpangomm-1.4-dev librust-gdk-pixbuf-dev sudo apt install cmake libclang-dev libudev-dev libgtk-3-dev libclang-dev libglib2.0-dev libatkmm-1.6-dev libpangomm-1.4-dev librust-gdk-pixbuf-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env" source "$HOME/.cargo/env"
make make
@@ -91,7 +91,7 @@ Requirements are rust >= 1.57 installed from rustup.io if the distro provided ve
**fedora:** **fedora:**
dnf install cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf-devel gtk3-devel libappindicator-gtk3 dnf install cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf2-devel gtk3-devel libappindicator-gtk3
make make
sudo make install sudo make install
@@ -100,7 +100,7 @@ Requirements are rust >= 1.57 installed from rustup.io if the distro provided ve
Works with KDE Plasma (without GTK packages) Works with KDE Plasma (without GTK packages)
zypper in -t pattern devel_basis zypper in -t pattern devel_basis
zypper in rustup cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf-devel gtk3-devel zypper in rustup make cmake systemd-devel clang-devel llvm-devel gdk-pixbuf-devel cairo-devel pango-devel freetype-devel gtk3-devel libexpat-devel libayatana-indicator3-7
make make
sudo make install sudo make install
@@ -126,6 +126,10 @@ You may also need to activate the service for debian install. If running Pop!_OS
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`. Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
# Contributing
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
# OTHER # OTHER
## Supporting more laptops ## Supporting more laptops
+2
View File
@@ -22,3 +22,5 @@ gif.workspace = true
tinybmp.workspace = true tinybmp.workspace = true
glam.workspace = true glam.workspace = true
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
cargo-husky.workspace = true
+41 -43
View File
@@ -10,7 +10,7 @@ use gumdrop::{Opt, Options};
use profiles_cli::{FanCurveCommand, ProfileCommand}; use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::usb::get_anime_type; use rog_anime::usb::get_anime_type;
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2}; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{self, AuraEffect}; use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClientBlocking; use rog_dbus::RogDbusClientBlocking;
use rog_platform::platform::GpuMode; use rog_platform::platform::GpuMode;
@@ -36,15 +36,14 @@ fn main() {
..Default::default() ..Default::default()
}, },
Err(err) => { Err(err) => {
eprintln!("source {}", err); panic!("source {}", err);
std::process::exit(2);
} }
}; };
let (dbus, _) = RogDbusClientBlocking::new() let (dbus, _) = RogDbusClientBlocking::new()
.map_err(|e| { .map_err(|e| {
print_error_help(&e, None); print_error_help(&e, None);
std::process::exit(3); panic!("Could not start dbus client");
}) })
.unwrap(); .unwrap();
@@ -54,7 +53,7 @@ fn main() {
.supported_functions() .supported_functions()
.map_err(|e| { .map_err(|e| {
print_error_help(&e, None); print_error_help(&e, None);
std::process::exit(4); panic!("Could not start dbus proxy");
}) })
.unwrap(); .unwrap();
@@ -158,7 +157,7 @@ fn do_parsed(
{ {
return false; return false;
} }
if supported.keyboard_led.dev_id != AuraDevice::X19B6 if supported.keyboard_led.dev_id != AuraDevice::X19b6
&& command.trim().starts_with("led-pow-2") && command.trim().starts_with("led-pow-2")
{ {
return false; return false;
@@ -260,7 +259,7 @@ fn handle_anime(
if let Some(lst) = image.self_command_list() { if let Some(lst) = image.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
verify_brightness(image.bright); verify_brightness(image.bright);
@@ -283,7 +282,7 @@ fn handle_anime(
if let Some(lst) = image.self_command_list() { if let Some(lst) = image.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
verify_brightness(image.bright); verify_brightness(image.bright);
@@ -304,7 +303,7 @@ fn handle_anime(
if let Some(lst) = gif.self_command_list() { if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
verify_brightness(gif.bright); verify_brightness(gif.bright);
@@ -338,7 +337,7 @@ fn handle_anime(
if let Some(lst) = gif.self_command_list() { if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
verify_brightness(gif.bright); verify_brightness(gif.bright);
@@ -374,7 +373,6 @@ fn verify_brightness(brightness: f32) {
"Image and global brightness must be between 0.0 and 1.0 (inclusive), was {}", "Image and global brightness must be between 0.0 and 1.0 (inclusive), was {}",
brightness brightness
); );
std::process::exit(1);
} }
} }
@@ -391,7 +389,7 @@ fn handle_led_mode(
println!("Commands available"); println!("Commands available");
if let Some(cmdlist) = LedModeCommand::command_list() { if let Some(cmdlist) = LedModeCommand::command_list() {
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_string()).collect(); let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
for command in commands.iter().filter(|command| { for command in commands.iter().filter(|command| {
for mode in &supported.basic_modes { for mode in &supported.basic_modes {
if command if command
@@ -474,10 +472,10 @@ fn handle_led_power_1_do_1866(
dbus: &RogDbusClientBlocking<'_>, dbus: &RogDbusClientBlocking<'_>,
power: &LedPowerCommand1, power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let mut enabled: Vec<AuraDev1866> = Vec::new(); let mut enabled: Vec<AuraDevRog1> = Vec::new();
let mut disabled: Vec<AuraDev1866> = Vec::new(); let mut disabled: Vec<AuraDevRog1> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDev1866| { let mut check = |e: Option<bool>, a: AuraDevRog1| {
if let Some(arg) = e { if let Some(arg) = e {
if arg { if arg {
enabled.push(a); enabled.push(a);
@@ -487,11 +485,11 @@ fn handle_led_power_1_do_1866(
} }
}; };
check(power.awake, AuraDev1866::Awake); check(power.awake, AuraDevRog1::Awake);
check(power.boot, AuraDev1866::Boot); check(power.boot, AuraDevRog1::Boot);
check(power.sleep, AuraDev1866::Sleep); check(power.sleep, AuraDevRog1::Sleep);
check(power.keyboard, AuraDev1866::Keyboard); check(power.keyboard, AuraDevRog1::Keyboard);
check(power.lightbar, AuraDev1866::Lightbar); check(power.lightbar, AuraDevRog1::Lightbar);
let data = AuraPowerDev { let data = AuraPowerDev {
x1866: enabled, x1866: enabled,
@@ -578,13 +576,13 @@ fn handle_led_power2(
return Ok(()); return Ok(());
} }
if supported.dev_id != AuraDevice::X19B6 { if supported.dev_id != AuraDevice::X19b6 {
println!("This option applies only to keyboards with product ID 0x19b6"); println!("This option applies only to keyboards with product ID 0x19b6");
} }
let mut enabled: Vec<AuraDev19b6> = Vec::new(); let mut enabled: Vec<AuraDevRog2> = Vec::new();
let mut disabled: Vec<AuraDev19b6> = Vec::new(); let mut disabled: Vec<AuraDevRog2> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDev19b6| { let mut check = |e: Option<bool>, a: AuraDevRog2| {
if let Some(arg) = e { if let Some(arg) = e {
if arg { if arg {
enabled.push(a); enabled.push(a);
@@ -596,28 +594,28 @@ fn handle_led_power2(
match pow { match pow {
aura_cli::SetAuraEnabled::Boot(arg) => { aura_cli::SetAuraEnabled::Boot(arg) => {
check(arg.keyboard, AuraDev19b6::BootKeyb); check(arg.keyboard, AuraDevRog2::BootKeyb);
check(arg.logo, AuraDev19b6::BootLogo); check(arg.logo, AuraDevRog2::BootLogo);
check(arg.lightbar, AuraDev19b6::BootBar); check(arg.lightbar, AuraDevRog2::BootBar);
check(arg.lid, AuraDev19b6::AwakeLid); check(arg.lid, AuraDevRog2::AwakeLid);
} }
aura_cli::SetAuraEnabled::Sleep(arg) => { aura_cli::SetAuraEnabled::Sleep(arg) => {
check(arg.keyboard, AuraDev19b6::SleepKeyb); check(arg.keyboard, AuraDevRog2::SleepKeyb);
check(arg.logo, AuraDev19b6::SleepLogo); check(arg.logo, AuraDevRog2::SleepLogo);
check(arg.lightbar, AuraDev19b6::SleepBar); check(arg.lightbar, AuraDevRog2::SleepBar);
check(arg.lid, AuraDev19b6::SleepLid); check(arg.lid, AuraDevRog2::SleepLid);
} }
aura_cli::SetAuraEnabled::Awake(arg) => { aura_cli::SetAuraEnabled::Awake(arg) => {
check(arg.keyboard, AuraDev19b6::AwakeKeyb); check(arg.keyboard, AuraDevRog2::AwakeKeyb);
check(arg.logo, AuraDev19b6::AwakeLogo); check(arg.logo, AuraDevRog2::AwakeLogo);
check(arg.lightbar, AuraDev19b6::AwakeBar); check(arg.lightbar, AuraDevRog2::AwakeBar);
check(arg.lid, AuraDev19b6::AwakeLid); check(arg.lid, AuraDevRog2::AwakeLid);
} }
aura_cli::SetAuraEnabled::Shutdown(arg) => { aura_cli::SetAuraEnabled::Shutdown(arg) => {
check(arg.keyboard, AuraDev19b6::ShutdownKeyb); check(arg.keyboard, AuraDevRog2::ShutdownKeyb);
check(arg.logo, AuraDev19b6::ShutdownLogo); check(arg.logo, AuraDevRog2::ShutdownLogo);
check(arg.lightbar, AuraDev19b6::ShutdownBar); check(arg.lightbar, AuraDevRog2::ShutdownBar);
check(arg.lid, AuraDev19b6::ShutdownBar); check(arg.lid, AuraDevRog2::ShutdownBar);
} }
} }
@@ -662,7 +660,7 @@ fn handle_profile(
if let Some(lst) = cmd.self_command_list() { if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
if cmd.next { if cmd.next {
@@ -706,14 +704,14 @@ fn handle_fan_curve(
if let Some(lst) = cmd.self_command_list() { if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
std::process::exit(1); return Ok(());
} }
if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some()) if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some())
&& cmd.mod_profile.is_none() && cmd.mod_profile.is_none()
{ {
println!("--enabled, --fan, and --data options require --mod-profile"); println!("--enabled, --fan, and --data options require --mod-profile");
std::process::exit(666); return Ok(());
} }
if cmd.get_enabled { if cmd.get_enabled {
+6 -3
View File
@@ -1,9 +1,9 @@
[package] [package]
name = "config-traits" name = "config-traits"
version = "0.1.0" license = "MPL-2.0"
authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2021" edition = "2021"
version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
serde.workspace = true serde.workspace = true
@@ -13,3 +13,6 @@ toml.workspace = true
ron.workspace = true ron.workspace = true
log.workspace = true log.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+10
View File
@@ -0,0 +1,10 @@
# config-traits
`config_traits` is a crate that broke out from the requirement to manage various
different config files, including parsing from different formats and updating
them from previous versions where fields or names are changed in some way.
The end canonical file format is `.ron` as this supports rust types well, and includes
the ability to add commenting, and is less verbose than `json`. Currently the crate will
also try to parse from `json` and `toml` if the `ron` parsing fails, then update to `ron`
format.
+38 -27
View File
@@ -1,4 +1,14 @@
use std::fs::{create_dir, File, OpenOptions}; //! `config_traits` is a crate that broke out from the requirement to manage
//! various different config files, including parsing from different formats and
//! updating them from previous versions where fields or names are changed in
//! some way.
//!
//! The end canonical file format is `.ron` as this supports rust types well,
//! and includes the ability to add commenting, and is less verbose than `json`.
//! Currently the crate will also try to parse from `json` and `toml` if the
//! `ron` parsing fails, then update to `ron` format.
use std::fs::{self, create_dir, File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::PathBuf; use std::path::PathBuf;
@@ -49,7 +59,7 @@ where
"Could not rename. Please remove {} then restart service: Error {}", "Could not rename. Please remove {} then restart service: Error {}",
self.file_name(), self.file_name(),
err err
) );
}); });
do_rename = false; do_rename = false;
} }
@@ -68,7 +78,7 @@ where
"Could not rename. Please remove {} then restart service: Error {}", "Could not rename. Please remove {} then restart service: Error {}",
self.file_name(), self.file_name(),
err err
) );
}); });
} }
config config
@@ -88,18 +98,10 @@ where
/// Open and parse the config file to self from ron format /// Open and parse the config file to self from ron format
fn read(&mut self) { fn read(&mut self) {
let mut file = match OpenOptions::new().read(true).open(self.file_path()) { if let Ok(data) = fs::read_to_string(self.file_path()) {
Ok(data) => data, if data.is_empty() {
Err(err) => {
error!("Error reading {:?}: {}", self.file_path(), err);
return;
}
};
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
warn!("File is empty {:?}", self.file_path()); warn!("File is empty {:?}", self.file_path());
} else if let Ok(data) = ron::from_str(&buf) { } else if let Ok(data) = ron::from_str(&data) {
*self = data; *self = data;
} else { } else {
warn!("Could not deserialise {:?}", self.file_path()); warn!("Could not deserialise {:?}", self.file_path());
@@ -137,13 +139,14 @@ where
self.file_name(), self.file_name(),
self.file_name() self.file_name()
); );
let cfg_old = self.file_path().to_string_lossy().to_string() + "-old"; let mut cfg_old = self.file_path().to_string_lossy().to_string();
cfg_old.push_str("-old");
std::fs::rename(self.file_path(), cfg_old).unwrap_or_else(|err| { std::fs::rename(self.file_path(), cfg_old).unwrap_or_else(|err| {
error!( error!(
"Could not rename. Please remove {} then restart service: Error {}", "Could not rename. Please remove {} then restart service: Error {}",
self.file_name(), self.file_name(),
err err
) );
}); });
} }
} }
@@ -160,13 +163,13 @@ macro_rules! std_config_load {
/// use serde::{Deserialize, Serialize}; /// use serde::{Deserialize, Serialize};
/// use config_traits::{StdConfig, StdConfigLoad2}; /// use config_traits::{StdConfig, StdConfigLoad2};
/// ///
/// #[derive(Deserialize, Serialize)] /// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfigOld {} /// struct FanCurveConfigOld {}
/// ///
/// #[derive(Deserialize, Serialize)] /// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfigOlder {} /// struct FanCurveConfigOlder {}
/// ///
/// #[derive(Deserialize, Serialize)] /// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfig {} /// struct FanCurveConfig {}
/// ///
/// impl From<FanCurveConfigOld> for FanCurveConfig { /// impl From<FanCurveConfigOld> for FanCurveConfig {
@@ -192,7 +195,7 @@ macro_rules! std_config_load {
/// new one created /// new one created
pub trait $trait_name<$($generic),*> pub trait $trait_name<$($generic),*>
where where
Self: $crate::StdConfig + DeserializeOwned + Serialize, Self: $crate::StdConfig +std::fmt::Debug + DeserializeOwned + Serialize,
$($generic: DeserializeOwned + Into<Self>),* $($generic: DeserializeOwned + Into<Self>),*
{ {
fn load(mut self) -> Self { fn load(mut self) -> Self {
@@ -202,14 +205,22 @@ macro_rules! std_config_load {
if read_len != 0 { if read_len != 0 {
if let Ok(data) = ron::from_str(&buf) { if let Ok(data) = ron::from_str(&buf) {
self = data; self = data;
log::info!("Parsed RON for {:?}", std::any::type_name::<Self>());
} else if let Ok(data) = serde_json::from_str(&buf) { } else if let Ok(data) = serde_json::from_str(&buf) {
self = data; self = data;
log::info!("Parsed JSON for {:?}", std::any::type_name::<Self>());
} else if let Ok(data) = toml::from_str(&buf) { } else if let Ok(data) = toml::from_str(&buf) {
self = data; self = data;
} $(else if let Ok(data) = serde_json::from_str::<$generic>(&buf) { log::info!("Parsed TOML for {:?}", std::any::type_name::<Self>());
} $(else if let Ok(data) = ron::from_str::<$generic>(&buf) {
self = data.into(); self = data.into();
log::info!("New version failed, trying previous: Parsed RON for {:?}", std::any::type_name::<$generic>());
} else if let Ok(data) = serde_json::from_str::<$generic>(&buf) {
self = data.into();
log::info!("New version failed, trying previous: Parsed JSON for {:?}", std::any::type_name::<$generic>());
} else if let Ok(data) = toml::from_str::<$generic>(&buf) { } else if let Ok(data) = toml::from_str::<$generic>(&buf) {
self = data.into(); self = data.into();
log::info!("Newvious version failed, trying previous: Parsed TOML for {:?}", std::any::type_name::<$generic>());
})* else { })* else {
self.rename_file_old(); self.rename_file_old();
self = Self::new(); self = Self::new();
@@ -237,10 +248,10 @@ mod tests {
#[test] #[test]
fn check_macro_from_1() { fn check_macro_from_1() {
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Test {} struct Test {}
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old1 {} struct Old1 {}
impl crate::StdConfig for Test { impl crate::StdConfig for Test {
@@ -268,16 +279,16 @@ mod tests {
#[test] #[test]
fn check_macro_from_3() { fn check_macro_from_3() {
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Test {} struct Test {}
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old1 {} struct Old1 {}
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old2 {} struct Old2 {}
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old3 {} struct Old3 {}
impl crate::StdConfig for Test { impl crate::StdConfig for Test {
+3
View File
@@ -34,3 +34,6 @@ zbus.workspace = true
# cli and logging # cli and logging
log.workspace = true log.workspace = true
env_logger.workspace = true env_logger.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+2 -13
View File
@@ -1,5 +1,4 @@
use std::fs::OpenOptions; use std::io::Write;
use std::io::{Read, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@@ -78,17 +77,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// if supported.keyboard_led.per_key_led_mode { // if supported.keyboard_led.per_key_led_mode {
if let Some(cfg) = config.active_aura { if let Some(cfg) = config.active_aura {
let mut aura_config = ConfigAura::new().set_name(cfg).load(); let mut aura_config = ConfigAura::new().set_name(cfg).load();
// let baord_name = std::fs::read_to_string(BOARD_NAME)?;
// Find and load a matching layout for laptop
let mut file = OpenOptions::new()
.read(true)
.open(PathBuf::from(BOARD_NAME))
.map_err(|e| {
println!("{BOARD_NAME}, {e}");
e
})?;
let mut board_name = String::new();
file.read_to_string(&mut board_name)?;
let led_support = LaptopLedData::get_data(); let led_support = LaptopLedData::get_data();
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Anime' from service //! data. Source: `Interface '/org/asuslinux/Anime' from service
//! 'org.asuslinux.Daemon' on session bus`. //! 'org.asuslinux.Daemon' on session bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus` object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::PeerProxy`] //! * [`zbus::fdo::PeerProxy`]
+3
View File
@@ -45,3 +45,6 @@ sysfs-class.workspace = true # used for backlight control and baord ID
concat-idents.workspace = true concat-idents.workspace = true
systemd-zbus = "*" systemd-zbus = "*"
[dev-dependencies]
cargo-husky.workspace = true
+2 -2
View File
@@ -3,7 +3,7 @@ use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "asusd.ron"; const CONFIG_FILE: &str = "asusd.ron";
#[derive(Deserialize, Serialize, Default)] #[derive(Deserialize, Serialize, Default, Debug)]
pub struct Config { pub struct Config {
/// Save charge limit for restoring on boot /// Save charge limit for restoring on boot
pub bat_charge_limit: u8, pub bat_charge_limit: u8,
@@ -29,7 +29,7 @@ impl StdConfig for Config {
} }
fn file_name(&self) -> String { fn file_name(&self) -> String {
CONFIG_FILE.to_string() CONFIG_FILE.to_owned()
} }
} }
+53 -7
View File
@@ -33,7 +33,12 @@ impl From<AnimeConfigV341> for AnimeConfig {
} else { } else {
vec![] vec![]
}, },
shutdown: if let Some(ani) = c.shutdown { shutdown: if let Some(ani) = c.shutdown.clone() {
vec![ani]
} else {
vec![]
},
sleep: if let Some(ani) = c.shutdown.clone() {
vec![ani] vec![ani]
} else { } else {
vec![] vec![]
@@ -60,6 +65,32 @@ impl From<AnimeConfigV352> for AnimeConfig {
system: c.system, system: c.system,
boot: c.boot, boot: c.boot,
wake: c.wake, wake: c.wake,
sleep: c.shutdown.clone(),
shutdown: c.shutdown,
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
}
}
}
#[derive(Deserialize, Serialize)]
pub struct AnimeConfigV460 {
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
}
impl From<AnimeConfigV460> for AnimeConfig {
fn from(c: AnimeConfigV460) -> AnimeConfig {
AnimeConfig {
system: c.system,
boot: c.boot,
wake: c.wake,
sleep: c.sleep,
shutdown: c.shutdown, shutdown: c.shutdown,
brightness: 1.0, brightness: 1.0,
awake_enabled: true, awake_enabled: true,
@@ -73,6 +104,7 @@ pub struct AnimeConfigCached {
pub system: Vec<ActionData>, pub system: Vec<ActionData>,
pub boot: Vec<ActionData>, pub boot: Vec<ActionData>,
pub wake: Vec<ActionData>, pub wake: Vec<ActionData>,
pub sleep: Vec<ActionData>,
pub shutdown: Vec<ActionData>, pub shutdown: Vec<ActionData>,
} }
@@ -100,6 +132,12 @@ impl AnimeConfigCached {
} }
self.wake = wake; self.wake = wake;
let mut sleep = Vec::with_capacity(config.sleep.len());
for ani in &config.sleep {
sleep.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.sleep = sleep;
let mut shutdown = Vec::with_capacity(config.shutdown.len()); let mut shutdown = Vec::with_capacity(config.shutdown.len());
for ani in &config.shutdown { for ani in &config.shutdown {
shutdown.push(ActionData::from_anime_action(anime_type, ani)?); shutdown.push(ActionData::from_anime_action(anime_type, ani)?);
@@ -110,11 +148,12 @@ impl AnimeConfigCached {
} }
/// Config for base system actions for the anime display /// Config for base system actions for the anime display
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize, Debug)]
pub struct AnimeConfig { pub struct AnimeConfig {
pub system: Vec<ActionLoader>, pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>, pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>, pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>, pub shutdown: Vec<ActionLoader>,
pub brightness: f32, pub brightness: f32,
pub awake_enabled: bool, pub awake_enabled: bool,
@@ -127,6 +166,7 @@ impl Default for AnimeConfig {
system: Vec::new(), system: Vec::new(),
boot: Vec::new(), boot: Vec::new(),
wake: Vec::new(), wake: Vec::new(),
sleep: Vec::new(),
shutdown: Vec::new(), shutdown: Vec::new(),
brightness: 1.0, brightness: 1.0,
awake_enabled: true, awake_enabled: true,
@@ -145,7 +185,7 @@ impl StdConfig for AnimeConfig {
} }
fn file_name(&self) -> String { fn file_name(&self) -> String {
CONFIG_FILE.to_string() CONFIG_FILE.to_owned()
} }
} }
@@ -164,7 +204,7 @@ impl AnimeConfig {
fn create_default() -> Self { fn create_default() -> Self {
// create a default config here // create a default config here
let config = AnimeConfig { AnimeConfig {
system: vec![], system: vec![],
boot: vec![ActionLoader::ImageAnimation { boot: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(), file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
@@ -190,6 +230,14 @@ impl AnimeConfig {
Duration::from_secs(2), Duration::from_secs(2),
)), )),
}], }],
sleep: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9,
angle: 0.0,
translation: Vec2::new(3.0, 2.0),
brightness: 1.0,
time: AnimTime::Infinite,
}],
shutdown: vec![ActionLoader::ImageAnimation { shutdown: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(), file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9, scale: 0.9,
@@ -201,8 +249,6 @@ impl AnimeConfig {
brightness: 1.0, brightness: 1.0,
awake_enabled: true, awake_enabled: true,
boot_anim_enabled: true, boot_anim_enabled: true,
}; }
config.write();
config
} }
} }
+6 -3
View File
@@ -113,9 +113,8 @@ impl CtrlAnime {
info!("AniMe no previous system thread running (now)"); info!("AniMe no previous system thread running (now)");
thread_exit.store(false, Ordering::SeqCst); thread_exit.store(false, Ordering::SeqCst);
thread_running.store(true, Ordering::SeqCst);
'main: loop { 'main: loop {
thread_running.store(true, Ordering::SeqCst);
for action in &actions { for action in &actions {
if thread_exit.load(Ordering::SeqCst) { if thread_exit.load(Ordering::SeqCst) {
break 'main; break 'main;
@@ -124,7 +123,7 @@ impl CtrlAnime {
ActionData::Animation(frames) => { ActionData::Animation(frames) => {
rog_anime::run_animation(frames, &|frame| { rog_anime::run_animation(frames, &|frame| {
if thread_exit.load(Ordering::Acquire) { if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: frame-loop was asked to exit"); info!("rog-anime: animation sub-loop was asked to exit");
return Ok(true); // Do safe exit return Ok(true); // Do safe exit
} }
inner inner
@@ -148,6 +147,10 @@ impl CtrlAnime {
Ok, Ok,
) )
}); });
if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: sub-loop exited and main loop exiting now");
break 'main;
}
} }
ActionData::Image(image) => { ActionData::Image(image) => {
once = false; once = false;
+10 -19
View File
@@ -3,10 +3,10 @@ use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use config_traits::StdConfig; use config_traits::StdConfig;
use log::{info, warn}; use log::warn;
use rog_anime::usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on}; use rog_anime::usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on};
use rog_anime::{AnimeDataBuffer, AnimePowerStates}; use rog_anime::{AnimeDataBuffer, AnimePowerStates};
use zbus::export::futures_util::lock::{Mutex, MutexGuard}; use zbus::export::futures_util::lock::Mutex;
use zbus::{dbus_interface, Connection, SignalContext}; use zbus::{dbus_interface, Connection, SignalContext};
use super::CtrlAnime; use super::CtrlAnime;
@@ -149,50 +149,41 @@ impl crate::CtrlTask for CtrlAnimeZbus {
} }
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
let run_action =
|start: bool, lock: MutexGuard<'_, CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
if start {
info!("CtrlAnimeTask running sleep animation");
CtrlAnime::run_thread(inner, lock.cache.shutdown.clone(), true);
} else {
info!("CtrlAnimeTask running wake animation");
CtrlAnime::run_thread(inner, lock.cache.wake.clone(), true);
}
};
let inner1 = self.0.clone(); let inner1 = self.0.clone();
let inner2 = self.0.clone(); let inner2 = self.0.clone();
let inner3 = self.0.clone(); let inner3 = self.0.clone();
let inner4 = self.0.clone(); let inner4 = self.0.clone();
self.create_sys_event_tasks( self.create_sys_event_tasks(
// Loop is required to try an attempt to get the mutex *without* blocking
// other threads - it is possible to end up with deadlocks otherwise.
move || { move || {
// on_sleep
let inner1 = inner1.clone(); let inner1 = inner1.clone();
async move { async move {
let lock = inner1.lock().await; let lock = inner1.lock().await;
run_action(true, lock, inner1.clone()); CtrlAnime::run_thread(inner1.clone(), lock.cache.sleep.clone(), true);
} }
}, },
move || { move || {
// on_wake
let inner2 = inner2.clone(); let inner2 = inner2.clone();
async move { async move {
let lock = inner2.lock().await; let lock = inner2.lock().await;
run_action(true, lock, inner2.clone()); CtrlAnime::run_thread(inner2.clone(), lock.cache.wake.clone(), true);
} }
}, },
move || { move || {
// on_shutdown
let inner3 = inner3.clone(); let inner3 = inner3.clone();
async move { async move {
let lock = inner3.lock().await; let lock = inner3.lock().await;
run_action(true, lock, inner3.clone()); CtrlAnime::run_thread(inner3.clone(), lock.cache.shutdown.clone(), true);
} }
}, },
move || { move || {
// on_boot
let inner4 = inner4.clone(); let inner4 = inner4.clone();
async move { async move {
let lock = inner4.lock().await; let lock = inner4.lock().await;
run_action(true, lock, inner4.clone()); CtrlAnime::run_thread(inner4.clone(), lock.cache.boot.clone(), true);
} }
}, },
) )
+66 -89
View File
@@ -1,11 +1,9 @@
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT}; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT};
use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardLed;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "aura.ron"; const CONFIG_FILE: &str = "aura.ron";
@@ -16,8 +14,8 @@ const CONFIG_FILE: &str = "aura.ron";
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuraPowerConfig { pub enum AuraPowerConfig {
AuraDevTuf(HashSet<AuraDevTuf>), AuraDevTuf(HashSet<AuraDevTuf>),
AuraDev1866(HashSet<AuraDev1866>), AuraDevRog1(HashSet<AuraDevRog1>),
AuraDev19b6(HashSet<AuraDev19b6>), AuraDevRog2(HashSet<AuraDevRog2>),
} }
impl AuraPowerConfig { impl AuraPowerConfig {
@@ -25,13 +23,13 @@ impl AuraPowerConfig {
pub fn to_bytes(control: &Self) -> [u8; 3] { pub fn to_bytes(control: &Self) -> [u8; 3] {
match control { match control {
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0], AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0],
AuraPowerConfig::AuraDev1866(c) => { AuraPowerConfig::AuraDevRog1(c) => {
let c: Vec<AuraDev1866> = c.iter().copied().collect(); let c: Vec<AuraDevRog1> = c.iter().copied().collect();
AuraDev1866::to_bytes(&c) AuraDevRog1::to_bytes(&c)
} }
AuraPowerConfig::AuraDev19b6(c) => { AuraPowerConfig::AuraDevRog2(c) => {
let c: Vec<AuraDev19b6> = c.iter().copied().collect(); let c: Vec<AuraDevRog2> = c.iter().copied().collect();
AuraDev19b6::to_bytes(&c) AuraDevRog2::to_bytes(&c)
} }
} }
} }
@@ -47,13 +45,13 @@ impl AuraPowerConfig {
]); ]);
} }
if let Self::AuraDev1866(c) = control { if let Self::AuraDevRog1(c) = control {
return Some([ return Some([
true, true,
c.contains(&AuraDev1866::Boot), c.contains(&AuraDevRog1::Boot),
c.contains(&AuraDev1866::Awake), c.contains(&AuraDevRog1::Awake),
c.contains(&AuraDev1866::Sleep), c.contains(&AuraDevRog1::Sleep),
c.contains(&AuraDev1866::Keyboard), c.contains(&AuraDevRog1::Keyboard),
]); ]);
} }
@@ -70,8 +68,8 @@ impl AuraPowerConfig {
} }
} }
pub fn set_0x1866(&mut self, power: AuraDev1866, on: bool) { pub fn set_0x1866(&mut self, power: AuraDevRog1, on: bool) {
if let Self::AuraDev1866(p) = self { if let Self::AuraDevRog1(p) = self {
if on { if on {
p.insert(power); p.insert(power);
} else { } else {
@@ -80,8 +78,8 @@ impl AuraPowerConfig {
} }
} }
pub fn set_0x19b6(&mut self, power: AuraDev19b6, on: bool) { pub fn set_0x19b6(&mut self, power: AuraDevRog2, on: bool) {
if let Self::AuraDev19b6(p) = self { if let Self::AuraDevRog2(p) = self {
if on { if on {
p.insert(power); p.insert(power);
} else { } else {
@@ -99,12 +97,12 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
x1866: vec![], x1866: vec![],
x19b6: vec![], x19b6: vec![],
}, },
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev { AuraPowerConfig::AuraDevRog1(d) => AuraPowerDev {
tuf: vec![], tuf: vec![],
x1866: d.iter().copied().collect(), x1866: d.iter().copied().collect(),
x19b6: vec![], x19b6: vec![],
}, },
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev { AuraPowerConfig::AuraDevRog2(d) => AuraPowerDev {
tuf: vec![], tuf: vec![],
x1866: vec![], x1866: vec![],
x19b6: d.iter().copied().collect(), x19b6: d.iter().copied().collect(),
@@ -113,7 +111,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
} }
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize, Debug, Clone)]
// #[serde(default)] // #[serde(default)]
pub struct AuraConfig { pub struct AuraConfig {
pub brightness: LedBrightness, pub brightness: LedBrightness,
@@ -124,38 +122,40 @@ pub struct AuraConfig {
pub enabled: AuraPowerConfig, pub enabled: AuraPowerConfig,
} }
impl Default for AuraConfig { impl StdConfig for AuraConfig {
fn default() -> Self { fn new() -> Self {
let mut prod_id = AuraDevice::Unknown; // Self::create_default(AuraDevice::X19b6, &LaptopLedData::get_data())
for prod in &ASUS_KEYBOARD_DEVICES { panic!("AuraConfig::new() should not be used, use AuraConfig::create_default() instead");
if HidRaw::new(prod).is_ok() { }
prod_id = AuraDevice::from(*prod);
break;
}
}
if prod_id == AuraDevice::Unknown { fn config_dir() -> std::path::PathBuf {
if let Ok(p) = KeyboardLed::new() { std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
if p.has_kbd_rgb_mode() { }
prod_id = AuraDevice::Tuf;
}
}
}
let enabled = if prod_id == AuraDevice::X19B6 { fn file_name(&self) -> String {
AuraPowerConfig::AuraDev19b6(HashSet::from([ CONFIG_FILE.to_owned()
AuraDev19b6::BootLogo, }
AuraDev19b6::BootKeyb, }
AuraDev19b6::SleepLogo,
AuraDev19b6::SleepKeyb, impl StdConfigLoad for AuraConfig {}
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb, impl AuraConfig {
AuraDev19b6::ShutdownLogo, pub fn create_default(prod_id: AuraDevice, support_data: &LaptopLedData) -> Self {
AuraDev19b6::ShutdownKeyb, // create a default config here
AuraDev19b6::BootBar, let enabled = if prod_id == AuraDevice::X19b6 {
AuraDev19b6::AwakeBar, AuraPowerConfig::AuraDevRog2(HashSet::from([
AuraDev19b6::SleepBar, AuraDevRog2::BootLogo,
AuraDev19b6::ShutdownBar, AuraDevRog2::BootKeyb,
AuraDevRog2::SleepLogo,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
AuraDevRog2::BootBar,
AuraDevRog2::AwakeBar,
AuraDevRog2::SleepBar,
AuraDevRog2::ShutdownBar,
])) ]))
} else if prod_id == AuraDevice::Tuf { } else if prod_id == AuraDevice::Tuf {
AuraPowerConfig::AuraDevTuf(HashSet::from([ AuraPowerConfig::AuraDevTuf(HashSet::from([
@@ -165,46 +165,22 @@ impl Default for AuraConfig {
AuraDevTuf::Keyboard, AuraDevTuf::Keyboard,
])) ]))
} else { } else {
AuraPowerConfig::AuraDev1866(HashSet::from([ AuraPowerConfig::AuraDevRog1(HashSet::from([
AuraDev1866::Awake, AuraDevRog1::Awake,
AuraDev1866::Boot, AuraDevRog1::Boot,
AuraDev1866::Sleep, AuraDevRog1::Sleep,
AuraDev1866::Keyboard, AuraDevRog1::Keyboard,
AuraDev1866::Lightbar, AuraDevRog1::Lightbar,
])) ]))
}; };
let mut config = AuraConfig {
AuraConfig {
brightness: LedBrightness::Med, brightness: LedBrightness::Med,
current_mode: AuraModeNum::Static, current_mode: AuraModeNum::Static,
builtins: BTreeMap::new(), builtins: BTreeMap::new(),
multizone: None, multizone: None,
multizone_on: false, multizone_on: false,
enabled, enabled,
} };
}
}
impl StdConfig for AuraConfig {
fn new() -> Self {
Self::create_default(&LaptopLedData::get_data())
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
fn file_name(&self) -> String {
CONFIG_FILE.to_string()
}
}
impl StdConfigLoad for AuraConfig {}
impl AuraConfig {
fn create_default(support_data: &LaptopLedData) -> Self {
// create a default config here
let mut config = AuraConfig::default();
for n in &support_data.basic_modes { for n in &support_data.basic_modes {
config config
@@ -232,7 +208,6 @@ impl AuraConfig {
} }
} }
} }
config.write();
config config
} }
@@ -277,13 +252,15 @@ impl AuraConfig {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::AuraDevice;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour}; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use super::AuraConfig; use super::AuraConfig;
#[test] #[test]
fn set_multizone_4key_config() { fn set_multizone_4key_config() {
let mut config = AuraConfig::default(); let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let effect = AuraEffect { let effect = AuraEffect {
colour1: Colour(0xff, 0x00, 0xff), colour1: Colour(0xff, 0x00, 0xff),
@@ -329,7 +306,7 @@ mod tests {
#[test] #[test]
fn set_multizone_multimode_config() { fn set_multizone_multimode_config() {
let mut config = AuraConfig::default(); let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let effect = AuraEffect { let effect = AuraEffect {
zone: AuraZone::Key1, zone: AuraZone::Key1,
+65 -25
View File
@@ -1,6 +1,6 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use config_traits::StdConfig; use config_traits::{StdConfig, StdConfigLoad};
use log::{info, warn}; use log::{info, warn};
use rog_aura::advanced::{LedUsbPackets, UsbPackets}; use rog_aura::advanced::{LedUsbPackets, UsbPackets};
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
@@ -25,9 +25,9 @@ impl GetSupported for CtrlKbdLed {
let advanced_type = laptop.advanced_type; let advanced_type = laptop.advanced_type;
let mut prod_id = AuraDevice::Unknown; let mut prod_id = AuraDevice::Unknown;
for prod in &ASUS_KEYBOARD_DEVICES { for prod in ASUS_KEYBOARD_DEVICES {
if HidRaw::new(prod).is_ok() { if HidRaw::new(prod.into()).is_ok() {
prod_id = AuraDevice::from(*prod); prod_id = prod;
break; break;
} }
} }
@@ -58,7 +58,7 @@ pub enum LEDNode {
pub struct CtrlKbdLed { pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this // TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: Option<String>, pub led_prod: AuraDevice,
pub led_node: LEDNode, pub led_node: LEDNode,
pub kd_brightness: KeyboardLed, pub kd_brightness: KeyboardLed,
pub supported_modes: LaptopLedData, pub supported_modes: LaptopLedData,
@@ -68,34 +68,43 @@ pub struct CtrlKbdLed {
} }
impl CtrlKbdLed { impl CtrlKbdLed {
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> { pub fn new(supported_modes: LaptopLedData) -> Result<Self, RogError> {
let mut led_prod = None; let mut led_prod = AuraDevice::Unknown;
let mut led_node = None; let mut usb_node = None;
for prod in &ASUS_KEYBOARD_DEVICES { for prod in ASUS_KEYBOARD_DEVICES {
match HidRaw::new(prod) { match HidRaw::new(prod.into()) {
Ok(node) => { Ok(node) => {
led_prod = Some((*prod).to_owned()); led_prod = prod;
led_node = Some(node); usb_node = Some(node);
info!("Looked for keyboard controller 0x{prod}: Found"); info!(
"Looked for keyboard controller 0x{}: Found",
<&str>::from(prod)
);
break; break;
} }
Err(err) => info!("Looked for keyboard controller 0x{prod}: {err}"), Err(err) => info!(
"Looked for keyboard controller 0x{}: {err}",
<&str>::from(prod)
),
} }
} }
let rgb_led = KeyboardLed::new()?; let rgb_led = KeyboardLed::new()?;
if led_node.is_none() && !rgb_led.has_kbd_rgb_mode() { if usb_node.is_none() && !rgb_led.has_kbd_rgb_mode() {
let dmi = sysfs_class::DmiId::default(); let dmi = sysfs_class::DmiId::default();
if let Ok(prod_family) = dmi.product_family() { if let Ok(prod_family) = dmi.product_family() {
if prod_family.contains("TUF") { if prod_family.contains("TUF") {
warn!("A kernel patch is in progress for TUF RGB support"); warn!(
"kbd_rgb_mode was not found in the /sys/. You require a minimum 6.1 \
kernel and a supported TUF laptop"
);
} }
} }
return Err(RogError::NoAuraKeyboard); return Err(RogError::NoAuraKeyboard);
} }
let led_node = if let Some(rog) = led_node { let led_node = if let Some(rog) = usb_node {
info!("Found ROG USB keyboard"); info!("Found ROG USB keyboard");
LEDNode::Rog(rog) LEDNode::Rog(rog)
} else if rgb_led.has_kbd_rgb_mode() { } else if rgb_led.has_kbd_rgb_mode() {
@@ -105,14 +114,44 @@ impl CtrlKbdLed {
LEDNode::None LEDNode::None
}; };
let mut config_init = AuraConfig::create_default(led_prod, &supported_modes);
let mut config_loaded = config_init.clone().load();
for mode in &mut config_init.builtins {
// update init values from loaded values if they exist
if let Some(loaded) = config_loaded.builtins.get(mode.0) {
*mode.1 = loaded.clone();
}
}
config_loaded.builtins = config_init.builtins;
if let (Some(mut multizone_init), Some(multizone_loaded)) =
(config_init.multizone, config_loaded.multizone.as_mut())
{
for mode in multizone_init.iter_mut() {
// update init values from loaded values if they exist
if let Some(loaded) = multizone_loaded.get(mode.0) {
let mut new_set = Vec::new();
// only reuse a zone mode if the mode is supported
for mode in loaded {
if supported_modes.basic_modes.contains(&mode.mode) {
new_set.push(mode.clone());
}
}
*mode.1 = new_set;
}
}
*multizone_loaded = multizone_init;
}
let ctrl = CtrlKbdLed { let ctrl = CtrlKbdLed {
led_prod, led_prod,
led_node, led_node, // on TUF this is the same as rgb_led / kd_brightness
kd_brightness: rgb_led, // If was none then we already returned above kd_brightness: rgb_led, // If was none then we already returned above
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
per_key_mode_active: false, per_key_mode_active: false,
config, config: config_loaded,
}; };
Ok(ctrl) Ok(ctrl)
} }
@@ -356,6 +395,7 @@ impl CtrlKbdLed {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rog_aura::aura_detection::LaptopLedData; use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::AuraDevice;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour}; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use rog_platform::keyboard_led::KeyboardLed; use rog_platform::keyboard_led::KeyboardLed;
@@ -367,7 +407,7 @@ mod tests {
// #[ignore = "Must be manually run due to detection stage"] // #[ignore = "Must be manually run due to detection stage"]
fn check_set_mode_errors() { fn check_set_mode_errors() {
// Checking to ensure set_mode errors when unsupported modes are tried // Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default(); let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData { let supported_modes = LaptopLedData {
board_name: String::new(), board_name: String::new(),
layout_name: "ga401".to_owned(), layout_name: "ga401".to_owned(),
@@ -376,7 +416,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None, advanced_type: rog_aura::AdvancedAuraType::None,
}; };
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: AuraDevice::X19b6,
led_node: LEDNode::None, led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
@@ -430,7 +470,7 @@ mod tests {
#[test] #[test]
fn create_multizone_if_no_config() { fn create_multizone_if_no_config() {
// Checking to ensure set_mode errors when unsupported modes are tried // Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default(); let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData { let supported_modes = LaptopLedData {
board_name: String::new(), board_name: String::new(),
layout_name: "ga401".to_owned(), layout_name: "ga401".to_owned(),
@@ -439,7 +479,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None, advanced_type: rog_aura::AdvancedAuraType::None,
}; };
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: AuraDevice::X19b6,
led_node: LEDNode::None, led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
@@ -468,7 +508,7 @@ mod tests {
#[test] #[test]
fn next_mode_create_multizone_if_no_config() { fn next_mode_create_multizone_if_no_config() {
// Checking to ensure set_mode errors when unsupported modes are tried // Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default(); let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData { let supported_modes = LaptopLedData {
board_name: String::new(), board_name: String::new(),
layout_name: "ga401".to_owned(), layout_name: "ga401".to_owned(),
@@ -477,7 +517,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None, advanced_type: rog_aura::AdvancedAuraType::None,
}; };
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: AuraDevice::X19b6,
led_node: LEDNode::None, led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
+1 -1
View File
@@ -1,4 +1,4 @@
pub mod config; pub mod config;
pub mod controller; pub mod controller;
/// Implements CtrlTask, Reloadable, ZbusRun /// Implements `CtrlTask`, `Reloadable`, `ZbusRun`
pub mod trait_impls; pub mod trait_impls;
+3 -9
View File
@@ -92,15 +92,8 @@ impl CtrlPlatform {
} }
pub fn get_boot_sound() -> Result<i8, RogError> { pub fn get_boot_sound() -> Result<i8, RogError> {
let path = ASUS_POST_LOGO_SOUND; let data = std::fs::read(ASUS_POST_LOGO_SOUND)
let mut file = OpenOptions::new() .map_err(|err| RogError::Read(ASUS_POST_LOGO_SOUND.into(), err))?;
.read(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let idx = data.len() - 1; let idx = data.len() - 1;
Ok(data[idx] as i8) Ok(data[idx] as i8)
@@ -115,6 +108,7 @@ impl CtrlPlatform {
.map_err(|err| RogError::Path(path.into(), err))?; .map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new(); let mut data = Vec::new();
#[allow(clippy::verbose_file_reads)]
file.read_to_end(&mut data) file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?; .map_err(|err| RogError::Read(path.into(), err))?;
+9 -33
View File
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::fan_curve_set::FanCurveSet;
use rog_profiles::{FanCurveProfiles, Profile}; use rog_profiles::Profile;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use crate::CONFIG_PATH_BASE; use crate::CONFIG_PATH_BASE;
@@ -28,7 +28,7 @@ impl StdConfig for ProfileConfig {
} }
fn file_name(&self) -> String { fn file_name(&self) -> String {
CONFIG_FILE.to_string() CONFIG_FILE.to_owned()
} }
} }
@@ -36,40 +36,16 @@ impl StdConfigLoad for ProfileConfig {}
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
pub struct FanCurveConfig { pub struct FanCurveConfig {
balanced: FanCurveSet, pub balanced: FanCurveSet,
performance: FanCurveSet, pub performance: FanCurveSet,
quiet: FanCurveSet, pub quiet: FanCurveSet,
#[serde(skip)]
device: FanCurveProfiles,
}
impl FanCurveConfig {
pub fn update_device_config(&mut self) {
self.balanced = self.device.balanced.clone();
self.performance = self.device.performance.clone();
self.quiet = self.device.quiet.clone();
}
pub fn update_config(&mut self) {
self.balanced = self.device.balanced.clone();
self.performance = self.device.performance.clone();
self.quiet = self.device.quiet.clone();
}
pub fn device(&self) -> &FanCurveProfiles {
&self.device
}
pub fn device_mut(&mut self) -> &mut FanCurveProfiles {
&mut self.device
}
} }
impl StdConfig for FanCurveConfig { impl StdConfig for FanCurveConfig {
/// Create a new config. The defaults are zeroed so the device must be read
/// to get the actual device defaults.
fn new() -> Self { fn new() -> Self {
let mut tmp = Self::default(); Self::default()
tmp.update_device_config();
tmp
} }
fn config_dir() -> std::path::PathBuf { fn config_dir() -> std::path::PathBuf {
@@ -77,7 +53,7 @@ impl StdConfig for FanCurveConfig {
} }
fn file_name(&self) -> String { fn file_name(&self) -> String {
CONFIG_FAN_FILE.to_string() CONFIG_FAN_FILE.to_owned()
} }
} }
+70 -20
View File
@@ -1,4 +1,4 @@
use config_traits::StdConfig; use config_traits::{StdConfig, StdConfigLoad};
use log::{info, warn}; use log::{info, warn};
use rog_platform::platform::AsusPlatform; use rog_platform::platform::AsusPlatform;
use rog_platform::supported::PlatformProfileFunctions; use rog_platform::supported::PlatformProfileFunctions;
@@ -9,9 +9,39 @@ use super::config::{FanCurveConfig, ProfileConfig};
use crate::error::RogError; use crate::error::RogError;
use crate::GetSupported; use crate::GetSupported;
// TODO: macro wrapper for warn/info/error log macros to add module name
const MOD_NAME: &str = "CtrlPlatformProfile";
pub struct FanCurves {
config_file: FanCurveConfig,
profiles: FanCurveProfiles,
}
impl FanCurves {
pub fn update_profiles_from_config(&mut self) {
self.profiles.balanced = self.config_file.balanced.clone();
self.profiles.performance = self.config_file.performance.clone();
self.profiles.quiet = self.config_file.quiet.clone();
}
pub fn update_config_from_profiles(&mut self) {
self.config_file.balanced = self.profiles.balanced.clone();
self.config_file.performance = self.profiles.performance.clone();
self.config_file.quiet = self.profiles.quiet.clone();
}
pub fn profiles(&self) -> &FanCurveProfiles {
&self.profiles
}
pub fn profiles_mut(&mut self) -> &mut FanCurveProfiles {
&mut self.profiles
}
}
pub struct CtrlPlatformProfile { pub struct CtrlPlatformProfile {
pub profile_config: ProfileConfig, pub profile_config: ProfileConfig,
pub fan_config: Option<FanCurveConfig>, pub fan_curves: Option<FanCurves>,
pub platform: AsusPlatform, pub platform: AsusPlatform,
} }
@@ -50,30 +80,50 @@ impl CtrlPlatformProfile {
pub fn new(config: ProfileConfig) -> Result<Self, RogError> { pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
let platform = AsusPlatform::new()?; let platform = AsusPlatform::new()?;
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() { if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
info!("Device has profile control available"); info!("{MOD_NAME}: Device has profile control available");
let mut controller = CtrlPlatformProfile { let mut controller = CtrlPlatformProfile {
profile_config: config, profile_config: config,
fan_config: None, fan_curves: None,
platform, platform,
}; };
if FanCurveProfiles::get_device().is_ok() { if FanCurveProfiles::get_device().is_ok() {
info!("Device has fan curves available"); info!("{MOD_NAME}: Device has fan curves available");
if controller.fan_config.is_none() { let fan_config = FanCurveConfig::new();
controller.fan_config = Some(Default::default()); // Only do defaults if the config doesn't already exist
if !fan_config.file_path().exists() {
info!("{MOD_NAME}: Fetching default fan curves");
controller.fan_curves = Some(FanCurves {
config_file: fan_config,
profiles: FanCurveProfiles::default(),
});
for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] { for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] {
// For each profile we need to switch to it before we
// can read the existing values from hardware. The ACPI method used
// for this is what limits us.
controller.set_next_profile()?; controller.set_next_profile()?;
// Make sure to set the baseline to default
controller.set_active_curve_to_defaults()?; controller.set_active_curve_to_defaults()?;
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced); let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
if let Some(curves) = controller.fan_config.as_ref() {
if let Some(curves) = controller.fan_curves.as_ref() {
info!( info!(
"{active:?}: {}", "{MOD_NAME}: {active:?}: {}",
String::from(curves.device().get_fan_curves_for(active)) String::from(curves.profiles().get_fan_curves_for(active))
); );
curves.write();
} }
} }
if let Some(curves) = controller.fan_curves.as_ref() {
curves.config_file.write();
}
} else {
info!("{MOD_NAME}: Fan curves previously stored, loading...");
let mut fan_curves = FanCurves {
config_file: fan_config.load(),
profiles: FanCurveProfiles::default(),
};
fan_curves.update_profiles_from_config();
controller.fan_curves = Some(fan_curves);
} }
} }
@@ -85,9 +135,9 @@ impl CtrlPlatformProfile {
pub fn save_config(&mut self) { pub fn save_config(&mut self) {
self.profile_config.write(); self.profile_config.write();
if let Some(fans) = self.fan_config.as_mut() { if let Some(fans) = self.fan_curves.as_mut() {
fans.update_config(); fans.update_config_from_profiles();
fans.write(); fans.config_file.write(); // config write
} }
} }
@@ -115,9 +165,9 @@ impl CtrlPlatformProfile {
/// Set the curve for the active profile active /// Set the curve for the active profile active
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> { pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
if let Some(curves) = &mut self.fan_config { if let Some(curves) = &mut self.fan_curves {
if let Ok(mut device) = FanCurveProfiles::get_device() { if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.device_mut().write_profile_curve_to_platform( curves.profiles_mut().write_profile_curve_to_platform(
self.profile_config.active_profile, self.profile_config.active_profile,
&mut device, &mut device,
)?; )?;
@@ -127,13 +177,13 @@ impl CtrlPlatformProfile {
} }
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> { pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
if let Some(curves) = self.fan_config.as_mut() { if let Some(curves) = self.fan_curves.as_mut() {
if let Ok(mut device) = FanCurveProfiles::get_device() { if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.device_mut().set_active_curve_to_defaults( curves.profiles_mut().set_active_curve_to_defaults(
self.profile_config.active_profile, self.profile_config.active_profile,
&mut device, &mut device,
)?; )?;
curves.update_config(); curves.update_config_from_profiles();
} }
} }
Ok(()) Ok(())
+24 -25
View File
@@ -15,6 +15,8 @@ use super::controller::CtrlPlatformProfile;
use crate::error::RogError; use crate::error::RogError;
use crate::CtrlTask; use crate::CtrlTask;
const MOD_NAME: &str = "ProfileZbus";
const ZBUS_PATH: &str = "/org/asuslinux/Profile"; const ZBUS_PATH: &str = "/org/asuslinux/Profile";
const UNSUPPORTED_MSG: &str = const UNSUPPORTED_MSG: &str =
"Fan curves are not supported on this laptop or you require a patched kernel"; "Fan curves are not supported on this laptop or you require a patched kernel";
@@ -39,7 +41,7 @@ impl ProfileZbus {
async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) { async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.set_next_profile() ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err)); .unwrap_or_else(|err| warn!("{MOD_NAME}: {}", err));
ctrl.save_config(); ctrl.save_config();
Self::notify_profile(&ctxt, ctrl.profile_config.active_profile) Self::notify_profile(&ctxt, ctrl.profile_config.active_profile)
@@ -64,11 +66,11 @@ impl ProfileZbus {
// Read first just incase the user has modified the config before calling this // Read first just incase the user has modified the config before calling this
ctrl.profile_config.read(); ctrl.profile_config.read();
Profile::set_profile(profile) Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e)) .map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok(); .ok();
ctrl.profile_config.active_profile = profile; ctrl.profile_config.active_profile = profile;
ctrl.write_profile_curve_to_platform() ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e)) .map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
.ok(); .ok();
ctrl.save_config(); ctrl.save_config();
@@ -82,8 +84,8 @@ impl ProfileZbus {
async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> { async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.profile_config.read(); ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config { if let Some(curves) = &mut ctrl.fan_curves {
return Ok(curves.device().get_enabled_curve_profiles()); return Ok(curves.profiles().get_enabled_curve_profiles());
} }
Err(Error::Failed(UNSUPPORTED_MSG.to_owned())) Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
} }
@@ -97,14 +99,13 @@ impl ProfileZbus {
) -> zbus::fdo::Result<()> { ) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.profile_config.read(); ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config { if let Some(curves) = &mut ctrl.fan_curves {
curves curves
.device_mut() .profiles_mut()
.set_profile_curve_enabled(profile, enabled); .set_profile_curve_enabled(profile, enabled);
curves.update_config();
ctrl.write_profile_curve_to_platform() ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e)) .map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
.ok(); .ok();
ctrl.save_config(); ctrl.save_config();
@@ -118,8 +119,8 @@ impl ProfileZbus {
async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> { async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.profile_config.read(); ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config { if let Some(curves) = &mut ctrl.fan_curves {
let curve = curves.device().get_fan_curves_for(profile); let curve = curves.profiles().get_fan_curves_for(profile);
return Ok(curve.clone()); return Ok(curve.clone());
} }
Err(Error::Failed(UNSUPPORTED_MSG.to_owned())) Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
@@ -130,17 +131,16 @@ impl ProfileZbus {
async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> { async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.profile_config.read(); ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config { if let Some(curves) = &mut ctrl.fan_curves {
curves curves
.device_mut() .profiles_mut()
.save_fan_curve(curve, profile) .save_fan_curve(curve, profile)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
curves.update_config();
} else { } else {
return Err(Error::Failed(UNSUPPORTED_MSG.to_owned())); return Err(Error::Failed(UNSUPPORTED_MSG.to_owned()));
} }
ctrl.write_profile_curve_to_platform() ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("Profile::set_profile, {}", e)) .map_err(|e| warn!("{MOD_NAME}: Profile::set_profile, {}", e))
.ok(); .ok();
ctrl.save_config(); ctrl.save_config();
@@ -156,7 +156,7 @@ impl ProfileZbus {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
ctrl.profile_config.read(); ctrl.profile_config.read();
ctrl.set_active_curve_to_defaults() ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e)) .map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
.ok(); .ok();
ctrl.save_config(); ctrl.save_config();
Ok(()) Ok(())
@@ -173,14 +173,14 @@ impl ProfileZbus {
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced); let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
Profile::set_profile(profile) Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e)) .map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok(); .ok();
ctrl.set_active_curve_to_defaults() ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e)) .map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
.ok(); .ok();
Profile::set_profile(active) Profile::set_profile(active)
.map_err(|e| warn!("set_profile, {}", e)) .map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok(); .ok();
ctrl.save_config(); ctrl.save_config();
Ok(()) Ok(())
@@ -222,12 +222,12 @@ impl CtrlTask for ProfileZbus {
let mut lock = ctrl.lock().await; let mut lock = ctrl.lock().await;
if let Ok(profile) = if let Ok(profile) =
lock.platform.get_throttle_thermal_policy().map_err(|e| { lock.platform.get_throttle_thermal_policy().map_err(|e| {
error!("get_throttle_thermal_policy error: {e}"); error!("{MOD_NAME}: get_throttle_thermal_policy error: {e}");
}) })
{ {
let new_profile = Profile::from_throttle_thermal_policy(profile); let new_profile = Profile::from_throttle_thermal_policy(profile);
if new_profile != lock.profile_config.active_profile { if new_profile != lock.profile_config.active_profile {
info!("platform_profile changed to {new_profile}"); info!("{MOD_NAME}: platform_profile changed to {new_profile}");
lock.profile_config.active_profile = new_profile; lock.profile_config.active_profile = new_profile;
lock.write_profile_curve_to_platform().unwrap(); lock.write_profile_curve_to_platform().unwrap();
lock.save_config(); lock.save_config();
@@ -262,7 +262,7 @@ impl CtrlTask for ProfileZbus {
error!("Profile::from_str(&profile) error: {e}"); error!("Profile::from_str(&profile) error: {e}");
}) { }) {
if new_profile != lock.profile_config.active_profile { if new_profile != lock.profile_config.active_profile {
info!("platform_profile changed to {new_profile}"); info!("{MOD_NAME}: platform_profile changed to {new_profile}");
lock.profile_config.active_profile = new_profile; lock.profile_config.active_profile = new_profile;
lock.write_profile_curve_to_platform().unwrap(); lock.write_profile_curve_to_platform().unwrap();
lock.save_config(); lock.save_config();
@@ -295,15 +295,14 @@ impl crate::Reloadable for ProfileZbus {
async fn reload(&mut self) -> Result<(), RogError> { async fn reload(&mut self) -> Result<(), RogError> {
let mut ctrl = self.0.lock().await; let mut ctrl = self.0.lock().await;
let active = ctrl.profile_config.active_profile; let active = ctrl.profile_config.active_profile;
if let Some(curves) = &mut ctrl.fan_config { if let Some(curves) = &mut ctrl.fan_curves {
if let Ok(mut device) = FanCurveProfiles::get_device() { if let Ok(mut device) = FanCurveProfiles::get_device() {
// There is a possibility that the curve was default zeroed, so this call // There is a possibility that the curve was default zeroed, so this call
// initialises the data from system read and we need to save it // initialises the data from system read and we need to save it
// after // after
curves curves
.device_mut() .profiles_mut()
.write_profile_curve_to_platform(active, &mut device)?; .write_profile_curve_to_platform(active, &mut device)?;
curves.update_config();
ctrl.profile_config.write(); ctrl.profile_config.write();
} }
} }
+3 -3
View File
@@ -11,7 +11,6 @@ use daemon::config::Config;
use daemon::ctrl_anime::config::AnimeConfig; use daemon::ctrl_anime::config::AnimeConfig;
use daemon::ctrl_anime::trait_impls::CtrlAnimeZbus; use daemon::ctrl_anime::trait_impls::CtrlAnimeZbus;
use daemon::ctrl_anime::CtrlAnime; use daemon::ctrl_anime::CtrlAnime;
use daemon::ctrl_aura::config::AuraConfig;
use daemon::ctrl_aura::controller::CtrlKbdLed; use daemon::ctrl_aura::controller::CtrlKbdLed;
use daemon::ctrl_aura::trait_impls::CtrlKbdLedZbus; use daemon::ctrl_aura::trait_impls::CtrlKbdLedZbus;
use daemon::ctrl_platform::CtrlPlatform; use daemon::ctrl_platform::CtrlPlatform;
@@ -124,8 +123,9 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
let laptop = LaptopLedData::get_data(); let laptop = LaptopLedData::get_data();
let aura_config = AuraConfig::new().load(); // CtrlKbdLed deviates from the config pattern above due to requiring a keyboard
match CtrlKbdLed::new(laptop, aura_config) { // detection first
match CtrlKbdLed::new(laptop) {
Ok(ctrl) => { Ok(ctrl) => {
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl))); let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
let sig_ctx = CtrlKbdLedZbus::signal_context(&connection)?; let sig_ctx = CtrlKbdLedZbus::signal_context(&connection)?;
+4 -1
View File
@@ -32,4 +32,7 @@ zbus = { workspace = true, optional = true }
sysfs-class = { workspace = true, optional = true } sysfs-class = { workspace = true, optional = true }
uhid-virt = "^0.0.5" uhid-virt = "^0.0.6"
[dev-dependencies]
cargo-husky.workspace = true
+1 -1
View File
@@ -212,7 +212,7 @@ pub fn run_animation(frames: &AnimeGif, callback: &dyn Fn(AnimeDataBuffer) -> Re
// TODO: Log this error // TODO: Log this error
if matches!(callback(output), Ok(true)) { if matches!(callback(output), Ok(true)) {
info!("rog-anime: frame-loop callback asked to exit early"); info!("rog-anime: animation frame-loop callback asked to exit early");
return; return;
} }
+3 -1
View File
@@ -141,7 +141,9 @@ impl AnimeImage {
/// ///
/// In relation to the display itself you should think of it as a full /// In relation to the display itself you should think of it as a full
/// square grid, so `first_x` is the x position on that grid where the /// square grid, so `first_x` is the x position on that grid where the
/// LED is actually positioned in relation to the Y. ```text /// LED is actually positioned in relation to the Y.
///
/// ```text
/// +------------+ /// +------------+
/// | | /// | |
/// | | /// | |
+3
View File
@@ -28,3 +28,6 @@ log.workspace = true
sysfs-class.workspace = true # used for backlight control and baord ID sysfs-class.workspace = true # used for backlight control and baord ID
ron = { version = "*", optional = true } ron = { version = "*", optional = true }
[dev-dependencies]
cargo-husky.workspace = true
+78 -1
View File
@@ -34,6 +34,20 @@
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: None,
), ),
(
board_name: "FX506LH",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "FX516P",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe],
basic_zones: [],
advanced_type: None,
),
( (
board_name: "G512", board_name: "G512",
layout_name: "g512", layout_name: "g512",
@@ -181,6 +195,13 @@
basic_zones: [], basic_zones: [],
advanced_type: PerKey, advanced_type: PerKey,
), ),
(
board_name: "G533Z",
layout_name: "g533q-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
( (
board_name: "G712LI", board_name: "G712LI",
layout_name: "gl503", layout_name: "gl503",
@@ -286,6 +307,20 @@
basic_zones: [], basic_zones: [],
advanced_type: PerKey, advanced_type: PerKey,
), ),
(
board_name: "G733Z",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "GA401Q",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
( (
board_name: "GA402R", board_name: "GA402R",
layout_name: "ga401q", layout_name: "ga401q",
@@ -391,6 +426,13 @@
basic_zones: [], basic_zones: [],
advanced_type: Zoned([SingleZone]), advanced_type: Zoned([SingleZone]),
), ),
(
board_name: "GU604V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [],
advanced_type: Zoned([SingleZone]),
),
( (
board_name: "GV301Q", board_name: "GV301Q",
layout_name: "ga401q", layout_name: "ga401q",
@@ -398,6 +440,20 @@
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: None,
), ),
(
board_name: "GV301V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV301VIC",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
( (
board_name: "GV601R", board_name: "GV601R",
layout_name: "ga401q", layout_name: "ga401q",
@@ -405,6 +461,13 @@
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: None,
), ),
(
board_name: "GV604V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
( (
board_name: "GX502", board_name: "GX502",
layout_name: "gx502", layout_name: "gx502",
@@ -433,6 +496,13 @@
basic_zones: [], basic_zones: [],
advanced_type: PerKey, advanced_type: PerKey,
), ),
(
board_name: "GX650P",
layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
( (
board_name: "GX701", board_name: "GX701",
layout_name: "gx531-per-key", layout_name: "gx531-per-key",
@@ -448,7 +518,14 @@
advanced_type: None, advanced_type: None,
), ),
( (
board_name: "ga401qQ", board_name: "GZ301V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GZ301VIC",
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
+1
View File
@@ -303,6 +303,7 @@ impl LedUsbPackets {
fn rgb_for_led_code(&mut self, led_code: LedCode) -> Option<&mut [u8]> { fn rgb_for_led_code(&mut self, led_code: LedCode) -> Option<&mut [u8]> {
let zoned = self.zoned; let zoned = self.zoned;
// Tuples are indexes in to array // Tuples are indexes in to array
#[allow(clippy::match_same_arms)]
let (row, col) = match led_code { let (row, col) = match led_code {
LedCode::VolDown => (0, 15), LedCode::VolDown => (0, 15),
LedCode::VolUp => (0, 18), LedCode::VolUp => (0, 18),
+1
View File
@@ -8,6 +8,7 @@ impl From<LedCode> for &str {
impl From<&LedCode> for &str { impl From<&LedCode> for &str {
fn from(k: &LedCode) -> Self { fn from(k: &LedCode) -> Self {
#[allow(clippy::match_same_arms)]
match k { match k {
LedCode::VolUp => "Volume Up", LedCode::VolUp => "Volume Up",
LedCode::VolDown => "Volume Down", LedCode::VolDown => "Volume Down",
+35 -37
View File
@@ -1,14 +1,20 @@
use std::fs::OpenOptions;
use std::io::Read;
use log::{error, info, warn}; use log::{error, info, warn};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use crate::usb::AuraDevice;
use crate::{AdvancedAuraType, AuraModeNum, AuraZone}; use crate::{AdvancedAuraType, AuraModeNum, AuraZone};
pub const ASUS_LED_MODE_CONF: &str = "/usr/share/asusd/aura_support.ron"; pub const ASUS_LED_MODE_CONF: &str = "/usr/share/asusd/aura_support.ron";
pub const ASUS_LED_MODE_USER_CONF: &str = "/etc/asusd/asusd_user_ledmodes.ron"; pub const ASUS_LED_MODE_USER_CONF: &str = "/etc/asusd/asusd_user_ledmodes.ron";
pub const ASUS_KEYBOARD_DEVICES: [&str; 4] = ["1866", "1869", "1854", "19b6"]; pub const ASUS_KEYBOARD_DEVICES: [AuraDevice; 7] = [
AuraDevice::Tuf,
AuraDevice::X1854,
AuraDevice::X1869,
AuraDevice::X1866,
AuraDevice::X18c6,
AuraDevice::X19b6,
AuraDevice::X1a30,
];
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct LedSupportFile(Vec<LaptopLedData>); pub struct LedSupportFile(Vec<LaptopLedData>);
@@ -76,39 +82,33 @@ impl LedSupportFile {
let mut loaded = false; let mut loaded = false;
let mut data = LedSupportFile::default(); let mut data = LedSupportFile::default();
// Load user configs first so they are first to be checked // Load user configs first so they are first to be checked
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_USER_CONF) { if let Ok(file) = std::fs::read_to_string(ASUS_LED_MODE_USER_CONF) {
let mut buf = String::new(); if file.is_empty() {
if let Ok(l) = file.read_to_string(&mut buf) { warn!("{} is empty", ASUS_LED_MODE_USER_CONF);
if l == 0 { } else {
warn!("{} is empty", ASUS_LED_MODE_USER_CONF); if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&file) {
} else { data.0.append(&mut tmp.0);
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&buf) {
data.0.append(&mut tmp.0);
}
info!(
"Loaded user-defined LED support data from {}",
ASUS_LED_MODE_USER_CONF
);
} }
info!(
"Loaded user-defined LED support data from {}",
ASUS_LED_MODE_USER_CONF
);
} }
} }
// Load and append the default LED support data // Load and append the default LED support data
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_CONF) { if let Ok(file) = std::fs::read_to_string(ASUS_LED_MODE_CONF) {
let mut buf = String::new(); if file.is_empty() {
if let Ok(l) = file.read_to_string(&mut buf) { warn!("{} is empty", ASUS_LED_MODE_CONF);
if l == 0 { } else {
warn!("{} is empty", ASUS_LED_MODE_CONF); let mut tmp: LedSupportFile = ron::from_str(&file)
} else { .map_err(|e| error!("{e}"))
let mut tmp: LedSupportFile = ron::from_str(&buf) .unwrap_or_else(|_| panic!("Could not deserialise {}", ASUS_LED_MODE_CONF));
.map_err(|e| error!("{e}")) data.0.append(&mut tmp.0);
.unwrap_or_else(|_| panic!("Could not deserialise {}", ASUS_LED_MODE_CONF)); loaded = true;
data.0.append(&mut tmp.0); info!(
loaded = true; "Loaded default LED support data from {}",
info!( ASUS_LED_MODE_CONF
"Loaded default LED support data from {}", );
ASUS_LED_MODE_CONF
);
}
} }
} }
data.0.sort_by(|a, b| a.board_name.cmp(&b.board_name)); data.0.sort_by(|a, b| a.board_name.cmp(&b.board_name));
@@ -125,7 +125,7 @@ impl LedSupportFile {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use ron::ser::PrettyConfig; use ron::ser::PrettyConfig;
@@ -155,9 +155,7 @@ mod tests {
let mut data = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
data.push("data/aura_support.ron"); data.push("data/aura_support.ron");
let mut file = OpenOptions::new().read(true).open(&data).unwrap(); let buf = std::fs::read_to_string(&data).unwrap();
let mut buf = String::new();
file.read_to_string(&mut buf).unwrap();
let tmp = ron::from_str::<LedSupportFile>(&buf).unwrap(); let tmp = ron::from_str::<LedSupportFile>(&buf).unwrap();
+3 -1
View File
@@ -284,7 +284,8 @@ impl FromStr for AuraZone {
} }
/// Default factory modes structure. This easily converts to an USB HID packet /// Default factory modes structure. This easily converts to an USB HID packet
/// with: ```rust /// with:
/// ```rust
/// // let bytes: [u8; LED_MSG_LEN] = mode.into(); /// // let bytes: [u8; LED_MSG_LEN] = mode.into();
/// ``` /// ```
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
@@ -350,6 +351,7 @@ pub struct AuraParameters {
pub direction: bool, pub direction: bool,
} }
#[allow(clippy::fn_params_excessive_bools)]
impl AuraParameters { impl AuraParameters {
pub const fn new( pub const fn new(
zone: bool, zone: bool,
+1 -1
View File
@@ -28,6 +28,6 @@ impl EffectState for InputBased {
} }
fn set_led(&mut self, address: LedCode) { fn set_led(&mut self, address: LedCode) {
self.led = address self.led = address;
} }
} }
+22 -27
View File
@@ -2,8 +2,6 @@
//! editable config. //! editable config.
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::{self, OpenOptions};
use std::io::Read;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::slice::Iter; use std::slice::Iter;
@@ -88,8 +86,8 @@ impl KeyShape {
/// The first `Key` will determine the row height. /// The first `Key` will determine the row height.
/// ///
/// Every row is considered to start a x=0, with the first row being y=0, /// Every row is considered to start a x=0, with the first row being y=0,
/// and following rows starting after the previous row_y+pad_top and /// and following rows starting after the previous `row_y + pad_top` and
/// row_x+pad_left /// `row_x + pad_left`
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
pub struct KeyRow { pub struct KeyRow {
pad_left: f32, pad_left: f32,
@@ -138,7 +136,7 @@ impl KeyRow {
}; };
if h < height { if h < height {
h = height h = height;
} }
} }
h h
@@ -192,15 +190,9 @@ pub struct KeyLayout {
impl KeyLayout { impl KeyLayout {
pub fn from_file(path: &Path) -> Result<Self, Error> { pub fn from_file(path: &Path) -> Result<Self, Error> {
let mut file = OpenOptions::new() let buf: String = std::fs::read_to_string(path)
.read(true)
.open(path)
.map_err(|e| Error::IoPath(path.to_string_lossy().to_string(), e))?; .map_err(|e| Error::IoPath(path.to_string_lossy().to_string(), e))?;
let mut buf = String::new(); if buf.is_empty() {
let read_len = file
.read_to_string(&mut buf)
.map_err(|e| Error::IoPath(path.to_string_lossy().to_string(), e))?;
if read_len == 0 {
Err(Error::IoPath( Err(Error::IoPath(
path.to_string_lossy().to_string(), path.to_string_lossy().to_string(),
std::io::ErrorKind::InvalidData.into(), std::io::ErrorKind::InvalidData.into(),
@@ -233,7 +225,7 @@ impl KeyLayout {
} }
} }
pub fn rows(&self) -> Iter<KeyRow> { pub fn rows(&self) -> Iter<'_, KeyRow> {
self.key_rows.iter() self.key_rows.iter()
} }
@@ -279,7 +271,7 @@ impl KeyLayout {
for r in &self.key_rows { for r in &self.key_rows {
let tmp = r.width(); let tmp = r.width();
if width < tmp { if width < tmp {
width = tmp width = tmp;
} }
} }
width width
@@ -288,7 +280,13 @@ impl KeyLayout {
/// Find a layout matching the name in `LaptopLedData` in the provided dir /// Find a layout matching the name in `LaptopLedData` in the provided dir
pub fn find_layout(led_data: LaptopLedData, mut data_path: PathBuf) -> Result<Self, Error> { pub fn find_layout(led_data: LaptopLedData, mut data_path: PathBuf) -> Result<Self, Error> {
// TODO: locales // TODO: locales
let layout_file = format!("{}_US.ron", led_data.layout_name); let layout_name = if led_data.layout_name.is_empty() {
"ga401q".to_owned() // Need some sort of default here due to ROGCC
// expecting it
} else {
led_data.layout_name
};
let layout_file = format!("{layout_name}_US.ron");
data_path.push("layouts"); data_path.push("layouts");
data_path.push(layout_file); data_path.push(layout_file);
let path = data_path.as_path(); let path = data_path.as_path();
@@ -305,7 +303,7 @@ impl KeyLayout {
data_path.push("layouts"); data_path.push("layouts");
let path = data_path.as_path(); let path = data_path.as_path();
let mut files = Vec::new(); let mut files = Vec::new();
fs::read_dir(path) std::fs::read_dir(path)
.map_err(|e| { .map_err(|e| {
println!("{:?}, {e}", path); println!("{:?}, {e}", path);
e e
@@ -471,7 +469,6 @@ mod tests {
data_path.push("data"); data_path.push("data");
data_path.push("layouts"); data_path.push("layouts");
let path = data_path.as_path(); let path = data_path.as_path();
let mut buf = String::new();
for p in fs::read_dir(path) for p in fs::read_dir(path)
.map_err(|e| { .map_err(|e| {
println!("{:?}, {e}", path); println!("{:?}, {e}", path);
@@ -479,9 +476,7 @@ mod tests {
}) })
.unwrap() .unwrap()
{ {
let path = p.unwrap().path(); let mut buf = std::fs::read_to_string(p.unwrap().path()).unwrap();
let mut file = OpenOptions::new().read(true).open(&path).unwrap();
file.read_to_string(&mut buf).unwrap();
let data: KeyLayout = ron::from_str(&buf).unwrap(); let data: KeyLayout = ron::from_str(&buf).unwrap();
@@ -501,9 +496,10 @@ mod tests {
} }
} }
if !unused.is_empty() { assert!(
panic!("The layout {path:?} had unused shapes {unused:?}",); unused.is_empty(),
} "The layout {path:?} had unused shapes {unused:?}",
);
buf.clear(); buf.clear();
} }
@@ -527,9 +523,7 @@ mod tests {
data_path.push("data"); data_path.push("data");
data_path.push("aura_support.ron"); data_path.push("aura_support.ron");
let mut buf = String::new(); let mut buf = std::fs::read_to_string(&data_path).unwrap();
let mut file = OpenOptions::new().read(true).open(&data_path).unwrap();
file.read_to_string(&mut buf).unwrap();
let data: LedSupportFile = ron::from_str(&buf).unwrap(); let data: LedSupportFile = ron::from_str(&buf).unwrap();
data_path.pop(); data_path.pop();
@@ -553,6 +547,7 @@ mod tests {
) )
}) })
.unwrap(); .unwrap();
#[allow(clippy::verbose_file_reads)]
if let Err(e) = file.read_to_string(&mut buf) { if let Err(e) = file.read_to_string(&mut buf) {
panic!( panic!(
"Error checking {data_path:?} for {} : {e:?}", "Error checking {data_path:?} for {} : {e:?}",
+131 -110
View File
@@ -23,25 +23,44 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
} }
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)]
pub enum AuraDevice { pub enum AuraDevice {
Tuf, Tuf,
X1854, X1854,
X1869, X1869,
X1866, X1866,
X18c6,
#[default] #[default]
X19B6, X19b6,
X1a30,
Unknown, Unknown,
} }
impl From<AuraDevice> for &str {
fn from(a: AuraDevice) -> Self {
match a {
AuraDevice::Tuf => "tuf",
AuraDevice::X1854 => "1854",
AuraDevice::X1869 => "1869",
AuraDevice::X1866 => "1866",
AuraDevice::X18c6 => "18c6",
AuraDevice::X19b6 => "19b6",
AuraDevice::X1a30 => "1a30",
AuraDevice::Unknown => "unknown",
}
}
}
impl From<&str> for AuraDevice { impl From<&str> for AuraDevice {
fn from(s: &str) -> Self { fn from(s: &str) -> Self {
match s.to_lowercase().as_str() { match s.to_lowercase().as_str() {
"tuf" => AuraDevice::Tuf, "tuf" => AuraDevice::Tuf,
"1866" | "0x1866" => AuraDevice::X1866, "1866" | "0x1866" => AuraDevice::X1866,
"18c6" | "0x18c6" => AuraDevice::X18c6,
"1869" | "0x1869" => AuraDevice::X1869, "1869" | "0x1869" => AuraDevice::X1869,
"1854" | "0x1854" => AuraDevice::X1854, "1854" | "0x1854" => AuraDevice::X1854,
"19b6" | "0x19b6" => AuraDevice::X19B6, "19b6" | "0x19b6" => AuraDevice::X19b6,
"1a30" | "0x1a30" => AuraDevice::X1a30,
_ => AuraDevice::Unknown, _ => AuraDevice::Unknown,
} }
} }
@@ -54,7 +73,9 @@ impl Debug for AuraDevice {
Self::X1854 => write!(f, "0x1854"), Self::X1854 => write!(f, "0x1854"),
Self::X1869 => write!(f, "0x1869"), Self::X1869 => write!(f, "0x1869"),
Self::X1866 => write!(f, "0x1866"), Self::X1866 => write!(f, "0x1866"),
Self::X19B6 => write!(f, "0x19B6"), Self::X18c6 => write!(f, "0x18c6"),
Self::X19b6 => write!(f, "0x19B6"),
Self::X1a30 => write!(f, "0x1A30"),
Self::Unknown => write!(f, "Unknown"), Self::Unknown => write!(f, "Unknown"),
} }
} }
@@ -65,8 +86,8 @@ impl Debug for AuraDevice {
#[derive(Clone, Default, Debug, Serialize, Deserialize)] #[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct AuraPowerDev { pub struct AuraPowerDev {
pub tuf: Vec<AuraDevTuf>, pub tuf: Vec<AuraDevTuf>,
pub x1866: Vec<AuraDev1866>, pub x1866: Vec<AuraDevRog1>,
pub x19b6: Vec<AuraDev19b6>, pub x19b6: Vec<AuraDevRog2>,
} }
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
@@ -85,7 +106,7 @@ impl AuraDevTuf {
} }
} }
/// # Bits for older 0x1866 keyboard model /// # Bits for older 0x1866, 0x1869, 0x1854 keyboard models
/// ///
/// Keybord and Lightbar require Awake, Boot and Sleep apply to both /// Keybord and Lightbar require Awake, Boot and Sleep apply to both
/// Keybord and Lightbar regardless of if either are enabled (or Awake is /// Keybord and Lightbar regardless of if either are enabled (or Awake is
@@ -102,7 +123,7 @@ impl AuraDevTuf {
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[repr(u32)] #[repr(u32)]
pub enum AuraDev1866 { pub enum AuraDevRog1 {
Awake = 0x000002, Awake = 0x000002,
Keyboard = 0x080000, Keyboard = 0x080000,
Lightbar = 0x040500, Lightbar = 0x040500,
@@ -110,13 +131,13 @@ pub enum AuraDev1866 {
Sleep = 0x300804, Sleep = 0x300804,
} }
impl From<AuraDev1866> for u32 { impl From<AuraDevRog1> for u32 {
fn from(a: AuraDev1866) -> Self { fn from(a: AuraDevRog1) -> Self {
a as u32 a as u32
} }
} }
impl AuraDev1866 { impl AuraDevRog1 {
pub fn to_bytes(control: &[Self]) -> [u8; 3] { pub fn to_bytes(control: &[Self]) -> [u8; 3] {
let mut a: u32 = 0; let mut a: u32 = 0;
for n in control { for n in control {
@@ -134,23 +155,23 @@ impl AuraDev1866 {
} }
} }
impl BitOr<AuraDev1866> for AuraDev1866 { impl BitOr<AuraDevRog1> for AuraDevRog1 {
type Output = u32; type Output = u32;
fn bitor(self, rhs: AuraDev1866) -> Self::Output { fn bitor(self, rhs: AuraDevRog1) -> Self::Output {
self as u32 | rhs as u32 self as u32 | rhs as u32
} }
} }
impl BitAnd<AuraDev1866> for AuraDev1866 { impl BitAnd<AuraDevRog1> for AuraDevRog1 {
type Output = u32; type Output = u32;
fn bitand(self, rhs: AuraDev1866) -> Self::Output { fn bitand(self, rhs: AuraDevRog1) -> Self::Output {
self as u32 & rhs as u32 self as u32 & rhs as u32
} }
} }
/// # Bits for 0x19b6 keyboard model /// # Bits for newer 0x18c6, 0x19B6, 0x1a30, keyboard models
/// ///
/// byte 4 in the USB packet is for keyboard + logo power states /// byte 4 in the USB packet is for keyboard + logo power states
/// default is on, `ff` /// default is on, `ff`
@@ -179,7 +200,7 @@ impl BitAnd<AuraDev1866> for AuraDev1866 {
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[repr(u32)] #[repr(u32)]
pub enum AuraDev19b6 { pub enum AuraDevRog2 {
BootLogo = 1, BootLogo = 1,
BootKeyb = 1 << 1, BootKeyb = 1 << 1,
AwakeLogo = 1 << 2, AwakeLogo = 1 << 2,
@@ -198,13 +219,13 @@ pub enum AuraDev19b6 {
ShutdownLid = 1 << (15 + 4), ShutdownLid = 1 << (15 + 4),
} }
impl From<AuraDev19b6> for u32 { impl From<AuraDevRog2> for u32 {
fn from(a: AuraDev19b6) -> Self { fn from(a: AuraDevRog2) -> Self {
a as u32 a as u32
} }
} }
impl AuraDev19b6 { impl AuraDevRog2 {
pub fn to_bytes(control: &[Self]) -> [u8; 3] { pub fn to_bytes(control: &[Self]) -> [u8; 3] {
let mut a: u32 = 0; let mut a: u32 = 0;
for n in control { for n in control {
@@ -222,58 +243,58 @@ impl AuraDev19b6 {
} }
} }
impl BitOr<AuraDev19b6> for AuraDev19b6 { impl BitOr<AuraDevRog2> for AuraDevRog2 {
type Output = u16; type Output = u16;
fn bitor(self, rhs: AuraDev19b6) -> Self::Output { fn bitor(self, rhs: AuraDevRog2) -> Self::Output {
self as u16 | rhs as u16 self as u16 | rhs as u16
} }
} }
impl BitAnd<AuraDev19b6> for AuraDev19b6 { impl BitAnd<AuraDevRog2> for AuraDevRog2 {
type Output = u16; type Output = u16;
fn bitand(self, rhs: AuraDev19b6) -> Self::Output { fn bitand(self, rhs: AuraDevRog2) -> Self::Output {
self as u16 & rhs as u16 self as u16 & rhs as u16
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::AuraDev1866; use super::AuraDevRog1;
use crate::usb::AuraDev19b6; use crate::usb::AuraDevRog2;
#[test] #[test]
fn check_0x1866_control_bytes() { fn check_0x1866_control_bytes() {
let bytes = [AuraDev1866::Keyboard, AuraDev1866::Awake]; let bytes = [AuraDevRog1::Keyboard, AuraDevRog1::Awake];
let bytes = AuraDev1866::to_bytes(&bytes); let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x08, 0x00, 0x02]); assert_eq!(bytes, [0x08, 0x00, 0x02]);
let bytes = [AuraDev1866::Lightbar, AuraDev1866::Awake]; let bytes = [AuraDevRog1::Lightbar, AuraDevRog1::Awake];
let bytes = AuraDev1866::to_bytes(&bytes); let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x04, 0x05, 0x02]); assert_eq!(bytes, [0x04, 0x05, 0x02]);
let bytes = [AuraDev1866::Sleep]; let bytes = [AuraDevRog1::Sleep];
let bytes = AuraDev1866::to_bytes(&bytes); let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x30, 0x08, 0x04]); assert_eq!(bytes, [0x30, 0x08, 0x04]);
let bytes = [AuraDev1866::Boot]; let bytes = [AuraDevRog1::Boot];
let bytes = AuraDev1866::to_bytes(&bytes); let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0xc3, 0x12, 0x09]); assert_eq!(bytes, [0xc3, 0x12, 0x09]);
let bytes = [ let bytes = [
AuraDev1866::Keyboard, AuraDevRog1::Keyboard,
AuraDev1866::Lightbar, AuraDevRog1::Lightbar,
AuraDev1866::Awake, AuraDevRog1::Awake,
AuraDev1866::Sleep, AuraDevRog1::Sleep,
AuraDev1866::Boot, AuraDevRog1::Boot,
]; ];
let bytes = AuraDev1866::to_bytes(&bytes); let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0xff, 0x1f, 0x000f]); assert_eq!(bytes, [0xff, 0x1f, 0x000f]);
} }
@@ -282,143 +303,143 @@ mod tests {
fn check_0x19b6_control_bytes() { fn check_0x19b6_control_bytes() {
// All on // All on
let byte1 = [ let byte1 = [
AuraDev19b6::BootLogo, AuraDevRog2::BootLogo,
AuraDev19b6::BootKeyb, AuraDevRog2::BootKeyb,
AuraDev19b6::SleepLogo, AuraDevRog2::SleepLogo,
AuraDev19b6::SleepKeyb, AuraDevRog2::SleepKeyb,
AuraDev19b6::AwakeLogo, AuraDevRog2::AwakeLogo,
AuraDev19b6::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDev19b6::ShutdownLogo, AuraDevRog2::ShutdownLogo,
AuraDev19b6::ShutdownKeyb, AuraDevRog2::ShutdownKeyb,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte1); let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[0], 0xff); assert_eq!(bytes[0], 0xff);
// //
let byte1 = [ let byte1 = [
// AuraControl::BootLogo, // AuraControl::BootLogo,
AuraDev19b6::BootKeyb, AuraDevRog2::BootKeyb,
AuraDev19b6::SleepLogo, AuraDevRog2::SleepLogo,
AuraDev19b6::SleepKeyb, AuraDevRog2::SleepKeyb,
AuraDev19b6::AwakeLogo, AuraDevRog2::AwakeLogo,
AuraDev19b6::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDev19b6::ShutdownLogo, AuraDevRog2::ShutdownLogo,
AuraDev19b6::ShutdownKeyb, AuraDevRog2::ShutdownKeyb,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte1); let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]); println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xfe); assert_eq!(bytes[0], 0xfe);
let byte1 = [ let byte1 = [
AuraDev19b6::BootLogo, AuraDevRog2::BootLogo,
// AuraControl::BootKeyb, // AuraControl::BootKeyb,
AuraDev19b6::SleepLogo, AuraDevRog2::SleepLogo,
AuraDev19b6::SleepKeyb, AuraDevRog2::SleepKeyb,
AuraDev19b6::AwakeLogo, AuraDevRog2::AwakeLogo,
AuraDev19b6::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDev19b6::ShutdownLogo, AuraDevRog2::ShutdownLogo,
AuraDev19b6::ShutdownKeyb, AuraDevRog2::ShutdownKeyb,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte1); let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]); println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xfd); assert_eq!(bytes[0], 0xfd);
let byte1 = [ let byte1 = [
AuraDev19b6::BootLogo, AuraDevRog2::BootLogo,
AuraDev19b6::BootKeyb, AuraDevRog2::BootKeyb,
// AuraControl::SleepLogo, // AuraControl::SleepLogo,
AuraDev19b6::SleepKeyb, AuraDevRog2::SleepKeyb,
AuraDev19b6::AwakeLogo, AuraDevRog2::AwakeLogo,
AuraDev19b6::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDev19b6::ShutdownLogo, AuraDevRog2::ShutdownLogo,
AuraDev19b6::ShutdownKeyb, AuraDevRog2::ShutdownKeyb,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte1); let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]); println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xef); assert_eq!(bytes[0], 0xef);
let byte1 = [ let byte1 = [
AuraDev19b6::BootLogo, AuraDevRog2::BootLogo,
AuraDev19b6::BootKeyb, AuraDevRog2::BootKeyb,
AuraDev19b6::SleepLogo, AuraDevRog2::SleepLogo,
// AuraControl::SleepKeyb, // AuraControl::SleepKeyb,
AuraDev19b6::AwakeLogo, AuraDevRog2::AwakeLogo,
AuraDev19b6::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDev19b6::ShutdownLogo, AuraDevRog2::ShutdownLogo,
AuraDev19b6::ShutdownKeyb, AuraDevRog2::ShutdownKeyb,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte1); let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]); println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xdf); assert_eq!(bytes[0], 0xdf);
let byte2 = [ let byte2 = [
AuraDev19b6::BootBar, AuraDevRog2::BootBar,
AuraDev19b6::AwakeBar, AuraDevRog2::AwakeBar,
AuraDev19b6::SleepBar, AuraDevRog2::SleepBar,
AuraDev19b6::ShutdownBar, AuraDevRog2::ShutdownBar,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte2); let bytes = AuraDevRog2::to_bytes(&byte2);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[1], 0x1e); assert_eq!(bytes[1], 0x1e);
let byte2 = [ let byte2 = [
AuraDev19b6::BootBar, AuraDevRog2::BootBar,
AuraDev19b6::AwakeBar, AuraDevRog2::AwakeBar,
// AuraControl::SleepBar, // AuraControl::SleepBar,
AuraDev19b6::ShutdownBar, AuraDevRog2::ShutdownBar,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte2); let bytes = AuraDevRog2::to_bytes(&byte2);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[1], 0x16); assert_eq!(bytes[1], 0x16);
let byte3 = [ let byte3 = [
AuraDev19b6::AwakeLid, AuraDevRog2::AwakeLid,
AuraDev19b6::BootLid, AuraDevRog2::BootLid,
AuraDev19b6::SleepLid, AuraDevRog2::SleepLid,
AuraDev19b6::ShutdownLid, AuraDevRog2::ShutdownLid,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte3); let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0f); assert_eq!(bytes[2], 0x0f);
let byte3 = [ let byte3 = [
// AuraDev19b6::AwakeLid, // AuraDev19b6::AwakeLid,
AuraDev19b6::BootLid, AuraDevRog2::BootLid,
AuraDev19b6::SleepLid, AuraDevRog2::SleepLid,
AuraDev19b6::ShutdownLid, AuraDevRog2::ShutdownLid,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte3); let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0d); assert_eq!(bytes[2], 0x0d);
let byte3 = [ let byte3 = [
AuraDev19b6::AwakeLid, AuraDevRog2::AwakeLid,
AuraDev19b6::BootLid, AuraDevRog2::BootLid,
// AuraControl::SleepLid, // AuraControl::SleepLid,
AuraDev19b6::ShutdownLid, AuraDevRog2::ShutdownLid,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte3); let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0b); assert_eq!(bytes[2], 0x0b);
let byte3 = [ let byte3 = [
AuraDev19b6::AwakeLid, AuraDevRog2::AwakeLid,
AuraDev19b6::BootLid, AuraDevRog2::BootLid,
AuraDev19b6::SleepLid, AuraDevRog2::SleepLid,
// AuraDev19b6::ShutdownLid, // AuraDev19b6::ShutdownLid,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte3); let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x07); assert_eq!(bytes[2], 0x07);
let byte3 = [ let byte3 = [
AuraDev19b6::AwakeLid, AuraDevRog2::AwakeLid,
// AuraDev19b6::BootLid, // AuraDev19b6::BootLid,
AuraDev19b6::SleepLid, AuraDevRog2::SleepLid,
// AuraDev19b6::ShutdownLid, // AuraDev19b6::ShutdownLid,
]; ];
let bytes = AuraDev19b6::to_bytes(&byte3); let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x06); assert_eq!(bytes[2], 0x06);
} }
+15 -4
View File
@@ -10,11 +10,13 @@ edition = "2021"
mocking = [] mocking = []
[dependencies] [dependencies]
egui = { git = "https://github.com/flukejones/egui", branch = "wayland_dark_theme" } egui = { git = "https://github.com/emilk/egui", rev = "b8e798777de519de3a1878798097ab2ab0bd4def"}
eframe = { git = "https://github.com/flukejones/egui", branch = "wayland_dark_theme" } eframe = { git = "https://github.com/emilk/egui", rev = "b8e798777de519de3a1878798097ab2ab0bd4def"}
# egui = { path = "../../egui/crates/egui" }
# eframe = { path = "../../egui/crates/eframe" }
libappindicator = "0.7" # Tray icon libappindicator = "0.8" # Tray icon
gtk = "0.15.5" gtk = "0.16"
daemon = { path = "../daemon" } daemon = { path = "../daemon" }
rog_anime = { path = "../rog-anime" } rog_anime = { path = "../rog-anime" }
@@ -39,5 +41,14 @@ notify-rust.workspace = true
png_pong.workspace = true png_pong.workspace = true
versions.workspace = true
nix = "^0.26.1" nix = "^0.26.1"
tempfile = "3.3.0" tempfile = "3.3.0"
# [patch.crates-io]
# egui = { git = "https://github.com/flukejones/egui" }
# eframe = { git = "https://github.com/flukejones/egui" }
[dev-dependencies]
cargo-husky.workspace = true
+32
View File
@@ -17,6 +17,7 @@ pub struct Config {
pub ac_command: String, pub ac_command: String,
pub bat_command: String, pub bat_command: String,
pub enable_notifications: bool, pub enable_notifications: bool,
pub dark_mode: bool,
// This field must be last // This field must be last
pub enabled_notifications: EnabledNotifications, pub enabled_notifications: EnabledNotifications,
} }
@@ -27,6 +28,7 @@ impl Default for Config {
run_in_background: true, run_in_background: true,
startup_in_background: false, startup_in_background: false,
enable_notifications: true, enable_notifications: true,
dark_mode: true,
enabled_notifications: EnabledNotifications::default(), enabled_notifications: EnabledNotifications::default(),
ac_command: String::new(), ac_command: String::new(),
bat_command: String::new(), bat_command: String::new(),
@@ -60,6 +62,8 @@ impl Config {
let mut buf = String::new(); let mut buf = String::new();
// Lint to allow, because we want the above file behaviour
#[allow(clippy::verbose_file_reads)]
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 {
warn!("Zero len read of Config file"); warn!("Zero len read of Config file");
@@ -70,6 +74,9 @@ impl Config {
} else if let Ok(data) = toml::from_str::<Config>(&buf) { } else if let Ok(data) = toml::from_str::<Config>(&buf) {
info!("Loaded config file {path:?}"); info!("Loaded config file {path:?}");
return Ok(data); return Ok(data);
} else if let Ok(data) = toml::from_str::<Config460>(&buf) {
info!("Loaded old v4.6.0 config file {path:?}");
return Ok(data.into());
} else if let Ok(data) = toml::from_str::<Config455>(&buf) { } else if let Ok(data) = toml::from_str::<Config455>(&buf) {
info!("Loaded old v4.5.5 config file {path:?}"); info!("Loaded old v4.5.5 config file {path:?}");
return Ok(data.into()); return Ok(data.into());
@@ -122,8 +129,33 @@ impl From<Config455> for Config {
startup_in_background: c.startup_in_background, startup_in_background: c.startup_in_background,
enable_notifications: c.enable_notifications, enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications, enabled_notifications: c.enabled_notifications,
dark_mode: true,
ac_command: String::new(), ac_command: String::new(),
bat_command: String::new(), bat_command: String::new(),
} }
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config460 {
pub run_in_background: bool,
pub startup_in_background: bool,
pub ac_command: String,
pub bat_command: String,
pub enable_notifications: bool,
pub enabled_notifications: EnabledNotifications,
}
impl From<Config460> for Config {
fn from(c: Config460) -> Self {
Self {
run_in_background: c.run_in_background,
startup_in_background: c.startup_in_background,
ac_command: c.ac_command,
bat_command: c.bat_command,
dark_mode: true,
enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications,
}
}
}
+8
View File
@@ -11,6 +11,7 @@ pub enum Error {
XdgVars, XdgVars,
Zbus(zbus::Error), Zbus(zbus::Error),
Notification(notify_rust::error::Error), Notification(notify_rust::error::Error),
Eframe(eframe::Error),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@@ -24,6 +25,7 @@ impl fmt::Display for Error {
Error::XdgVars => write!(f, "XDG environment vars appear unset"), Error::XdgVars => write!(f, "XDG environment vars appear unset"),
Error::Zbus(err) => write!(f, "Error: {}", err), Error::Zbus(err) => write!(f, "Error: {}", err),
Error::Notification(err) => write!(f, "Notification Error: {}", err), Error::Notification(err) => write!(f, "Notification Error: {}", err),
Error::Eframe(err) => write!(f, "Eframe Error: {}", err),
} }
} }
} }
@@ -53,3 +55,9 @@ impl From<notify_rust::error::Error> for Error {
Error::Notification(err) Error::Notification(err)
} }
} }
impl From<eframe::Error> for Error {
fn from(err: eframe::Error) -> Self {
Error::Eframe(err)
}
}
+4 -2
View File
@@ -81,6 +81,8 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
// First entry is the actual state // First entry is the actual state
if buf[0] == SHOWING_GUI { if buf[0] == SHOWING_GUI {
ipc_file.write_all(&[SHOWING_GUI])?; // Store state again as we drained the fifo ipc_file.write_all(&[SHOWING_GUI])?; // Store state again as we drained the fifo
// Early exit is not an error and we don't want to pass back a dir
#[allow(clippy::exit)]
exit(0); exit(0);
} else if buf[0] == SHOW_GUI { } else if buf[0] == SHOW_GUI {
remove_dir_all(&path)?; remove_dir_all(&path)?;
@@ -89,7 +91,7 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
.rand_bytes(0) .rand_bytes(0)
.tempdir(); .tempdir();
} }
exit(-1); panic!("Invalid exit or app state");
} }
pub fn get_ipc_file() -> Result<File, crate::error::Error> { pub fn get_ipc_file() -> Result<File, crate::error::Error> {
@@ -103,6 +105,6 @@ pub fn get_ipc_file() -> Result<File, crate::error::Error> {
Ok(OpenOptions::new() Ok(OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.truncate(true) // .truncate(true)
.open(&fifo_path)?) .open(&fifo_path)?)
} }
+61 -54
View File
@@ -1,12 +1,14 @@
use std::env::args; use std::env::args;
use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use eframe::{IconData, NativeOptions}; use eframe::IconData;
use gumdrop::Options; use gumdrop::Options;
use log::{error, info, warn}; use log::{debug, error, info, warn, LevelFilter};
use rog_aura::aura_detection::{LaptopLedData, LedSupportFile}; use rog_aura::aura_detection::{LaptopLedData, LedSupportFile};
use rog_aura::layouts::KeyLayout; use rog_aura::layouts::KeyLayout;
use rog_control_center::cli_options::CliStart; use rog_control_center::cli_options::CliStart;
@@ -46,6 +48,7 @@ fn main() -> Result<()> {
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
.filter_level(LevelFilter::Warn)
.parse_default_env() .parse_default_env()
.target(env_logger::Target::Stdout) .target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
@@ -73,7 +76,9 @@ fn main() -> Result<()> {
"ROG Control Center", "ROG Control Center",
native_options.clone(), native_options.clone(),
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))), Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
); )
.map_err(|e| error!("{e}"))
.ok();
}) })
.unwrap(); .unwrap();
@@ -84,14 +89,16 @@ fn main() -> Result<()> {
"ROG Control Center", "ROG Control Center",
native_options.clone(), native_options.clone(),
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))), Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
); )
.map_err(|e| error!("{e}"))
.ok();
SupportedFunctions::default() SupportedFunctions::default()
} }
}; };
// Startup // Startup
let mut config = Config::load()?; let mut config = Config::load()?;
let mut start_closed = config.startup_in_background; let running_in_bg = Arc::new(AtomicBool::new(config.startup_in_background));
if config.startup_in_background { if config.startup_in_background {
config.run_in_background = true; config.run_in_background = true;
@@ -101,15 +108,10 @@ fn main() -> Result<()> {
let enabled_notifications = EnabledNotifications::tokio_mutex(&config); let enabled_notifications = EnabledNotifications::tokio_mutex(&config);
// Find and load a matching layout for laptop // Find and load a matching layout for laptop
let mut file = OpenOptions::new() let mut board_name = std::fs::read_to_string(BOARD_NAME).map_err(|e| {
.read(true) println!("DOH! {BOARD_NAME}, {e}");
.open(PathBuf::from(BOARD_NAME)) e
.map_err(|e| { })?;
println!("DOH! {BOARD_NAME}, {e}");
e
})?;
let mut board_name = String::new();
file.read_to_string(&mut board_name)?;
let mut led_support = LaptopLedData::get_data(); let mut led_support = LaptopLedData::get_data();
@@ -122,7 +124,7 @@ fn main() -> Result<()> {
path.push("rog-aura"); path.push("rog-aura");
path.push("data"); path.push("data");
} }
layouts = KeyLayout::layout_files(path.to_owned()).unwrap(); layouts = KeyLayout::layout_files(path.clone()).unwrap();
if let Some(name) = &cli_parsed.board_name { if let Some(name) = &cli_parsed.board_name {
if let Some(modes) = LedSupportFile::load_from_config() { if let Some(modes) = LedSupportFile::load_from_config() {
@@ -130,7 +132,7 @@ fn main() -> Result<()> {
led_support = data; led_support = data;
} }
} }
board_name = name.to_owned(); board_name = name.clone();
for layout in &layouts { for layout in &layouts {
if layout if layout
.file_name() .file_name()
@@ -138,11 +140,11 @@ fn main() -> Result<()> {
.to_string_lossy() .to_string_lossy()
.contains(&led_support.layout_name.to_lowercase()) .contains(&led_support.layout_name.to_lowercase())
{ {
layout_name = Some(layout.to_owned()); layout_name = Some(layout.clone());
} }
} }
} else { } else {
board_name = "GQ401QM".to_string() board_name = "GQ401QM".to_owned();
}; };
if cli_parsed.layout_viewing { if cli_parsed.layout_viewing {
@@ -182,33 +184,55 @@ fn main() -> Result<()> {
layout_name, layout_name,
layout, layout,
layouts, layouts,
enabled_notifications, &enabled_notifications,
&config, &config,
&supported, &supported,
)?; )?;
init_tray(supported, states.clone()); init_tray(supported, states.clone());
let mut bg_check_spawned = false;
loop { loop {
if !start_closed { if !running_in_bg.load(Ordering::Relaxed) {
start_app(states.clone(), native_options.clone())?; // blocks until window is closed
let states = states.clone();
let mut ipc_file = get_ipc_file()?;
ipc_file.write_all(&[SHOWING_GUI])?;
eframe::run_native(
"ROG Control Center",
native_options.clone(),
Box::new(move |cc| {
Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())
}),
)?;
running_in_bg.store(true, Ordering::SeqCst);
bg_check_spawned = false;
} }
let config = Config::load()?;
if !config.run_in_background || cli_parsed.board_name.is_some() || cli_parsed.layout_viewing if !config.run_in_background || cli_parsed.board_name.is_some() || cli_parsed.layout_viewing
{ {
break; break;
} }
if config.run_in_background { if config.run_in_background && running_in_bg.load(Ordering::Acquire) && !bg_check_spawned {
let mut buf = [0u8; 4]; let running_in_bg = running_in_bg.clone();
// blocks until it is read, typically the read will happen after a second thread::spawn(move || {
// process writes to the IPC (so there is data to actually read) let mut buf = [0u8; 4];
if get_ipc_file()?.read(&mut buf).is_ok() && buf[0] == SHOW_GUI { // blocks until it is read, typically the read will happen after a second
start_closed = false; // process writes to the IPC (so there is data to actually read)
continue; loop {
} if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
running_in_bg.store(false, Ordering::Release);
debug!("Wait thread got from tray {buf:#?}");
break;
}
}
});
bg_check_spawned = true;
} }
// Prevent hogging CPU
thread::sleep(Duration::from_millis(500));
} }
// loop { // loop {
@@ -222,7 +246,7 @@ fn setup_page_state_and_notifs(
layout_testing: Option<PathBuf>, layout_testing: Option<PathBuf>,
keyboard_layout: KeyLayout, keyboard_layout: KeyLayout,
keyboard_layouts: Vec<PathBuf>, keyboard_layouts: Vec<PathBuf>,
enabled_notifications: Arc<Mutex<EnabledNotifications>>, enabled_notifications: &Arc<Mutex<EnabledNotifications>>,
config: &Config, config: &Config,
supported: &SupportedFunctions, supported: &SupportedFunctions,
) -> Result<Arc<Mutex<SystemState>>> { ) -> Result<Arc<Mutex<SystemState>>> {
@@ -234,40 +258,23 @@ fn setup_page_state_and_notifs(
supported, supported,
)?)); )?));
start_notifications(config, page_states.clone(), enabled_notifications)?; start_notifications(config, &page_states, enabled_notifications)?;
Ok(page_states) Ok(page_states)
} }
fn start_app(states: Arc<Mutex<SystemState>>, native_options: NativeOptions) -> Result<()> {
let mut ipc_file = get_ipc_file()?;
ipc_file.write_all(&[SHOWING_GUI])?;
eframe::run_native(
"ROG Control Center",
native_options,
Box::new(move |cc| Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())),
);
Ok(())
}
/// Bah.. the icon dosn't work on wayland anyway, but we'll leave it in for now. /// Bah.. the icon dosn't work on wayland anyway, but we'll leave it in for now.
fn load_icon() -> IconData { fn load_icon() -> IconData {
let path = PathBuf::from(APP_ICON_PATH); let path = PathBuf::from(APP_ICON_PATH);
let mut buf = Vec::new();
let mut rgba = Vec::new(); let mut rgba = Vec::new();
let mut height = 512; let mut height = 512;
let mut width = 512; let mut width = 512;
if path.exists() { if path.exists() {
if let Ok(mut file) = OpenOptions::new() if let Ok(data) = std::fs::read(path)
.read(true) .map_err(|e| error!("Error reading app icon: {e:?}"))
.open(path)
.map_err(|e| error!("Error opening app icon: {e:?}")) .map_err(|e| error!("Error opening app icon: {e:?}"))
{ {
file.read_to_end(&mut buf) let data = std::io::Cursor::new(data);
.map_err(|e| error!("Error reading app icon: {e:?}"))
.ok();
let data = std::io::Cursor::new(buf);
let decoder = png_pong::Decoder::new(data).unwrap().into_steps(); let decoder = png_pong::Decoder::new(data).unwrap().into_steps();
let png_pong::Step { raster, delay: _ } = decoder.last().unwrap().unwrap(); let png_pong::Step { raster, delay: _ } = decoder.last().unwrap().unwrap();
@@ -295,7 +302,7 @@ fn do_cli_help(parsed: &CliStart) -> bool {
println!(); println!();
if let Some(cmdlist) = CliStart::command_list() { if let Some(cmdlist) = CliStart::command_list() {
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect(); let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
for command in commands.iter() { for command in &commands {
println!("{}", command); println!("{}", command);
} }
} }
+99 -137
View File
@@ -2,7 +2,6 @@
//! commands over an MPSC channel. //! commands over an MPSC channel.
use std::io::Write; use std::io::Write;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
@@ -14,8 +13,10 @@ use log::{debug, error, info, trace, warn};
use rog_dbus::zbus_platform::RogBiosProxyBlocking; use rog_dbus::zbus_platform::RogBiosProxyBlocking;
use rog_platform::platform::GpuMode; use rog_platform::platform::GpuMode;
use rog_platform::supported::SupportedFunctions; use rog_platform::supported::SupportedFunctions;
use supergfxctl::actions::UserActionRequired as GfxUserActionRequired;
use supergfxctl::pci_device::{GfxMode, GfxPower}; use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking; use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking;
use versions::Versioning;
use crate::error::Result; use crate::error::Result;
use crate::system_state::SystemState; use crate::system_state::SystemState;
@@ -79,6 +80,8 @@ pub struct ROGTray {
menu: gtk::Menu, menu: gtk::Menu,
icon: &'static str, icon: &'static str,
bios_proxy: RogBiosProxyBlocking<'static>, bios_proxy: RogBiosProxyBlocking<'static>,
gfx_proxy_is_active: bool,
gfx_action: Arc<Mutex<GfxUserActionRequired>>,
gfx_proxy: GfxProxyBlocking<'static>, gfx_proxy: GfxProxyBlocking<'static>,
} }
@@ -88,6 +91,12 @@ impl ROGTray {
error!("ROGTray: {e}"); error!("ROGTray: {e}");
e e
})?; })?;
let gfx_proxy = GfxProxyBlocking::new(&conn).map_err(|e| {
error!("ROGTray: {e}");
e
})?;
let rog_tray = Self { let rog_tray = Self {
tray: AppIndicator::new(TRAY_LABEL, TRAY_APP_ICON), tray: AppIndicator::new(TRAY_LABEL, TRAY_APP_ICON),
menu: gtk::Menu::new(), menu: gtk::Menu::new(),
@@ -96,10 +105,9 @@ impl ROGTray {
error!("ROGTray: {e}"); error!("ROGTray: {e}");
e e
})?, })?,
gfx_proxy: GfxProxyBlocking::new(&conn).map_err(|e| { gfx_proxy_is_active: gfx_proxy.mode().is_ok(),
error!("ROGTray: {e}"); gfx_action: Arc::new(Mutex::new(GfxUserActionRequired::Nothing)),
e gfx_proxy,
})?,
}; };
Ok(rog_tray) Ok(rog_tray)
} }
@@ -208,6 +216,7 @@ impl ROGTray {
if let Ok(mut ipc) = get_ipc_file().map_err(|e| { if let Ok(mut ipc) = get_ipc_file().map_err(|e| {
error!("ROGTray: get_ipc_file: {}", e); error!("ROGTray: get_ipc_file: {}", e);
}) { }) {
debug!("Tray told app to show self");
ipc.write_all(&[SHOW_GUI]).ok(); ipc.write_all(&[SHOW_GUI]).ok();
} }
}); });
@@ -238,132 +247,64 @@ impl ROGTray {
} }
} }
fn menu_add_gpu(&mut self, supported: &SupportedFunctions, current_mode: GfxMode) { fn menu_add_supergfx(&mut self, supported_gfx: &[GfxMode], current_mode: GfxMode) {
let set_mux_off = Arc::new(AtomicBool::new(false)); if !self.gfx_proxy_is_active {
trace!("menu_add_supergfx: gfx_proxy_is_active is false");
return;
}
let gfx_dbus = self.gfx_proxy.clone(); let gfx_dbus = self.gfx_proxy.clone();
let set_mux_off1 = set_mux_off.clone(); let gfx_action = self.gfx_action.clone();
let mut gpu_menu = RadioGroup::new("Integrated", move |_| { let mut gpu_menu = RadioGroup::new("Integrated", move |_| {
let mode = gfx_dbus if current_mode != GfxMode::Integrated {
.mode() if let Ok(res) = gfx_dbus.set_mode(&GfxMode::Integrated).map_err(|e| {
.map_err(|e| { error!("ROGTray: srt_mode: {e}");
error!("ROGTray: mode: {e}");
e e
}) }) {
.unwrap_or(GfxMode::None); if let Ok(mut lock) = gfx_action.lock() {
if mode != GfxMode::Integrated { *lock = res;
gfx_dbus }
.set_mode(&GfxMode::Integrated) }
.map_err(|e| {
error!("ROGTray: srt_mode: {e}");
e
})
.ok();
} }
set_mux_off1.store(true, Ordering::Relaxed);
}); });
let gfx_dbus = self.gfx_proxy.clone(); let mut func = |menu_mode: GfxMode| {
let set_mux_off1 = set_mux_off.clone();
gpu_menu.add("Hybrid", move |_| {
let mode = gfx_dbus
.mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GfxMode::None);
if mode != GfxMode::Hybrid {
gfx_dbus
.set_mode(&GfxMode::Hybrid)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
set_mux_off1.store(true, Ordering::Relaxed);
});
if supported.rog_bios_ctrl.egpu_enable {
let set_mux_off1 = set_mux_off.clone();
let gfx_dbus = self.gfx_proxy.clone(); let gfx_dbus = self.gfx_proxy.clone();
gpu_menu.add("eGPU", move |_| { let gfx_action = self.gfx_action.clone();
let mode = gfx_dbus gpu_menu.add(&format!("{menu_mode}"), move |_| {
.mode() if current_mode != menu_mode {
.map_err(|e| { if let Ok(res) = gfx_dbus.set_mode(&menu_mode).map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GfxMode::None);
if mode != GfxMode::Egpu {
gfx_dbus
.set_mode(&GfxMode::Egpu)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
set_mux_off1.store(true, Ordering::Relaxed);
});
}
let mut reboot_required = false;
if supported.rog_bios_ctrl.gpu_mux {
let gfx_dbus = self.bios_proxy.clone();
gpu_menu.add("Ultimate (Reboot required)", move |_| {
let mode = gfx_dbus
.gpu_mux_mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GpuMode::Error);
if mode != GpuMode::Discrete {
gfx_dbus
.set_gpu_mux_mode(GpuMode::Discrete)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
});
if set_mux_off.load(Ordering::Relaxed) {
warn!("Selected non-dgpu mode, must set MUX to optimus");
self.bios_proxy
.set_gpu_mux_mode(GpuMode::Optimus)
.map_err(|e| {
error!("ROGTray: set_mode: {e}"); error!("ROGTray: set_mode: {e}");
e e
}) }) {
.ok(); if let Ok(mut lock) = gfx_action.lock() {
} *lock = res;
}
if let Ok(mode) = self.bios_proxy.gpu_mux_mode() { }
let mode = match mode { }
GpuMode::Discrete => GfxMode::AsusMuxDiscreet, });
_ => GfxMode::Hybrid,
};
reboot_required = mode != current_mode;
}
}
let active = match current_mode {
GfxMode::AsusMuxDiscreet => "Discreet".to_owned(),
_ => current_mode.to_string(),
}; };
let reboot_required = if reboot_required { for item in supported_gfx {
"(Reboot required)" if *item == GfxMode::Integrated {
continue;
}
func(*item);
}
let action_required = if let Ok(lock) = self.gfx_action.lock() {
if matches!(*lock, GfxUserActionRequired::Nothing) {
""
} else {
<&str>::from(*lock)
}
} else { } else {
"" ""
}; };
self.add_radio_sub_menu( self.add_radio_sub_menu(
&format!("GPU Mode: {active} {reboot_required}"), &format!("GPU Mode: {current_mode} {action_required}"),
active.as_str(), &current_mode.to_string(),
&gpu_menu, &gpu_menu,
); );
@@ -376,7 +317,7 @@ impl ROGTray {
let mut reboot_required = false; let mut reboot_required = false;
if let Ok(mode) = gfx_dbus.gpu_mux_mode() { if let Ok(mode) = gfx_dbus.gpu_mux_mode() {
let mode = match mode { let mode = match mode {
GpuMode::Discrete => GfxMode::AsusMuxDiscreet, GpuMode::Discrete => GfxMode::AsusMuxDgpu,
_ => GfxMode::Hybrid, _ => GfxMode::Hybrid,
}; };
reboot_required = mode != current_mode; reboot_required = mode != current_mode;
@@ -406,7 +347,7 @@ impl ROGTray {
}); });
let active = match current_mode { let active = match current_mode {
GfxMode::AsusMuxDiscreet => "Ultimate".to_owned(), GfxMode::AsusMuxDgpu => "Ultimate".to_owned(),
GfxMode::Hybrid => "Optimus".to_owned(), GfxMode::Hybrid => "Optimus".to_owned(),
_ => current_mode.to_string(), _ => current_mode.to_string(),
}; };
@@ -441,7 +382,7 @@ impl ROGTray {
fn rebuild_and_update( fn rebuild_and_update(
&mut self, &mut self,
supported: &SupportedFunctions, supported: &SupportedFunctions,
has_supergfx: bool, supported_gfx: &[GfxMode],
current_gfx_mode: GfxMode, current_gfx_mode: GfxMode,
charge_limit: u8, charge_limit: u8,
panel_od: bool, panel_od: bool,
@@ -450,8 +391,9 @@ impl ROGTray {
self.menu_add_base(); self.menu_add_base();
self.menu_add_charge_limit(supported, charge_limit); self.menu_add_charge_limit(supported, charge_limit);
self.menu_add_panel_od(supported, panel_od); self.menu_add_panel_od(supported, panel_od);
if has_supergfx { if self.gfx_proxy_is_active {
self.menu_add_gpu(supported, current_gfx_mode); // Add a supergfxctl specific menu
self.menu_add_supergfx(supported_gfx, current_gfx_mode);
} else if supported.rog_bios_ctrl.gpu_mux { } else if supported.rog_bios_ctrl.gpu_mux {
self.menu_add_mux(current_gfx_mode); self.menu_add_mux(current_gfx_mode);
} }
@@ -466,20 +408,12 @@ pub fn init_tray(
let (send, recv) = channel(); let (send, recv) = channel();
let _send = Arc::new(Mutex::new(send)); let _send = Arc::new(Mutex::new(send));
let has_supergfx = if let Ok(lock) = states.try_lock() {
lock.gfx_state.has_supergfx
} else {
false
};
std::thread::spawn(move || { std::thread::spawn(move || {
if gtk::init() let gtk_init = gtk::init().map_err(|e| {
.map_err(|e| { error!("ROGTray: gtk init {e}");
error!("ROGTray: gtk init {e}"); e
e });
}) if gtk_init.is_err() {
.is_err()
{
return; return;
} // Make this the main thread for gtk } // Make this the main thread for gtk
debug!("init_tray gtk"); debug!("init_tray gtk");
@@ -497,7 +431,29 @@ pub fn init_tray(
return; return;
} }
}; };
tray.rebuild_and_update(&supported, has_supergfx, GfxMode::Hybrid, 100, false);
let supported_gfx = if tray.gfx_proxy_is_active {
if let Ok(version) = tray.gfx_proxy.version() {
if let Some(version) = Versioning::new(&version) {
let curr_gfx = Versioning::new("5.0.3-RC4").unwrap();
warn!("supergfxd version = {version}");
if version < curr_gfx {
// Don't allow mode changing if too old a version
warn!("supergfxd found but is too old to use");
tray.gfx_proxy_is_active = false;
}
}
}
if tray.gfx_proxy_is_active {
tray.gfx_proxy.supported().unwrap()
} else {
Default::default()
}
} else {
Default::default()
};
tray.rebuild_and_update(&supported, &supported_gfx, GfxMode::Hybrid, 100, false);
tray.set_icon(TRAY_APP_ICON); tray.set_icon(TRAY_APP_ICON);
info!("Started ROGTray"); info!("Started ROGTray");
@@ -509,13 +465,13 @@ pub fn init_tray(
lock.gfx_state.mode lock.gfx_state.mode
} else { } else {
match lock.bios.dedicated_gfx { match lock.bios.dedicated_gfx {
GpuMode::Discrete => GfxMode::AsusMuxDiscreet, GpuMode::Discrete => GfxMode::AsusMuxDgpu,
_ => GfxMode::Hybrid, _ => GfxMode::Hybrid,
} }
}; };
tray.rebuild_and_update( tray.rebuild_and_update(
&supported, &supported,
has_supergfx, &supported_gfx,
current_gpu_mode, current_gpu_mode,
lock.power_state.charge_limit, lock.power_state.charge_limit,
lock.bios.panel_overdrive, lock.bios.panel_overdrive,
@@ -525,13 +481,19 @@ pub fn init_tray(
match lock.gfx_state.power_status { match lock.gfx_state.power_status {
GfxPower::Suspended => tray.set_icon("asus_notif_blue"), GfxPower::Suspended => tray.set_icon("asus_notif_blue"),
GfxPower::Off => tray.set_icon("asus_notif_green"), GfxPower::Off => {
if lock.gfx_state.mode == GfxMode::Vfio {
tray.set_icon("asus_notif_red")
} else {
tray.set_icon("asus_notif_green")
}
}
GfxPower::AsusDisabled => tray.set_icon("asus_notif_white"), GfxPower::AsusDisabled => tray.set_icon("asus_notif_white"),
GfxPower::AsusMuxDiscreet | GfxPower::Active => { GfxPower::AsusMuxDiscreet | GfxPower::Active => {
tray.set_icon("asus_notif_red"); tray.set_icon("asus_notif_red");
} }
GfxPower::Unknown => { GfxPower::Unknown => {
if has_supergfx { if tray.gfx_proxy_is_active {
tray.set_icon("gpu-integrated"); tray.set_icon("gpu-integrated");
} else { } else {
tray.set_icon("asus_notif_red"); tray.set_icon("asus_notif_red");
+106 -38
View File
@@ -17,7 +17,8 @@ use rog_dbus::zbus_profile::ProfileProxy;
use rog_platform::platform::GpuMode; use rog_platform::platform::GpuMode;
use rog_profiles::Profile; use rog_profiles::Profile;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use supergfxctl::pci_device::GfxPower; use supergfxctl::actions::UserActionRequired as GfxUserAction;
use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy; use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
use tokio::time::sleep; use tokio::time::sleep;
use zbus::export::futures_util::{future, StreamExt}; use zbus::export::futures_util::{future, StreamExt};
@@ -139,8 +140,8 @@ type SharedHandle = Arc<Mutex<Option<NotificationHandle>>>;
pub fn start_notifications( pub fn start_notifications(
config: &Config, config: &Config,
page_states: Arc<Mutex<SystemState>>, page_states: &Arc<Mutex<SystemState>>,
enabled_notifications: Arc<Mutex<EnabledNotifications>>, enabled_notifications: &Arc<Mutex<EnabledNotifications>>,
) -> Result<()> { ) -> Result<()> {
let last_notification: SharedHandle = Arc::new(Mutex::new(None)); let last_notification: SharedHandle = Arc::new(Mutex::new(None));
@@ -406,6 +407,7 @@ pub fn start_notifications(
do_notification do_notification
); );
let page_states1 = page_states.clone();
tokio::spawn(async move { tokio::spawn(async move {
let conn = zbus::Connection::system() let conn = zbus::Connection::system()
.await .await
@@ -426,15 +428,25 @@ pub fn start_notifications(
while let Some(e) = p.next().await { while let Some(e) = p.next().await {
if let Ok(out) = e.args() { if let Ok(out) = e.args() {
let action = out.action(); let action = out.action();
do_gfx_action_notif( let mode = if let Ok(lock) = page_states1.lock() {
"Gfx mode change requires", convert_gfx_mode(lock.gfx_state.mode)
&format!("{action:?}",), } else {
) GpuMode::Error
};
match action {
supergfxctl::actions::UserActionRequired::Reboot => {
do_mux_notification(
"Graphics mode change requires reboot",
&mode,
)
}
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
}
.map_err(|e| { .map_err(|e| {
error!("zbus signal: do_gfx_action_notif: {e}"); error!("zbus signal: do_gfx_action_notif: {e}");
e e
}) })
.unwrap(); .ok();
} }
} }
}; };
@@ -445,6 +457,18 @@ pub fn start_notifications(
Ok(()) Ok(())
} }
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
match gfx {
GfxMode::Hybrid => GpuMode::Optimus,
GfxMode::Integrated => GpuMode::Integrated,
GfxMode::NvidiaNoModeset => GpuMode::Discrete,
GfxMode::Vfio => GpuMode::Vfio,
GfxMode::AsusEgpu => GpuMode::Egpu,
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
GfxMode::None => GpuMode::Error,
}
}
fn base_notification<T>(message: &str, data: &T) -> Notification fn base_notification<T>(message: &str, data: &T) -> Notification
where where
T: Display, T: Display,
@@ -516,47 +540,91 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Result<NotificationHan
Ok(Notification::show(&notif)?) Ok(Notification::show(&notif)?)
} }
fn do_gfx_action_notif<T>(message: &str, data: &T) -> Result<()> fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
where if matches!(action, GfxUserAction::Reboot) {
T: Display, do_mux_notification("Graphics mode change requires reboot", &mode).ok();
{ return Ok(());
let mut notif = base_notification(message, data); }
notif.action("gnome-session-quit", "Logout");
notif.urgency(Urgency::Critical); let mut notif = Notification::new();
notif.timeout(3000); notif
notif.icon("dialog-warning"); .summary(NOTIF_HEADER)
notif.hint(Hint::Transient(true)); .body(&format!("Changing to {mode}. {message}"))
let handle = notif.show()?; .timeout(2000)
handle.wait_for_action(|id| { //.hint(Hint::Resident(true))
if id == "gnome-session-quit" { .hint(Hint::Category("device".into()))
let mut cmd = Command::new("gnome-session-quit"); .urgency(Urgency::Critical)
cmd.spawn().ok(); .timeout(3000)
} else if id == "__closed" { .icon("dialog-warning")
// TODO: cancel the switching .hint(Hint::Transient(true));
if matches!(action, GfxUserAction::Logout) {
notif.action("gfx-mode-session-action", "Logout");
let handle = notif.show()?;
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0"]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else {
// todo: handle alternatives
}
} }
}); } else {
notif.show()?;
}
Ok(()) Ok(())
} }
/// Actual `GpuMode` unused as data is never correct until switched by reboot /// Actual `GpuMode` unused as data is never correct until switched by reboot
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> { fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
let mut notif = base_notification(message, &m.to_string()); let mut notif = base_notification(message, &m.to_string());
notif.action("gnome-session-quit", "Reboot"); notif
notif.urgency(Urgency::Critical); .action("gfx-mode-session-action", "Reboot")
notif.icon("system-reboot-symbolic"); .urgency(Urgency::Critical)
notif.hint(Hint::Transient(true)); .icon("system-reboot-symbolic")
.hint(Hint::Transient(true));
let handle = notif.show()?; let handle = notif.show()?;
std::thread::spawn(|| { std::thread::spawn(|| {
handle.wait_for_action(|id| { if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if id == "gnome-session-quit" { if desktop.to_lowercase() == "gnome" {
let mut cmd = Command::new("gnome-session-quit"); handle.wait_for_action(|id| {
cmd.arg("--reboot"); if id == "gfx-mode-session-action" {
cmd.spawn().ok(); let mut cmd = Command::new("gnome-session-quit");
} else if id == "__closed" { cmd.arg("--reboot");
// TODO: cancel the switching cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0"]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} }
}) }
}); });
Ok(()) Ok(())
} }
+34 -32
View File
@@ -1,5 +1,5 @@
use egui::{RichText, Ui}; use egui::{RichText, Ui};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::AuraZone; use rog_aura::AuraZone;
use rog_platform::supported::SupportedFunctions; use rog_platform::supported::SupportedFunctions;
@@ -12,7 +12,9 @@ pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => { AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => {
aura_power1(supported, states, ui); aura_power1(supported, states, ui);
} }
AuraDevice::X19B6 => aura_power2(supported, states, ui), AuraDevice::X19b6 | AuraDevice::X18c6 | AuraDevice::X1a30 => {
aura_power2(supported, states, ui)
}
AuraDevice::Tuf => aura_power1(supported, states, ui), AuraDevice::Tuf => aura_power1(supported, states, ui),
AuraDevice::Unknown => {} AuraDevice::Unknown => {}
} }
@@ -20,10 +22,10 @@ pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState
fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) { fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) {
let enabled_states = &mut states.aura.enabled; let enabled_states = &mut states.aura.enabled;
let mut boot = enabled_states.x1866.contains(&AuraDev1866::Boot); let mut boot = enabled_states.x1866.contains(&AuraDevRog1::Boot);
let mut sleep = enabled_states.x1866.contains(&AuraDev1866::Sleep); let mut sleep = enabled_states.x1866.contains(&AuraDevRog1::Sleep);
let mut keyboard = enabled_states.x1866.contains(&AuraDev1866::Keyboard); let mut keyboard = enabled_states.x1866.contains(&AuraDevRog1::Keyboard);
let mut lightbar = enabled_states.x1866.contains(&AuraDev1866::Lightbar); let mut lightbar = enabled_states.x1866.contains(&AuraDevRog1::Lightbar);
if supported.keyboard_led.dev_id == AuraDevice::Tuf { if supported.keyboard_led.dev_id == AuraDevice::Tuf {
boot = enabled_states.tuf.contains(&AuraDevTuf::Boot); boot = enabled_states.tuf.contains(&AuraDevTuf::Boot);
sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep); sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep);
@@ -148,7 +150,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
let mut enabled = Vec::new(); let mut enabled = Vec::new();
let mut disabled = Vec::new(); let mut disabled = Vec::new();
let mut modify_x1866 = |b: bool, a: AuraDev1866| { let mut modify_x1866 = |b: bool, a: AuraDevRog1| {
if b { if b {
enabled.push(a); enabled.push(a);
if !enabled_states.x1866.contains(&a) { if !enabled_states.x1866.contains(&a) {
@@ -169,14 +171,14 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
} }
} }
}; };
modify_x1866(boot, AuraDev1866::Boot); modify_x1866(boot, AuraDevRog1::Boot);
modify_x1866(sleep, AuraDev1866::Sleep); modify_x1866(sleep, AuraDevRog1::Sleep);
modify_x1866(keyboard, AuraDev1866::Keyboard); modify_x1866(keyboard, AuraDevRog1::Keyboard);
if !supported.keyboard_led.basic_zones.is_empty() { if !supported.keyboard_led.basic_zones.is_empty() {
modify_x1866(lightbar, AuraDev1866::Lightbar); modify_x1866(lightbar, AuraDevRog1::Lightbar);
} }
let mut send = |enable: bool, data: Vec<AuraDev1866>| { let mut send = |enable: bool, data: Vec<AuraDevRog1>| {
let options = AuraPowerDev { let options = AuraPowerDev {
tuf: vec![], tuf: vec![],
x1866: data, x1866: data,
@@ -211,17 +213,17 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
.basic_zones .basic_zones
.contains(&AuraZone::BarRight); .contains(&AuraZone::BarRight);
let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar); let boot_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeBar);
let boot_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootLogo); let boot_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootLogo);
let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootKeyb); let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootKeyb);
let awake_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootBar); let awake_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootBar);
let awake_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeLogo); let awake_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeLogo);
let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeKeyb); let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeKeyb);
let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepBar); let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepBar);
let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepLogo); let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepLogo);
let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepKeyb); let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepKeyb);
let mut changed = false; let mut changed = false;
@@ -265,7 +267,7 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
let mut enabled = Vec::new(); let mut enabled = Vec::new();
let mut disabled = Vec::new(); let mut disabled = Vec::new();
let mut modify = |b: bool, a: AuraDev19b6| { let mut modify = |b: bool, a: AuraDevRog2| {
if b { if b {
enabled.push(a); enabled.push(a);
if !enabled_states.x19b6.contains(&a) { if !enabled_states.x19b6.contains(&a) {
@@ -286,25 +288,25 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
} }
} }
}; };
modify(*boot_keyb, AuraDev19b6::BootKeyb); modify(*boot_keyb, AuraDevRog2::BootKeyb);
modify(*sleep_keyb, AuraDev19b6::SleepKeyb); modify(*sleep_keyb, AuraDevRog2::SleepKeyb);
modify(*awake_keyb, AuraDev19b6::AwakeKeyb); modify(*awake_keyb, AuraDevRog2::AwakeKeyb);
if supported.keyboard_led.basic_zones.contains(&AuraZone::Logo) { if supported.keyboard_led.basic_zones.contains(&AuraZone::Logo) {
modify(*boot_logo, AuraDev19b6::BootLogo); modify(*boot_logo, AuraDevRog2::BootLogo);
modify(*sleep_logo, AuraDev19b6::SleepLogo); modify(*sleep_logo, AuraDevRog2::SleepLogo);
modify(*awake_logo, AuraDev19b6::AwakeLogo); modify(*awake_logo, AuraDevRog2::AwakeLogo);
} }
if supported if supported
.keyboard_led .keyboard_led
.basic_zones .basic_zones
.contains(&AuraZone::BarLeft) .contains(&AuraZone::BarLeft)
{ {
modify(*boot_bar, AuraDev19b6::AwakeBar); modify(*boot_bar, AuraDevRog2::AwakeBar);
modify(*sleep_bar, AuraDev19b6::SleepBar); modify(*sleep_bar, AuraDevRog2::SleepBar);
modify(*awake_bar, AuraDev19b6::BootBar); modify(*awake_bar, AuraDevRog2::BootBar);
} }
let mut send = |enable: bool, data: Vec<AuraDev19b6>| { let mut send = |enable: bool, data: Vec<AuraDevRog2>| {
let options = AuraPowerDev { let options = AuraPowerDev {
tuf: vec![], tuf: vec![],
x1866: vec![], x1866: vec![],
@@ -25,7 +25,7 @@ pub fn keyboard(
AdvancedAuraType::None => (false, keyboard_layout.max_width(), false), AdvancedAuraType::None => (false, keyboard_layout.max_width(), false),
AdvancedAuraType::Zoned(zones) => { AdvancedAuraType::Zoned(zones) => {
let width = if let Some(row) = keyboard_layout.rows_ref().get(2) { let width = if let Some(row) = keyboard_layout.rows_ref().get(2) {
row.width() as f32 row.width()
} else { } else {
0.0 0.0
}; };
+31 -1
View File
@@ -8,7 +8,7 @@ impl RogApp {
// The top panel is often a good place for a menu bar: // The top panel is often a good place for a menu bar:
egui::menu::bar(ui, |ui| { egui::menu::bar(ui, |ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
egui::global_dark_light_mode_buttons(ui); self.dark_light_mode_buttons(ui);
egui::warn_if_debug_build(ui); egui::warn_if_debug_build(ui);
}); });
@@ -45,4 +45,34 @@ impl RogApp {
}); });
}); });
} }
fn dark_light_mode_buttons(&mut self, ui: &mut egui::Ui) {
let load_from_cfg = self.config.dark_mode != ui.ctx().style().visuals.dark_mode;
if ui
.add(egui::SelectableLabel::new(
!self.config.dark_mode,
"☀ Light",
))
.clicked()
|| (load_from_cfg && !self.config.dark_mode)
{
ui.ctx().set_visuals(egui::Visuals::light());
}
if ui
.add(egui::SelectableLabel::new(self.config.dark_mode, "🌙 Dark"))
.clicked()
|| (load_from_cfg && self.config.dark_mode)
{
ui.ctx().set_visuals(egui::Visuals::dark());
}
let applied_dark_mode = ui.ctx().style().visuals.dark_mode;
if self.config.dark_mode != applied_dark_mode {
self.config.dark_mode = applied_dark_mode;
let tmp = self.config.enabled_notifications.clone();
self.config.save(&tmp).ok();
}
}
} }
+3
View File
@@ -15,3 +15,6 @@ rog_aura = { path = "../rog-aura" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
rog_platform = { path = "../rog-platform" } rog_platform = { path = "../rog-platform" }
zbus.workspace = true zbus.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Aura' from service //! data. Source: `Interface '/org/asuslinux/Aura' from service
//! 'org.asuslinux.Daemon' on system bus`. //! 'org.asuslinux.Daemon' on system bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus` object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::PeerProxy`] //! * [`zbus::fdo::PeerProxy`]
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Platform' from service //! data. Source: `Interface '/org/asuslinux/Platform' from service
//! 'org.asuslinux.Daemon' on system bus`. //! 'org.asuslinux.Daemon' on system bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus` object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::PropertiesProxy`] //! * [`zbus::fdo::PropertiesProxy`]
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Charge' from service //! data. Source: `Interface '/org/asuslinux/Charge' from service
//! 'org.asuslinux.Daemon' on system bus`. //! 'org.asuslinux.Daemon' on system bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus` object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::PropertiesProxy`] //! * [`zbus::fdo::PropertiesProxy`]
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Profile' from service //! data. Source: `Interface '/org/asuslinux/Profile' from service
//! 'org.asuslinux.Daemon' on system bus`. //! 'org.asuslinux.Daemon' on system bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::IntrospectableProxy`] //! * [`zbus::fdo::IntrospectableProxy`]
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon` //! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection //! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Supported' from service //! data. Source: `Interface '/org/asuslinux/Supported' from service
//! 'org.asuslinux.Daemon' on system bus`. //! 'org.asuslinux.Daemon' on system bus`.
//! //!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) //! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation. //! section of the zbus documentation.
//! //!
//! This DBus object implements //! This `DBus` object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), //! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: //! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//! //!
//! * [`zbus::fdo::PeerProxy`] //! * [`zbus::fdo::PeerProxy`]
+3
View File
@@ -16,3 +16,6 @@ udev.workspace = true
inotify.workspace = true inotify.workspace = true
rusb.workspace = true rusb.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+1 -39
View File
@@ -51,7 +51,7 @@ pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<(
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> { pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
if let Some(value) = device.attribute_value(attr_name) { if let Some(value) = device.attribute_value(attr_name) {
let tmp = value.to_string_lossy(); let tmp = value.to_string_lossy();
return tmp.parse::<u8>().map_err(|_| PlatformError::ParseNum); return tmp.parse::<u8>().map_err(|_e| PlatformError::ParseNum);
} }
Err(PlatformError::AttrNotFound(attr_name.to_owned())) Err(PlatformError::AttrNotFound(attr_name.to_owned()))
} }
@@ -114,41 +114,3 @@ mod tests {
assert_eq!(tmp, &[1, 2, 3, 4, 5]); assert_eq!(tmp, &[1, 2, 3, 4, 5]);
} }
} }
// pub fn find_led_node(id_product: &str) -> Result<Device, PlatformError> {
// let mut enumerator = udev::Enumerator::new().map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("enumerator failed".into(), err)
// })?;
// enumerator.match_subsystem("hidraw").map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("match_subsystem failed".into(), err)
// })?;
// for device in enumerator.scan_devices().map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("scan_devices failed".into(), err)
// })? {
// if let Some(parent) = device
// .parent_with_subsystem_devtype("usb", "usb_device")
// .map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("parent_with_subsystem_devtype
// failed".into(), err) })?
// {
// if parent
// .attribute_value("idProduct")
// .ok_or_else(|| PlatformError::NotFound("LED
// idProduct".into()))? == id_product
// {
// if let Some(dev_node) = device.devnode() {
// info!("Using device at: {:?} for LED control", dev_node);
// return Ok(device);
// }
// }
// }
// }
// Err(PlatformError::MissingFunction(
// "ASUS LED device node not found".into(),
// ))
// }
+4
View File
@@ -76,6 +76,8 @@ pub enum GpuMode {
Optimus, Optimus,
Integrated, Integrated,
Egpu, Egpu,
Vfio,
Ultimate,
#[default] #[default]
Error, Error,
NotSupported, NotSupported,
@@ -135,6 +137,8 @@ impl Display for GpuMode {
GpuMode::Optimus => write!(f, "Optimus"), GpuMode::Optimus => write!(f, "Optimus"),
GpuMode::Integrated => write!(f, "Integrated"), GpuMode::Integrated => write!(f, "Integrated"),
GpuMode::Egpu => write!(f, "eGPU"), GpuMode::Egpu => write!(f, "eGPU"),
GpuMode::Vfio => write!(f, "VFIO"),
GpuMode::Ultimate => write!(f, "Ultimate"),
GpuMode::Error => write!(f, "Error"), GpuMode::Error => write!(f, "Error"),
GpuMode::NotSupported => write!(f, "Not Supported"), GpuMode::NotSupported => write!(f, "Not Supported"),
} }
+3
View File
@@ -15,3 +15,6 @@ serde.workspace = true
serde_derive.workspace = true serde_derive.workspace = true
zbus = { workspace = true, optional = true } zbus = { workspace = true, optional = true }
[dev-dependencies]
cargo-husky.workspace = true
+1 -1
View File
@@ -19,7 +19,7 @@ pub enum ProfileError {
impl fmt::Display for ProfileError { impl fmt::Display for ProfileError {
// This trait requires `fmt` with this exact signature. // This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ProfileError::Path(path, error) => write!(f, "Path {}: {}", path, error), ProfileError::Path(path, error) => write!(f, "Path {}: {}", path, error),
ProfileError::Read(path, error) => write!(f, "Read {}: {}", path, error), ProfileError::Read(path, error) => write!(f, "Read {}: {}", path, error),
+4 -4
View File
@@ -7,7 +7,7 @@ use crate::error::ProfileError;
use crate::FanCurvePU; use crate::FanCurvePU;
pub(crate) fn pwm_str(fan: char, index: usize) -> String { pub(crate) fn pwm_str(fan: char, index: usize) -> String {
let mut buf = "pwm1_auto_point1_pwm".to_string(); let mut buf = "pwm1_auto_point1_pwm".to_owned();
unsafe { unsafe {
let tmp = buf.as_bytes_mut(); let tmp = buf.as_bytes_mut();
tmp[3] = fan as u8; tmp[3] = fan as u8;
@@ -17,7 +17,7 @@ pub(crate) fn pwm_str(fan: char, index: usize) -> String {
} }
pub(crate) fn temp_str(fan: char, index: usize) -> String { pub(crate) fn temp_str(fan: char, index: usize) -> String {
let mut buf = "pwm1_auto_point1_temp".to_string(); let mut buf = "pwm1_auto_point1_temp".to_owned();
unsafe { unsafe {
let tmp = buf.as_bytes_mut(); let tmp = buf.as_bytes_mut();
tmp[3] = fan as u8; tmp[3] = fan as u8;
@@ -146,10 +146,10 @@ impl CurveData {
for attr in device.attributes() { for attr in device.attributes() {
let tmp = attr.name().to_string_lossy(); let tmp = attr.name().to_string_lossy();
if tmp.starts_with("pwm1") && tmp.ends_with("_temp") { if tmp.starts_with("pwm1") && tmp.ends_with("_temp") {
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.temp) Self::set_val_from_attr(tmp.as_ref(), device, &mut self.temp);
} }
if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") { if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") {
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.pwm) Self::set_val_from_attr(tmp.as_ref(), device, &mut self.pwm);
} }
} }
} }
+4 -10
View File
@@ -2,8 +2,8 @@ pub mod error;
pub mod fan_curve_set; pub mod fan_curve_set;
use std::fmt::Display; use std::fmt::Display;
use std::fs::OpenOptions; use std::fs::{self, OpenOptions};
use std::io::{Read, Write}; use std::io::Write;
use std::path::Path; use std::path::Path;
use error::ProfileError; use error::ProfileError;
@@ -49,18 +49,12 @@ impl Profile {
} }
pub fn get_active_profile() -> Result<Profile, ProfileError> { pub fn get_active_profile() -> Result<Profile, ProfileError> {
let mut file = OpenOptions::new().read(true).open(PLATFORM_PROFILE)?; let buf = fs::read_to_string(PLATFORM_PROFILE)?;
let mut buf = String::new();
file.read_to_string(&mut buf)?;
Ok(buf.as_str().into()) Ok(buf.as_str().into())
} }
pub fn get_profile_names() -> Result<Vec<Profile>, ProfileError> { pub fn get_profile_names() -> Result<Vec<Profile>, ProfileError> {
let mut file = OpenOptions::new().read(true).open(PLATFORM_PROFILES)?; let buf = fs::read_to_string(PLATFORM_PROFILES)?;
let mut buf = String::new();
file.read_to_string(&mut buf)?;
Ok(buf.rsplit(' ').map(|p| p.into()).collect()) Ok(buf.rsplit(' ').map(|p| p.into()).collect())
} }