Compare commits

...

57 Commits

Author SHA1 Message Date
Denis Benato 907d4694f3 Merge branch 'devel' 2025-11-15 18:17:38 +01:00
Denis Benato 1dcc4ff502 Update CHANGELOG.md 2025-11-15 18:15:55 +01:00
Denis Benato cf232047b0 Merge branch 'patch-1' into 'main'
Add aura support for G614FR (ROG Strix G16 2025)

See merge request asus-linux/asusctl!232
2025-11-15 15:08:19 +00:00
Henry Zhang ff99ec9a39 Add aura support for G614FR (ROG Strix G16 2025) 2025-11-15 16:13:38 +08:00
Denis Benato 8a19374a41 Merge branch 'aura-support-fa617xs' into 'main'
Add aura support for ASUS TUF Gaming A16 (FA617XS, AMD Advantage Edition)

Closes #696

See merge request asus-linux/asusctl!231
2025-11-14 06:56:21 +00:00
AB 4cec1f49b4 Add FA617XS (TUF A16 AMD Advantage Edition) support to aura_support.ron 2025-11-12 16:29:38 +05:30
Denis Benato 01aae200f3 Fix: do not crash if no battery is present 2025-11-11 22:41:54 +01:00
Denis Benato 4c6db9f0a9 Chore: ignore push-blocking features that would make older rust toolchains error 2025-11-11 22:21:32 +01:00
Denis Benato 7207d3287a Chore: avoid rebuilding after make 2025-11-11 22:03:45 +01:00
Denis Benato 1b2d8d83fc Chore: prepare for 6.1.18 release 2025-11-11 21:55:42 +01:00
Denis Benato 6d8db91583 Chore: reduce trace logging from libraries 2025-11-11 21:49:00 +01:00
Denis Benato 20c3628476 Chore: update dependencies 2025-11-11 21:44:27 +01:00
Denis Benato 4edecfce1c Merge commit '34699a7021a85e1c0ba3d6ac0876c6beb8ae394f' 2025-11-11 21:39:01 +01:00
Denis Benato 34699a7021 Fix: notifications not respecting settings 2025-11-06 02:57:20 +01:00
Denis Benato ef311689ec Fix: do not stall the boot process 2025-11-06 00:55:20 +01:00
Denis Benato 8ee0281b4f Fix: fedora build 2025-11-05 22:40:58 +01:00
Denis Benato d8504b5430 Changelog for 6.1.17 2025-11-05 21:14:21 +01:00
Denis Benato 5c4d833fbd Prepare for 6.1.17 2025-11-05 21:09:18 +01:00
Denis Benato 698999e828 cargo fmt and README.md restyle 2025-11-05 20:02:43 +01:00
Denis Benato 0eae9e55c6 Merge branch 'devel' 2025-11-05 19:54:21 +01:00
Denis Benato 07171888a1 Merge branch 'main' into 'main'
feat: Allow setting default profile for ac and battery

See merge request asus-linux/asusctl!229
2025-11-05 18:53:53 +00:00
matszwe02 9321fde6af feat: Allow setting default profile for ac and battery 2025-11-05 01:44:31 +01:00
Denis Benato f90d0a6673 Merge branch 'devel' into 'devel'
Add install-data-asusd_user to install-data in Makefile

See merge request asus-linux/asusctl!228
2025-10-29 18:49:50 +00:00
Synby bbd03c128d Edit Makefile
add install-data-asusd_user to install-data
2025-10-29 17:23:29 +00:00
Denis Benato 132a2f3665 Chore: complete the switch back to stable 2025-10-23 14:50:40 +02:00
Denis Benato 180566e5f1 Fix: share a single HID device
Avoid opening multiple handles to the same device whenever possible.
2025-10-22 22:05:17 +02:00
Denis Benato c9e76f3273 Chore: prepare for 6.1.16 release 2025-10-20 19:15:36 +02:00
Denis Benato 2997ae83ff Merge branch 'devel' 2025-10-20 04:08:20 +02:00
Denis Benato 151d681e16 feat: expose MCU Powersave toggle on rogcc 2025-10-20 03:47:09 +02:00
Denis Benato 90b3f43a36 Chore: add more debugging 2025-10-20 02:49:47 +02:00
Denis Benato a345b09ce1 Chore: type abttery -> battery 2025-10-20 02:46:07 +02:00
Denis Benato f26b0d8de5 Merge branch 'profile-match' into 'main'
Allow flexible profile cli input for LowPower

See merge request asus-linux/asusctl!226
2025-10-20 00:40:54 +00:00
yanganto 9366b0ec04 Allow flexible profile cli input for LowPower 2025-10-20 00:40:54 +00:00
Denis Benato 415712143b Feat: add screen_auto_brightness 2025-10-20 02:08:59 +02:00
Denis Benato 60fce30a06 Chore: flush out requirement for nightly 2025-10-20 00:39:17 +02:00
Denis Benato d8f06230fa Chore: Added support for FX607J 2025-10-19 23:02:45 +02:00
Denis Benato 834464a527 Fix: fixed ac_command/bat_command 2025-10-19 23:00:23 +02:00
Denis Benato 4faa96298a Chore: Added supprot for G614JIR 2025-10-19 22:32:05 +02:00
Denis Benato 78c574b761 chore_ add supprot for GU605CR 2025-10-19 21:27:33 +02:00
Denis Benato 9785eafd53 Modified to README.md to not mislead users attempting to compile it 2025-10-19 20:45:49 +02:00
Denis Benato 51cad9ea7e chore: make the startup more verbose 2025-10-16 15:17:27 +02:00
Denis Benato 319373faea chore: Prepare for 6.1.15 release 2025-10-14 01:57:03 +02:00
Denis Benato f6aa3e3d01 Merge branch 'devel' 2025-10-14 01:50:20 +02:00
Denis Benato d11fc20bab feat: apply the proper configuration depending on the plug status 2025-10-13 21:36:01 +02:00
Denis Benato b0e1b21e4b chore: cargo clippy fix 2025-10-12 22:34:20 +02:00
Denis Benato 1c1daaa6d2 chore: reimplement default for FanCurveCPU 2025-10-12 19:47:26 +02:00
HiFiPhile c3b5de843f Add TX Air rule 2025-10-12 19:44:30 +02:00
Denis Benato 09dcfb4065 Fix multiple warnings 2025-10-12 19:43:07 +02:00
Denis Benato b2e7211bbe chore: cargo fmt 2025-10-12 19:43:05 +02:00
Denis Benato 1ab1adf937 Merge branch 'tx_air' into 'main'
Add TX Air (TUF Chinese version) udev rule

See merge request asus-linux/asusctl!227
2025-10-12 17:42:09 +00:00
HiFiPhile a21bf779b0 Add TX Air rule 2025-10-12 13:20:07 +02:00
Denis Benato 0dba22529c feat: change limits dynamically 2025-10-11 20:51:57 +02:00
Denis Benato 180d63620b Fix multiple warnings 2025-10-08 01:19:38 +02:00
Denis Benato daea1f538c chore: cargo fmt 2025-10-08 01:01:43 +02:00
Denis Benato f5e2484797 chore: release 6.1.14 2025-10-08 00:56:25 +02:00
Denis Benato 7105ae40c6 chore: attempt to fix tests 2025-10-08 00:35:09 +02:00
Denis Benato 33f9900ef9 chore: fix formatting 2025-10-08 00:19:43 +02:00
50 changed files with 1781 additions and 1173 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
set -e set -e
echo '+cargo +nightly fmt --all -- --check' echo '+cargo fmt --all -- --check'
cargo +nightly fmt --all -- --check cargo fmt --all -- --check
git add -u git add -u
+2 -2
View File
@@ -2,8 +2,8 @@
set -e set -e
echo '+cargo +nightly fmt --all -- --check' echo '+cargo fmt --all -- --check'
cargo +nightly fmt --all -- --check cargo fmt --all -- --check
echo '+cargo clippy --all -- -D warnings' echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings cargo clippy --all -- -D warnings
echo '+cargo cranky' echo '+cargo cranky'
+6 -7
View File
@@ -31,8 +31,7 @@ format:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- echo "nightly" > rust-toolchain - rustup component add rustfmt || true
- rustup component add rustfmt
- cargo fmt --check - cargo fmt --check
check: check:
@@ -40,8 +39,8 @@ check:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- rustup component add clippy - rustup component add clippy || true
- cargo check - cargo check --locked --workspace
# deny currently catches too much # deny currently catches too much
#- cargo install cargo-deny && cargo deny #- cargo install cargo-deny && cargo deny
- cargo install cargo-cranky && cargo cranky - cargo install cargo-cranky && cargo cranky
@@ -52,7 +51,7 @@ test:
<<: *rust_cache <<: *rust_cache
script: script:
- mkdir -p .git/hooks > /dev/null - mkdir -p .git/hooks > /dev/null
- cargo test --all -- --test-threads=1 - cargo test --locked --all
release: release:
only: only:
@@ -60,7 +59,7 @@ release:
<<: *rust_cache <<: *rust_cache
script: script:
- cargo install cargo-vendor-filterer - cargo install cargo-vendor-filterer
- make && make vendor - make FROZEN=1 && make vendor
artifacts: artifacts:
paths: paths:
- vendor_asusctl*.tar.xz - vendor_asusctl*.tar.xz
@@ -72,7 +71,7 @@ pages:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- cargo doc --document-private-items --no-deps --workspace - cargo doc --locked --document-private-items --no-deps --workspace
- rm -rf public - rm -rf public
- mkdir public - mkdir public
- cp -R target/doc/* public - cp -R target/doc/* public
+31
View File
@@ -2,6 +2,37 @@
## [Unreleased] ## [Unreleased]
## [6.1.18]
### Changed
- Add aura support for G614FR (ROG Strix G16 2025)
- all notifications now respects the timeout
- improve udev daemon-starting rule
- reduce log noise
## [v6.1.17]
### Changed
- Fix Makefile
- Share a single HID device
## [v6.1.16]
### Changed
- Expose more properties via rog-control-center
- Add support for a few more models
## [v6.1.15]
### Changed
- Reflect the current asus-armoury status on AC plug connection status change
## [v6.1.14]
### Changed
- Fix formatting
- Attempt to fix tests
## [v6.1.13] ## [v6.1.13]
### Changed ### Changed
Generated
+632 -637
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace.package] [workspace.package]
version = "6.1.13" version = "6.1.18"
rust-version = "1.82" rust-version = "1.82"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
+21 -5
View File
@@ -37,6 +37,15 @@ ifeq ($(X11),1)
ARGS += --features "rog-control-center/x11" ARGS += --features "rog-control-center/x11"
endif endif
# Always use the versions in Cargo.lock by default
ARGS += --locked
# Allow optionally freezing the build to avoid any network access and enforce Cargo.lock strictly
FROZEN ?= 0
ifeq ($(FROZEN),1)
ARGS += --frozen
endif
VENDORED ?= 0 VENDORED ?= 0
ifeq ($(VENDORED),1) ifeq ($(VENDORED),1)
ARGS += --frozen ARGS += --frozen
@@ -50,10 +59,17 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
target/$(TARGET)/$(BIN_D): build target/$(TARGET)/$(BIN_D): $(SRC)
target/$(TARGET)/$(BIN_C): build $(MAKE) build
target/$(TARGET)/$(BIN_U): build
target/$(TARGET)/$(BIN_ROG): build target/$(TARGET)/$(BIN_C): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_U): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_ROG): $(SRC)
$(MAKE) build
install-asusd: target/$(TARGET)/$(BIN_D) install-asusd: target/$(TARGET)/$(BIN_D)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
@@ -104,7 +120,7 @@ install-data-asusd_user:
.PHONY: install-data-asusd install-data-asusd_user .PHONY: install-data-asusd install-data-asusd_user
install-data: install-data-asusd install-data-rog_gui install-data: install-data-asusd install-data-asusd_user install-data-rog_gui
install: install-program install-data install: install-program install-data
$(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE" $(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE"
+31 -23
View File
@@ -46,13 +46,13 @@ See the [rog-aura readme](./rog-aura/README.md) for more details.
Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar
to this: to this:
``` ```plain
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
``` ```
or or
``` ```plain
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown] Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
``` ```
@@ -74,39 +74,47 @@ The list is a bit outdated as many features have been enabled in the Linux kerne
- [x] Toggle bios setting for boot/POST sound - [x] Toggle bios setting for boot/POST sound
- [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops) - [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops)
# GUI ## GUI
A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already. A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already.
**NOTE**: Xorg is not supported. **NOTE**: Xorg is not supported.
# BUILDING ## BUILDING
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/) or from the distro repos if newer than 1.75. Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/).
Distro packaging should work with the stable toolchain. If your distro does not provide a recent Rust toolchain, install rustup and use the stable toolchain.
**fedora:** **fedora:**
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel ```sh
make dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**openSUSE:** **openSUSE:**
Works with KDE Plasma (without GTK packages) Works with KDE Plasma (without GTK packages)
zypper in -t pattern devel_basis ```sh
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel zypper in -t pattern devel_basis
make zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**Debian(unsuported):** **Debian(unsuported):**
officially unsuported,but you can still try and test it by yourself(some features may not be available). officially unsuported,but you can still try and test it by yourself(some features may not be available).
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev ```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
make curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
sudo make install make
sudo make install
```
**Ubuntu, Popos (unsuported):** **Ubuntu, Popos (unsuported):**
@@ -133,15 +141,15 @@ You may also need to activate the service for debian install. If running Pop!\_O
If you are upgrading from a previous installed version, you will need to restart the service or reboot. If you are upgrading from a previous installed version, you will need to restart the service or reboot.
``` ```sh
$ systemctl daemon-reload && systemctl restart asusd systemctl daemon-reload && systemctl restart asusd
``` ```
## Uninstalling ## Uninstalling
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 ## 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`). See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
@@ -149,17 +157,17 @@ Generation of the bindings with `make bindings` requires `typeshare` to be insta
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`. Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
# OTHER ## OTHER
## AniMe Matrix simulator ### AniMe Matrix simulator
A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop _with_ the display, the simulated display will be used instead of the physical display. A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop _with_ the display, the simulated display will be used instead of the physical display.
## Supporting more laptops ### Supporting more laptops
Please file a support request. Please file a support request.
# License & Trademarks ## License & Trademarks
Mozilla Public License 2 (MPL-2.0) Mozilla Public License 2 (MPL-2.0)
+8 -5
View File
@@ -21,11 +21,14 @@ fn main() {
let brightness = args[2].parse::<f32>().unwrap(); let brightness = args[2].parse::<f32>().unwrap();
let anime_type = get_anime_type(); let anime_type = get_anime_type();
let mut seq = Sequences::new(anime_type); let mut seq = Sequences::new(anime_type);
seq.insert(0, &ActionLoader::AsusAnimation { seq.insert(
file: path.into(), 0,
time: rog_anime::AnimTime::Infinite, &ActionLoader::AsusAnimation {
brightness, file: path.into(),
}) time: rog_anime::AnimTime::Infinite,
brightness,
},
)
.unwrap(); .unwrap();
loop { loop {
+2
View File
@@ -181,6 +181,7 @@ pub struct TwoColourSpeed {
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiZone { pub struct MultiZone {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -195,6 +196,7 @@ pub struct MultiZone {
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiColourSpeed { pub struct MultiColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
+10
View File
@@ -74,6 +74,16 @@ pub struct ProfileCommand {
#[options(meta = "", help = "set the active profile")] #[options(meta = "", help = "set the active profile")]
pub profile_set: Option<PlatformProfile>, pub profile_set: Option<PlatformProfile>,
#[options(short = "a", meta = "", help = "set the profile to use on AC power")]
pub profile_set_ac: Option<PlatformProfile>,
#[options(
short = "b",
meta = "",
help = "set the profile to use on battery power"
)]
pub profile_set_bat: Option<PlatformProfile>,
} }
#[derive(Options)] #[derive(Options)]
+18 -2
View File
@@ -979,7 +979,13 @@ fn handle_throttle_profile(
return Err(ProfileError::NotSupported.into()); return Err(ProfileError::NotSupported.into());
} }
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get { if !cmd.next
&& !cmd.list
&& cmd.profile_set.is_none()
&& !cmd.profile_get
&& cmd.profile_set_ac.is_none()
&& cmd.profile_set_bat.is_none()
{
if !cmd.help { if !cmd.help {
println!("Missing arg or command\n"); println!("Missing arg or command\n");
} }
@@ -999,6 +1005,10 @@ fn handle_throttle_profile(
proxy.set_platform_profile(PlatformProfile::next(current, &choices))?; proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
} else if let Some(profile) = cmd.profile_set { } else if let Some(profile) = cmd.profile_set {
proxy.set_platform_profile(profile)?; proxy.set_platform_profile(profile)?;
} else if let Some(profile) = cmd.profile_set_ac {
proxy.set_platform_profile_on_ac(profile)?;
} else if let Some(profile) = cmd.profile_set_bat {
proxy.set_platform_profile_on_battery(profile)?;
} }
if cmd.list { if cmd.list {
@@ -1009,6 +1019,11 @@ fn handle_throttle_profile(
if cmd.profile_get { if cmd.profile_get {
println!("Active profile is {current:?}"); println!("Active profile is {current:?}");
println!("Profile on AC is {:?}", proxy.platform_profile_on_ac()?);
println!(
"Profile on Battery is {:?}",
proxy.platform_profile_on_battery()?
);
} }
Ok(()) Ok(())
@@ -1169,9 +1184,10 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
Ok(()) Ok(())
} }
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)]
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
{ {
if cmd.free.is_empty() || cmd.free.len() % 2 != 0 || cmd.help { if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help {
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5"; const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
if cmd.free.len() % 2 != 0 { if cmd.free.len() % 2 != 0 {
println!( println!(
+187 -50
View File
@@ -1,12 +1,12 @@
use std::sync::Arc; use std::sync::Arc;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info}; use log::{debug, error, info};
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value}; use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value};
use zbus::{fdo, interface, Connection}; use zbus::{fdo, interface, Connection};
@@ -55,6 +55,25 @@ impl AsusArmouryAttribute {
String::from(self.attr.name()) String::from(self.attr.name())
} }
fn resolve_i32_value(refreshed: Option<i32>, cached: &AttrValue) -> i32 {
refreshed
.or(match cached {
AttrValue::Integer(i) => Some(*i),
_ => None,
})
.unwrap_or(-1)
}
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
let path = dbus_path_for_attr(self.attr.name());
let signal = SignalEmitter::new(connection, path)?;
self.min_value_changed(&signal).await?;
self.max_value_changed(&signal).await?;
self.scalar_increment_changed(&signal).await?;
self.current_value_changed(&signal).await?;
Ok(())
}
pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> { pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> {
let path = dbus_path_for_attr(self.attr.name()); let path = dbus_path_for_attr(self.attr.name());
connection connection
@@ -91,7 +110,8 @@ impl AsusArmouryAttribute {
.await; .await;
} else { } else {
info!( info!(
"inotify event stream failed for {} ({}). You can ignore this if unsupported", "inotify event stream failed for {} ({}). You can ignore this \
if unsupported",
name, $attr_str name, $attr_str
); );
} }
@@ -116,11 +136,40 @@ impl AsusArmouryAttribute {
} }
} }
#[derive(Clone, Default)]
pub struct ArmouryAttributeRegistry {
attrs: Vec<AsusArmouryAttribute>,
}
impl ArmouryAttributeRegistry {
pub fn push(&mut self, attr: AsusArmouryAttribute) {
self.attrs.push(attr);
}
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
let mut last_err: Option<RogError> = None;
for attr in &self.attrs {
if let Err(e) = attr.emit_limits(connection).await {
error!(
"Failed to emit updated limits for attribute '{}': {e:?}",
attr.attribute_name()
);
last_err = Some(e);
}
}
if let Some(err) = last_err {
Err(err)
} else {
Ok(())
}
}
}
impl crate::Reloadable for AsusArmouryAttribute { impl crate::Reloadable for AsusArmouryAttribute {
async fn reload(&mut self) -> Result<(), RogError> { async fn reload(&mut self) -> Result<(), RogError> {
info!("Reloading {}", self.attr.name()); info!("Reloading {}", self.attr.name());
let name: FirmwareAttribute = self.attr.name().into(); let name: FirmwareAttribute = self.attr.name().into();
if name.is_ppt() { if name.is_ppt() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
@@ -130,25 +179,31 @@ impl crate::Reloadable for AsusArmouryAttribute {
error!("Could not get power status: {e:?}"); error!("Could not get power status: {e:?}");
e e
}) })
.unwrap_or_default(); .unwrap_or_default()
let config = if power_plugged == 1 { == 1;
&self.config.lock().await.ac_profile_tunings
} else { let apply_value = {
&self.config.lock().await.dc_profile_tunings let config = self.config.lock().await;
config
.select_tunings_ref(power_plugged, profile)
.and_then(|tuning| {
if tuning.enabled {
tuning.group.get(&self.name()).copied()
} else {
None
}
})
}; };
if let Some(tuning) = config.get(&profile) {
if tuning.enabled { if let Some(tune) = apply_value {
if let Some(tune) = tuning.group.get(&self.name()) { self.attr
self.attr .set_current_value(&AttrValue::Integer(tune))
.set_current_value(&AttrValue::Integer(*tune)) .map_err(|e| {
.map_err(|e| { error!("Could not set {} value: {e:?}", self.attr.name());
error!("Could not set {} value: {e:?}", self.attr.name()); self.attr.base_path_exists();
self.attr.base_path_exists(); e
e })?;
})?; info!("Set {} to {:?}", self.attr.name(), tune);
info!("Set {} to {:?}", self.attr.name(), tune);
}
}
} }
} else { } else {
// Handle non-PPT attributes (boolean and other settings) // Handle non-PPT attributes (boolean and other settings)
@@ -160,7 +215,11 @@ impl crate::Reloadable for AsusArmouryAttribute {
self.attr.base_path_exists(); self.attr.base_path_exists();
e e
})?; })?;
info!("Restored armoury setting {} to {:?}", self.attr.name(), saved_value); info!(
"Restored armoury setting {} to {:?}",
self.attr.name(),
saved_value
);
} }
} }
@@ -251,26 +310,20 @@ impl AsusArmouryAttribute {
#[zbus(property)] #[zbus(property)]
async fn min_value(&self) -> i32 { async fn min_value(&self) -> i32 {
match self.attr.min_value() { Self::resolve_i32_value(self.attr.refresh_min_value(), self.attr.min_value())
AttrValue::Integer(i) => *i,
_ => -1,
}
} }
#[zbus(property)] #[zbus(property)]
async fn max_value(&self) -> i32 { async fn max_value(&self) -> i32 {
match self.attr.max_value() { Self::resolve_i32_value(self.attr.refresh_max_value(), self.attr.max_value())
AttrValue::Integer(i) => *i,
_ => -1,
}
} }
#[zbus(property)] #[zbus(property)]
async fn scalar_increment(&self) -> i32 { async fn scalar_increment(&self) -> i32 {
match self.attr.scalar_increment() { Self::resolve_i32_value(
AttrValue::Integer(i) => *i, self.attr.refresh_scalar_increment(),
_ => -1, self.attr.scalar_increment(),
} )
} }
#[zbus(property)] #[zbus(property)]
@@ -292,12 +345,15 @@ impl AsusArmouryAttribute {
error!("Could not get power status: {e:?}"); error!("Could not get power status: {e:?}");
e e
}) })
.unwrap_or_default(); .unwrap_or_default()
let mut config = self.config.lock().await; == 1;
let tuning = config.select_tunings(power_plugged == 1, profile); let config = self.config.lock().await;
if let Some(tune) = tuning.group.get(&self.name()) { if let Some(tuning) = config.select_tunings_ref(power_plugged, profile) {
return Ok(*tune); if let Some(tune) = tuning.group.get(&self.name()) {
} else if let AttrValue::Integer(i) = self.attr.default_value() { return Ok(*tune);
}
}
if let AttrValue::Integer(i) = self.attr.default_value() {
return Ok(*i); return Ok(*i);
} }
return Err(fdo::Error::Failed( return Err(fdo::Error::Failed(
@@ -313,6 +369,83 @@ impl AsusArmouryAttribute {
)) ))
} }
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
if !self.name().is_ppt() {
return Err(fdo::Error::NotSupported(
"Stored values are only available for PPT attributes".to_string(),
));
}
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let config = self.config.lock().await;
if let Some(tuning) = config.select_tunings_ref(on_ac, profile) {
if let Some(tune) = tuning.group.get(&self.name()) {
return Ok(*tune);
}
}
if let AttrValue::Integer(i) = self.attr.default_value() {
return Ok(*i);
}
Err(fdo::Error::Failed(
"Could not read stored value".to_string(),
))
}
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
if !self.name().is_ppt() {
return Err(fdo::Error::NotSupported(
"Setting stored values is only supported for PPT attributes".to_string(),
));
}
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let apply_now;
{
let mut config = self.config.lock().await;
let tuning = config.select_tunings(on_ac, profile);
if let Some(tune) = tuning.group.get_mut(&self.name()) {
*tune = value;
} else {
tuning.group.insert(self.name(), value);
debug!(
"Store {} value for {} power = {}",
self.attr.name(),
if on_ac { "AC" } else { "DC" },
value
);
}
apply_now = tuning.enabled;
config.write();
}
if apply_now {
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default()
!= 0;
if power_plugged == on_ac {
self.attr
.set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
}
}
Ok(())
}
#[zbus(property)] #[zbus(property)]
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> { async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
if self.name().is_ppt() { if self.name().is_ppt() {
@@ -388,7 +521,8 @@ pub async fn start_attributes_zbus(
power: AsusPower, power: AsusPower,
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
) -> Result<(), RogError> { ) -> Result<ArmouryAttributeRegistry, RogError> {
let mut registry = ArmouryAttributeRegistry::default();
for attr in attributes.attributes() { for attr in attributes.attributes() {
let mut attr = AsusArmouryAttribute::new( let mut attr = AsusArmouryAttribute::new(
attr.clone(), attr.clone(),
@@ -397,6 +531,8 @@ pub async fn start_attributes_zbus(
config.clone(), config.clone(),
); );
let registry_attr = attr.clone();
if let Err(e) = attr.reload().await { if let Err(e) = attr.reload().await {
error!( error!(
"Skipping attribute '{}' due to reload error: {e:?}", "Skipping attribute '{}' due to reload error: {e:?}",
@@ -412,24 +548,25 @@ pub async fn start_attributes_zbus(
match zbus::object_server::SignalEmitter::new(conn, path) { match zbus::object_server::SignalEmitter::new(conn, path) {
Ok(sig) => { Ok(sig) => {
if let Err(e) = attr.watch_and_notify(sig).await { if let Err(e) = attr.watch_and_notify(sig).await {
error!( error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
"Failed to start watcher for '{}': {e:?}",
attr.attr.name()
);
} }
} }
Err(e) => { Err(e) => {
error!("Failed to create SignalEmitter for '{}': {e:?}", attr.attr.name()); error!(
"Failed to create SignalEmitter for '{}': {e:?}",
attr.attr.name()
);
} }
} }
if let Err(e) = attr.move_to_zbus(conn).await { if let Err(e) = attr.move_to_zbus(conn).await {
error!( error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
"Failed to register attribute '{attr_name}' on zbus: {e:?}" continue;
);
} }
registry.push(registry_attr);
} }
Ok(()) Ok(registry)
} }
pub async fn set_config_or_default( pub async fn set_config_or_default(
+2 -2
View File
@@ -8,7 +8,6 @@ use std::sync::Arc;
use std::thread::sleep; use std::thread::sleep;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_anime::usb::{ use rog_anime::usb::{
pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim, pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim,
@@ -17,6 +16,7 @@ use rog_anime::usb::{
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType}; use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw; use rog_platform::usb_raw::USBRaw;
use tokio::sync::Mutex;
use self::config::{AniMeConfig, AniMeConfigCached}; use self::config::{AniMeConfig, AniMeConfigCached};
use crate::error::RogError; use crate::error::RogError;
@@ -51,7 +51,7 @@ impl AniMe {
/// Will fail if something is already holding the config lock /// Will fail if something is already holding the config lock
async fn do_init_cache(&mut self) { async fn do_init_cache(&mut self) {
if let Some(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
if let Err(e) = self.cache.init_from_config(&config, config.anime_type) { if let Err(e) = self.cache.init_from_config(&config, config.anime_type) {
error!( error!(
"Trying to cache the Anime Config failed, will reset to default config: {e:?}" "Trying to cache the Anime Config failed, will reset to default config: {e:?}"
+7 -7
View File
@@ -85,7 +85,7 @@ impl AniMeZbus {
/// Set base brightness level /// Set base brightness level
#[zbus(property)] #[zbus(property)]
async fn brightness(&self) -> Brightness { async fn brightness(&self) -> Brightness {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.display_brightness; return config.display_brightness;
} }
Brightness::Off Brightness::Off
@@ -117,7 +117,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn builtins_enabled(&self) -> bool { async fn builtins_enabled(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims_enabled; return config.builtin_anims_enabled;
} }
false false
@@ -162,7 +162,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn builtin_animations(&self) -> Animations { async fn builtin_animations(&self) -> Animations {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims; return config.builtin_anims;
} }
Animations::default() Animations::default()
@@ -195,7 +195,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn enable_display(&self) -> bool { async fn enable_display(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.display_enabled; return config.display_enabled;
} }
false false
@@ -218,7 +218,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_unplugged(&self) -> bool { async fn off_when_unplugged(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_unplugged; return config.off_when_unplugged;
} }
false false
@@ -245,7 +245,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_suspended(&self) -> bool { async fn off_when_suspended(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_suspended; return config.off_when_suspended;
} }
false false
@@ -261,7 +261,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_lid_closed(&self) -> bool { async fn off_when_lid_closed(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_lid_closed; return config.off_when_lid_closed;
} }
false false
+97 -55
View File
@@ -82,8 +82,9 @@ impl AuraConfig {
config config
.builtins .builtins
.insert(*n, AuraEffect::default_with_mode(*n)); .insert(*n, AuraEffect::default_with_mode(*n));
}
if !config.support_data.basic_zones.is_empty() { if !config.support_data.basic_zones.is_empty() {
for n in &config.support_data.basic_modes {
let mut default = vec![]; let mut default = vec![];
for (i, tmp) in config.support_data.basic_zones.iter().enumerate() { for (i, tmp) in config.support_data.basic_zones.iter().enumerate() {
default.push(AuraEffect { default.push(AuraEffect {
@@ -118,14 +119,14 @@ impl AuraConfig {
self.multizone_on = false; self.multizone_on = false;
} else { } else {
if let Some(multi) = self.multizone.as_mut() { if let Some(multi) = self.multizone.as_mut() {
if let Some(fx) = multi.get_mut(effect.mode()) { if let Some(fx_vec) = multi.get_mut(effect.mode()) {
for fx in fx.iter_mut() { for fx in fx_vec.iter_mut() {
if fx.zone == effect.zone { if fx.zone == effect.zone {
*fx = effect; *fx = effect;
return; return;
} }
} }
fx.push(effect); fx_vec.push(effect);
} else { } else {
multi.insert(*effect.mode(), vec![effect]); multi.insert(*effect.mode(), vec![effect]);
} }
@@ -230,6 +231,8 @@ impl AuraConfig {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::{Mutex, MutexGuard, OnceLock};
use rog_aura::keyboard::AuraPowerState; use rog_aura::keyboard::AuraPowerState;
use rog_aura::{ use rog_aura::{
AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed, AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed,
@@ -237,8 +240,20 @@ mod tests {
use super::AuraConfig; use super::AuraConfig;
// Global mutex to serialize tests that rely on process-wide environment
// variables
static TEST_MUTEX: OnceLock<Mutex<()>> = OnceLock::new();
fn test_lock() -> MutexGuard<'static, ()> {
TEST_MUTEX
.get_or_init(|| Mutex::new(()))
.lock()
.expect("TEST_MUTEX poisoned")
}
#[test] #[test]
fn set_multizone_4key_config() { fn set_multizone_4key_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", ""); std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
@@ -294,30 +309,43 @@ mod tests {
let res = config.multizone.unwrap(); let res = config.multizone.unwrap();
let sta = res.get(&AuraModeNum::Static).unwrap(); let sta = res.get(&AuraModeNum::Static).unwrap();
assert_eq!(sta.len(), 4); assert_eq!(sta.len(), 4);
assert_eq!(sta[0].colour1, Colour { assert_eq!(
r: 0xff, sta[0].colour1,
g: 0x00, Colour {
b: 0xff r: 0xff,
}); g: 0x00,
assert_eq!(sta[1].colour1, Colour { b: 0xff
r: 0x00, }
g: 0xff, );
b: 0xff assert_eq!(
}); sta[1].colour1,
assert_eq!(sta[2].colour1, Colour { Colour {
r: 0xff, r: 0x00,
g: 0xff, g: 0xff,
b: 0x00 b: 0xff
}); }
assert_eq!(sta[3].colour1, Colour { );
r: 0x00, assert_eq!(
g: 0xff, sta[2].colour1,
b: 0x00 Colour {
}); r: 0xff,
g: 0xff,
b: 0x00
}
);
assert_eq!(
sta[3].colour1,
Colour {
r: 0x00,
g: 0xff,
b: 0x00
}
);
} }
#[test] #[test]
fn set_multizone_multimode_config() { fn set_multizone_multimode_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", ""); std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
@@ -366,51 +394,65 @@ mod tests {
#[test] #[test]
fn verify_0x1866_g531i() { fn verify_0x1866_g531i() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G513I"); std::env::set_var("BOARD_NAME", "G513I");
let mut config = AuraConfig::new("1866"); let mut config = AuraConfig::new("1866");
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 5); assert_eq!(config.builtins.len(), 5);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
mode: AuraModeNum::Static, config.builtins.first_entry().unwrap().get(),
zone: AuraZone::None, &AuraEffect {
colour1: Colour { r: 166, g: 0, b: 0 }, mode: AuraModeNum::Static,
colour2: Colour { r: 0, g: 0, b: 0 }, zone: AuraZone::None,
speed: Speed::Med, colour1: Colour { r: 166, g: 0, b: 0 },
direction: Direction::Right colour2: Colour { r: 0, g: 0, b: 0 },
}); speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 1); assert_eq!(config.enabled.states.len(), 1);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
zone: PowerZones::KeyboardAndLightbar, config.enabled.states[0],
boot: true, AuraPowerState {
awake: true, zone: PowerZones::KeyboardAndLightbar,
sleep: true, boot: true,
shutdown: true awake: true,
}); sleep: true,
shutdown: true
}
);
} }
#[test] #[test]
fn verify_0x19b6_g634j() { fn verify_0x19b6_g634j() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G634J"); std::env::set_var("BOARD_NAME", "G634J");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 12); assert_eq!(config.builtins.len(), 12);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
mode: AuraModeNum::Static, config.builtins.first_entry().unwrap().get(),
zone: AuraZone::None, &AuraEffect {
colour1: Colour { r: 166, g: 0, b: 0 }, mode: AuraModeNum::Static,
colour2: Colour { r: 0, g: 0, b: 0 }, zone: AuraZone::None,
speed: Speed::Med, colour1: Colour { r: 166, g: 0, b: 0 },
direction: Direction::Right colour2: Colour { r: 0, g: 0, b: 0 },
}); speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 4); assert_eq!(config.enabled.states.len(), 4);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
zone: PowerZones::Keyboard, config.enabled.states[0],
boot: true, AuraPowerState {
awake: true, zone: PowerZones::Keyboard,
sleep: true, boot: true,
shutdown: true awake: true,
}); sleep: true,
shutdown: true
}
);
} }
} }
+2 -2
View File
@@ -2,13 +2,13 @@ use std::sync::Arc;
use config::AuraConfig; use config::AuraConfig;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::{Mutex, MutexGuard};
use log::info; use log::info;
use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets}; use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets};
use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET}; use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET};
use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN}; use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardBacklight; use rog_platform::keyboard_led::KeyboardBacklight;
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
@@ -28,7 +28,7 @@ impl Aura {
Ok(()) Ok(())
} }
pub async fn lock_config(&self) -> MutexGuard<AuraConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, AuraConfig> {
self.config.lock().await self.config.lock().await
} }
+2 -2
View File
@@ -112,7 +112,7 @@ impl AuraZbus {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
// let ctrl = self.0.lock().await; // let ctrl = self.0.lock().await;
// Ok(config.current_mode) // Ok(config.current_mode)
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
Ok(config.current_mode) Ok(config.current_mode)
} else { } else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string())) Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
@@ -140,7 +140,7 @@ impl AuraZbus {
#[zbus(property)] #[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> { async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode; let mode = config.current_mode;
match config.builtins.get(&mode) { match config.builtins.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
+63 -12
View File
@@ -4,15 +4,16 @@
// - Add it to Zbus server // - Add it to Zbus server
// - If udev sees device removed then remove the zbus path // - If udev sees device removed then remove the zbus path
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use dmi_id::DMIID; use dmi_id::DMIID;
use futures_lite::future::block_on; use futures_lite::future::block_on;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use mio::{Events, Interest, Poll, Token}; use mio::{Events, Interest, Poll, Token};
use rog_platform::error::PlatformError; use rog_platform::error::PlatformError;
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use tokio::sync::Mutex;
use udev::{Device, MonitorBuilder}; use udev::{Device, MonitorBuilder};
use zbus::zvariant::{ObjectPath, OwnedObjectPath}; use zbus::zvariant::{ObjectPath, OwnedObjectPath};
use zbus::Connection; use zbus::Connection;
@@ -92,16 +93,39 @@ fn dev_prop_matches(dev: &Device, prop: &str, value: &str) -> bool {
pub struct AsusDevice { pub struct AsusDevice {
device: DeviceHandle, device: DeviceHandle,
dbus_path: OwnedObjectPath, dbus_path: OwnedObjectPath,
hid_key: Option<String>,
} }
pub struct DeviceManager { pub struct DeviceManager {
_dbus_connection: Connection, _dbus_connection: Connection,
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
} }
impl DeviceManager { impl DeviceManager {
#[allow(clippy::type_complexity)]
async fn get_or_create_hid_handle(
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
endpoint: &Device,
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
let dev_node = endpoint
.devnode()
.ok_or_else(|| RogError::MissingFunction("hidraw devnode missing".to_string()))?;
let key = dev_node.to_string_lossy().to_string();
if let Some(existing) = handles.lock().await.get(&key).cloned() {
return Ok((existing, key));
}
let hidraw = HidRaw::from_device(endpoint.clone())?;
let handle = Arc::new(Mutex::new(hidraw));
handles.lock().await.insert(key.clone(), handle.clone());
Ok((handle, key))
}
async fn init_hid_devices( async fn init_hid_devices(
connection: &Connection, connection: &Connection,
device: Device, device: Device,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> { ) -> Result<Vec<AsusDevice>, RogError> {
let mut devices = Vec::new(); let mut devices = Vec::new();
if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? { if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? {
@@ -116,9 +140,10 @@ impl DeviceManager {
// 1. Generate an interface path // 1. Generate an interface path
// 2. Create the device // 2. Create the device
// Use the top-level endpoint, not the parent // Use the top-level endpoint, not the parent
if let Ok(hidraw) = HidRaw::from_device(device) { if let Ok((dev, hid_key)) =
Self::get_or_create_hid_handle(&handles, &device).await
{
debug!("Testing device {usb_id:?}"); debug!("Testing device {usb_id:?}");
let dev = Arc::new(Mutex::new(hidraw));
// SLASH DEVICE // SLASH DEVICE
if let Ok(dev_type) = DeviceHandle::new_slash_hid( if let Ok(dev_type) = DeviceHandle::new_slash_hid(
dev.clone(), dev.clone(),
@@ -134,6 +159,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
@@ -152,6 +178,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
@@ -170,9 +197,12 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key),
}); });
} }
} }
} else {
warn!("Failed to initialise shared hid handle for {usb_id:?}");
} }
} }
} }
@@ -181,7 +211,10 @@ impl DeviceManager {
} }
/// To be called on daemon startup /// To be called on daemon startup
async fn init_all_hid(connection: &Connection) -> Result<Vec<AsusDevice>, RogError> { async fn init_all_hid(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> {
// track and ensure we use only one hidraw per prod_id // track and ensure we use only one hidraw per prod_id
// let mut interfaces = HashSet::new(); // let mut interfaces = HashSet::new();
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
@@ -200,7 +233,7 @@ impl DeviceManager {
.scan_devices() .scan_devices()
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))? .map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
{ {
devices.append(&mut Self::init_hid_devices(connection, device).await?); devices.append(&mut Self::init_hid_devices(connection, device, handles.clone()).await?);
} }
Ok(devices) Ok(devices)
@@ -228,6 +261,7 @@ impl DeviceManager {
return Some(AsusDevice { return Some(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -275,10 +309,13 @@ impl DeviceManager {
Ok(devices) Ok(devices)
} }
pub async fn find_all_devices(connection: &Connection) -> Vec<AsusDevice> { pub async fn find_all_devices(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Vec<AsusDevice> {
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
// HID first, always // HID first, always
if let Ok(devs) = &mut Self::init_all_hid(connection).await { if let Ok(devs) = &mut Self::init_all_hid(connection, handles.clone()).await {
devices.append(devs); devices.append(devs);
} }
// USB after, need to check if HID picked something up and if so, skip it // USB after, need to check if HID picked something up and if so, skip it
@@ -306,6 +343,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} else { } else {
@@ -328,6 +366,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -355,6 +394,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -370,16 +410,19 @@ impl DeviceManager {
pub async fn new(connection: Connection) -> Result<Self, RogError> { pub async fn new(connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone(); let conn_copy = connection.clone();
let devices = Self::find_all_devices(&conn_copy).await; let hid_handles = Arc::new(Mutex::new(HashMap::new()));
let devices = Self::find_all_devices(&conn_copy, hid_handles.clone()).await;
info!("Found {} valid devices on startup", devices.len()); info!("Found {} valid devices on startup", devices.len());
let devices = Arc::new(Mutex::new(devices)); let devices = Arc::new(Mutex::new(devices));
let manager = Self { let manager = Self {
_dbus_connection: connection, _dbus_connection: connection,
_hid_handles: hid_handles.clone(),
}; };
// TODO: The /sysfs/ LEDs don't cause events, so they need to be manually // TODO: The /sysfs/ LEDs don't cause events, so they need to be manually
// checked for and added // checked for and added
let hid_handles_thread = hid_handles.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut monitor = MonitorBuilder::new()?.listen()?; let mut monitor = MonitorBuilder::new()?.listen()?;
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
@@ -408,6 +451,7 @@ impl DeviceManager {
let devices = devices.clone(); let devices = devices.clone();
let conn_copy = conn_copy.clone(); let conn_copy = conn_copy.clone();
let hid_handles = hid_handles_thread.clone();
block_on(async move { block_on(async move {
// SCSCI devs // SCSCI devs
if subsys == "block" { if subsys == "block" {
@@ -483,6 +527,7 @@ impl DeviceManager {
// Iter in reverse so as to not screw up indexing // Iter in reverse so as to not screw up indexing
for index in removals.iter().rev() { for index in removals.iter().rev() {
let dev = devices.lock().await.remove(*index); let dev = devices.lock().await.remove(*index);
let hid_key = dev.hid_key.clone();
let path = path.clone(); let path = path.clone();
let res = match dev.device { let res = match dev.device {
DeviceHandle::Aura(_) => { DeviceHandle::Aura(_) => {
@@ -512,14 +557,20 @@ impl DeviceManager {
_ => todo!(), _ => todo!(),
}; };
info!("AuraManager removed: {path:?}, {res}"); info!("AuraManager removed: {path:?}, {res}");
if let Some(key) = hid_key {
hid_handles.lock().await.remove(&key);
}
} }
} }
} else if action == "add" { } else if action == "add" {
let evdev = event.device(); let evdev = event.device();
if let Ok(mut new_devs) = if let Ok(mut new_devs) = Self::init_hid_devices(
Self::init_hid_devices(&conn_copy, evdev) &conn_copy,
.await evdev,
.map_err(|e| error!("Couldn't add new device: {e:?}")) hid_handles.clone(),
)
.await
.map_err(|e| error!("Couldn't add new device: {e:?}"))
{ {
devices.lock().await.append(&mut new_devs); devices.lock().await.append(&mut new_devs);
} }
+2 -2
View File
@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use config::ScsiConfig; use config::ScsiConfig;
use futures_util::lock::{Mutex, MutexGuard};
use rog_scsi::{AuraEffect, Device, Task}; use rog_scsi::{AuraEffect, Device, Task};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
@@ -20,7 +20,7 @@ impl ScsiAura {
Self { device, config } Self { device, config }
} }
pub async fn lock_config(&self) -> MutexGuard<ScsiConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, ScsiConfig> {
self.config.lock().await self.config.lock().await
} }
+1 -1
View File
@@ -83,7 +83,7 @@ impl ScsiZbus {
#[zbus(property)] #[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> { async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode; let mode = config.current_mode;
match config.modes.get(&mode) { match config.modes.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
+2 -2
View File
@@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use config::SlashConfig; use config::SlashConfig;
use futures_util::lock::{Mutex, MutexGuard};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw; use rog_platform::usb_raw::USBRaw;
use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode}; use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
@@ -27,7 +27,7 @@ impl Slash {
Self { hid, usb, config } Self { hid, usb, config }
} }
pub async fn lock_config(&self) -> MutexGuard<SlashConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, SlashConfig> {
self.config.lock().await self.config.lock().await
} }
+1 -1
View File
@@ -1,7 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use futures_util::lock::Mutex;
use log::{debug, error, info}; use log::{debug, error, info};
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_anime::usb::get_anime_type; use rog_anime::usb::get_anime_type;
@@ -13,6 +12,7 @@ use rog_platform::usb_raw::USBRaw;
use rog_scsi::{open_device, ScsiType}; use rog_scsi::{open_device, ScsiType};
use rog_slash::error::SlashError; use rog_slash::error::SlashError;
use rog_slash::SlashType; use rog_slash::SlashType;
use tokio::sync::Mutex;
use crate::aura_anime::config::AniMeConfig; use crate::aura_anime::config::AniMeConfig;
use crate::aura_anime::AniMe; use crate::aura_anime::AniMe;
+20 -2
View File
@@ -67,6 +67,19 @@ impl Config {
}; };
config.entry(profile).or_insert_with(Tuning::default) config.entry(profile).or_insert_with(Tuning::default)
} }
pub fn select_tunings_ref(
&self,
power_plugged: bool,
profile: PlatformProfile,
) -> Option<&Tuning> {
let config = if power_plugged {
&self.ac_profile_tunings
} else {
&self.dc_profile_tunings
};
config.get(&profile)
}
} }
impl Default for Config { impl Default for Config {
@@ -146,7 +159,7 @@ pub struct Config611 {
impl From<Config611> for Config { impl From<Config611> for Config {
fn from(c: Config611) -> Self { fn from(c: Config611) -> Self {
Self { let mut config = Self {
// Restore the base charge limit // Restore the base charge limit
charge_control_end_threshold: c.charge_control_end_threshold, charge_control_end_threshold: c.charge_control_end_threshold,
base_charge_control_end_threshold: c.charge_control_end_threshold, base_charge_control_end_threshold: c.charge_control_end_threshold,
@@ -168,7 +181,12 @@ impl From<Config611> for Config {
armoury_settings: HashMap::default(), armoury_settings: HashMap::default(),
screenpad_gamma: None, screenpad_gamma: None,
screenpad_sync_primary: Default::default(), screenpad_sync_primary: Default::default(),
} };
config.ac_profile_tunings = c.ac_profile_tunings;
config.dc_profile_tunings = c.dc_profile_tunings;
config.armoury_settings = c.armoury_settings;
config
} }
} }
+2 -2
View File
@@ -2,9 +2,9 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{info, warn}; use log::{info, warn};
use rog_platform::backlight::{Backlight, BacklightType}; use rog_platform::backlight::{Backlight, BacklightType};
use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr; use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
@@ -13,7 +13,7 @@ use crate::config::Config;
use crate::error::RogError; use crate::error::RogError;
use crate::ASUS_ZBUS_PATH; use crate::ASUS_ZBUS_PATH;
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct CtrlBacklight { pub struct CtrlBacklight {
backlights: Vec<Backlight>, backlights: Vec<Backlight>,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
+1 -1
View File
@@ -3,13 +3,13 @@ use std::sync::Arc;
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use futures_lite::StreamExt; use futures_lite::StreamExt;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_profiles::error::ProfileError; use rog_profiles::error::ProfileError;
use rog_profiles::fan_curve_set::CurveData; use rog_profiles::fan_curve_set::CurveData;
use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles}; use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
+85 -13
View File
@@ -3,17 +3,17 @@ use std::process::Command;
use std::sync::Arc; use std::sync::Arc;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes};
use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP}; use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP};
use rog_platform::platform::{PlatformProfile, Properties, RogPlatform}; use rog_platform::platform::{PlatformProfile, Properties, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr; use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
use crate::asus_armoury::set_config_or_default; use crate::asus_armoury::{set_config_or_default, ArmouryAttributeRegistry};
use crate::config::Config; use crate::config::Config;
use crate::error::RogError; use crate::error::RogError;
use crate::{task_watch_item, CtrlTask, ReloadAndNotify}; use crate::{task_watch_item, CtrlTask, ReloadAndNotify};
@@ -46,9 +46,12 @@ pub struct CtrlPlatform {
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
cpu_control: Option<CPUControl>, cpu_control: Option<CPUControl>,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
connection: Connection,
armoury_registry: ArmouryAttributeRegistry,
} }
impl CtrlPlatform { impl CtrlPlatform {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
@@ -56,6 +59,8 @@ impl CtrlPlatform {
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
config_path: &Path, config_path: &Path,
signal_context: SignalEmitter<'static>, signal_context: SignalEmitter<'static>,
connection: Connection,
armoury_registry: ArmouryAttributeRegistry,
) -> Result<Self, RogError> { ) -> Result<Self, RogError> {
let config1 = config.clone(); let config1 = config.clone();
let config_path = config_path.to_owned(); let config_path = config_path.to_owned();
@@ -68,6 +73,8 @@ impl CtrlPlatform {
cpu_control: CPUControl::new() cpu_control: CPUControl::new()
.map_err(|e| error!("Couldn't get CPU control sysfs: {e}")) .map_err(|e| error!("Couldn't get CPU control sysfs: {e}"))
.ok(), .ok(),
connection,
armoury_registry,
}; };
let mut inotify_self = ret_self.clone(); let mut inotify_self = ret_self.clone();
@@ -161,7 +168,7 @@ impl CtrlPlatform {
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect() .collect()
}; };
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(&prog[0]); let mut cmd = Command::new(&prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(arg); cmd.arg(arg);
@@ -288,16 +295,39 @@ impl CtrlPlatform {
#[zbus(property)] #[zbus(property)]
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> { fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
let limit = self.power.get_charge_control_end_threshold()?; if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let limit = self.power.get_charge_control_end_threshold().map_err(|e| {
FdoErr::Failed(format!(
"Could not read charge_control_end_threshold: {e:?}"
))
})?;
Ok(limit) Ok(limit)
} }
#[zbus(property)] #[zbus(property)]
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> { async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
if !(20..=100).contains(&limit) { if !(20..=100).contains(&limit) {
return Err(RogError::ChargeLimit(limit))?; return Err(RogError::ChargeLimit(limit))?;
} }
self.power.set_charge_control_end_threshold(limit)?;
self.power
.set_charge_control_end_threshold(limit)
.map_err(|e| {
FdoErr::Failed(format!("Could not set charge_control_end_threshold: {e:?}"))
})?;
self.config.lock().await.charge_control_end_threshold = limit; self.config.lock().await.charge_control_end_threshold = limit;
self.config.lock().await.base_charge_control_end_threshold = limit; self.config.lock().await.base_charge_control_end_threshold = limit;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -305,12 +335,22 @@ impl CtrlPlatform {
} }
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> { async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let base_limit = std::mem::replace( let base_limit = std::mem::replace(
&mut self.config.lock().await.charge_control_end_threshold, &mut self.config.lock().await.charge_control_end_threshold,
100, 100,
); );
if base_limit != 100 { if base_limit != 100 {
self.power.set_charge_control_end_threshold(100)?; self.power
.set_charge_control_end_threshold(100)
.map_err(|e| {
FdoErr::Failed(format!("Could not set one_shot_full_charge: {e:?}"))
})?;
self.config.lock().await.base_charge_control_end_threshold = base_limit; self.config.lock().await.base_charge_control_end_threshold = base_limit;
self.config.lock().await.write(); self.config.lock().await.write();
} }
@@ -729,6 +769,31 @@ impl CtrlTask for CtrlPlatform {
} }
if !sleeping { if !sleeping {
platform1.run_ac_or_bat_cmd(power_plugged > 0).await; platform1.run_ac_or_bat_cmd(power_plugged > 0).await;
if let Ok(profile) =
platform1.platform.get_platform_profile().map(|p| p.into())
{
let attrs = FirmwareAttributes::new();
{
let mut cfg = platform1.config.lock().await;
set_config_or_default(
&attrs,
&mut cfg,
power_plugged > 0,
profile,
)
.await;
}
if let Err(e) = platform1
.armoury_registry
.emit_limits(&platform1.connection)
.await
{
error!(
"Failed to emit armoury updates after power change: \
{e:?}"
);
}
}
} }
platform1.config.lock().await.last_power_plugged = power_plugged; platform1.config.lock().await.last_power_plugged = power_plugged;
} }
@@ -789,13 +854,17 @@ impl CtrlTask for CtrlPlatform {
{ {
// TODO: manage this better, shouldn't need to create every time // TODO: manage this better, shouldn't need to create every time
let attrs = FirmwareAttributes::new(); let attrs = FirmwareAttributes::new();
set_config_or_default( {
&attrs, let mut cfg = platform3.config.lock().await;
&mut *platform3.config.lock().await, set_config_or_default(&attrs, &mut cfg, power_plugged, profile).await;
power_plugged, }
profile, if let Err(e) = platform3
) .armoury_registry
.await; .emit_limits(&platform3.connection)
.await
{
error!("Failed to emit armoury updates after AC/DC toggle: {e:?}");
}
platform3 platform3
.enable_ppt_group_changed(&signal_ctxt_copy) .enable_ppt_group_changed(&signal_ctxt_copy)
.await .await
@@ -852,6 +921,9 @@ impl CtrlTask for CtrlPlatform {
profile, profile,
) )
.await; .await;
if let Err(e) = ctrl.armoury_registry.emit_limits(&ctrl.connection).await {
error!("Failed to emit armoury updates after profile change: {e:?}");
}
} }
} }
} }
+25 -6
View File
@@ -3,7 +3,7 @@ use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use ::zbus::Connection; use ::zbus::Connection;
use asusd::asus_armoury::start_attributes_zbus; use asusd::asus_armoury::{start_attributes_zbus, ArmouryAttributeRegistry};
use asusd::aura_manager::DeviceManager; use asusd::aura_manager::DeviceManager;
use asusd::config::Config; use asusd::config::Config;
use asusd::ctrl_backlight::CtrlBacklight; use asusd::ctrl_backlight::CtrlBacklight;
@@ -11,15 +11,17 @@ use asusd::ctrl_fancurves::CtrlFanCurveZbus;
use asusd::ctrl_platform::CtrlPlatform; use asusd::ctrl_platform::CtrlPlatform;
use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME}; use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME};
use config_traits::{StdConfig, StdConfigLoad2}; use config_traits::{StdConfig, StdConfigLoad2};
use futures_util::lock::Mutex;
use log::{error, info}; use log::{error, info};
use rog_platform::asus_armoury::FirmwareAttributes; use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::RogPlatform; use rog_platform::platform::RogPlatform;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use tokio::sync::Mutex;
use zbus::fdo::ObjectManager; use zbus::fdo::ObjectManager;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Starting asusd daemon...");
// console_subscriber::init(); // console_subscriber::init();
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
@@ -74,7 +76,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let platform = RogPlatform::new()?; // TODO: maybe needs async mutex? let platform = RogPlatform::new()?; // TODO: maybe needs async mutex?
let power = AsusPower::new()?; // TODO: maybe needs async mutex? let power = AsusPower::new()?; // TODO: maybe needs async mutex?
let attributes = FirmwareAttributes::new(); let attributes = FirmwareAttributes::new();
if let Err(e) = start_attributes_zbus( let armoury_registry = match start_attributes_zbus(
&server, &server,
platform.clone(), platform.clone(),
power.clone(), power.clone(),
@@ -83,13 +85,22 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
) )
.await .await
{ {
error!("Failed to initialize firmware attributes over zbus: {e:?}"); Ok(registry) => {
} info!("attribute on zbus initialized");
registry
}
Err(e) => {
error!("Failed to initialize firmware attributes over zbus: {e:?}");
ArmouryAttributeRegistry::default()
}
};
match CtrlFanCurveZbus::new() { match CtrlFanCurveZbus::new() {
Ok(ctrl) => { Ok(ctrl) => {
info!("FanCurves: found supported fancurves");
let sig_ctx = CtrlFanCurveZbus::signal_context(&server)?; let sig_ctx = CtrlFanCurveZbus::signal_context(&server)?;
start_tasks(ctrl, &mut server, sig_ctx).await?; start_tasks(ctrl, &mut server, sig_ctx).await?;
info!("FanCurves: initialized");
} }
Err(err) => { Err(err) => {
error!("FanCurves: {}", err); error!("FanCurves: {}", err);
@@ -98,8 +109,10 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
match CtrlBacklight::new(config.clone()) { match CtrlBacklight::new(config.clone()) {
Ok(backlight) => { Ok(backlight) => {
info!("Backlight: found supported backlight");
backlight.start_watch_primary().await?; backlight.start_watch_primary().await?;
backlight.add_to_server(&mut server).await; backlight.add_to_server(&mut server).await;
info!("Backlight: initialized");
} }
Err(err) => { Err(err) => {
error!("Backlight: {}", err); error!("Backlight: {}", err);
@@ -113,10 +126,14 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
config.clone(), config.clone(),
&cfg_path, &cfg_path,
CtrlPlatform::signal_context(&server)?, CtrlPlatform::signal_context(&server)?,
server.clone(),
armoury_registry,
) { ) {
Ok(ctrl) => { Ok(ctrl) => {
info!("CtrlPlatform: initialized");
let sig_ctx = CtrlPlatform::signal_context(&server)?; let sig_ctx = CtrlPlatform::signal_context(&server)?;
start_tasks(ctrl, &mut server, sig_ctx).await?; start_tasks(ctrl, &mut server, sig_ctx).await?;
info!("CtrlPlatform: tasks started");
} }
Err(err) => { Err(err) => {
error!("CtrlPlatform: {}", err); error!("CtrlPlatform: {}", err);
@@ -125,10 +142,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let _ = DeviceManager::new(server.clone()).await?; let _ = DeviceManager::new(server.clone()).await?;
info!("DeviceManager initialized");
// Request dbus name after finishing initalizing all functions // Request dbus name after finishing initalizing all functions
server.request_name(DBUS_NAME).await?; server.request_name(DBUS_NAME).await?;
info!("Startup success, begining dbus server loop"); info!("Startup success on dbus name {DBUS_NAME}: begining dbus server loop");
loop { loop {
// This is just a blocker to idle and ensure the reator reacts // This is just a blocker to idle and ensure the reator reacts
server.executor().tick().await; server.executor().tick().await;
+3 -2
View File
@@ -9,12 +9,13 @@ ENV{DMI_FAMILY}=="*Strix*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*Vivo*ook*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*Vivo*ook*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*Zenbook*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*Zenbook*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*TX Air*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
# No match so # No match so
GOTO="asusd_end" GOTO="asusd_end"
LABEL="asusd_start" LABEL="asusd_start"
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service" ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", RUN+="/usr/bin/systemctl restart asusd.service" ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
LABEL="asusd_end" LABEL="asusd_end"
+4 -1
View File
@@ -6,7 +6,10 @@ After=nvidia-powerd.service systemd-udevd.service
[Service] [Service]
Environment=IS_SERVICE=1 Environment=IS_SERVICE=1
Environment=RUST_LOG="debug" # Reduce noisy span logs while keeping useful debug info for asusd and related crates.
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error"
# required to prevent init issues with hid_asus and MCU # required to prevent init issues with hid_asus and MCU
ExecStartPre=/bin/sleep 1 ExecStartPre=/bin/sleep 1
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd
+4 -2
View File
@@ -20,7 +20,7 @@
%global debug_package %{nil} %global debug_package %{nil}
%endif %endif
%define version 6.1.13 %define version 6.1.18
%define specrelease %{?dist} %define specrelease %{?dist}
%define pkg_release 9%{specrelease} %define pkg_release 9%{specrelease}
@@ -92,7 +92,9 @@ EOF
%build %build
export RUSTFLAGS="%{rustflags}" export RUSTFLAGS="%{rustflags}"
%if %{defined fedora} %if %{defined fedora}
%cargo_build %# Use an explicit cargo invocation for Fedora to avoid the macro adding `--locked`.
%# `--locked` breaks Fedora builds because the lockfile may not be appropriate for the distro buildroot.
/usr/bin/cargo auditable build --release
%else %else
/usr/bin/cargo auditable build --release /usr/bin/cargo auditable build --release
%endif %endif
+3 -3
View File
@@ -169,7 +169,7 @@ impl AnimeImage {
// first 5 rows for GA401 are always at X = 0 // first 5 rows for GA401 are always at X = 0
return 0; return 0;
} }
(y + 1) / 2 - 3 y.div_ceil(2) - 3
} }
AnimeType::GU604 => { AnimeType::GU604 => {
// first 9 rows start at zero // first 9 rows start at zero
@@ -185,7 +185,7 @@ impl AnimeImage {
return 0; return 0;
} }
// and then their offset grows by one every two rows // and then their offset grows by one every two rows
(y + 1) / 2 - 5 y.div_ceil(2) - 5
} }
} }
} }
@@ -213,7 +213,7 @@ impl AnimeImage {
// First 5 rows for GA401 are always 33 physical LEDs long // First 5 rows for GA401 are always 33 physical LEDs long
return 33; return 33;
} }
36 - (y + 1) / 2 36 - y.div_ceil(2)
} }
AnimeType::GU604 => { AnimeType::GU604 => {
if y <= 9 { if y <= 9 {
+109 -64
View File
@@ -5,7 +5,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -14,7 +14,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle], basic_modes: [Static, Breathe, RainbowCycle],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -23,7 +23,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -32,7 +32,7 @@
layout_name: "fa507", layout_name: "fa507",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -41,7 +41,16 @@
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617XS",
product_id: "",
layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -50,7 +59,7 @@
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -59,7 +68,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -68,7 +77,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -77,7 +86,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -86,7 +95,16 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FX607J",
product_id: "",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -95,7 +113,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -104,16 +122,16 @@
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
device_name: "FX706H", device_name: "FX706H",
product_id: "", product_id: "",
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle], basic_modes: [Static, Breathe, RainbowCycle],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -122,7 +140,7 @@
layout_name: "g512", layout_name: "g512",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -140,7 +158,7 @@
layout_name: "g513i", layout_name: "g513i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -185,7 +203,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -194,7 +212,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -233,13 +251,31 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "G614FR",
product_id: "",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G614J", device_name: "G614J",
product_id: "", product_id: "",
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar],
),
(
device_name: "G614JIR",
product_id: "",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -248,7 +284,7 @@
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -257,7 +293,7 @@
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -275,7 +311,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -284,7 +320,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -293,7 +329,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -302,7 +338,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -311,7 +347,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -320,7 +356,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -329,7 +365,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -365,7 +401,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -383,7 +419,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight], basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -401,7 +437,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -410,7 +446,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -419,7 +455,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -482,7 +518,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -491,7 +527,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -500,7 +536,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -509,7 +545,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -518,7 +554,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -527,7 +563,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -536,7 +572,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -545,7 +581,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -554,7 +590,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -563,7 +599,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -572,7 +608,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -590,7 +626,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -599,7 +635,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -608,7 +644,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight], basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -626,7 +662,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -635,7 +671,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -644,7 +680,7 @@
layout_name: "fa507", layout_name: "fa507",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -692,6 +728,15 @@
advanced_type: Zoned([SingleZone]), advanced_type: Zoned([SingleZone]),
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "GU605C",
product_id: "",
layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [],
advanced_type: Zoned([SingleZone]),
power_zones: [Keyboard],
),
( (
device_name: "GU605M", device_name: "GU605M",
product_id: "", product_id: "",
@@ -707,7 +752,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -716,7 +761,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -725,7 +770,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -734,7 +779,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -752,7 +797,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -770,7 +815,7 @@
layout_name: "gx531-per-key", layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -824,7 +869,7 @@
layout_name: "gx531-per-key", layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -833,7 +878,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -842,7 +887,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -851,8 +896,8 @@
layout_name: "", layout_name: "",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [None], power_zones: [r#None],
), ),
( (
device_name: "GZ301Z", device_name: "GZ301Z",
@@ -860,7 +905,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -869,7 +914,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
( (
@@ -878,7 +923,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
]) ])
+5 -3
View File
@@ -207,12 +207,14 @@ mod tests {
fn single_key_next_state_then_create() { fn single_key_next_state_then_create() {
let layout = KeyLayout::default_layout(); let layout = KeyLayout::default_layout();
let mut seq = AdvancedEffects::new(false); let mut seq = AdvancedEffects::new(false);
seq.effects seq.effects.push(Effect::Static(Static::new(
.push(Effect::Static(Static::new(LedCode::F, Colour { LedCode::F,
Colour {
r: 255, r: 255,
g: 127, g: 127,
b: 0, b: 0,
}))); },
)));
seq.next_state(&layout); seq.next_state(&layout);
let packets = seq.create_packets(); let packets = seq.create_packets();
+111 -87
View File
@@ -335,93 +335,117 @@ impl KeyLayout {
KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1), KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1),
)]), )]),
key_rows: vec![ key_rows: vec![
KeyRow::new(0.1, 0.1, vec![ KeyRow::new(
(LedCode::Esc, "regular".to_owned()), 0.1,
(LedCode::F1, "regular".to_owned()), 0.1,
(LedCode::F2, "regular".to_owned()), vec![
(LedCode::F3, "regular".to_owned()), (LedCode::Esc, "regular".to_owned()),
(LedCode::F4, "regular".to_owned()), (LedCode::F1, "regular".to_owned()),
// not sure which key to put here (LedCode::F2, "regular".to_owned()),
(LedCode::F5, "regular".to_owned()), (LedCode::F3, "regular".to_owned()),
(LedCode::F6, "regular".to_owned()), (LedCode::F4, "regular".to_owned()),
(LedCode::F7, "regular".to_owned()), // not sure which key to put here
(LedCode::F8, "regular".to_owned()), (LedCode::F5, "regular".to_owned()),
(LedCode::F9, "regular".to_owned()), (LedCode::F6, "regular".to_owned()),
(LedCode::F10, "regular".to_owned()), (LedCode::F7, "regular".to_owned()),
(LedCode::F11, "regular".to_owned()), (LedCode::F8, "regular".to_owned()),
(LedCode::F12, "regular".to_owned()), (LedCode::F9, "regular".to_owned()),
]), (LedCode::F10, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::F11, "regular".to_owned()),
(LedCode::Tilde, "regular".to_owned()), (LedCode::F12, "regular".to_owned()),
(LedCode::N1, "regular".to_owned()), ],
(LedCode::N2, "regular".to_owned()), ),
(LedCode::N3, "regular".to_owned()), KeyRow::new(
(LedCode::N4, "regular".to_owned()), 0.1,
(LedCode::N5, "regular".to_owned()), 0.1,
(LedCode::N6, "regular".to_owned()), vec![
(LedCode::N7, "regular".to_owned()), (LedCode::Tilde, "regular".to_owned()),
(LedCode::N8, "regular".to_owned()), (LedCode::N1, "regular".to_owned()),
(LedCode::N9, "regular".to_owned()), (LedCode::N2, "regular".to_owned()),
(LedCode::N0, "regular".to_owned()), (LedCode::N3, "regular".to_owned()),
(LedCode::Hyphen, "regular".to_owned()), (LedCode::N4, "regular".to_owned()),
(LedCode::Equals, "regular".to_owned()), (LedCode::N5, "regular".to_owned()),
(LedCode::Backspace, "regular".to_owned()), (LedCode::N6, "regular".to_owned()),
]), (LedCode::N7, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::N8, "regular".to_owned()),
(LedCode::Tab, "regular".to_owned()), (LedCode::N9, "regular".to_owned()),
(LedCode::Q, "regular".to_owned()), (LedCode::N0, "regular".to_owned()),
(LedCode::W, "regular".to_owned()), (LedCode::Hyphen, "regular".to_owned()),
(LedCode::E, "regular".to_owned()), (LedCode::Equals, "regular".to_owned()),
(LedCode::R, "regular".to_owned()), (LedCode::Backspace, "regular".to_owned()),
(LedCode::T, "regular".to_owned()), ],
(LedCode::Y, "regular".to_owned()), ),
(LedCode::U, "regular".to_owned()), KeyRow::new(
(LedCode::I, "regular".to_owned()), 0.1,
(LedCode::O, "regular".to_owned()), 0.1,
(LedCode::P, "regular".to_owned()), vec![
(LedCode::LBracket, "regular".to_owned()), (LedCode::Tab, "regular".to_owned()),
(LedCode::RBracket, "regular".to_owned()), (LedCode::Q, "regular".to_owned()),
(LedCode::BackSlash, "regular".to_owned()), (LedCode::W, "regular".to_owned()),
]), (LedCode::E, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::R, "regular".to_owned()),
(LedCode::Caps, "regular".to_owned()), (LedCode::T, "regular".to_owned()),
(LedCode::A, "regular".to_owned()), (LedCode::Y, "regular".to_owned()),
(LedCode::S, "regular".to_owned()), (LedCode::U, "regular".to_owned()),
(LedCode::D, "regular".to_owned()), (LedCode::I, "regular".to_owned()),
(LedCode::F, "regular".to_owned()), (LedCode::O, "regular".to_owned()),
(LedCode::G, "regular".to_owned()), (LedCode::P, "regular".to_owned()),
(LedCode::H, "regular".to_owned()), (LedCode::LBracket, "regular".to_owned()),
(LedCode::J, "regular".to_owned()), (LedCode::RBracket, "regular".to_owned()),
(LedCode::K, "regular".to_owned()), (LedCode::BackSlash, "regular".to_owned()),
(LedCode::L, "regular".to_owned()), ],
(LedCode::SemiColon, "regular".to_owned()), ),
(LedCode::Quote, "regular".to_owned()), KeyRow::new(
(LedCode::Return, "regular".to_owned()), 0.1,
]), 0.1,
KeyRow::new(0.1, 0.1, vec![ vec![
(LedCode::LShift, "regular".to_owned()), (LedCode::Caps, "regular".to_owned()),
(LedCode::Z, "regular".to_owned()), (LedCode::A, "regular".to_owned()),
(LedCode::X, "regular".to_owned()), (LedCode::S, "regular".to_owned()),
(LedCode::C, "regular".to_owned()), (LedCode::D, "regular".to_owned()),
(LedCode::V, "regular".to_owned()), (LedCode::F, "regular".to_owned()),
(LedCode::B, "regular".to_owned()), (LedCode::G, "regular".to_owned()),
(LedCode::N, "regular".to_owned()), (LedCode::H, "regular".to_owned()),
(LedCode::M, "regular".to_owned()), (LedCode::J, "regular".to_owned()),
(LedCode::Comma, "regular".to_owned()), (LedCode::K, "regular".to_owned()),
(LedCode::Period, "regular".to_owned()), (LedCode::L, "regular".to_owned()),
(LedCode::FwdSlash, "regular".to_owned()), (LedCode::SemiColon, "regular".to_owned()),
(LedCode::Rshift, "regular".to_owned()), (LedCode::Quote, "regular".to_owned()),
]), (LedCode::Return, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ ],
(LedCode::LCtrl, "regular".to_owned()), ),
(LedCode::LFn, "regular".to_owned()), KeyRow::new(
(LedCode::Meta, "regular".to_owned()), 0.1,
(LedCode::LAlt, "regular".to_owned()), 0.1,
(LedCode::Spacebar, "regular".to_owned()), vec![
(LedCode::RAlt, "regular".to_owned()), (LedCode::LShift, "regular".to_owned()),
(LedCode::PrtSc, "regular".to_owned()), (LedCode::Z, "regular".to_owned()),
(LedCode::RCtrl, "regular".to_owned()), (LedCode::X, "regular".to_owned()),
]), (LedCode::C, "regular".to_owned()),
(LedCode::V, "regular".to_owned()),
(LedCode::B, "regular".to_owned()),
(LedCode::N, "regular".to_owned()),
(LedCode::M, "regular".to_owned()),
(LedCode::Comma, "regular".to_owned()),
(LedCode::Period, "regular".to_owned()),
(LedCode::FwdSlash, "regular".to_owned()),
(LedCode::Rshift, "regular".to_owned()),
],
),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::LCtrl, "regular".to_owned()),
(LedCode::LFn, "regular".to_owned()),
(LedCode::Meta, "regular".to_owned()),
(LedCode::LAlt, "regular".to_owned()),
(LedCode::Spacebar, "regular".to_owned()),
(LedCode::RAlt, "regular".to_owned()),
(LedCode::PrtSc, "regular".to_owned()),
(LedCode::RCtrl, "regular".to_owned()),
],
),
], ],
} }
} }
+1 -1
View File
@@ -12,7 +12,7 @@ edition.workspace = true
default = [] default = []
mocking = [] mocking = []
x11 = ["slint/backend-winit-x11"] x11 = ["slint/backend-winit-x11"]
# Requires RUSTFLAGS="--cfg tokio_unstable" # Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
tokio-debug = ["console-subscriber"] tokio-debug = ["console-subscriber"]
[dependencies] [dependencies]
+15 -5
View File
@@ -116,26 +116,26 @@ pub fn start_notifications(
if p == 0 && p != last_state { if p == 0 && p != last_state {
let prog: Vec<&str> = bat.split_whitespace().collect(); let prog: Vec<&str> = bat.split_whitespace().collect();
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(prog[0]); let mut cmd = Command::new(prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(*arg); cmd.arg(*arg);
} }
cmd.spawn() cmd.spawn()
.map_err(|e| error!("AC command error: {e:?}")) .map_err(|e| error!("Battery power command error: {e:?}"))
.ok(); .ok();
} }
} else if p != last_state { } else if p != last_state {
let prog: Vec<&str> = ac.split_whitespace().collect(); let prog: Vec<&str> = ac.split_whitespace().collect();
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(prog[0]); let mut cmd = Command::new(prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(*arg); cmd.arg(*arg);
} }
cmd.spawn() cmd.spawn()
.map_err(|e| error!("AC command error: {e:?}")) .map_err(|e| error!("AC power command error: {e:?}"))
.ok(); .ok();
} }
} }
@@ -203,11 +203,19 @@ pub fn start_notifications(
})?; })?;
let proxy_copy = proxy.clone(); let proxy_copy = proxy.clone();
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
let mut p = proxy.receive_notify_action().await?; let mut p = proxy.receive_notify_action().await?;
tokio::spawn(async move { tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_action"); info!("Started zbus signal thread: receive_notify_action");
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() {
// Respect user notification settings for gpu actions
if let Ok(cfg) = enabled_notifications_copy_action.lock() {
if !cfg.notifications.enabled || !cfg.notifications.receive_notify_gfx {
continue;
}
}
let action = out.action(); let action = out.action();
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default()); let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
match action { match action {
@@ -309,7 +317,9 @@ fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> R
//.hint(Hint::Resident(true)) //.hint(Hint::Resident(true))
.hint(Hint::Category("device".into())) .hint(Hint::Category("device".into()))
.urgency(Urgency::Critical) .urgency(Urgency::Critical)
.timeout(Timeout::Never) // For user-action notifications keep them visible if they require interaction
// but for non-interactive actions we prefer they auto-hide like other notifs.
.timeout(Timeout::Milliseconds(6000))
.icon("dialog-warning") .icon("dialog-warning")
.hint(Hint::Transient(true)); .hint(Hint::Transient(true));
+130 -115
View File
@@ -12,7 +12,7 @@ use slint::{ComponentHandle, Model, ModelRc, SharedString, VecModel};
use super::show_toast; use super::show_toast;
use crate::config::Config; use crate::config::Config;
use crate::zbus_proxies::find_iface_async; use crate::zbus_proxies::find_iface_async;
use crate::{set_ui_callbacks, set_ui_props_async, AttrMinMax, MainWindow, SystemPageData}; use crate::{set_ui_callbacks, AttrMinMax, MainWindow, SystemPageData};
const MINMAX: AttrMinMax = AttrMinMax { const MINMAX: AttrMinMax = AttrMinMax {
min: 0, min: 0,
@@ -40,6 +40,8 @@ pub fn setup_system_page(ui: &MainWindow, _config: Arc<Mutex<Config>>) {
ui.global::<SystemPageData>().set_platform_profile(-1); ui.global::<SystemPageData>().set_platform_profile(-1);
ui.global::<SystemPageData>().set_panel_overdrive(-1); ui.global::<SystemPageData>().set_panel_overdrive(-1);
ui.global::<SystemPageData>().set_boot_sound(-1); ui.global::<SystemPageData>().set_boot_sound(-1);
ui.global::<SystemPageData>().set_screen_auto_brightness(-1);
ui.global::<SystemPageData>().set_mcu_powersave(-1);
ui.global::<SystemPageData>().set_mini_led_mode(-1); ui.global::<SystemPageData>().set_mini_led_mode(-1);
ui.global::<SystemPageData>().set_screenpad_brightness(-1); ui.global::<SystemPageData>().set_screenpad_brightness(-1);
ui.global::<SystemPageData>().set_ppt_pl1_spl(MINMAX); ui.global::<SystemPageData>().set_ppt_pl1_spl(MINMAX);
@@ -308,6 +310,7 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
let platform_copy = platform.clone(); let platform_copy = platform.clone();
if let Ok(mut value) = platform.platform_profile_choices().await { if let Ok(mut value) = platform.platform_profile_choices().await {
debug!("Available platform profile choices: {:?}", value);
handle handle
.upgrade_in_event_loop(move |handle| { .upgrade_in_event_loop(move |handle| {
value.sort(); value.sort();
@@ -519,7 +522,7 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
set_ui_callbacks!(handle, set_ui_callbacks!(handle,
SystemPageData(as i32), SystemPageData(as i32),
platform_copy.platform_profile_on_battery(.into()), platform_copy.platform_profile_on_battery(.into()),
"Throttle policy on abttery set to {}", "Throttle policy on battery set to {}",
"Setting Throttle policy on battery failed" "Setting Throttle policy on battery failed"
); );
set_ui_callbacks!(handle, set_ui_callbacks!(handle,
@@ -572,120 +575,132 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
for attr in armoury_attrs { for attr in armoury_attrs {
if let Ok(value) = attr.current_value().await { if let Ok(value) = attr.current_value().await {
let name = attr.name().await.unwrap(); if let Ok(name) = attr.name().await {
debug!("Setting up {} = {value}", <&str>::from(name)); debug!("Setting up {} = {value}", <&str>::from(name));
let platform = platform.clone(); let platform = platform.clone();
handle handle
.upgrade_in_event_loop(move |handle| match name { .upgrade_in_event_loop(move |handle| match name {
FirmwareAttribute::ApuMem => {} FirmwareAttribute::ApuMem => {}
FirmwareAttribute::CoresPerformance => {} FirmwareAttribute::CoresPerformance => {}
FirmwareAttribute::CoresEfficiency => {} FirmwareAttribute::CoresEfficiency => {}
FirmwareAttribute::PptEnabled => { FirmwareAttribute::PptEnabled => {
init_property!(ppt_enabled, handle, value, bool); init_property!(ppt_enabled, handle, value, bool);
setup_callback!(ppt_enabled, handle, attr, bool); setup_callback!(ppt_enabled, handle, attr, bool);
let handle_copy = handle.as_weak(); let handle_copy = handle.as_weak();
let proxy_copy = attr.clone(); let proxy_copy = attr.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut x = proxy_copy.receive_current_value_changed().await; let mut x = proxy_copy.receive_current_value_changed().await;
use futures_util::StreamExt; use futures_util::StreamExt;
while let Some(e) = x.next().await { while let Some(e) = x.next().await {
if let Ok(out) = e.get().await { if let Ok(out) = e.get().await {
handle_copy handle_copy
.upgrade_in_event_loop(move |handle| { .upgrade_in_event_loop(move |handle| {
handle handle
.global::<SystemPageData>() .global::<SystemPageData>()
.set_enable_ppt_group(out == 1); .set_enable_ppt_group(out == 1);
handle handle
.global::<SystemPageData>() .global::<SystemPageData>()
.set_ppt_enabled(out == 1); .set_ppt_enabled(out == 1);
}) })
.ok(); .ok();
}
} }
} });
}); handle
handle .global::<SystemPageData>()
.global::<SystemPageData>() .set_ppt_enabled_available(true);
.set_ppt_enabled_available(true); handle
handle .global::<SystemPageData>()
.global::<SystemPageData>() .set_enable_ppt_group(value == 1);
.set_enable_ppt_group(value == 1); }
} FirmwareAttribute::PptPl1Spl => {
FirmwareAttribute::PptPl1Spl => { init_minmax_property!(ppt_pl1_spl, handle, attr);
init_minmax_property!(ppt_pl1_spl, handle, attr); setup_callback!(ppt_pl1_spl, handle, attr, i32);
setup_callback!(ppt_pl1_spl, handle, attr, i32); setup_callback_restore_default!(ppt_pl1_spl, handle, attr);
setup_callback_restore_default!(ppt_pl1_spl, handle, attr); setup_minmax_external!(ppt_pl1_spl, handle, attr, platform);
setup_minmax_external!(ppt_pl1_spl, handle, attr, platform); }
} FirmwareAttribute::PptPl2Sppt => {
FirmwareAttribute::PptPl2Sppt => { init_minmax_property!(ppt_pl2_sppt, handle, attr);
init_minmax_property!(ppt_pl2_sppt, handle, attr); setup_callback!(ppt_pl2_sppt, handle, attr, i32);
setup_callback!(ppt_pl2_sppt, handle, attr, i32); setup_callback_restore_default!(ppt_pl2_sppt, handle, attr);
setup_callback_restore_default!(ppt_pl2_sppt, handle, attr); setup_minmax_external!(ppt_pl2_sppt, handle, attr, platform);
setup_minmax_external!(ppt_pl2_sppt, handle, attr, platform); }
} FirmwareAttribute::PptPl3Fppt => {
FirmwareAttribute::PptPl3Fppt => { init_minmax_property!(ppt_pl3_fppt, handle, attr);
init_minmax_property!(ppt_pl3_fppt, handle, attr); setup_callback!(ppt_pl3_fppt, handle, attr, i32);
setup_callback!(ppt_pl3_fppt, handle, attr, i32); setup_callback_restore_default!(ppt_pl3_fppt, handle, attr);
setup_callback_restore_default!(ppt_pl3_fppt, handle, attr); setup_minmax_external!(ppt_pl3_fppt, handle, attr, platform);
setup_minmax_external!(ppt_pl3_fppt, handle, attr, platform); }
} FirmwareAttribute::PptFppt => {
FirmwareAttribute::PptFppt => { init_minmax_property!(ppt_fppt, handle, attr);
init_minmax_property!(ppt_fppt, handle, attr); setup_callback!(ppt_fppt, handle, attr, i32);
setup_callback!(ppt_fppt, handle, attr, i32); setup_callback_restore_default!(ppt_fppt, handle, attr);
setup_callback_restore_default!(ppt_fppt, handle, attr); setup_minmax_external!(ppt_fppt, handle, attr, platform);
setup_minmax_external!(ppt_fppt, handle, attr, platform); }
} FirmwareAttribute::PptApuSppt => {
FirmwareAttribute::PptApuSppt => { init_minmax_property!(ppt_apu_sppt, handle, attr);
init_minmax_property!(ppt_apu_sppt, handle, attr); setup_callback!(ppt_apu_sppt, handle, attr, i32);
setup_callback!(ppt_apu_sppt, handle, attr, i32); setup_callback_restore_default!(ppt_apu_sppt, handle, attr);
setup_callback_restore_default!(ppt_apu_sppt, handle, attr); setup_minmax_external!(ppt_apu_sppt, handle, attr, platform);
setup_minmax_external!(ppt_apu_sppt, handle, attr, platform); }
} FirmwareAttribute::PptPlatformSppt => {
FirmwareAttribute::PptPlatformSppt => { init_minmax_property!(ppt_platform_sppt, handle, attr);
init_minmax_property!(ppt_platform_sppt, handle, attr); setup_callback!(ppt_platform_sppt, handle, attr, i32);
setup_callback!(ppt_platform_sppt, handle, attr, i32); setup_callback_restore_default!(ppt_platform_sppt, handle, attr);
setup_callback_restore_default!(ppt_platform_sppt, handle, attr); setup_minmax_external!(ppt_platform_sppt, handle, attr, platform);
setup_minmax_external!(ppt_platform_sppt, handle, attr, platform); }
} FirmwareAttribute::NvDynamicBoost => {
FirmwareAttribute::NvDynamicBoost => { init_minmax_property!(nv_dynamic_boost, handle, attr);
init_minmax_property!(nv_dynamic_boost, handle, attr); setup_callback!(nv_dynamic_boost, handle, attr, i32);
setup_callback!(nv_dynamic_boost, handle, attr, i32); setup_callback_restore_default!(nv_dynamic_boost, handle, attr);
setup_callback_restore_default!(nv_dynamic_boost, handle, attr); setup_minmax_external!(nv_dynamic_boost, handle, attr, platform);
setup_minmax_external!(nv_dynamic_boost, handle, attr, platform); }
} FirmwareAttribute::NvTempTarget => {
FirmwareAttribute::NvTempTarget => { init_minmax_property!(nv_temp_target, handle, attr);
init_minmax_property!(nv_temp_target, handle, attr); setup_callback!(nv_temp_target, handle, attr, i32);
setup_callback!(nv_temp_target, handle, attr, i32); setup_callback_restore_default!(nv_temp_target, handle, attr);
setup_callback_restore_default!(nv_temp_target, handle, attr); setup_minmax_external!(nv_temp_target, handle, attr, platform);
setup_minmax_external!(nv_temp_target, handle, attr, platform); }
} FirmwareAttribute::DgpuBaseTgp => {}
FirmwareAttribute::DgpuBaseTgp => {} FirmwareAttribute::DgpuTgp => {}
FirmwareAttribute::DgpuTgp => {} FirmwareAttribute::ChargeMode => {}
FirmwareAttribute::ChargeMode => {} FirmwareAttribute::BootSound => {
FirmwareAttribute::BootSound => { init_property!(boot_sound, handle, value, i32);
init_property!(boot_sound, handle, value, i32); setup_callback!(boot_sound, handle, attr, i32);
setup_callback!(boot_sound, handle, attr, i32); setup_external!(boot_sound, i32, handle, attr, value)
setup_external!(boot_sound, i32, handle, attr, value) }
} FirmwareAttribute::ScreenAutoBrightness => {
FirmwareAttribute::McuPowersave => {} init_property!(screen_auto_brightness, handle, value, i32);
FirmwareAttribute::PanelOverdrive => { setup_callback!(screen_auto_brightness, handle, attr, i32);
init_property!(panel_overdrive, handle, value, i32); setup_external!(screen_auto_brightness, i32, handle, attr, value)
setup_callback!(panel_overdrive, handle, attr, i32); }
setup_external!(panel_overdrive, i32, handle, attr, value) FirmwareAttribute::McuPowersave => {
} init_property!(mcu_powersave, handle, value, i32);
FirmwareAttribute::PanelHdMode => {} setup_callback!(mcu_powersave, handle, attr, i32);
FirmwareAttribute::EgpuConnected => {} setup_external!(mcu_powersave, i32, handle, attr, value)
FirmwareAttribute::EgpuEnable => {} }
FirmwareAttribute::DgpuDisable => {} FirmwareAttribute::PanelOverdrive => {
FirmwareAttribute::GpuMuxMode => {} init_property!(panel_overdrive, handle, value, i32);
FirmwareAttribute::MiniLedMode => { setup_callback!(panel_overdrive, handle, attr, i32);
init_property!(mini_led_mode, handle, value, i32); setup_external!(panel_overdrive, i32, handle, attr, value)
setup_callback!(mini_led_mode, handle, attr, i32); }
setup_external!(mini_led_mode, i32, handle, attr, value); FirmwareAttribute::PanelHdMode => {}
} FirmwareAttribute::EgpuConnected => {}
FirmwareAttribute::PendingReboot => {} FirmwareAttribute::EgpuEnable => {}
FirmwareAttribute::None => {} FirmwareAttribute::DgpuDisable => {}
}) FirmwareAttribute::GpuMuxMode => {}
.ok(); FirmwareAttribute::MiniLedMode => {
init_property!(mini_led_mode, handle, value, i32);
setup_callback!(mini_led_mode, handle, attr, i32);
setup_external!(mini_led_mode, i32, handle, attr, value);
}
FirmwareAttribute::PendingReboot => {}
FirmwareAttribute::None => {}
})
.ok();
} else {
error!("Attribute with no name, skipping");
}
} }
} }
handle handle
+3 -1
View File
@@ -190,7 +190,9 @@ export component MainWindow inherits Window {
y: 0px; y: 0px;
width: root.width; width: root.width;
height: root.height; height: root.height;
padding: 10px;
//padding only has effect on layout elements
//padding: 10px;
background: Palette.background; background: Palette.background;
border-color: Palette.border; border-color: Palette.border;
+2 -1
View File
@@ -37,7 +37,8 @@ export component PageAnime inherits Rectangle {
property <bool> show_builtin_advanced: false; property <bool> show_builtin_advanced: false;
clip: true; clip: true;
// TODO: slow with border-radius // TODO: slow with border-radius
padding: 8px; //padding only has effect on layout elements
//padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2; // height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px; // TODO: border-radius: 8px;
VerticalLayout { VerticalLayout {
@@ -16,7 +16,9 @@ export component PageAppSettings inherits VerticalLayout {
Rectangle { Rectangle {
clip: true; clip: true;
// TODO: slow with border-radius // TODO: slow with border-radius
padding: 8px; //padding only has effect on layout elements
//padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2; // height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px; // TODO: border-radius: 8px;
mainview := VerticalLayout { mainview := VerticalLayout {
+6 -3
View File
@@ -113,7 +113,8 @@ export component PageAura inherits Rectangle {
min-height: 80px; min-height: 80px;
max-height: 90px; max-height: 90px;
RogItem { RogItem {
padding: 0px; //padding only has effect on layout elements
//padding: 0px;
VerticalBox { VerticalBox {
Text { Text {
text: @tr("Zone"); text: @tr("Zone");
@@ -136,7 +137,8 @@ export component PageAura inherits Rectangle {
} }
RogItem { RogItem {
padding: 0px; //padding only has effect on layout elements
//padding: 0px;
VerticalBox { VerticalBox {
Text { Text {
text: @tr("Direction"); text: @tr("Direction");
@@ -158,7 +160,8 @@ export component PageAura inherits Rectangle {
} }
RogItem { RogItem {
padding: 0px; //padding only has effect on layout elements
//padding: 0px;
VerticalBox { VerticalBox {
Text { Text {
text: @tr("Speed"); text: @tr("Speed");
+31 -10
View File
@@ -51,6 +51,10 @@ export global SystemPageData {
callback cb_panel_overdrive(int); callback cb_panel_overdrive(int);
in-out property <int> boot_sound; in-out property <int> boot_sound;
callback cb_boot_sound(int); callback cb_boot_sound(int);
in-out property <int> screen_auto_brightness;
callback cb_screen_auto_brightness(int);
in-out property <int> mcu_powersave;
callback cb_mcu_powersave(int);
in-out property <int> mini_led_mode; in-out property <int> mini_led_mode;
callback cb_mini_led_mode(int); callback cb_mini_led_mode(int);
@@ -140,7 +144,8 @@ export component PageSystem inherits Rectangle {
property <bool> show_fade_cover: false; property <bool> show_fade_cover: false;
property <bool> show_throttle_advanced: false; property <bool> show_throttle_advanced: false;
clip: true; clip: true;
padding: 8px; //padding only has effect on layout elements
//padding: 8px;
ScrollView { ScrollView {
VerticalLayout { VerticalLayout {
padding: 10px; padding: 10px;
@@ -299,9 +304,25 @@ export component PageSystem inherits Rectangle {
SystemPageData.cb_boot_sound(SystemPageData.boot_sound) SystemPageData.cb_boot_sound(SystemPageData.boot_sound)
} }
} }
if SystemPageData.screen_auto_brightness != -1: SystemToggleInt {
text: @tr("Screen Auto Brightness");
checked_int <=> SystemPageData.screen_auto_brightness;
toggled => {
SystemPageData.cb_screen_auto_brightness(SystemPageData.screen_auto_brightness)
}
}
if SystemPageData.mcu_powersave != -1: SystemToggleInt {
text: @tr("MCU Powersave");
checked_int <=> SystemPageData.mcu_powersave;
toggled => {
SystemPageData.cb_mcu_powersave(SystemPageData.mcu_powersave)
}
}
} }
if SystemPageData.ppt_pl1_spl.current != -1 || SystemPageData.ppt_pl2_sppt.current != -1 || SystemPageData.ppt_pl3_fppt.current != -1 || SystemPageData.ppt_fppt.current != -1 || SystemPageData.ppt_apu_sppt.current != -1 || SystemPageData.nv_temp_target.current != -1 || SystemPageData.nv_dynamic_boost.current != -1: HorizontalLayout { if (SystemPageData.ppt_pl1_spl.max > 0 && SystemPageData.ppt_pl1_spl.current != -1) || (SystemPageData.ppt_pl2_sppt.max > 0 && SystemPageData.ppt_pl2_sppt.current != -1) || (SystemPageData.ppt_pl3_fppt.max > 0 && SystemPageData.ppt_pl3_fppt.current != -1) || (SystemPageData.ppt_fppt.max > 0 && SystemPageData.ppt_fppt.current != -1) || (SystemPageData.ppt_apu_sppt.max > 0 && SystemPageData.ppt_apu_sppt.current != -1) || (SystemPageData.nv_temp_target.max > 0 && SystemPageData.nv_temp_target.current != -1) || (SystemPageData.nv_dynamic_boost.max > 0 && SystemPageData.nv_dynamic_boost.current != -1): HorizontalLayout {
padding-right: 10px; padding-right: 10px;
padding-left: 10px; padding-left: 10px;
alignment: LayoutAlignment.space-between; alignment: LayoutAlignment.space-between;
@@ -330,7 +351,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.ppt_pl1_spl.current != -1: SystemSlider { if SystemPageData.ppt_pl1_spl.max > 0 && SystemPageData.ppt_pl1_spl.current != -1: SystemSlider {
text: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit"); text: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
title: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit"); title: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
help_text: @tr("ppt_pl1_spl_help" => "Long-term CPU power limit that affects sustained workload performance. Higher values may increase heat and power consumption."); help_text: @tr("ppt_pl1_spl_help" => "Long-term CPU power limit that affects sustained workload performance. Higher values may increase heat and power consumption.");
@@ -348,7 +369,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.ppt_pl2_sppt.current != -1: SystemSlider { if SystemPageData.ppt_pl2_sppt.max > 0 && SystemPageData.ppt_pl2_sppt.current != -1: SystemSlider {
text: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit"); text: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
title: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit"); title: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
help_text: @tr("ppt_pl2_sppt_help" => "Short-term CPU power limit for boost periods. Controls maximum power during brief high-performance bursts."); help_text: @tr("ppt_pl2_sppt_help" => "Short-term CPU power limit for boost periods. Controls maximum power during brief high-performance bursts.");
@@ -366,7 +387,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.ppt_pl3_fppt.current != -1: SystemSlider { if SystemPageData.ppt_pl3_fppt.max > 0 && SystemPageData.ppt_pl3_fppt.current != -1: SystemSlider {
text: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit"); text: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
title: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit"); title: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
help_text: @tr("ppt_pl3_fppt_help" => "Ultra-short duration power limit for instantaneous CPU bursts. Affects responsiveness during sudden workload spikes."); help_text: @tr("ppt_pl3_fppt_help" => "Ultra-short duration power limit for instantaneous CPU bursts. Affects responsiveness during sudden workload spikes.");
@@ -383,7 +404,7 @@ export component PageSystem inherits Rectangle {
SystemPageData.cb_ppt_pl3_fppt(Math.round(value)); SystemPageData.cb_ppt_pl3_fppt(Math.round(value));
} }
} }
if SystemPageData.ppt_fppt.current != -1: SystemSlider { if SystemPageData.ppt_fppt.max > 0 && SystemPageData.ppt_fppt.current != -1: SystemSlider {
text: @tr("ppt_fppt" => "Fast Package Power Limit"); text: @tr("ppt_fppt" => "Fast Package Power Limit");
title: @tr("ppt_fppt" => "Fast Package Power Limit"); title: @tr("ppt_fppt" => "Fast Package Power Limit");
help_text: @tr("ppt_fppt_help" => "Ultra-short duration power limit for system package. Controls maximum power during millisecond-scale load spikes."); help_text: @tr("ppt_fppt_help" => "Ultra-short duration power limit for system package. Controls maximum power during millisecond-scale load spikes.");
@@ -401,7 +422,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.ppt_apu_sppt.current != -1: SystemSlider { if SystemPageData.ppt_apu_sppt.max > 0 && SystemPageData.ppt_apu_sppt.current != -1: SystemSlider {
text: @tr("ppt_apu_sppt" => "APU Sustained Power Limit"); text: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
title: @tr("ppt_apu_sppt" => "APU Sustained Power Limit"); title: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
help_text: @tr("ppt_apu_sppt_help" => "Long-term power limit for integrated graphics and CPU combined. Affects sustained performance of APU-based workloads."); help_text: @tr("ppt_apu_sppt_help" => "Long-term power limit for integrated graphics and CPU combined. Affects sustained performance of APU-based workloads.");
@@ -419,7 +440,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.ppt_platform_sppt.current != -1: SystemSlider { if SystemPageData.ppt_platform_sppt.max > 0 && SystemPageData.ppt_platform_sppt.current != -1: SystemSlider {
text: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit"); text: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
title: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit"); title: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
help_text: @tr("ppt_platform_sppt_help" => "Overall system power limit for sustained operations. Controls total platform power consumption over extended periods."); help_text: @tr("ppt_platform_sppt_help" => "Overall system power limit for sustained operations. Controls total platform power consumption over extended periods.");
@@ -437,7 +458,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.nv_dynamic_boost.current != -1: SystemSlider { if SystemPageData.nv_dynamic_boost.max > 0 && SystemPageData.nv_dynamic_boost.current != -1: SystemSlider {
text: @tr("nv_dynamic_boost" => "GPU Power Boost"); text: @tr("nv_dynamic_boost" => "GPU Power Boost");
title: @tr("nv_dynamic_boost" => "GPU Power Boost"); title: @tr("nv_dynamic_boost" => "GPU Power Boost");
help_text: @tr("nv_dynamic_boost_help" => "Additional power allocation for GPU dynamic boost. Higher values increase GPU performance but generate more heat."); help_text: @tr("nv_dynamic_boost_help" => "Additional power allocation for GPU dynamic boost. Higher values increase GPU performance but generate more heat.");
@@ -455,7 +476,7 @@ export component PageSystem inherits Rectangle {
} }
} }
if SystemPageData.nv_temp_target.current != -1: SystemSlider { if SystemPageData.nv_temp_target.max > 0 && SystemPageData.nv_temp_target.current != -1: SystemSlider {
text: @tr("nv_temp_target" => "GPU Temperature Limit"); text: @tr("nv_temp_target" => "GPU Temperature Limit");
title: @tr("nv_temp_target" => "GPU Temperature Limit"); title: @tr("nv_temp_target" => "GPU Temperature Limit");
help_text: @tr("nv_temp_target_help" => "Maximum GPU temperature threshold in Celsius. GPU will throttle to maintain temperature below this limit."); help_text: @tr("nv_temp_target_help" => "Maximum GPU temperature threshold in Celsius. GPU will throttle to maintain temperature below this limit.");
+2 -1
View File
@@ -4,7 +4,8 @@
import { Palette, HorizontalBox, VerticalBox } from "std-widgets.slint"; import { Palette, HorizontalBox, VerticalBox } from "std-widgets.slint";
component SideBarItem inherits Rectangle { component SideBarItem inherits Rectangle {
padding: 10px; // padding only has effect on layout elements
// padding: 10px;
in property <bool> selected; in property <bool> selected;
in property <bool> has-focus; in property <bool> has-focus;
in-out property <string> text <=> label.text; in-out property <string> text <=> label.text;
+42 -4
View File
@@ -124,6 +124,22 @@ impl Attribute {
&self.scalar_increment &self.scalar_increment
} }
fn read_attr_i32(&self, name: &str) -> Option<i32> {
read_i32(&self.base_path.join(name)).ok()
}
pub fn refresh_min_value(&self) -> Option<i32> {
self.read_attr_i32("min_value")
}
pub fn refresh_max_value(&self) -> Option<i32> {
self.read_attr_i32("max_value")
}
pub fn refresh_scalar_increment(&self) -> Option<i32> {
self.read_attr_i32("scalar_increment")
}
/// Read all the immutable values to struct data. These should *never* /// Read all the immutable values to struct data. These should *never*
/// change, if they do then it is possibly a driver issue - although this is /// change, if they do then it is possibly a driver issue - although this is
/// subject to `firmware_attributes` class changes in kernel. /// subject to `firmware_attributes` class changes in kernel.
@@ -256,10 +272,29 @@ macro_rules! define_attribute_getters {
} }
define_attribute_getters!( define_attribute_getters!(
apu_mem, cores_performance, cores_efficiency, ppt_pl1_spl, ppt_pl2_sppt, ppt_apu_sppt, apu_mem,
ppt_platform_sppt, ppt_fppt, nv_dynamic_boost, nv_temp_target, dgpu_base_tgp, dgpu_tgp, cores_performance,
charge_mode, boot_sound, mcu_powersave, panel_od, panel_hd_mode, egpu_connected, egpu_enable, cores_efficiency,
dgpu_disable, gpu_mux_mode, mini_led_mode ppt_pl1_spl,
ppt_pl2_sppt,
ppt_apu_sppt,
ppt_platform_sppt,
ppt_fppt,
nv_dynamic_boost,
nv_temp_target,
dgpu_base_tgp,
dgpu_tgp,
charge_mode,
boot_sound,
mcu_powersave,
panel_od,
panel_hd_mode,
egpu_connected,
egpu_enable,
dgpu_disable,
gpu_mux_mode,
mini_led_mode,
screen_auto_brightness
); );
/// CamelCase names of the properties. Intended for use with DBUS /// CamelCase names of the properties. Intended for use with DBUS
@@ -306,6 +341,7 @@ pub enum FirmwareAttribute {
PendingReboot = 23, PendingReboot = 23,
PptEnabled = 24, PptEnabled = 24,
None = 25, None = 25,
ScreenAutoBrightness = 26,
} }
impl FirmwareAttribute { impl FirmwareAttribute {
@@ -359,6 +395,7 @@ impl From<&str> for FirmwareAttribute {
"gpu_mux_mode" => Self::GpuMuxMode, "gpu_mux_mode" => Self::GpuMuxMode,
"mini_led_mode" => Self::MiniLedMode, "mini_led_mode" => Self::MiniLedMode,
"pending_reboot" => Self::PendingReboot, "pending_reboot" => Self::PendingReboot,
"screen_auto_brightness" => Self::ScreenAutoBrightness,
_ => { _ => {
error!("Invalid firmware attribute: {}", s); error!("Invalid firmware attribute: {}", s);
Self::None Self::None
@@ -395,6 +432,7 @@ impl From<FirmwareAttribute> for &str {
FirmwareAttribute::GpuMuxMode => "gpu_mux_mode", FirmwareAttribute::GpuMuxMode => "gpu_mux_mode",
FirmwareAttribute::MiniLedMode => "mini_led_mode", FirmwareAttribute::MiniLedMode => "mini_led_mode",
FirmwareAttribute::PendingReboot => "pending_reboot", FirmwareAttribute::PendingReboot => "pending_reboot",
FirmwareAttribute::ScreenAutoBrightness => "screen_auto_brightness",
FirmwareAttribute::None => "none", FirmwareAttribute::None => "none",
} }
} }
+17 -11
View File
@@ -267,18 +267,24 @@ mod tests {
fn check_cpu() { fn check_cpu() {
let cpu = CPUControl::new().unwrap(); let cpu = CPUControl::new().unwrap();
assert_eq!(cpu.get_governor().unwrap(), CPUGovernor::Powersave); assert_eq!(cpu.get_governor().unwrap(), CPUGovernor::Powersave);
assert_eq!(cpu.get_available_governors().unwrap(), vec![ assert_eq!(
CPUGovernor::Performance, cpu.get_available_governors().unwrap(),
CPUGovernor::Powersave vec![
]); CPUGovernor::Performance,
CPUGovernor::Powersave
]
);
assert_eq!(cpu.get_epp().unwrap(), CPUEPP::BalancePower); assert_eq!(cpu.get_epp().unwrap(), CPUEPP::BalancePower);
assert_eq!(cpu.get_available_epp().unwrap(), vec![ assert_eq!(
CPUEPP::Default, cpu.get_available_epp().unwrap(),
CPUEPP::Performance, vec![
CPUEPP::BalancePerformance, CPUEPP::Default,
CPUEPP::BalancePower, CPUEPP::Performance,
CPUEPP::Power, CPUEPP::BalancePerformance,
]); CPUEPP::BalancePower,
CPUEPP::Power,
]
);
} }
} }
+14 -4
View File
@@ -275,11 +275,16 @@ impl std::str::FromStr for PlatformProfile {
type Err = PlatformError; type Err = PlatformError;
fn from_str(profile: &str) -> Result<Self> { fn from_str(profile: &str) -> Result<Self> {
match profile.to_ascii_lowercase().trim() { match profile
.to_ascii_lowercase()
.trim()
.replace(|c| !char::is_alphabetic(c), "")
.as_str()
{
"balanced" => Ok(PlatformProfile::Balanced), "balanced" => Ok(PlatformProfile::Balanced),
"performance" => Ok(PlatformProfile::Performance), "performance" => Ok(PlatformProfile::Performance),
"quiet" => Ok(PlatformProfile::Quiet), "quiet" => Ok(PlatformProfile::Quiet),
"low-power" => Ok(PlatformProfile::LowPower), "lowpower" => Ok(PlatformProfile::LowPower),
"custom" => Ok(PlatformProfile::Custom), "custom" => Ok(PlatformProfile::Custom),
_ => Err(PlatformError::NotSupported), _ => Err(PlatformError::NotSupported),
} }
@@ -288,11 +293,16 @@ impl std::str::FromStr for PlatformProfile {
impl From<&str> for PlatformProfile { impl From<&str> for PlatformProfile {
fn from(profile: &str) -> Self { fn from(profile: &str) -> Self {
match profile.to_ascii_lowercase().trim() { match profile
.to_ascii_lowercase()
.trim()
.replace(|c| !char::is_alphabetic(c), "")
.as_str()
{
"balanced" => PlatformProfile::Balanced, "balanced" => PlatformProfile::Balanced,
"performance" => PlatformProfile::Performance, "performance" => PlatformProfile::Performance,
"quiet" => PlatformProfile::Quiet, "quiet" => PlatformProfile::Quiet,
"low-power" => PlatformProfile::LowPower, "lowpower" => PlatformProfile::LowPower,
"custom" => PlatformProfile::Custom, "custom" => PlatformProfile::Custom,
_ => { _ => {
warn!("{profile} is unknown, using ThrottlePolicy::Balanced"); warn!("{profile} is unknown, using ThrottlePolicy::Balanced");
+10 -3
View File
@@ -101,8 +101,15 @@ impl AsusPower {
}); });
} }
Err(PlatformError::MissingFunction( // No battery found. Return an AsusPower with an empty battery path so
"Did not find a battery".to_owned(), // callers can still be constructed and query `has_*` methods which
)) // will correctly report absence. This avoids hard-failing on systems
// where the asus-nb-wmi driver loads on desktops with no battery.
info!("Did not find a battery, continuing without battery support");
Ok(Self {
mains,
battery: PathBuf::new(),
usb,
})
} }
} }
+2 -7
View File
@@ -37,8 +37,9 @@ pub fn find_fan_curve_node() -> Result<Device, ProfileError> {
derive(Type, Value, OwnedValue), derive(Type, Value, OwnedValue),
zvariant(signature = "s") zvariant(signature = "s")
)] )]
#[derive(Deserialize, Serialize, Debug, Hash, PartialEq, Eq, Clone, Copy)] #[derive(Default, Deserialize, Serialize, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum FanCurvePU { pub enum FanCurvePU {
#[default]
CPU = 0, CPU = 0,
GPU = 1, GPU = 1,
MID = 2, MID = 2,
@@ -100,12 +101,6 @@ impl std::str::FromStr for FanCurvePU {
} }
} }
impl Default for FanCurvePU {
fn default() -> Self {
Self::CPU
}
}
/// Main purpose of `FanCurves` is to enable restoring state on system boot /// Main purpose of `FanCurves` is to enable restoring state on system boot
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
+1
View File
@@ -157,6 +157,7 @@ fn main() -> Result<(), Box<dyn Error>> {
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() { for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
canvas.set_draw_color(Color::RGB(*b, *b, *b)); canvas.set_draw_color(Color::RGB(*b, *b, *b));
#[allow(clippy::manual_is_multiple_of)]
let x: i32 = w + x_count as i32 * w let x: i32 = w + x_count as i32 * w
- if (y_count + y_offset as usize) % 2 != 0 { - if (y_count + y_offset as usize) % 2 != 0 {
0 0