mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
15 Commits
6.3.2
...
devel-dyna
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e5cebc781 | ||
|
|
def691f9d0 | ||
|
|
80eeafd9e1 | ||
|
|
bf173300e0 | ||
|
|
07874d7452 | ||
|
|
894a0d2b11 | ||
|
|
11dc02612e | ||
|
|
fccb233e9e | ||
|
|
c13612e02c | ||
|
|
80147966a9 | ||
|
|
a1815ac40c | ||
|
|
ad051bd7b8 | ||
|
|
90676b390e | ||
|
|
974f2acafa | ||
|
|
6ae3ae5284 |
@@ -8,9 +8,6 @@ indent_style = space
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[*.slint]
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -20,8 +20,3 @@ desktop-extensions/gnome*/@types/gir-generated
|
|||||||
desktop-extensions/gnome*/node_modules
|
desktop-extensions/gnome*/node_modules
|
||||||
desktop-extensions/gnome*/schemas/gschemas.compiled
|
desktop-extensions/gnome*/schemas/gschemas.compiled
|
||||||
desktop-extensions/gnome*/*.zip
|
desktop-extensions/gnome*/*.zip
|
||||||
|
|
||||||
# agents and reference
|
|
||||||
CLAUDE.md
|
|
||||||
AGENTS.md
|
|
||||||
/reference
|
|
||||||
|
|||||||
@@ -1,26 +1,22 @@
|
|||||||
image: rust:latest
|
image: rust:latest
|
||||||
|
|
||||||
# Use shallow clone to reduce checkout size
|
|
||||||
variables:
|
|
||||||
GIT_DEPTH: "1"
|
|
||||||
# Put cargo home and target under project dir so we can clean them easily
|
|
||||||
CARGO_HOME: "$CI_PROJECT_DIR/.cargo"
|
|
||||||
CARGO_TARGET_DIR: "$CI_PROJECT_DIR/ci-target"
|
|
||||||
GIT_SUBMODULE_STRATEGY: normal
|
|
||||||
|
|
||||||
# Cache only cargo registries/git metadata to speed dependency fetches.
|
|
||||||
# Avoid caching compiled `target` artifacts which are large and easily fill disk.
|
|
||||||
.rust_cache: &rust_cache
|
.rust_cache: &rust_cache
|
||||||
cache:
|
cache:
|
||||||
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
# key: $CI_COMMIT_REF_SLUG
|
||||||
paths:
|
paths:
|
||||||
- .cargo/registry
|
# Don't include `incremental` to save space
|
||||||
- .cargo/git
|
# Debug
|
||||||
|
- target/debug/build/
|
||||||
|
- target/debug/deps/
|
||||||
|
- target/debug/.fingerprint/
|
||||||
|
- target/debug/.cargo-lock
|
||||||
|
# Release
|
||||||
|
- target/release/build/
|
||||||
|
- target/release/deps/
|
||||||
|
- target/release/.fingerprint/
|
||||||
|
- target/release/.cargo-lock
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- df -h
|
|
||||||
- echo "Cleaning stale targets to free space if present"
|
|
||||||
- rm -rf "$CI_PROJECT_DIR/target" "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev
|
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
@@ -37,9 +33,6 @@ format:
|
|||||||
script:
|
script:
|
||||||
- rustup component add rustfmt || true
|
- rustup component add rustfmt || true
|
||||||
- cargo fmt --check
|
- cargo fmt --check
|
||||||
after_script:
|
|
||||||
- du -sh "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
except:
|
except:
|
||||||
@@ -51,8 +44,6 @@ check:
|
|||||||
# 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
|
||||||
after_script:
|
|
||||||
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
except:
|
except:
|
||||||
@@ -61,8 +52,6 @@ test:
|
|||||||
script:
|
script:
|
||||||
- mkdir -p .git/hooks > /dev/null
|
- mkdir -p .git/hooks > /dev/null
|
||||||
- cargo test --locked --all
|
- cargo test --locked --all
|
||||||
after_script:
|
|
||||||
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
only:
|
only:
|
||||||
@@ -70,15 +59,11 @@ release:
|
|||||||
<<: *rust_cache
|
<<: *rust_cache
|
||||||
script:
|
script:
|
||||||
- cargo install cargo-vendor-filterer
|
- cargo install cargo-vendor-filterer
|
||||||
- cargo fetch
|
|
||||||
- make FROZEN=1 && make vendor
|
- make FROZEN=1 && make vendor
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- vendor_asusctl*.tar.xz
|
- vendor_asusctl*.tar.xz
|
||||||
- cargo-config
|
- cargo-config
|
||||||
expire_in: 1 week
|
|
||||||
after_script:
|
|
||||||
- rm -rf vendor vendor_asusctl*.tar.xz "$CI_PROJECT_DIR/ci-target" || true
|
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
@@ -89,11 +74,11 @@ pages:
|
|||||||
- cargo doc --locked --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 ci-target/doc/* public
|
- cp -R target/doc/* public
|
||||||
- if [ -f extra/index.html ]; then cp extra/index.html public; else echo "no extra/index.html to copy"; fi
|
- cp extra/index.html public
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
expire_in: 1 week
|
|
||||||
after_script:
|
variables:
|
||||||
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
GIT_SUBMODULE_STRATEGY: normal
|
||||||
|
|||||||
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,68 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [6.3.2]
|
## [Unreleased]
|
||||||
|
|
||||||
### Changes
|
|
||||||
- Improve the notification area, @shevchenko0013 strikes again!
|
|
||||||
- Improve firmware attributes handling
|
|
||||||
- Very good looking UI restyling from @shevchenko0013
|
|
||||||
- Added support for GA402NV matrix: thanks @Ghoul4500
|
|
||||||
- Fixed aura CLI interface
|
|
||||||
- Fixed LEDs handling in rogcc
|
|
||||||
|
|
||||||
## [6.3.1]
|
|
||||||
|
|
||||||
### Changes
|
|
||||||
- Removed a lighting mode that is unavailable in windows to G835L: thanks to @shevchenko0013 again!
|
|
||||||
- Added translations for Ukranian language, thanks @shevchenko0013!
|
|
||||||
- Added LEDs definition for G615LR, thanks @btnrv
|
|
||||||
- Fix improper usage of Quiet when only LowPower is available
|
|
||||||
|
|
||||||
## [6.3.0]
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Added support for TUF keyboard powerstate control
|
- Make the boot process more reliable
|
||||||
- Improved AniMe Matrix support thanks to @Seom1177 !
|
- tie nv_ properties to power profiles
|
||||||
- Fixed a bug with one-shot battery change, thanks @bitr8 !
|
- Better support nv_tgp
|
||||||
- Changed the CLI interface of asusctl to be less confusing
|
|
||||||
- Added support for G835L, thanks to @shevchenko0013 !
|
|
||||||
|
|
||||||
## [6.2.0]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Added aura support for FX607V: thanks @jomp16
|
|
||||||
- Added testing support for G835LW
|
|
||||||
- Added support for GU605C models slash lighting: thanks @Otters
|
|
||||||
- Restore fedora: thanks @ali205412
|
|
||||||
- Add support to G614F models slash lighting
|
|
||||||
|
|
||||||
## [6.1.22]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Allow configuration of nv_tgp
|
|
||||||
- Treat dGPU attributes as power profiles
|
|
||||||
- Add EXPERTBOOK DMI match to ensure the service is loaded
|
|
||||||
- Support G815L thanks to @solost !
|
|
||||||
|
|
||||||
## [6.1.21]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Kill Fedora: screw your cursed cargo bullshit
|
|
||||||
- Restore CI building
|
|
||||||
|
|
||||||
## [6.1.20]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Addded support for G635L: thanks @luca_pisl !
|
|
||||||
- Suppress verbose output in applications too, not just daemon
|
|
||||||
|
|
||||||
## [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]
|
## [v6.1.17]
|
||||||
|
|
||||||
|
|||||||
1292
Cargo.lock
generated
1292
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
@@ -1,12 +1,9 @@
|
|||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "6.3.2"
|
version = "6.1.17"
|
||||||
rust-version = "1.82"
|
rust-version = "1.82"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
"Luke <luke@ljones.dev>",
|
|
||||||
"Denis Benato <benato.denis96@gmail.com>"
|
|
||||||
]
|
|
||||||
repository = "https://gitlab.com/asus-linux/asusctl"
|
repository = "https://gitlab.com/asus-linux/asusctl"
|
||||||
homepage = "https://gitlab.com/asus-linux/asusctl"
|
homepage = "https://gitlab.com/asus-linux/asusctl"
|
||||||
description = "Laptop feature control for ASUS ROG laptops and others"
|
description = "Laptop feature control for ASUS ROG laptops and others"
|
||||||
@@ -47,7 +44,7 @@ smol = "^2.0"
|
|||||||
mio = "0.8.11"
|
mio = "0.8.11"
|
||||||
|
|
||||||
futures-util = "0.3.31"
|
futures-util = "0.3.31"
|
||||||
zbus = "5.13.1"
|
zbus = "5.5.0"
|
||||||
logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] }
|
logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] }
|
||||||
|
|
||||||
serde = { version = "^1.0", features = ["serde_derive"] }
|
serde = { version = "^1.0", features = ["serde_derive"] }
|
||||||
@@ -60,12 +57,12 @@ glam = { version = "^0.22", features = ["serde"] }
|
|||||||
gumdrop = "^0.8"
|
gumdrop = "^0.8"
|
||||||
udev = { version = "^0.8", features = ["mio"] }
|
udev = { version = "^0.8", features = ["mio"] }
|
||||||
rusb = "^0.9"
|
rusb = "^0.9"
|
||||||
inotify = "^0.10"
|
inotify = "^0.10.0"
|
||||||
|
|
||||||
png_pong = "^0.8"
|
png_pong = "^0.8"
|
||||||
pix = "^0.13"
|
pix = "^0.13"
|
||||||
tinybmp = "^0.4"
|
tinybmp = "^0.4.0"
|
||||||
gif = "^0.12"
|
gif = "^0.12.0"
|
||||||
|
|
||||||
versions = "6.2"
|
versions = "6.2"
|
||||||
|
|
||||||
|
|||||||
17
Makefile
17
Makefile
@@ -59,17 +59,10 @@ clean:
|
|||||||
distclean:
|
distclean:
|
||||||
rm -rf .cargo vendor vendor.tar.xz
|
rm -rf .cargo vendor vendor.tar.xz
|
||||||
|
|
||||||
target/$(TARGET)/$(BIN_D): $(SRC)
|
target/$(TARGET)/$(BIN_D): build
|
||||||
$(MAKE) build
|
target/$(TARGET)/$(BIN_C): build
|
||||||
|
target/$(TARGET)/$(BIN_U): build
|
||||||
target/$(TARGET)/$(BIN_C): $(SRC)
|
target/$(TARGET)/$(BIN_ROG): build
|
||||||
$(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)"
|
||||||
@@ -158,8 +151,6 @@ vendor:
|
|||||||
mv .cargo/config ./cargo-config
|
mv .cargo/config ./cargo-config
|
||||||
rm -rf .cargo
|
rm -rf .cargo
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
# Ensure cargo-vendor-filterer is installed (CI installs it already)
|
|
||||||
command -v cargo-vendor-filterer >/dev/null 2>&1 || cargo install --locked cargo-vendor-filterer
|
|
||||||
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
|
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
|
||||||
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ Now includes a GUI, `rog-control-center`.
|
|||||||
|
|
||||||
Due to on-going driver work the minimum suggested kernel version is always **the latest*, as improvements and fixes are continuous.
|
Due to on-going driver work the minimum suggested kernel version is always **the latest*, as improvements and fixes are continuous.
|
||||||
|
|
||||||
Support for TDP is tied to the new asus-armoury driver: available mainline since linux 6.19: everything older is not supported.
|
Support for some new features is not avilable unless you run a patched kernel with the work I am doing [in this github repo](https://github.com/flukejones/linux/tree/wip/ally-6.13). Use the linked branch, or `wip/ally-6.12`. Everything that is done here is upstreamed eventually (a long process).
|
||||||
|
|
||||||
|
Z13 devices will need [these](https://lore.kernel.org/linux-input/20240416090402.31057-1-luke@ljones.dev/T/#t)
|
||||||
|
|
||||||
## X11 support
|
## X11 support
|
||||||
|
|
||||||
@@ -178,7 +180,3 @@ Reference to any ASUS products, services, processes, or other information and/or
|
|||||||
The use of ROG and ASUS trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with ASUS ROG laptops.
|
The use of ROG and ASUS trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with ASUS ROG laptops.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## AI Disaclaimer
|
|
||||||
|
|
||||||
Portions of this code have been written by various AI tools and reviewed by the maintainer exaclty as with every other contribution.
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ env_logger.workspace = true
|
|||||||
ron.workspace = true
|
ron.workspace = true
|
||||||
gumdrop.workspace = true
|
gumdrop.workspace = true
|
||||||
zbus.workspace = true
|
zbus.workspace = true
|
||||||
argh = "0.1"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
|||||||
@@ -1,547 +0,0 @@
|
|||||||
//! LED scanning tool for discovering AniMe Matrix buffer-to-LED mappings.
|
|
||||||
//!
|
|
||||||
//! This tool lights up one buffer index at a time, allowing you to observe
|
|
||||||
//! which physical LED corresponds to each buffer position. This is essential
|
|
||||||
//! for mapping new device types like G835L where the exact layout is unknown.
|
|
||||||
//!
|
|
||||||
//! You might want to use it slowly, as it sometimes doesn't work properly.
|
|
||||||
//! Maybe there's better ways to make this reliable but for now it works for my use case.
|
|
||||||
//!
|
|
||||||
//! # Usage
|
|
||||||
//! ```
|
|
||||||
//! cargo run --example anime-led-scan -- [options]
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! # Controls
|
|
||||||
//! - `n` or `Enter`: Next index
|
|
||||||
//! - `p` or `Backspace`: Previous index
|
|
||||||
//! - `j` followed by number: Jump to specific index
|
|
||||||
//! - `+` / `-`: Adjust step size (default 1)
|
|
||||||
//! - `s`: Save current index to notes file
|
|
||||||
//! - `r`: Mark current index as row start
|
|
||||||
//! - `q` or `Ctrl+C`: Quit
|
|
||||||
//!
|
|
||||||
//! # Output
|
|
||||||
//! Creates a `led-scan-notes.txt` file with recorded observations.
|
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::{self, BufRead, Write};
|
|
||||||
|
|
||||||
use rog_anime::usb::{get_anime_type, Brightness};
|
|
||||||
use rog_anime::{AnimeDataBuffer, AnimeType};
|
|
||||||
use rog_dbus::zbus_anime::AnimeProxyBlocking;
|
|
||||||
use zbus::blocking::Connection;
|
|
||||||
|
|
||||||
/// Saved device state for restoration on exit
|
|
||||||
struct SavedState {
|
|
||||||
builtins_enabled: bool,
|
|
||||||
brightness: Brightness,
|
|
||||||
display_enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_help(scan_len: usize, buffer_len: usize) {
|
|
||||||
println!("\n=== LED Scan Tool ===");
|
|
||||||
println!(
|
|
||||||
"Scan range: 0-{} (buffer size: {})",
|
|
||||||
scan_len - 1,
|
|
||||||
buffer_len
|
|
||||||
);
|
|
||||||
println!("Commands:");
|
|
||||||
println!(" n, Enter - Next index");
|
|
||||||
println!(" p, Backspace - Previous index");
|
|
||||||
println!(" j <num> - Jump to index");
|
|
||||||
println!(" + / - - Increase/decrease step size");
|
|
||||||
println!(" s - Save note for current index");
|
|
||||||
println!(" r - Mark as row start");
|
|
||||||
println!(" a - Auto-scan (runs through all indices)");
|
|
||||||
println!(" f - Fill all buffer bytes");
|
|
||||||
println!(" f <start> <end> - Fill range (inclusive)");
|
|
||||||
println!(" p1/p2/p3 - Fill pane 1/2/3 only (each is 627 bytes)");
|
|
||||||
println!(" hold - Hold current LED (press Enter to release)");
|
|
||||||
println!(" hold <s> <e> - Hold range (press Enter to release)");
|
|
||||||
println!(" c - Clear display");
|
|
||||||
println!(" row - Step through rows (G835L, provisional)");
|
|
||||||
println!(" row <n> - Show specific row (G835L, provisional)");
|
|
||||||
println!(" allrows - Light all rows sequentially (G835L)");
|
|
||||||
println!(" rowmap - Print the full row mapping (G835L)");
|
|
||||||
println!(" h - Show this help");
|
|
||||||
println!(" q - Quit and restore state");
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_note(index: usize, note: &str) -> io::Result<()> {
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.append(true)
|
|
||||||
.open("led-scan-notes.txt")?;
|
|
||||||
writeln!(file, "Index {}: {}", index, note)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_single_led(
|
|
||||||
proxy: &AnimeProxyBlocking,
|
|
||||||
anime_type: AnimeType,
|
|
||||||
index: usize,
|
|
||||||
brightness: u8,
|
|
||||||
) {
|
|
||||||
let mut buffer = AnimeDataBuffer::new(anime_type);
|
|
||||||
let data = buffer.data_mut();
|
|
||||||
if index < data.len() {
|
|
||||||
data[index] = brightness;
|
|
||||||
}
|
|
||||||
if let Err(e) = proxy.write(buffer) {
|
|
||||||
eprintln!("Error writing to device: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_display(proxy: &AnimeProxyBlocking, anime_type: AnimeType) {
|
|
||||||
let buffer = AnimeDataBuffer::new(anime_type);
|
|
||||||
let _ = proxy.write(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_display(proxy: &AnimeProxyBlocking, anime_type: AnimeType, brightness: u8) {
|
|
||||||
let mut buffer = AnimeDataBuffer::new(anime_type);
|
|
||||||
let data = buffer.data_mut();
|
|
||||||
for byte in data.iter_mut() {
|
|
||||||
*byte = brightness;
|
|
||||||
}
|
|
||||||
if let Err(e) = proxy.write(buffer) {
|
|
||||||
eprintln!("Error writing to device: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fill a range of LEDs. Both start and end are INCLUSIVE.
|
|
||||||
fn fill_range(
|
|
||||||
proxy: &AnimeProxyBlocking,
|
|
||||||
anime_type: AnimeType,
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
brightness: u8,
|
|
||||||
) {
|
|
||||||
let mut buffer = AnimeDataBuffer::new(anime_type);
|
|
||||||
let data = buffer.data_mut();
|
|
||||||
for i in start..=end.min(data.len().saturating_sub(1)) {
|
|
||||||
data[i] = brightness;
|
|
||||||
}
|
|
||||||
if let Err(e) = proxy.write(buffer) {
|
|
||||||
eprintln!("Error writing to device: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_pane(proxy: &AnimeProxyBlocking, anime_type: AnimeType, pane: usize, brightness: u8) {
|
|
||||||
const PANE_LEN: usize = 627;
|
|
||||||
let start = pane * PANE_LEN;
|
|
||||||
let end = start + PANE_LEN - 1;
|
|
||||||
fill_range(proxy, anime_type, start, end, brightness);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// G835L row pattern (PROVISIONAL - needs hardware verification):
|
|
||||||
/// - Rows 0-1: 1 LED each
|
|
||||||
/// - Rows 2-3: 2 LEDs each
|
|
||||||
/// - ... (pairs of rows with same length)
|
|
||||||
/// - Rows 26-27: 14 LEDs each
|
|
||||||
/// - Rows 28+: 15 LEDs each (constant)
|
|
||||||
///
|
|
||||||
/// Returns (start_index, end_index_inclusive, row_length)
|
|
||||||
fn g835l_row_bounds(row: usize) -> (usize, usize, usize) {
|
|
||||||
let triangle_rows = 28;
|
|
||||||
let triangle_leds = 210;
|
|
||||||
|
|
||||||
if row < triangle_rows {
|
|
||||||
let length = row / 2 + 1;
|
|
||||||
let mut start = 0usize;
|
|
||||||
for r in 0..row {
|
|
||||||
start += r / 2 + 1;
|
|
||||||
}
|
|
||||||
(start, start + length - 1, length)
|
|
||||||
} else {
|
|
||||||
let rows_after_triangle = row - triangle_rows;
|
|
||||||
let start = triangle_leds + rows_after_triangle * 15;
|
|
||||||
(start, start + 14, 15)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn g835l_total_rows() -> usize {
|
|
||||||
28 + 40
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_state(proxy: &AnimeProxyBlocking) -> SavedState {
|
|
||||||
SavedState {
|
|
||||||
builtins_enabled: proxy.builtins_enabled().unwrap_or(false),
|
|
||||||
brightness: proxy.brightness().unwrap_or(Brightness::Med),
|
|
||||||
display_enabled: proxy.enable_display().unwrap_or(true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn restore_state(proxy: &AnimeProxyBlocking, state: &SavedState) {
|
|
||||||
let _ = proxy.set_builtins_enabled(state.builtins_enabled);
|
|
||||||
let _ = proxy.set_brightness(state.brightness);
|
|
||||||
let _ = proxy.set_enable_display(state.display_enabled);
|
|
||||||
let _ = proxy.run_main_loop(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
|
|
||||||
let mut start_index = 0usize;
|
|
||||||
let mut brightness = 200u8;
|
|
||||||
let mut scan_limit: Option<usize> = None;
|
|
||||||
|
|
||||||
let mut i = 1;
|
|
||||||
while i < args.len() {
|
|
||||||
match args[i].as_str() {
|
|
||||||
"--start" | "-s" => {
|
|
||||||
if i + 1 < args.len() {
|
|
||||||
start_index = args[i + 1].parse().unwrap_or(0);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"--brightness" | "-b" => {
|
|
||||||
if i + 1 < args.len() {
|
|
||||||
brightness = args[i + 1].parse().unwrap_or(200);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"--limit" | "-l" => {
|
|
||||||
if i + 1 < args.len() {
|
|
||||||
scan_limit = args[i + 1].parse().ok();
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"--help" | "-h" => {
|
|
||||||
println!("LED Scan Tool for AniMe Matrix");
|
|
||||||
println!();
|
|
||||||
println!("Usage: anime-led-scan [options]");
|
|
||||||
println!();
|
|
||||||
println!("Options:");
|
|
||||||
println!(" -s, --start <N> Start at index N (default: 0)");
|
|
||||||
println!(" -b, --brightness <N> LED brightness 0-255 (default: 200)");
|
|
||||||
println!(" -l, --limit <N> Cap scan range to N indices (e.g. 810 for G835L)");
|
|
||||||
println!(" -h, --help Show this help");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let conn = match Connection::system() {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to connect to D-Bus: {}", e);
|
|
||||||
eprintln!("Make sure asusd is running.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let proxy = match AnimeProxyBlocking::new(&conn) {
|
|
||||||
Ok(p) => p,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to create Anime proxy: {}", e);
|
|
||||||
eprintln!("Make sure asusd supports your device.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let anime_type = get_anime_type();
|
|
||||||
let buffer_len = anime_type.data_length();
|
|
||||||
let scan_len = scan_limit.unwrap_or(buffer_len).min(buffer_len);
|
|
||||||
|
|
||||||
println!("=== LED Scan Tool ===");
|
|
||||||
println!("Device type: {:?}", anime_type);
|
|
||||||
println!("Buffer length: {} bytes", buffer_len);
|
|
||||||
println!("Scan range: 0-{}", scan_len - 1);
|
|
||||||
println!("Brightness: {}", brightness);
|
|
||||||
println!();
|
|
||||||
|
|
||||||
// Save current state for restoration
|
|
||||||
let saved_state = save_state(&proxy);
|
|
||||||
println!("Saved device state for restoration on exit.");
|
|
||||||
|
|
||||||
// Stop system animations
|
|
||||||
if let Err(e) = proxy.run_main_loop(false) {
|
|
||||||
eprintln!("Warning: Could not stop main loop: {}", e);
|
|
||||||
}
|
|
||||||
println!("Stopped system animations.");
|
|
||||||
|
|
||||||
print_help(scan_len, buffer_len);
|
|
||||||
|
|
||||||
let mut current_index = start_index.min(scan_len - 1);
|
|
||||||
let mut step = 1usize;
|
|
||||||
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
|
|
||||||
let stdin = io::stdin();
|
|
||||||
let mut input = String::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
input.clear();
|
|
||||||
print!("> ");
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
|
|
||||||
if stdin.lock().read_line(&mut input).is_err() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cmd = input.trim();
|
|
||||||
|
|
||||||
match cmd {
|
|
||||||
"q" | "quit" | "exit" => {
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
restore_state(&proxy, &saved_state);
|
|
||||||
println!("Restored device state. Goodbye!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
"n" | "" => {
|
|
||||||
current_index = (current_index + step).min(scan_len - 1);
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
}
|
|
||||||
"p" => {
|
|
||||||
current_index = current_index.saturating_sub(step);
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
}
|
|
||||||
"+" => {
|
|
||||||
step = step.saturating_mul(2).max(1);
|
|
||||||
println!("Step size: {}", step);
|
|
||||||
}
|
|
||||||
"-" => {
|
|
||||||
step = step.saturating_div(2).max(1);
|
|
||||||
println!("Step size: {}", step);
|
|
||||||
}
|
|
||||||
"r" => {
|
|
||||||
if let Err(e) = save_note(current_index, "ROW START") {
|
|
||||||
eprintln!("Error saving note: {}", e);
|
|
||||||
} else {
|
|
||||||
println!("Saved: Index {} marked as ROW START", current_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"h" | "help" | "?" => {
|
|
||||||
print_help(scan_len, buffer_len);
|
|
||||||
}
|
|
||||||
cmd if cmd.starts_with('j') => {
|
|
||||||
let num_str = cmd.trim_start_matches('j').trim();
|
|
||||||
if let Ok(idx) = num_str.parse::<usize>() {
|
|
||||||
if idx < scan_len {
|
|
||||||
current_index = idx;
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
} else {
|
|
||||||
println!("Index {} out of range (max: {})", idx, scan_len - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Usage: j <number>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd if cmd.starts_with('s') && !cmd.starts_with("show") => {
|
|
||||||
let note = cmd.trim_start_matches('s').trim();
|
|
||||||
let note = if note.is_empty() { "observed" } else { note };
|
|
||||||
if let Err(e) = save_note(current_index, note) {
|
|
||||||
eprintln!("Error saving note: {}", e);
|
|
||||||
} else {
|
|
||||||
println!("Saved note for index {}", current_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"a" => {
|
|
||||||
println!("Auto-scan mode (0 to {})...", scan_len - 1);
|
|
||||||
let delay = std::time::Duration::from_millis(10);
|
|
||||||
for idx in current_index..scan_len {
|
|
||||||
write_single_led(&proxy, anime_type, idx, brightness);
|
|
||||||
print!("\rIndex: {} / {} ", idx, scan_len - 1);
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
std::thread::sleep(delay);
|
|
||||||
current_index = idx;
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
println!("Auto-scan complete. Current index: {}", current_index);
|
|
||||||
}
|
|
||||||
"c" => {
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
println!("Display cleared");
|
|
||||||
}
|
|
||||||
"f" => {
|
|
||||||
fill_display(&proxy, anime_type, brightness);
|
|
||||||
println!("All buffer bytes filled at brightness {}", brightness);
|
|
||||||
}
|
|
||||||
"p1" => {
|
|
||||||
fill_pane(&proxy, anime_type, 0, brightness);
|
|
||||||
println!("Pane 1 (indices 0-626) filled");
|
|
||||||
}
|
|
||||||
"p2" => {
|
|
||||||
fill_pane(&proxy, anime_type, 1, brightness);
|
|
||||||
println!("Pane 2 (indices 627-1253) filled");
|
|
||||||
}
|
|
||||||
"p3" => {
|
|
||||||
fill_pane(&proxy, anime_type, 2, brightness);
|
|
||||||
println!("Pane 3 (indices 1254-1880) filled");
|
|
||||||
}
|
|
||||||
cmd if cmd.starts_with("f ") => {
|
|
||||||
let parts: Vec<&str> = cmd.split_whitespace().collect();
|
|
||||||
if parts.len() == 3 {
|
|
||||||
if let (Ok(start), Ok(end)) =
|
|
||||||
(parts[1].parse::<usize>(), parts[2].parse::<usize>())
|
|
||||||
{
|
|
||||||
fill_range(&proxy, anime_type, start, end, brightness);
|
|
||||||
println!("Filled indices {} to {}", start, end);
|
|
||||||
} else {
|
|
||||||
println!("Usage: f <start> <end>");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Usage: f <start> <end>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"show" => {
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
}
|
|
||||||
"row" => {
|
|
||||||
if anime_type != AnimeType::G835L {
|
|
||||||
println!("Warning: Row commands use G835L mapping (provisional). You can add to this code to support other types. `examples/anime-led-scan.rs[402:425]`");
|
|
||||||
}
|
|
||||||
println!("Row stepping mode. Press Enter for next row, 'q' to quit.");
|
|
||||||
let total = g835l_total_rows();
|
|
||||||
for row_num in 0..total {
|
|
||||||
let (start, end, len) = g835l_row_bounds(row_num);
|
|
||||||
if end >= scan_len {
|
|
||||||
println!("Row {} exceeds scan limit, stopping.", row_num);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
println!("Row {}: indices {}-{} ({} LEDs)", row_num, start, end, len);
|
|
||||||
fill_range(&proxy, anime_type, start, end, brightness);
|
|
||||||
input.clear();
|
|
||||||
print!("(Enter=next, q=quit) > ");
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
if stdin.lock().read_line(&mut input).is_err() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if input.trim() == "q" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
}
|
|
||||||
println!("Row stepping done.");
|
|
||||||
}
|
|
||||||
cmd if cmd.starts_with("row ") => {
|
|
||||||
if anime_type != AnimeType::G835L {
|
|
||||||
println!("Warning: Row commands use G835L mapping (provisional).");
|
|
||||||
}
|
|
||||||
let row_str = cmd.trim_start_matches("row ").trim();
|
|
||||||
if let Ok(row_num) = row_str.parse::<usize>() {
|
|
||||||
let total = g835l_total_rows();
|
|
||||||
if row_num < total {
|
|
||||||
let (start, end, len) = g835l_row_bounds(row_num);
|
|
||||||
if end < scan_len {
|
|
||||||
println!("Row {}: indices {}-{} ({} LEDs)", row_num, start, end, len);
|
|
||||||
fill_range(&proxy, anime_type, start, end, brightness);
|
|
||||||
} else {
|
|
||||||
println!("Row {} exceeds scan limit", row_num);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Row {} out of range (max: {})", row_num, total - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Usage: row <number>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"allrows" => {
|
|
||||||
if anime_type != AnimeType::G835L {
|
|
||||||
println!("Warning: Row commands use G835L mapping (provisional).");
|
|
||||||
}
|
|
||||||
println!("Lighting all rows sequentially (200ms each)...");
|
|
||||||
let total = g835l_total_rows();
|
|
||||||
let delay = std::time::Duration::from_millis(200);
|
|
||||||
for row_num in 0..total {
|
|
||||||
let (start, end, len) = g835l_row_bounds(row_num);
|
|
||||||
if end >= scan_len {
|
|
||||||
println!("\nRow {} exceeds scan limit, stopping.", row_num);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
print!(
|
|
||||||
"\rRow {}/{}: indices {}-{} ({} LEDs) ",
|
|
||||||
row_num,
|
|
||||||
total - 1,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
len
|
|
||||||
);
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
fill_range(&proxy, anime_type, start, end, brightness);
|
|
||||||
std::thread::sleep(delay);
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
}
|
|
||||||
println!("\nDone.");
|
|
||||||
}
|
|
||||||
"rowmap" => {
|
|
||||||
if anime_type != AnimeType::G835L {
|
|
||||||
println!("Warning: Row map is for G835L (provisional).");
|
|
||||||
}
|
|
||||||
println!("G835L Row Map:");
|
|
||||||
let total = g835l_total_rows();
|
|
||||||
for row_num in 0..total {
|
|
||||||
let (start, end, len) = g835l_row_bounds(row_num);
|
|
||||||
let marker = if end >= scan_len {
|
|
||||||
" (exceeds limit)"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
println!(
|
|
||||||
" Row {:2}: indices {:4}-{:4} ({:2} LEDs){}",
|
|
||||||
row_num, start, end, len, marker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"hold" => {
|
|
||||||
// Single write, wait for Enter to release
|
|
||||||
println!("Holding index {}. Press Enter to release...", current_index);
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
input.clear();
|
|
||||||
let _ = stdin.lock().read_line(&mut input);
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
println!("Released.");
|
|
||||||
}
|
|
||||||
cmd if cmd.starts_with("hold ") => {
|
|
||||||
let arg = cmd.trim_start_matches("hold ").trim();
|
|
||||||
let (start, end): (usize, usize) = match arg {
|
|
||||||
"p1" | "1" => (0, 626),
|
|
||||||
"p2" | "2" => (627, 1253),
|
|
||||||
_ => {
|
|
||||||
let parts: Vec<&str> = arg.split_whitespace().collect();
|
|
||||||
if parts.len() == 2 {
|
|
||||||
if let (Ok(s), Ok(e)) = (parts[0].parse(), parts[1].parse()) {
|
|
||||||
(s, e)
|
|
||||||
} else {
|
|
||||||
println!("Usage: hold p1, hold p2, or hold <start> <end>");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Usage: hold p1, hold p2, or hold <start> <end>");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("Holding range {}-{}. Press Enter to release...", start, end);
|
|
||||||
fill_range(&proxy, anime_type, start, end, brightness);
|
|
||||||
input.clear();
|
|
||||||
let _ = stdin.lock().read_line(&mut input);
|
|
||||||
clear_display(&proxy, anime_type);
|
|
||||||
println!("Released.");
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if let Ok(idx) = cmd.parse::<usize>() {
|
|
||||||
if idx < scan_len {
|
|
||||||
current_index = idx;
|
|
||||||
write_single_led(&proxy, anime_type, current_index, brightness);
|
|
||||||
println!(">>> Index: {} (step: {})", current_index, step);
|
|
||||||
} else {
|
|
||||||
println!("Index {} out of range (max: {})", idx, scan_len - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Unknown command: '{}'. Type 'h' for help.", cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,151 +1,154 @@
|
|||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping};
|
use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
|
||||||
use rog_anime::AnimeType;
|
use rog_anime::AnimeType;
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "anime", description = "anime commands")]
|
|
||||||
pub struct AnimeCommand {
|
pub struct AnimeCommand {
|
||||||
#[argh(option, description = "override the display type")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "override the display type")]
|
||||||
pub override_type: Option<AnimeType>,
|
pub override_type: Option<AnimeType>,
|
||||||
#[argh(option, description = "enable/disable the display")]
|
#[options(meta = "", help = "enable/disable the display")]
|
||||||
pub enable_display: Option<bool>,
|
pub enable_display: Option<bool>,
|
||||||
#[argh(
|
#[options(meta = "", help = "enable/disable the builtin run/powersave animation")]
|
||||||
option,
|
|
||||||
description = "enable/disable the builtin run/powersave animation"
|
|
||||||
)]
|
|
||||||
pub enable_powersave_anim: Option<bool>,
|
pub enable_powersave_anim: Option<bool>,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "set global base brightness value <off, low, med, high>"
|
help = "set global base brightness value <Off, Low, Med, High>"
|
||||||
)]
|
)]
|
||||||
pub brightness: Option<rog_anime::usb::Brightness>,
|
pub brightness: Option<Brightness>,
|
||||||
#[argh(switch, description = "clear the display")]
|
#[options(help = "clear the display")]
|
||||||
pub clear: bool,
|
pub clear: bool,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
no_short,
|
||||||
description = "turn the anime off when external power is unplugged"
|
meta = "",
|
||||||
|
help = "turn the anime off when external power is unplugged"
|
||||||
)]
|
)]
|
||||||
pub off_when_unplugged: Option<bool>,
|
pub off_when_unplugged: Option<bool>,
|
||||||
#[argh(option, description = "turn the anime off when the laptop suspends")]
|
#[options(
|
||||||
|
no_short,
|
||||||
|
meta = "",
|
||||||
|
help = "turn the anime off when the laptop suspends"
|
||||||
|
)]
|
||||||
pub off_when_suspended: Option<bool>,
|
pub off_when_suspended: Option<bool>,
|
||||||
#[argh(option, description = "turn the anime off when the lid is closed")]
|
#[options(
|
||||||
|
no_short,
|
||||||
|
meta = "",
|
||||||
|
help = "turn the anime off when the lid is closed"
|
||||||
|
)]
|
||||||
pub off_when_lid_closed: Option<bool>,
|
pub off_when_lid_closed: Option<bool>,
|
||||||
#[argh(option, description = "off with his head!!!")]
|
#[options(no_short, meta = "", help = "Off with his head!!!")]
|
||||||
pub off_with_his_head: Option<bool>,
|
pub off_with_his_head: Option<bool>,
|
||||||
#[argh(subcommand)]
|
#[options(command)]
|
||||||
pub command: Option<AnimeActions>,
|
pub command: Option<AnimeActions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Anime subcommands (image, gif, builtins, etc.)
|
#[derive(Options)]
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum AnimeActions {
|
pub enum AnimeActions {
|
||||||
|
#[options(help = "display a PNG image")]
|
||||||
Image(AnimeImage),
|
Image(AnimeImage),
|
||||||
|
#[options(help = "display a diagonal/pixel-perfect PNG")]
|
||||||
PixelImage(AnimeImageDiagonal),
|
PixelImage(AnimeImageDiagonal),
|
||||||
|
#[options(help = "display an animated GIF")]
|
||||||
Gif(AnimeGif),
|
Gif(AnimeGif),
|
||||||
|
#[options(help = "display an animated diagonal/pixel-perfect GIF")]
|
||||||
PixelGif(AnimeGifDiagonal),
|
PixelGif(AnimeGifDiagonal),
|
||||||
|
#[options(help = "change which builtin animations are shown")]
|
||||||
SetBuiltins(Builtins),
|
SetBuiltins(Builtins),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "set-builtins",
|
|
||||||
description = "change which builtin animations are shown"
|
|
||||||
)]
|
|
||||||
pub struct Builtins {
|
pub struct Builtins {
|
||||||
#[argh(
|
#[options(help = "print help message")]
|
||||||
option,
|
pub help: bool,
|
||||||
description = "default is used if unspecified, <default:GlitchConstruction, StaticEmergence>"
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
help = "Default is used if unspecified, <default:GlitchConstruction, StaticEmergence>"
|
||||||
)]
|
)]
|
||||||
pub boot: AnimBooting,
|
pub boot: AnimBooting,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "default is used if unspecified, <default:BinaryBannerScroll, RogLogoGlitch>"
|
help = "Default is used if unspecified, <default:BinaryBannerScroll, RogLogoGlitch>"
|
||||||
)]
|
)]
|
||||||
pub awake: AnimAwake,
|
pub awake: AnimAwake,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "default is used if unspecified, <default:BannerSwipe, Starfield>"
|
help = "Default is used if unspecified, <default:BannerSwipe, Starfield>"
|
||||||
)]
|
)]
|
||||||
pub sleep: AnimSleeping,
|
pub sleep: AnimSleeping,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "default is used if unspecified, <default:GlitchOut, SeeYa>"
|
help = "Default is used if unspecified, <default:GlitchOut, SeeYa>"
|
||||||
)]
|
)]
|
||||||
pub shutdown: AnimShutdown,
|
pub shutdown: AnimShutdown,
|
||||||
#[argh(option, description = "set/apply the animations <true/false>")]
|
#[options(meta = "", help = "set/apply the animations <true/false>")]
|
||||||
pub set: Option<bool>,
|
pub set: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "image", description = "display a PNG image")]
|
|
||||||
pub struct AnimeImage {
|
pub struct AnimeImage {
|
||||||
#[argh(option, description = "full path to the png to display")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "full path to the png to display")]
|
||||||
pub path: String,
|
pub path: String,
|
||||||
#[argh(option, default = "1.0", description = "scale 1.0 == normal")]
|
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
|
||||||
pub scale: f32,
|
pub scale: f32,
|
||||||
#[argh(option, default = "0.0", description = "x position (float)")]
|
#[options(meta = "", default = "0.0", help = "x position (float)")]
|
||||||
pub x_pos: f32,
|
pub x_pos: f32,
|
||||||
#[argh(option, default = "0.0", description = "y position (float)")]
|
#[options(meta = "", default = "0.0", help = "y position (float)")]
|
||||||
pub y_pos: f32,
|
pub y_pos: f32,
|
||||||
#[argh(option, default = "0.0", description = "the angle in radians")]
|
#[options(meta = "", default = "0.0", help = "the angle in radians")]
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
#[argh(option, default = "1.0", description = "brightness 0.0-1.0")]
|
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||||
pub bright: f32,
|
pub bright: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "pixel-image",
|
|
||||||
description = "display a diagonal/pixel-perfect PNG"
|
|
||||||
)]
|
|
||||||
pub struct AnimeImageDiagonal {
|
pub struct AnimeImageDiagonal {
|
||||||
#[argh(option, description = "full path to the png to display")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "full path to the png to display")]
|
||||||
pub path: String,
|
pub path: String,
|
||||||
#[argh(option, default = "1.0", description = "brightness 0.0-1.0")]
|
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||||
pub bright: f32,
|
pub bright: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "gif", description = "display an animated GIF")]
|
|
||||||
pub struct AnimeGif {
|
pub struct AnimeGif {
|
||||||
#[argh(option, description = "full path to the gif to display")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "full path to the png to display")]
|
||||||
pub path: String,
|
pub path: String,
|
||||||
#[argh(option, default = "1.0", description = "scale 1.0 == normal")]
|
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
|
||||||
pub scale: f32,
|
pub scale: f32,
|
||||||
#[argh(option, default = "0.0", description = "x position (float)")]
|
#[options(meta = "", default = "0.0", help = "x position (float)")]
|
||||||
pub x_pos: f32,
|
pub x_pos: f32,
|
||||||
#[argh(option, default = "0.0", description = "y position (float)")]
|
#[options(meta = "", default = "0.0", help = "y position (float)")]
|
||||||
pub y_pos: f32,
|
pub y_pos: f32,
|
||||||
#[argh(option, default = "0.0", description = "the angle in radians")]
|
#[options(meta = "", default = "0.0", help = "the angle in radians")]
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
#[argh(option, default = "1.0", description = "brightness 0.0-1.0")]
|
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||||
pub bright: f32,
|
pub bright: f32,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
default = "0",
|
default = "1",
|
||||||
description = "how many loops to play - 0 is infinite"
|
help = "how many loops to play - 0 is infinite"
|
||||||
)]
|
)]
|
||||||
pub loops: u32,
|
pub loops: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "pixel-gif",
|
|
||||||
description = "display an animated diagonal/pixel-perfect GIF"
|
|
||||||
)]
|
|
||||||
pub struct AnimeGifDiagonal {
|
pub struct AnimeGifDiagonal {
|
||||||
#[argh(option, description = "full path to the gif to display")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "full path to the png to display")]
|
||||||
pub path: String,
|
pub path: String,
|
||||||
#[argh(option, default = "1.0", description = "brightness 0.0-1.0")]
|
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||||
pub bright: f32,
|
pub bright: f32,
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
default = "0",
|
default = "1",
|
||||||
description = "how many loops to play - 0 is infinite"
|
help = "how many loops to play - 0 is infinite"
|
||||||
)]
|
)]
|
||||||
pub loops: u32,
|
pub loops: u32,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +1,68 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_aura::error::Error;
|
use rog_aura::error::Error;
|
||||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed};
|
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed};
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone)]
|
#[derive(Options, Debug)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "power-tuf",
|
|
||||||
description = "aura power (old ROGs and TUF laptops)"
|
|
||||||
)]
|
|
||||||
pub struct LedPowerCommand1 {
|
pub struct LedPowerCommand1 {
|
||||||
#[argh(
|
#[options(help = "print help message")]
|
||||||
option,
|
pub help: bool,
|
||||||
description = "control if LEDs enabled while awake <true/false>"
|
#[options(meta = "", help = "Control if LEDs enabled while awake <true/false>")]
|
||||||
)]
|
|
||||||
pub awake: Option<bool>,
|
pub awake: Option<bool>,
|
||||||
|
#[options(help = "Use with awake option, if excluded defaults to false")]
|
||||||
#[argh(
|
|
||||||
switch,
|
|
||||||
description = "use with awake option; if excluded defaults to false"
|
|
||||||
)]
|
|
||||||
pub keyboard: bool,
|
pub keyboard: bool,
|
||||||
|
#[options(help = "Use with awake option, if excluded defaults to false")]
|
||||||
#[argh(
|
|
||||||
switch,
|
|
||||||
description = "use with awake option; if excluded defaults to false"
|
|
||||||
)]
|
|
||||||
pub lightbar: bool,
|
pub lightbar: bool,
|
||||||
|
#[options(meta = "", help = "Control boot animations <true/false>")]
|
||||||
#[argh(option, description = "control boot animations <true/false>")]
|
|
||||||
pub boot: Option<bool>,
|
pub boot: Option<bool>,
|
||||||
|
#[options(meta = "", help = "Control suspend animations <true/false>")]
|
||||||
#[argh(option, description = "control suspend animations <true/false>")]
|
|
||||||
pub sleep: Option<bool>,
|
pub sleep: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone)]
|
#[derive(Options, Debug)]
|
||||||
#[argh(subcommand, name = "power", description = "aura power")]
|
|
||||||
pub struct LedPowerCommand2 {
|
pub struct LedPowerCommand2 {
|
||||||
#[argh(subcommand)]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(command)]
|
||||||
pub command: Option<SetAuraZoneEnabled>,
|
pub command: Option<SetAuraZoneEnabled>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subcommands to enable/disable specific aura zones
|
#[derive(Options, Debug)]
|
||||||
#[derive(FromArgs, Debug, Clone)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum SetAuraZoneEnabled {
|
pub enum SetAuraZoneEnabled {
|
||||||
Keyboard(KeyboardPower),
|
/// Applies to both old and new models
|
||||||
Logo(LogoPower),
|
#[options(help = "")]
|
||||||
Lightbar(LightbarPower),
|
Keyboard(AuraPowerStates),
|
||||||
Lid(LidPower),
|
#[options(help = "")]
|
||||||
RearGlow(RearGlowPower),
|
Logo(AuraPowerStates),
|
||||||
Ally(AllyPower),
|
#[options(help = "")]
|
||||||
|
Lightbar(AuraPowerStates),
|
||||||
|
#[options(help = "")]
|
||||||
|
Lid(AuraPowerStates),
|
||||||
|
#[options(help = "")]
|
||||||
|
RearGlow(AuraPowerStates),
|
||||||
|
#[options(help = "")]
|
||||||
|
Ally(AuraPowerStates),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Keyboard brightness argument helper
|
#[derive(Debug, Clone, Options)]
|
||||||
#[derive(Debug, Clone)]
|
pub struct AuraPowerStates {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(help = "defaults to false if option unused")]
|
||||||
|
pub boot: bool,
|
||||||
|
#[options(help = "defaults to false if option unused")]
|
||||||
|
pub awake: bool,
|
||||||
|
#[options(help = "defaults to false if option unused")]
|
||||||
|
pub sleep: bool,
|
||||||
|
#[options(help = "defaults to false if option unused")]
|
||||||
|
pub shutdown: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
pub struct LedBrightness {
|
pub struct LedBrightness {
|
||||||
level: Option<u8>,
|
level: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LedBrightness {
|
impl LedBrightness {
|
||||||
pub fn new(level: Option<u8>) -> Self {
|
pub fn new(level: Option<u8>) -> Self {
|
||||||
LedBrightness { level }
|
LedBrightness { level }
|
||||||
@@ -71,429 +72,176 @@ impl LedBrightness {
|
|||||||
self.level
|
self.level
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for LedBrightness {
|
impl FromStr for LedBrightness {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let s = s.to_lowercase();
|
let s = s.to_lowercase();
|
||||||
match s.as_str() {
|
match s.as_str() {
|
||||||
"off" => Ok(Self::new(Some(0x00))),
|
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
||||||
"low" => Ok(Self::new(Some(0x01))),
|
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||||
"med" => Ok(Self::new(Some(0x02))),
|
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||||
"high" => Ok(Self::new(Some(0x03))),
|
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||||
_ => Err(Error::ParseBrightness),
|
_ => {
|
||||||
|
print!("Invalid argument, must be one of: off, low, med, high");
|
||||||
|
Err(Error::ParseBrightness)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::to_string_trait_impl)]
|
||||||
impl fmt::Display for LedBrightness {
|
impl ToString for LedBrightness {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn to_string(&self) -> String {
|
||||||
let s = match self.level {
|
let s = match self.level {
|
||||||
Some(0x00) => "off",
|
Some(0x00) => "low",
|
||||||
Some(0x01) => "low",
|
Some(0x01) => "med",
|
||||||
Some(0x02) => "med",
|
Some(0x02) => "high",
|
||||||
Some(0x03) => "high",
|
|
||||||
_ => "unknown",
|
_ => "unknown",
|
||||||
};
|
};
|
||||||
write!(f, "{}", s)
|
s.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "keyboard",
|
|
||||||
description = "set power states for keyboard zone"
|
|
||||||
)]
|
|
||||||
pub struct KeyboardPower {
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "logo",
|
|
||||||
description = "set power states for logo zone"
|
|
||||||
)]
|
|
||||||
pub struct LogoPower {
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "lightbar",
|
|
||||||
description = "set power states for lightbar zone"
|
|
||||||
)]
|
|
||||||
pub struct LightbarPower {
|
|
||||||
#[argh(switch, description = "enable power while device is booting")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "enable power while device is awake")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "enable power while device is sleeping")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(
|
|
||||||
switch,
|
|
||||||
description = "enable power while device is shutting down or hibernating"
|
|
||||||
)]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "lid",
|
|
||||||
description = "set power states for lid zone"
|
|
||||||
)]
|
|
||||||
pub struct LidPower {
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "rear-glow",
|
|
||||||
description = "set power states for rear glow zone"
|
|
||||||
)]
|
|
||||||
pub struct RearGlowPower {
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "ally",
|
|
||||||
description = "set power states for ally zone"
|
|
||||||
)]
|
|
||||||
pub struct AllyPower {
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub boot: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub awake: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub sleep: bool,
|
|
||||||
#[argh(switch, description = "defaults to false if option unused")]
|
|
||||||
pub shutdown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Single speed-based effect
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "rainbow-cycle",
|
|
||||||
description = "single speed-based effect"
|
|
||||||
)]
|
|
||||||
pub struct SingleSpeed {
|
pub struct SingleSpeed {
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
|
#[options(
|
||||||
#[argh(
|
no_long,
|
||||||
option,
|
meta = "",
|
||||||
default = "AuraZone::None",
|
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
)]
|
||||||
pub zone: AuraZone,
|
pub zone: AuraZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single speed effect with direction
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "rainbow-wave",
|
|
||||||
description = "single speed effect with direction"
|
|
||||||
)]
|
|
||||||
pub struct SingleSpeedDirection {
|
pub struct SingleSpeedDirection {
|
||||||
#[argh(option, description = "set the direction: up, down, left, right")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
||||||
pub direction: Direction,
|
pub direction: Direction,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
|
#[options(
|
||||||
#[argh(
|
no_long,
|
||||||
option,
|
meta = "",
|
||||||
default = "AuraZone::None",
|
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
)]
|
||||||
pub zone: AuraZone,
|
pub zone: AuraZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static single-colour effect
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "static",
|
|
||||||
description = "static single-colour effect"
|
|
||||||
)]
|
|
||||||
pub struct SingleColour {
|
pub struct SingleColour {
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
pub colour: Colour,
|
pub colour: Colour,
|
||||||
|
#[options(
|
||||||
#[argh(
|
no_long,
|
||||||
option,
|
meta = "",
|
||||||
default = "AuraZone::None",
|
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
)]
|
||||||
pub zone: AuraZone,
|
pub zone: AuraZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single-colour effect with speed
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "highlight",
|
|
||||||
description = "single-colour effect with speed"
|
|
||||||
)]
|
|
||||||
pub struct SingleColourSpeed {
|
pub struct SingleColourSpeed {
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
pub colour: Colour,
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
|
#[options(
|
||||||
#[argh(
|
no_long,
|
||||||
option,
|
meta = "",
|
||||||
default = "AuraZone::None",
|
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
)]
|
||||||
pub zone: AuraZone,
|
pub zone: AuraZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Two-colour breathing effect
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "breathe",
|
|
||||||
description = "two-colour breathing effect"
|
|
||||||
)]
|
|
||||||
pub struct TwoColourSpeed {
|
pub struct TwoColourSpeed {
|
||||||
#[argh(option, description = "set the first RGB value e.g. ff00ff")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
||||||
pub colour: Colour,
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
||||||
#[argh(option, description = "set the second RGB value e.g. ff00ff")]
|
|
||||||
pub colour2: Colour,
|
pub colour2: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
|
#[options(
|
||||||
#[argh(
|
no_long,
|
||||||
option,
|
meta = "",
|
||||||
default = "AuraZone::None",
|
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
)]
|
||||||
pub zone: AuraZone,
|
pub zone: AuraZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Two-colour star effect (separate subcommand name)
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(subcommand, name = "stars", description = "two-colour star effect")]
|
|
||||||
pub struct StarsTwoColour {
|
|
||||||
#[argh(option, description = "set the first RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(option, description = "set the second RGB value e.g. ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
|
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rain effect (single-speed, separate subcommand name)
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "rain",
|
|
||||||
description = "single speed-based rain effect"
|
|
||||||
)]
|
|
||||||
pub struct RainSingleSpeed {
|
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Laser (single-colour with speed) separate subcommand
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "laser",
|
|
||||||
description = "single-colour effect with speed"
|
|
||||||
)]
|
|
||||||
pub struct LaserSingleColourSpeed {
|
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ripple (single-colour with speed) separate subcommand
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "ripple",
|
|
||||||
description = "single-colour effect with speed"
|
|
||||||
)]
|
|
||||||
pub struct RippleSingleColourSpeed {
|
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pulse / Comet / Flash variants (single-colour) separate subcommands
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(subcommand, name = "pulse", description = "single-colour pulse effect")]
|
|
||||||
pub struct PulseSingleColour {
|
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(subcommand, name = "comet", description = "single-colour comet effect")]
|
|
||||||
pub struct CometSingleColour {
|
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[argh(subcommand, name = "flash", description = "single-colour flash effect")]
|
|
||||||
pub struct FlashSingleColour {
|
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "AuraZone::None",
|
|
||||||
description = "set the zone for this effect e.g. 0, 1, one, logo, lightbar-left"
|
|
||||||
)]
|
|
||||||
pub zone: AuraZone,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Multi-zone colour settings
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[argh(description = "multi-zone colour settings")]
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
pub struct MultiZone {
|
pub struct MultiZone {
|
||||||
#[argh(option, short = 'a', description = "set the RGB value e.g. ff00ff")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
pub colour1: Colour,
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'b', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour2: Colour,
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour3: Colour,
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'd', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour4: Colour,
|
pub colour4: Colour,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multi-colour with speed
|
|
||||||
#[derive(FromArgs, Debug, Clone, Default)]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[argh(description = "multi-colour with speed")]
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
pub struct MultiColourSpeed {
|
pub struct MultiColourSpeed {
|
||||||
#[argh(option, short = 'a', description = "set the RGB value e.g. ff00ff")]
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
pub colour1: Colour,
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'b', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour2: Colour,
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'c', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour3: Colour,
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
#[argh(option, short = 'd', description = "set the RGB value e.g. ff00ff")]
|
|
||||||
pub colour4: Colour,
|
pub colour4: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
#[argh(option, description = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builtin aura effects
|
/// Byte value for setting the built-in mode.
|
||||||
#[derive(FromArgs, Debug)]
|
///
|
||||||
#[argh(subcommand)]
|
/// Enum corresponds to the required integer value
|
||||||
|
// NOTE: The option names here must match those in rog-aura crate
|
||||||
|
#[derive(Options)]
|
||||||
pub enum SetAuraBuiltin {
|
pub enum SetAuraBuiltin {
|
||||||
Static(SingleColour), // 0
|
#[options(help = "set a single static colour")]
|
||||||
Breathe(TwoColourSpeed), // 1
|
Static(SingleColour), // 0
|
||||||
RainbowCycle(SingleSpeed), // 2
|
#[options(help = "pulse between one or two colours")]
|
||||||
|
Breathe(TwoColourSpeed), // 1
|
||||||
|
#[options(help = "strobe through all colours")]
|
||||||
|
RainbowCycle(SingleSpeed), // 2
|
||||||
|
#[options(help = "rainbow cycling in one of four directions")]
|
||||||
RainbowWave(SingleSpeedDirection), // 3
|
RainbowWave(SingleSpeedDirection), // 3
|
||||||
Stars(StarsTwoColour), // 4
|
#[options(help = "rain pattern mimicking raindrops")]
|
||||||
Rain(RainSingleSpeed), // 5
|
Stars(TwoColourSpeed), // 4
|
||||||
Highlight(SingleColourSpeed), // 6
|
#[options(help = "rain pattern of three preset colours")]
|
||||||
Laser(LaserSingleColourSpeed), // 7
|
Rain(SingleSpeed), // 5
|
||||||
Ripple(RippleSingleColourSpeed), // 8
|
#[options(help = "pressed keys are highlighted to fade")]
|
||||||
Pulse(PulseSingleColour), // 10
|
Highlight(SingleColourSpeed), // 6
|
||||||
Comet(CometSingleColour), // 11
|
#[options(help = "pressed keys generate horizontal laser")]
|
||||||
Flash(FlashSingleColour), // 12
|
Laser(SingleColourSpeed), // 7
|
||||||
|
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||||
|
Ripple(SingleColourSpeed), // 8
|
||||||
|
#[options(help = "set a rapid pulse")]
|
||||||
|
Pulse(SingleColour), // 10
|
||||||
|
#[options(help = "set a vertical line zooming from left")]
|
||||||
|
Comet(SingleColour), // 11
|
||||||
|
#[options(help = "set a wide vertical line zooming from left")]
|
||||||
|
Flash(SingleColour), // 12
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SetAuraBuiltin {
|
impl Default for SetAuraBuiltin {
|
||||||
@@ -555,79 +303,6 @@ impl From<&SingleSpeedDirection> for AuraEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&StarsTwoColour> for AuraEffect {
|
|
||||||
fn from(aura: &StarsTwoColour) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
colour2: aura.colour2,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&RainSingleSpeed> for AuraEffect {
|
|
||||||
fn from(aura: &RainSingleSpeed) -> Self {
|
|
||||||
Self {
|
|
||||||
speed: aura.speed,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&LaserSingleColourSpeed> for AuraEffect {
|
|
||||||
fn from(aura: &LaserSingleColourSpeed) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
speed: aura.speed,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&RippleSingleColourSpeed> for AuraEffect {
|
|
||||||
fn from(aura: &RippleSingleColourSpeed) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
speed: aura.speed,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&PulseSingleColour> for AuraEffect {
|
|
||||||
fn from(aura: &PulseSingleColour) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&CometSingleColour> for AuraEffect {
|
|
||||||
fn from(aura: &CometSingleColour) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&FlashSingleColour> for AuraEffect {
|
|
||||||
fn from(aura: &FlashSingleColour) -> Self {
|
|
||||||
Self {
|
|
||||||
colour1: aura.colour,
|
|
||||||
zone: aura.zone,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&SetAuraBuiltin> for AuraEffect {
|
impl From<&SetAuraBuiltin> for AuraEffect {
|
||||||
fn from(aura: &SetAuraBuiltin) -> Self {
|
fn from(aura: &SetAuraBuiltin) -> Self {
|
||||||
match aura {
|
match aura {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_platform::platform::PlatformProfile;
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
use crate::anime_cli::AnimeCommand;
|
use crate::anime_cli::AnimeCommand;
|
||||||
@@ -7,321 +7,128 @@ use crate::fan_curve_cli::FanCurveCommand;
|
|||||||
use crate::scsi_cli::ScsiCommand;
|
use crate::scsi_cli::ScsiCommand;
|
||||||
use crate::slash_cli::SlashCommand;
|
use crate::slash_cli::SlashCommand;
|
||||||
|
|
||||||
#[derive(FromArgs, Default, Debug)]
|
#[derive(Default, Options)]
|
||||||
/// asusctl command-line options
|
|
||||||
pub struct CliStart {
|
pub struct CliStart {
|
||||||
#[argh(subcommand)]
|
#[options(help_flag, help = "print help message")]
|
||||||
pub command: CliCommand,
|
pub help: bool,
|
||||||
|
#[options(help = "show program version number")]
|
||||||
|
pub version: bool,
|
||||||
|
#[options(help = "show supported functions of this laptop")]
|
||||||
|
pub show_supported: bool,
|
||||||
|
#[options(meta = "", help = "<off, low, med, high>")]
|
||||||
|
pub kbd_bright: Option<LedBrightness>,
|
||||||
|
#[options(help = "Toggle to next keyboard brightness")]
|
||||||
|
pub next_kbd_bright: bool,
|
||||||
|
#[options(help = "Toggle to previous keyboard brightness")]
|
||||||
|
pub prev_kbd_bright: bool,
|
||||||
|
#[options(meta = "", help = "Set your battery charge limit <20-100>")]
|
||||||
|
pub chg_limit: Option<u8>,
|
||||||
|
#[options(help = "Toggle one-shot battery charge to 100%")]
|
||||||
|
pub one_shot_chg: bool,
|
||||||
|
#[options(command)]
|
||||||
|
pub command: Option<CliCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Top-level subcommands for asusctl
|
#[derive(Options)]
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum CliCommand {
|
pub enum CliCommand {
|
||||||
Aura(AuraCommand),
|
#[options(help = "Set the keyboard lighting from built-in modes")]
|
||||||
Brightness(BrightnessCommand),
|
Aura(LedModeCommand),
|
||||||
|
#[options(help = "Set the LED power states")]
|
||||||
|
AuraPowerOld(LedPowerCommand1),
|
||||||
|
#[options(help = "Set the LED power states")]
|
||||||
|
AuraPower(LedPowerCommand2),
|
||||||
|
#[options(help = "Set or select platform_profile")]
|
||||||
Profile(ProfileCommand),
|
Profile(ProfileCommand),
|
||||||
|
#[options(help = "Set, select, or modify fan curves if supported")]
|
||||||
FanCurve(FanCurveCommand),
|
FanCurve(FanCurveCommand),
|
||||||
|
#[options(help = "Set the graphics mode (obsoleted by supergfxctl)")]
|
||||||
|
Graphics(GraphicsCommand),
|
||||||
|
#[options(name = "anime", help = "Manage AniMe Matrix")]
|
||||||
Anime(AnimeCommand),
|
Anime(AnimeCommand),
|
||||||
|
#[options(name = "slash", help = "Manage Slash Ledbar")]
|
||||||
Slash(SlashCommand),
|
Slash(SlashCommand),
|
||||||
|
#[options(name = "scsi", help = "Manage SCSI external drive")]
|
||||||
Scsi(ScsiCommand),
|
Scsi(ScsiCommand),
|
||||||
|
#[options(
|
||||||
|
help = "Change platform settings. This is a new interface exposed by the asus-armoury \
|
||||||
|
driver, some of the settings will be the same as the older platform interface"
|
||||||
|
)]
|
||||||
Armoury(ArmouryCommand),
|
Armoury(ArmouryCommand),
|
||||||
|
#[options(name = "backlight", help = "Set screen backlight levels")]
|
||||||
Backlight(BacklightCommand),
|
Backlight(BacklightCommand),
|
||||||
Battery(BatteryCommand),
|
|
||||||
Info(InfoCommand),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CliCommand {
|
#[derive(Debug, Clone, Options)]
|
||||||
fn default() -> Self {
|
|
||||||
CliCommand::Info(InfoCommand::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand, name = "profile", description = "profile management")]
|
|
||||||
pub struct ProfileCommand {
|
pub struct ProfileCommand {
|
||||||
#[argh(subcommand)]
|
#[options(help = "print help message")]
|
||||||
pub command: ProfileSubCommand,
|
pub help: bool,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[options(help = "toggle to next profile in list")]
|
||||||
#[argh(subcommand)]
|
pub next: bool,
|
||||||
pub enum ProfileSubCommand {
|
|
||||||
Next(ProfileNextCommand),
|
|
||||||
List(ProfileListCommand),
|
|
||||||
Get(ProfileGetCommand),
|
|
||||||
Set(ProfileSetCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ProfileSubCommand {
|
#[options(help = "list available profiles")]
|
||||||
fn default() -> Self {
|
pub list: bool,
|
||||||
ProfileSubCommand::List(ProfileListCommand::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[options(help = "get profile")]
|
||||||
#[argh(
|
pub profile_get: bool,
|
||||||
subcommand,
|
|
||||||
name = "next",
|
|
||||||
description = "toggle to next profile in list"
|
|
||||||
)]
|
|
||||||
pub struct ProfileNextCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[options(meta = "", help = "set the active profile")]
|
||||||
#[argh(subcommand, name = "list", description = "list available profiles")]
|
pub profile_set: Option<PlatformProfile>,
|
||||||
pub struct ProfileListCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[options(short = "a", meta = "", help = "set the profile to use on AC power")]
|
||||||
#[argh(subcommand, name = "get", description = "get profile")]
|
pub profile_set_ac: Option<PlatformProfile>,
|
||||||
pub struct ProfileGetCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[options(
|
||||||
#[argh(subcommand, name = "set", description = "set profile")]
|
short = "b",
|
||||||
pub struct ProfileSetCommand {
|
meta = "",
|
||||||
#[argh(positional, description = "profile to set")]
|
help = "set the profile to use on battery power"
|
||||||
pub profile: PlatformProfile,
|
|
||||||
|
|
||||||
#[argh(
|
|
||||||
switch,
|
|
||||||
short = 'a',
|
|
||||||
description = "set the profile to use on AC power"
|
|
||||||
)]
|
)]
|
||||||
pub ac: bool,
|
pub profile_set_bat: Option<PlatformProfile>,
|
||||||
|
|
||||||
#[argh(
|
|
||||||
switch,
|
|
||||||
short = 'b',
|
|
||||||
description = "set the profile to use on battery power"
|
|
||||||
)]
|
|
||||||
pub battery: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "effect", description = "led mode commands")]
|
|
||||||
pub struct LedModeCommand {
|
pub struct LedModeCommand {
|
||||||
#[argh(switch, description = "switch to next aura mode")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(help = "switch to next aura mode")]
|
||||||
pub next_mode: bool,
|
pub next_mode: bool,
|
||||||
|
#[options(help = "switch to previous aura mode")]
|
||||||
#[argh(switch, description = "switch to previous aura mode")]
|
|
||||||
pub prev_mode: bool,
|
pub prev_mode: bool,
|
||||||
|
#[options(command)]
|
||||||
#[argh(subcommand)]
|
|
||||||
pub command: Option<SetAuraBuiltin>,
|
pub command: Option<SetAuraBuiltin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "aura", description = "aura device commands")]
|
pub struct GraphicsCommand {
|
||||||
pub struct AuraCommand {
|
#[options(help = "print help message")]
|
||||||
#[argh(subcommand)]
|
pub help: bool,
|
||||||
pub command: AuraSubCommand,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options, Debug)]
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum AuraSubCommand {
|
|
||||||
Power(LedPowerCommand2),
|
|
||||||
PowerTuf(LedPowerCommand1),
|
|
||||||
Effect(LedModeCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "armoury",
|
|
||||||
description = "armoury / firmware attributes"
|
|
||||||
)]
|
|
||||||
pub struct ArmouryCommand {
|
pub struct ArmouryCommand {
|
||||||
#[argh(subcommand)]
|
#[options(help = "print help message")]
|
||||||
pub command: ArmourySubCommand,
|
pub help: bool,
|
||||||
}
|
#[options(
|
||||||
|
free,
|
||||||
#[derive(FromArgs, Debug)]
|
help = "append each value name followed by the value to set. `-1` sets to default"
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum ArmourySubCommand {
|
|
||||||
Set(ArmouryPropertySetCommand),
|
|
||||||
Get(ArmouryPropertyGetCommand),
|
|
||||||
List(ArmouryPropertyListCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ArmourySubCommand {
|
|
||||||
fn default() -> Self {
|
|
||||||
ArmourySubCommand::List(ArmouryPropertyListCommand::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "set",
|
|
||||||
description = "set an asus-armoury firmware-attribute"
|
|
||||||
)]
|
|
||||||
pub struct ArmouryPropertySetCommand {
|
|
||||||
#[argh(
|
|
||||||
positional,
|
|
||||||
description = "name of the attribute to set (see asus-armoury list for available properties)"
|
|
||||||
)]
|
)]
|
||||||
pub property: String,
|
pub free: Vec<String>,
|
||||||
|
|
||||||
#[argh(positional, description = "value to set for the given attribute")]
|
|
||||||
pub value: i32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
#[derive(Options)]
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "list",
|
|
||||||
description = "list all firmware-attributes supported by asus-armoury"
|
|
||||||
)]
|
|
||||||
pub struct ArmouryPropertyListCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "get",
|
|
||||||
description = "get a firmware-attribute from asus-armoury"
|
|
||||||
)]
|
|
||||||
pub struct ArmouryPropertyGetCommand {
|
|
||||||
#[argh(
|
|
||||||
positional,
|
|
||||||
description = "name of the property to get (see asus-armoury list for available properties)"
|
|
||||||
)]
|
|
||||||
pub property: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(subcommand, name = "backlight", description = "backlight options")]
|
|
||||||
pub struct BacklightCommand {
|
pub struct BacklightCommand {
|
||||||
#[argh(option, description = "set screen brightness <0-100>")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "Set screen brightness <0-100>")]
|
||||||
pub screenpad_brightness: Option<i32>,
|
pub screenpad_brightness: Option<i32>,
|
||||||
|
#[options(
|
||||||
#[argh(
|
meta = "",
|
||||||
option,
|
help = "Set screenpad gamma brightness 0.5 - 2.2, 1.0 == linear"
|
||||||
description = "set screenpad gamma brightness 0.5 - 2.2, 1.0 == linear"
|
|
||||||
)]
|
)]
|
||||||
pub screenpad_gamma: Option<f32>,
|
pub screenpad_gamma: Option<f32>,
|
||||||
|
#[options(
|
||||||
#[argh(
|
meta = "",
|
||||||
option,
|
help = "Set screenpad brightness to sync with primary display"
|
||||||
description = "set screenpad brightness to sync with primary display"
|
|
||||||
)]
|
)]
|
||||||
pub sync_screenpad_brightness: Option<bool>,
|
pub sync_screenpad_brightness: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand, name = "battery", description = "battery options")]
|
|
||||||
pub struct BatteryCommand {
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub command: BatterySubCommand,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum BatterySubCommand {
|
|
||||||
Limit(BatteryLimitCommand),
|
|
||||||
OneShot(BatteryOneShotCommand),
|
|
||||||
Info(BatteryInfoCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for BatterySubCommand {
|
|
||||||
fn default() -> Self {
|
|
||||||
BatterySubCommand::OneShot(BatteryOneShotCommand::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "limit",
|
|
||||||
description = "set battery charge limit <20-100>"
|
|
||||||
)]
|
|
||||||
pub struct BatteryLimitCommand {
|
|
||||||
#[argh(positional, description = "charge limit percentage 20-100")]
|
|
||||||
pub limit: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "oneshot",
|
|
||||||
description = "one-shot full charge (optional percent)"
|
|
||||||
)]
|
|
||||||
pub struct BatteryOneShotCommand {
|
|
||||||
#[argh(positional, description = "optional target percent (defaults to 100)")]
|
|
||||||
pub percent: Option<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "info",
|
|
||||||
description = "show current battery charge limit"
|
|
||||||
)]
|
|
||||||
pub struct BatteryInfoCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "info",
|
|
||||||
description = "show program version and system info"
|
|
||||||
)]
|
|
||||||
pub struct InfoCommand {
|
|
||||||
#[argh(switch, description = "show supported functions of this laptop")]
|
|
||||||
pub show_supported: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand, name = "leds", description = "keyboard brightness control")]
|
|
||||||
pub struct BrightnessCommand {
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub command: BrightnessSubCommand,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
pub enum BrightnessSubCommand {
|
|
||||||
Set(BrightnessSetCommand),
|
|
||||||
Get(BrightnessGetCommand),
|
|
||||||
Next(BrightnessNextCommand),
|
|
||||||
Prev(BrightnessPrevCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for BrightnessSubCommand {
|
|
||||||
fn default() -> Self {
|
|
||||||
BrightnessSubCommand::Get(BrightnessGetCommand::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "set",
|
|
||||||
description = "set keyboard brightness <off, low, med, high>"
|
|
||||||
)]
|
|
||||||
pub struct BrightnessSetCommand {
|
|
||||||
#[argh(positional, description = "brightness level: off, low, med, high")]
|
|
||||||
pub level: LedBrightness,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "get",
|
|
||||||
description = "get current keyboard brightness"
|
|
||||||
)]
|
|
||||||
pub struct BrightnessGetCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "next",
|
|
||||||
description = "toggle to next keyboard brightness"
|
|
||||||
)]
|
|
||||||
pub struct BrightnessNextCommand {}
|
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Default)]
|
|
||||||
#[argh(
|
|
||||||
subcommand,
|
|
||||||
name = "prev",
|
|
||||||
description = "toggle to previous keyboard brightness"
|
|
||||||
)]
|
|
||||||
pub struct BrightnessPrevCommand {}
|
|
||||||
|
|||||||
@@ -1,44 +1,49 @@
|
|||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_platform::platform::PlatformProfile;
|
use rog_platform::platform::PlatformProfile;
|
||||||
use rog_profiles::fan_curve_set::CurveData;
|
use rog_profiles::fan_curve_set::CurveData;
|
||||||
use rog_profiles::FanCurvePU;
|
use rog_profiles::FanCurvePU;
|
||||||
|
|
||||||
#[derive(FromArgs, Debug, Clone)]
|
#[derive(Debug, Clone, Options)]
|
||||||
#[argh(subcommand, name = "fan-curve", description = "fan curve commands")]
|
|
||||||
pub struct FanCurveCommand {
|
pub struct FanCurveCommand {
|
||||||
#[argh(switch, description = "get enabled fan profiles")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
|
||||||
|
#[options(help = "get enabled fan profiles")]
|
||||||
pub get_enabled: bool,
|
pub get_enabled: bool,
|
||||||
|
|
||||||
#[argh(switch, description = "set the active profile's fan curve to default")]
|
#[options(help = "set the active profile's fan curve to default")]
|
||||||
pub default: bool,
|
pub default: bool,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "profile to modify fan-curve for. shows data if no options provided"
|
help = "profile to modify fan-curve for. Shows data if no options provided"
|
||||||
)]
|
)]
|
||||||
pub mod_profile: Option<PlatformProfile>,
|
pub mod_profile: Option<PlatformProfile>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "enable or disable <true/false> fan all curves for a profile; --mod_profile required"
|
help = "enable or disable <true/false> fan all curves for a profile. `--mod_profile` \
|
||||||
|
required"
|
||||||
)]
|
)]
|
||||||
pub enable_fan_curves: Option<bool>,
|
pub enable_fan_curves: Option<bool>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "enable or disable <true/false> a single fan curve for a profile; --mod_profile and --fan required"
|
help = "enable or disable <true/false> a single fan curve for a profile. `--mod_profile` \
|
||||||
|
and `--fan` required"
|
||||||
)]
|
)]
|
||||||
pub enable_fan_curve: Option<bool>,
|
pub enable_fan_curve: Option<bool>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "select fan <cpu/gpu/mid> to modify; --mod_profile required"
|
help = "select fan <cpu/gpu/mid> to modify. `--mod_profile` required"
|
||||||
)]
|
)]
|
||||||
pub fan: Option<FanCurvePU>,
|
pub fan: Option<FanCurvePU>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "data format = 30c:1%,49c:2%,...; --mod-profile required. If '%' is omitted the fan range is 0-255"
|
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%. \
|
||||||
|
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
|
||||||
)]
|
)]
|
||||||
pub data: Option<CurveData>,
|
pub data: Option<CurveData>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::env::args;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
@@ -7,11 +8,12 @@ use anime_cli::{AnimeActions, AnimeCommand};
|
|||||||
use aura_cli::{LedPowerCommand1, LedPowerCommand2};
|
use aura_cli::{LedPowerCommand1, LedPowerCommand2};
|
||||||
use dmi_id::DMIID;
|
use dmi_id::DMIID;
|
||||||
use fan_curve_cli::FanCurveCommand;
|
use fan_curve_cli::FanCurveCommand;
|
||||||
use log::{error, info, LevelFilter};
|
use gumdrop::{Opt, Options};
|
||||||
|
use log::{error, info};
|
||||||
use rog_anime::usb::get_anime_type;
|
use rog_anime::usb::get_anime_type;
|
||||||
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
|
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
|
||||||
use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower};
|
use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower};
|
||||||
use rog_aura::{self, AuraEffect, PowerZones};
|
use rog_aura::{self, AuraDeviceType, AuraEffect, PowerZones};
|
||||||
use rog_dbus::asus_armoury::AsusArmouryProxyBlocking;
|
use rog_dbus::asus_armoury::AsusArmouryProxyBlocking;
|
||||||
use rog_dbus::list_iface_blocking;
|
use rog_dbus::list_iface_blocking;
|
||||||
use rog_dbus::scsi_aura::ScsiAuraProxyBlocking;
|
use rog_dbus::scsi_aura::ScsiAuraProxyBlocking;
|
||||||
@@ -30,6 +32,7 @@ use scsi_cli::ScsiCommand;
|
|||||||
use zbus::blocking::proxy::ProxyImpl;
|
use zbus::blocking::proxy::ProxyImpl;
|
||||||
use zbus::blocking::Connection;
|
use zbus::blocking::Connection;
|
||||||
|
|
||||||
|
use crate::aura_cli::{AuraPowerStates, LedBrightness};
|
||||||
use crate::cli_opts::*;
|
use crate::cli_opts::*;
|
||||||
use crate::slash_cli::SlashCommand;
|
use crate::slash_cli::SlashCommand;
|
||||||
|
|
||||||
@@ -41,19 +44,30 @@ mod scsi_cli;
|
|||||||
mod slash_cli;
|
mod slash_cli;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Ensure tracing spans are quiet by default unless user overrides
|
|
||||||
if std::env::var_os("RUST_LOG").is_none() {
|
|
||||||
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
|
|
||||||
}
|
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
logger
|
logger
|
||||||
.parse_default_env()
|
.parse_default_env()
|
||||||
.filter_level(LevelFilter::Info)
|
.target(env_logger::Target::Stdout)
|
||||||
.target(env_logger::Target::Stderr)
|
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
|
.filter_level(log::LevelFilter::Debug)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let parsed: CliStart = argh::from_env();
|
let self_version = env!("CARGO_PKG_VERSION");
|
||||||
|
println!("Starting version {self_version}");
|
||||||
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
|
|
||||||
|
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
||||||
|
let parsed = match CliStart::parse_args_default(&args) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(err) if err.to_string() == missing_argument_k.to_string() => CliStart {
|
||||||
|
kbd_bright: Some(LedBrightness::new(None)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let conn = Connection::system().unwrap();
|
let conn = Connection::system().unwrap();
|
||||||
if let Ok(platform_proxy) = PlatformProxyBlocking::new(&conn).map_err(|e| {
|
if let Ok(platform_proxy) = PlatformProxyBlocking::new(&conn).map_err(|e| {
|
||||||
@@ -72,7 +86,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let self_version = env!("CARGO_PKG_VERSION");
|
|
||||||
if asusd_version != self_version {
|
if asusd_version != self_version {
|
||||||
println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}");
|
println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}");
|
||||||
return;
|
return;
|
||||||
@@ -93,6 +106,12 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if parsed.version {
|
||||||
|
println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
|
||||||
|
println!();
|
||||||
|
print_info();
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(err) = do_parsed(&parsed, &supported_interfaces, &supported_properties, conn) {
|
if let Err(err) = do_parsed(&parsed, &supported_interfaces, &supported_properties, conn) {
|
||||||
print_error_help(&*err, &supported_interfaces, &supported_properties);
|
print_error_help(&*err, &supported_interfaces, &supported_properties);
|
||||||
}
|
}
|
||||||
@@ -119,9 +138,9 @@ fn print_info() {
|
|||||||
let dmi = DMIID::new().unwrap_or_default();
|
let dmi = DMIID::new().unwrap_or_default();
|
||||||
let board_name = dmi.board_name;
|
let board_name = dmi.board_name;
|
||||||
let prod_family = dmi.product_family;
|
let prod_family = dmi.product_family;
|
||||||
println!("Software version: {}", env!("CARGO_PKG_VERSION"));
|
println!("asusctl version: {}", env!("CARGO_PKG_VERSION"));
|
||||||
println!(" Product family: {}", prod_family.trim());
|
println!(" Product family: {}", prod_family.trim());
|
||||||
println!(" Board name: {}", board_name.trim());
|
println!(" Board name: {}", board_name.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_service(name: &str) -> bool {
|
fn check_service(name: &str) -> bool {
|
||||||
@@ -186,65 +205,149 @@ fn do_parsed(
|
|||||||
conn: Connection,
|
conn: Connection,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
match &parsed.command {
|
match &parsed.command {
|
||||||
CliCommand::Aura(a) => match &a.command {
|
Some(CliCommand::Aura(mode)) => handle_led_mode(mode)?,
|
||||||
crate::cli_opts::AuraSubCommand::Effect(mode) => handle_led_mode(mode)?,
|
Some(CliCommand::AuraPowerOld(pow)) => handle_led_power1(pow)?,
|
||||||
crate::cli_opts::AuraSubCommand::PowerTuf(pow) => handle_led_power1(pow)?,
|
Some(CliCommand::AuraPower(pow)) => handle_led_power2(pow)?,
|
||||||
crate::cli_opts::AuraSubCommand::Power(pow) => handle_led_power2(pow)?,
|
Some(CliCommand::Profile(cmd)) => {
|
||||||
},
|
handle_throttle_profile(&conn, supported_properties, cmd)?
|
||||||
CliCommand::Brightness(cmd) => handle_brightness(cmd)?,
|
|
||||||
CliCommand::Profile(cmd) => handle_throttle_profile(&conn, supported_properties, cmd)?,
|
|
||||||
CliCommand::FanCurve(cmd) => handle_fan_curve(&conn, cmd)?,
|
|
||||||
CliCommand::Anime(cmd) => handle_anime(cmd)?,
|
|
||||||
CliCommand::Slash(cmd) => handle_slash(cmd)?,
|
|
||||||
CliCommand::Scsi(cmd) => handle_scsi(cmd)?,
|
|
||||||
CliCommand::Armoury(cmd) => handle_armoury_command(cmd)?,
|
|
||||||
CliCommand::Backlight(cmd) => handle_backlight(cmd)?,
|
|
||||||
CliCommand::Battery(cmd) => handle_battery(cmd, &conn)?,
|
|
||||||
CliCommand::Info(info_opt) => {
|
|
||||||
handle_info(info_opt, supported_interfaces, supported_properties)?
|
|
||||||
}
|
}
|
||||||
}
|
Some(CliCommand::FanCurve(cmd)) => {
|
||||||
|
handle_fan_curve(&conn, cmd)?;
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_battery(
|
|
||||||
cmd: &BatteryCommand,
|
|
||||||
conn: &Connection,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
match &cmd.command {
|
|
||||||
BatterySubCommand::Limit(l) => {
|
|
||||||
let proxy = PlatformProxyBlocking::new(conn)?;
|
|
||||||
proxy.set_charge_control_end_threshold(l.limit)?;
|
|
||||||
}
|
}
|
||||||
BatterySubCommand::OneShot(o) => {
|
Some(CliCommand::Graphics(_)) => do_gfx(),
|
||||||
let proxy = PlatformProxyBlocking::new(conn)?;
|
Some(CliCommand::Anime(cmd)) => handle_anime(cmd)?,
|
||||||
if let Some(p) = o.percent {
|
Some(CliCommand::Slash(cmd)) => handle_slash(cmd)?,
|
||||||
proxy.set_charge_control_end_threshold(p)?;
|
Some(CliCommand::Scsi(cmd)) => handle_scsi(cmd)?,
|
||||||
|
Some(CliCommand::Armoury(cmd)) => handle_armoury_command(cmd)?,
|
||||||
|
Some(CliCommand::Backlight(cmd)) => handle_backlight(cmd)?,
|
||||||
|
None => {
|
||||||
|
if (!parsed.show_supported
|
||||||
|
&& parsed.kbd_bright.is_none()
|
||||||
|
&& parsed.chg_limit.is_none()
|
||||||
|
&& !parsed.next_kbd_bright
|
||||||
|
&& !parsed.prev_kbd_bright
|
||||||
|
&& !parsed.one_shot_chg)
|
||||||
|
|| parsed.help
|
||||||
|
{
|
||||||
|
println!("{}", CliStart::usage());
|
||||||
|
println!();
|
||||||
|
if let Some(cmdlist) = CliStart::command_list() {
|
||||||
|
let dev_type =
|
||||||
|
if let Ok(proxy) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") {
|
||||||
|
// TODO: commands on all?
|
||||||
|
proxy
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.device_type()
|
||||||
|
.unwrap_or(AuraDeviceType::Unknown)
|
||||||
|
} else {
|
||||||
|
AuraDeviceType::Unknown
|
||||||
|
};
|
||||||
|
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||||
|
for command in commands.iter().filter(|command| {
|
||||||
|
if command.trim().starts_with("fan-curve")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.FanCurves".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("aura")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.Aura".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("anime")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.Anime".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("slash")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.Slash".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("platform")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.Platform".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("armoury")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.AsusArmoury".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if command.trim().starts_with("backlight")
|
||||||
|
&& !supported_interfaces.contains(&"xyz.ljones.Backlight".to_string())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dev_type.is_old_laptop()
|
||||||
|
&& !dev_type.is_tuf_laptop()
|
||||||
|
&& command.trim().starts_with("aura-power-old")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if !dev_type.is_new_laptop() && command.trim().starts_with("aura-power") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}) {
|
||||||
|
println!("{}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nExtra help can be requested on any command or subcommand:");
|
||||||
|
println!(" asusctl aura --help");
|
||||||
|
println!(" asusctl aura static --help");
|
||||||
}
|
}
|
||||||
proxy.one_shot_full_charge()?;
|
|
||||||
}
|
|
||||||
BatterySubCommand::Info(_) => {
|
|
||||||
let proxy = PlatformProxyBlocking::new(conn)?;
|
|
||||||
let limit = proxy.charge_control_end_threshold()?;
|
|
||||||
println!("Current battery charge limit: {}%", limit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
if let Some(brightness) = &parsed.kbd_bright {
|
||||||
}
|
if let Ok(aura) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") {
|
||||||
|
for aura in aura.iter() {
|
||||||
|
match brightness.level() {
|
||||||
|
None => {
|
||||||
|
let level = aura.brightness()?;
|
||||||
|
println!("Current keyboard led brightness: {level:?}");
|
||||||
|
}
|
||||||
|
Some(level) => aura.set_brightness(rog_aura::LedBrightness::from(level))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("No aura interface found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_info(
|
if parsed.next_kbd_bright {
|
||||||
info_opt: &InfoCommand,
|
if let Ok(aura) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") {
|
||||||
supported_interfaces: &[String],
|
for aura in aura.iter() {
|
||||||
supported_properties: &[Properties],
|
let brightness = aura.brightness()?;
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
aura.set_brightness(brightness.next())?;
|
||||||
println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
|
}
|
||||||
println!();
|
} else {
|
||||||
print_info();
|
println!("No aura interface found");
|
||||||
println!();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if info_opt.show_supported {
|
if parsed.prev_kbd_bright {
|
||||||
|
if let Ok(aura) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") {
|
||||||
|
for aura in aura.iter() {
|
||||||
|
let brightness = aura.brightness()?;
|
||||||
|
aura.set_brightness(brightness.prev())?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("No aura interface found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if parsed.show_supported {
|
||||||
println!("Supported Core Functions:\n{:#?}", supported_interfaces);
|
println!("Supported Core Functions:\n{:#?}", supported_interfaces);
|
||||||
println!(
|
println!(
|
||||||
"Supported Platform Properties:\n{:#?}",
|
"Supported Platform Properties:\n{:#?}",
|
||||||
@@ -265,14 +368,35 @@ fn handle_info(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(chg_limit) = parsed.chg_limit {
|
||||||
|
let proxy = PlatformProxyBlocking::new(&conn)?;
|
||||||
|
proxy.set_charge_control_end_threshold(chg_limit)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parsed.one_shot_chg {
|
||||||
|
let proxy = PlatformProxyBlocking::new(&conn)?;
|
||||||
|
proxy.one_shot_full_charge()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_gfx() {
|
||||||
|
println!(
|
||||||
|
"Please use supergfxctl for graphics switching. supergfxctl is the result of making \
|
||||||
|
asusctl graphics switching generic so all laptops can use it"
|
||||||
|
);
|
||||||
|
println!("This command will be removed in future");
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_backlight(cmd: &BacklightCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_backlight(cmd: &BacklightCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if cmd.screenpad_brightness.is_none()
|
if (cmd.screenpad_brightness.is_none()
|
||||||
&& cmd.screenpad_gamma.is_none()
|
&& cmd.screenpad_gamma.is_none()
|
||||||
&& cmd.sync_screenpad_brightness.is_none()
|
&& cmd.sync_screenpad_brightness.is_none())
|
||||||
|
|| cmd.help
|
||||||
{
|
{
|
||||||
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
|
|
||||||
let backlights = find_iface::<BacklightProxyBlocking>("xyz.ljones.Backlight")?;
|
let backlights = find_iface::<BacklightProxyBlocking>("xyz.ljones.Backlight")?;
|
||||||
for backlight in backlights {
|
for backlight in backlights {
|
||||||
println!("Current screenpad settings:");
|
println!("Current screenpad settings:");
|
||||||
@@ -305,50 +429,8 @@ fn handle_backlight(cmd: &BacklightCommand) -> Result<(), Box<dyn std::error::Er
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_brightness(cmd: &BrightnessCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let Ok(aura_proxies) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") else {
|
|
||||||
println!("No aura interface found");
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
match &cmd.command {
|
|
||||||
BrightnessSubCommand::Set(s) => {
|
|
||||||
for aura in aura_proxies.iter() {
|
|
||||||
if let Some(level) = s.level.level() {
|
|
||||||
aura.set_brightness(rog_aura::LedBrightness::from(level))?;
|
|
||||||
} else {
|
|
||||||
let current = aura.brightness()?;
|
|
||||||
println!("Current keyboard led brightness: {current:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BrightnessSubCommand::Get(_) => {
|
|
||||||
for aura in aura_proxies.iter() {
|
|
||||||
let level = aura.brightness()?;
|
|
||||||
println!("Current keyboard led brightness: {level:?}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
BrightnessSubCommand::Next(_) => {
|
|
||||||
for aura in aura_proxies.iter() {
|
|
||||||
let brightness = aura.brightness()?;
|
|
||||||
aura.set_brightness(brightness.next())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BrightnessSubCommand::Prev(_) => {
|
|
||||||
for aura in aura_proxies.iter() {
|
|
||||||
let brightness = aura.brightness()?;
|
|
||||||
aura.set_brightness(brightness.prev())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if cmd.command.is_none()
|
if (cmd.command.is_none()
|
||||||
&& cmd.enable_display.is_none()
|
&& cmd.enable_display.is_none()
|
||||||
&& cmd.enable_powersave_anim.is_none()
|
&& cmd.enable_powersave_anim.is_none()
|
||||||
&& cmd.brightness.is_none()
|
&& cmd.brightness.is_none()
|
||||||
@@ -356,9 +438,13 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
&& cmd.off_when_suspended.is_none()
|
&& cmd.off_when_suspended.is_none()
|
||||||
&& cmd.off_when_unplugged.is_none()
|
&& cmd.off_when_unplugged.is_none()
|
||||||
&& cmd.off_with_his_head.is_none()
|
&& cmd.off_with_his_head.is_none()
|
||||||
&& !cmd.clear
|
&& !cmd.clear)
|
||||||
|
|| cmd.help
|
||||||
{
|
{
|
||||||
println!("Missing arg or command; run 'asusctl anime --help' for usage");
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let animes = find_iface::<AnimeProxyBlocking>("xyz.ljones.Anime").map_err(|e| {
|
let animes = find_iface::<AnimeProxyBlocking>("xyz.ljones.Anime").map_err(|e| {
|
||||||
@@ -405,10 +491,11 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
if let Some(action) = cmd.command.as_ref() {
|
if let Some(action) = cmd.command.as_ref() {
|
||||||
match action {
|
match action {
|
||||||
AnimeActions::Image(image) => {
|
AnimeActions::Image(image) => {
|
||||||
if image.path.is_empty() {
|
if image.help_requested() || image.path.is_empty() {
|
||||||
println!(
|
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||||
"Missing arg or command; run 'asusctl anime image --help' for usage"
|
if let Some(lst) = image.self_command_list() {
|
||||||
);
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
verify_brightness(image.bright);
|
verify_brightness(image.bright);
|
||||||
@@ -425,8 +512,11 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?)?;
|
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?)?;
|
||||||
}
|
}
|
||||||
AnimeActions::PixelImage(image) => {
|
AnimeActions::PixelImage(image) => {
|
||||||
if image.path.is_empty() {
|
if image.help_requested() || image.path.is_empty() {
|
||||||
println!("Missing arg or command; run 'asusctl anime pixel-image --help' for usage");
|
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||||
|
if let Some(lst) = image.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
verify_brightness(image.bright);
|
verify_brightness(image.bright);
|
||||||
@@ -441,10 +531,11 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
proxy.write(matrix.into_data_buffer(anime_type)?)?;
|
proxy.write(matrix.into_data_buffer(anime_type)?)?;
|
||||||
}
|
}
|
||||||
AnimeActions::Gif(gif) => {
|
AnimeActions::Gif(gif) => {
|
||||||
if gif.path.is_empty() {
|
if gif.help_requested() || gif.path.is_empty() {
|
||||||
println!(
|
println!("Missing arg or command\n\n{}", gif.self_usage());
|
||||||
"Missing arg or command; run 'asusctl anime gif --help' for usage"
|
if let Some(lst) = gif.self_command_list() {
|
||||||
);
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
verify_brightness(gif.bright);
|
verify_brightness(gif.bright);
|
||||||
@@ -474,8 +565,11 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimeActions::PixelGif(gif) => {
|
AnimeActions::PixelGif(gif) => {
|
||||||
if gif.path.is_empty() {
|
if gif.help_requested() || gif.path.is_empty() {
|
||||||
println!("Missing arg or command; run 'asusctl anime pixel-gif --help' for usage");
|
println!("Missing arg or command\n\n{}", gif.self_usage());
|
||||||
|
if let Some(lst) = gif.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
verify_brightness(gif.bright);
|
verify_brightness(gif.bright);
|
||||||
@@ -502,8 +596,14 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimeActions::SetBuiltins(builtins) => {
|
AnimeActions::SetBuiltins(builtins) => {
|
||||||
if builtins.set.is_none() {
|
if builtins.help_requested() || builtins.set.is_none() {
|
||||||
println!("Missing arg; run 'asusctl anime set-builtins --help' for usage");
|
println!(
|
||||||
|
"\nAny unspecified args will be set to default (first shown var)\n"
|
||||||
|
);
|
||||||
|
println!("\n{}", builtins.self_usage());
|
||||||
|
if let Some(lst) = builtins.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,19 +630,24 @@ fn verify_brightness(brightness: f32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_slash(cmd: &SlashCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_slash(cmd: &SlashCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if cmd.brightness.is_none()
|
if (cmd.brightness.is_none()
|
||||||
&& cmd.interval.is_none()
|
&& cmd.interval.is_none()
|
||||||
&& cmd.show_on_boot.is_none()
|
&& cmd.show_on_boot.is_none()
|
||||||
&& cmd.show_on_shutdown.is_none()
|
&& cmd.show_on_shutdown.is_none()
|
||||||
&& cmd.show_on_sleep.is_none()
|
&& cmd.show_on_sleep.is_none()
|
||||||
&& cmd.show_on_battery.is_none()
|
&& cmd.show_on_battery.is_none()
|
||||||
&& cmd.show_battery_warning.is_none()
|
&& cmd.show_battery_warning.is_none()
|
||||||
|
// && cmd.show_on_lid_closed.is_none()
|
||||||
&& cmd.mode.is_none()
|
&& cmd.mode.is_none()
|
||||||
&& !cmd.list
|
&& !cmd.list
|
||||||
&& !cmd.enable
|
&& !cmd.enable
|
||||||
&& !cmd.disable
|
&& !cmd.disable)
|
||||||
|
|| cmd.help
|
||||||
{
|
{
|
||||||
println!("Missing arg or command; run 'asusctl slash --help' for usage");
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let slashes = find_iface::<SlashProxyBlocking>("xyz.ljones.Slash")?;
|
let slashes = find_iface::<SlashProxyBlocking>("xyz.ljones.Slash")?;
|
||||||
@@ -593,8 +698,13 @@ fn handle_slash(cmd: &SlashCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_scsi(cmd: &ScsiCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_scsi(cmd: &ScsiCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if !cmd.list && cmd.enable.is_none() && cmd.mode.is_none() && cmd.colours.is_empty() {
|
if (!cmd.list && cmd.enable.is_none() && cmd.mode.is_none() && cmd.colours.is_empty())
|
||||||
println!("Missing arg or command; run 'asusctl scsi --help' for usage");
|
|| cmd.help
|
||||||
|
{
|
||||||
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let scsis = find_iface::<ScsiAuraProxyBlocking>("xyz.ljones.ScsiAura")?;
|
let scsis = find_iface::<ScsiAuraProxyBlocking>("xyz.ljones.ScsiAura")?;
|
||||||
@@ -660,15 +770,38 @@ fn handle_scsi(cmd: &ScsiCommand) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
fn handle_led_mode(mode: &LedModeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_led_mode(mode: &LedModeCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
||||||
println!("Missing arg or command; run 'asusctl aura --help' for usage");
|
if !mode.help {
|
||||||
// print available modes when possible
|
println!("Missing arg or command\n");
|
||||||
if let Ok(aura) = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura") {
|
}
|
||||||
|
println!("{}\n", mode.self_usage());
|
||||||
|
println!("Commands available");
|
||||||
|
|
||||||
|
if let Some(cmdlist) = LedModeCommand::command_list() {
|
||||||
|
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||||
|
// TODO: multiple rgb check
|
||||||
|
let aura = find_iface::<AuraProxyBlocking>("xyz.ljones.Aura")?;
|
||||||
let modes = aura.first().unwrap().supported_basic_modes()?;
|
let modes = aura.first().unwrap().supported_basic_modes()?;
|
||||||
println!("Available modes:");
|
for command in commands.iter().filter(|command| {
|
||||||
for m in modes {
|
for mode in &modes {
|
||||||
println!(" {:?}", m);
|
let mut mode = <&str>::from(mode).to_string();
|
||||||
|
if let Some(pos) = mode.chars().skip(1).position(|c| c.is_uppercase()) {
|
||||||
|
mode.insert(pos + 1, '-');
|
||||||
|
}
|
||||||
|
if command.trim().starts_with(&mode.to_lowercase()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
// if !supported.basic_zones.is_empty() && command.trim().starts_with("multi") {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
false
|
||||||
|
}) {
|
||||||
|
println!("{}", command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("\nHelp can also be requested on modes, e.g: static --help");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -700,6 +833,10 @@ fn handle_led_mode(mode: &LedModeCommand) -> Result<(), Box<dyn std::error::Erro
|
|||||||
aura.set_led_mode(modes[pos])?;
|
aura.set_led_mode(modes[pos])?;
|
||||||
}
|
}
|
||||||
} else if let Some(mode) = mode.command.as_ref() {
|
} else if let Some(mode) = mode.command.as_ref() {
|
||||||
|
if mode.help_requested() {
|
||||||
|
println!("{}", mode.self_usage());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
for aura in aura {
|
for aura in aura {
|
||||||
aura.set_led_mode_data(<AuraEffect>::from(mode))?;
|
aura.set_led_mode_data(<AuraEffect>::from(mode))?;
|
||||||
}
|
}
|
||||||
@@ -722,7 +859,10 @@ fn handle_led_power1(power: &LedPowerCommand1) -> Result<(), Box<dyn std::error:
|
|||||||
&& !power.keyboard
|
&& !power.keyboard
|
||||||
&& !power.lightbar
|
&& !power.lightbar
|
||||||
{
|
{
|
||||||
println!("Missing arg or command; run 'asusctl aura power-tuf --help' for usage");
|
if !power.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
println!("{}\n", power.self_usage());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,47 +914,51 @@ fn handle_led_power2(power: &LedPowerCommand2) -> Result<(), Box<dyn std::error:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if power.command.is_none() {
|
if power.command().is_none() {
|
||||||
println!("Missing arg or command; run 'asusctl aura power --help' for usage");
|
if !power.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
println!("{}\n", power.self_usage());
|
||||||
println!("Commands available");
|
println!("Commands available");
|
||||||
|
|
||||||
|
if let Some(cmdlist) = LedPowerCommand2::command_list() {
|
||||||
|
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||||
|
for command in &commands {
|
||||||
|
println!("{}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nHelp can also be requested on commands, e.g: boot --help");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_pow) = power.command.as_ref() {
|
if let Some(pow) = power.command.as_ref() {
|
||||||
|
if pow.help_requested() {
|
||||||
|
println!("{}", pow.self_usage());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let mut states = aura.led_power()?;
|
let mut states = aura.led_power()?;
|
||||||
let mut set =
|
let mut set = |zone: PowerZones, set_to: &AuraPowerStates| {
|
||||||
|zone: PowerZones, boot_v: bool, awake_v: bool, sleep_v: bool, shutdown_v: bool| {
|
for state in states.states.iter_mut() {
|
||||||
for state in states.states.iter_mut() {
|
if state.zone == zone {
|
||||||
if state.zone == zone {
|
state.boot = set_to.boot;
|
||||||
state.boot = boot_v;
|
state.awake = set_to.awake;
|
||||||
state.awake = awake_v;
|
state.sleep = set_to.sleep;
|
||||||
state.sleep = sleep_v;
|
state.shutdown = set_to.shutdown;
|
||||||
state.shutdown = shutdown_v;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(cmd) = &power.command {
|
if let Some(cmd) = &power.command {
|
||||||
match cmd {
|
match cmd {
|
||||||
aura_cli::SetAuraZoneEnabled::Keyboard(k) => {
|
aura_cli::SetAuraZoneEnabled::Keyboard(k) => set(PowerZones::Keyboard, k),
|
||||||
set(PowerZones::Keyboard, k.boot, k.awake, k.sleep, k.shutdown)
|
aura_cli::SetAuraZoneEnabled::Logo(l) => set(PowerZones::Logo, l),
|
||||||
}
|
aura_cli::SetAuraZoneEnabled::Lightbar(l) => set(PowerZones::Lightbar, l),
|
||||||
aura_cli::SetAuraZoneEnabled::Logo(l) => {
|
aura_cli::SetAuraZoneEnabled::Lid(l) => set(PowerZones::Lid, l),
|
||||||
set(PowerZones::Logo, l.boot, l.awake, l.sleep, l.shutdown)
|
aura_cli::SetAuraZoneEnabled::RearGlow(r) => set(PowerZones::RearGlow, r),
|
||||||
}
|
aura_cli::SetAuraZoneEnabled::Ally(r) => set(PowerZones::Ally, r),
|
||||||
aura_cli::SetAuraZoneEnabled::Lightbar(l) => {
|
|
||||||
set(PowerZones::Lightbar, l.boot, l.awake, l.sleep, l.shutdown)
|
|
||||||
}
|
|
||||||
aura_cli::SetAuraZoneEnabled::Lid(l) => {
|
|
||||||
set(PowerZones::Lid, l.boot, l.awake, l.sleep, l.shutdown)
|
|
||||||
}
|
|
||||||
aura_cli::SetAuraZoneEnabled::RearGlow(r) => {
|
|
||||||
set(PowerZones::RearGlow, r.boot, r.awake, r.sleep, r.shutdown)
|
|
||||||
}
|
|
||||||
aura_cli::SetAuraZoneEnabled::Ally(r) => {
|
|
||||||
set(PowerZones::Ally, r.boot, r.awake, r.sleep, r.shutdown)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,39 +979,53 @@ 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
|
||||||
|
&& cmd.profile_set_ac.is_none()
|
||||||
|
&& cmd.profile_set_bat.is_none()
|
||||||
|
{
|
||||||
|
if !cmd.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
println!("{}", ProfileCommand::usage());
|
||||||
|
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let proxy = PlatformProxyBlocking::new(conn)?;
|
let proxy = PlatformProxyBlocking::new(conn)?;
|
||||||
let current = proxy.platform_profile()?;
|
let current = proxy.platform_profile()?;
|
||||||
let choices = proxy.platform_profile_choices()?;
|
let choices = proxy.platform_profile_choices()?;
|
||||||
|
|
||||||
match &cmd.command {
|
if cmd.next {
|
||||||
crate::cli_opts::ProfileSubCommand::Next(_) => {
|
proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
|
||||||
proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
|
} else if let Some(profile) = cmd.profile_set {
|
||||||
}
|
proxy.set_platform_profile(profile)?;
|
||||||
crate::cli_opts::ProfileSubCommand::Set(s) => {
|
} else if let Some(profile) = cmd.profile_set_ac {
|
||||||
if !s.ac && !s.battery {
|
proxy.set_platform_profile_on_ac(profile)?;
|
||||||
proxy.set_platform_profile(s.profile)?;
|
} else if let Some(profile) = cmd.profile_set_bat {
|
||||||
} else {
|
proxy.set_platform_profile_on_battery(profile)?;
|
||||||
if s.ac {
|
}
|
||||||
proxy.set_platform_profile_on_ac(s.profile)?;
|
|
||||||
}
|
if cmd.list {
|
||||||
if s.battery {
|
for p in &choices {
|
||||||
proxy.set_platform_profile_on_battery(s.profile)?;
|
println!("{:?}", p);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::cli_opts::ProfileSubCommand::List(_) => {
|
|
||||||
for p in &choices {
|
|
||||||
println!("{:?}", p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::cli_opts::ProfileSubCommand::Get(_) => {
|
|
||||||
println!("Active profile: {current:?}");
|
|
||||||
println!();
|
|
||||||
println!("AC profile {:?}", proxy.platform_profile_on_ac()?);
|
|
||||||
println!("Battery profile {:?}", proxy.platform_profile_on_battery()?);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd.profile_get {
|
||||||
|
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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,7 +1040,14 @@ fn handle_fan_curve(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !cmd.get_enabled && !cmd.default && cmd.mod_profile.is_none() {
|
if !cmd.get_enabled && !cmd.default && cmd.mod_profile.is_none() {
|
||||||
println!("Missing arg or command; run 'asusctl fan-curve --help' for usage");
|
if !cmd.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
println!("{}", FanCurveCommand::usage());
|
||||||
|
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,35 +1184,38 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)]
|
#[allow(clippy::manual_is_multiple_of)]
|
||||||
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 nested subcommand provided, handle set/get/list.
|
{
|
||||||
match &cmd.command {
|
// Avoid using `.is_multiple_of(2)` to satisfy the request. Use modulus check
|
||||||
ArmourySubCommand::List(_) => {
|
// and simplify the boolean expression.
|
||||||
if let Ok(attrs) = find_iface::<AsusArmouryProxyBlocking>("xyz.ljones.AsusArmoury") {
|
let odd_len = cmd.free.len() % 2 != 0;
|
||||||
for attr in attrs.iter() {
|
if cmd.free.is_empty() || odd_len || cmd.help {
|
||||||
|
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
|
||||||
|
if odd_len {
|
||||||
|
println!(
|
||||||
|
"Incorrect number of args, each attribute label must be paired with a setting:"
|
||||||
|
);
|
||||||
|
println!("{USAGE}");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(attr) = find_iface::<AsusArmouryProxyBlocking>("xyz.ljones.AsusArmoury") {
|
||||||
|
println!("\n{USAGE}\n");
|
||||||
|
println!("Available firmware attributes: ");
|
||||||
|
for attr in attr.iter() {
|
||||||
print_firmware_attr(attr)?;
|
print_firmware_attr(attr)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
return Ok(());
|
||||||
}
|
}
|
||||||
ArmourySubCommand::Get(g) => {
|
|
||||||
if let Ok(attrs) = find_iface::<AsusArmouryProxyBlocking>("xyz.ljones.AsusArmoury") {
|
if let Ok(attr) = find_iface::<AsusArmouryProxyBlocking>("xyz.ljones.AsusArmoury") {
|
||||||
for attr in attrs.iter() {
|
for cmd in cmd.free.chunks(2) {
|
||||||
|
for attr in attr.iter() {
|
||||||
let name = attr.name()?;
|
let name = attr.name()?;
|
||||||
if <&str>::from(name) == g.property {
|
if <&str>::from(name) == cmd[0] {
|
||||||
print_firmware_attr(attr)?;
|
let mut value: i32 = cmd[1].parse()?;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
ArmourySubCommand::Set(s) => {
|
|
||||||
if let Ok(attrs) = find_iface::<AsusArmouryProxyBlocking>("xyz.ljones.AsusArmoury") {
|
|
||||||
for attr in attrs.iter() {
|
|
||||||
let name = attr.name()?;
|
|
||||||
if <&str>::from(name) == s.property {
|
|
||||||
let mut value: i32 = s.value;
|
|
||||||
if value == -1 {
|
if value == -1 {
|
||||||
info!("Setting to default");
|
info!("Setting to default");
|
||||||
value = attr.default_value()?;
|
value = attr.default_value()?;
|
||||||
@@ -1057,7 +1225,7 @@ fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_scsi::{AuraMode, Colour, Direction, Speed};
|
use rog_scsi::{AuraMode, Colour, Direction, Speed};
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "scsi", description = "scsi LED commands")]
|
|
||||||
pub struct ScsiCommand {
|
pub struct ScsiCommand {
|
||||||
#[argh(option, description = "enable the SCSI drive LEDs")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
|
||||||
|
#[options(help = "Enable the SCSI drive LEDs")]
|
||||||
pub enable: Option<bool>,
|
pub enable: Option<bool>,
|
||||||
|
|
||||||
#[argh(option, description = "set LED mode (use 'list' for all options)")]
|
#[options(meta = "", help = "Set LED mode (so 'list' for all options)")]
|
||||||
pub mode: Option<AuraMode>,
|
pub mode: Option<AuraMode>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "set LED mode speed <slowest, slow, med, fast, fastest>"
|
help = "Set LED mode speed <slowest, slow, med, fast, fastest> (does not apply to all)"
|
||||||
)]
|
)]
|
||||||
pub speed: Option<Speed>,
|
pub speed: Option<Speed>,
|
||||||
|
|
||||||
#[argh(option, description = "set LED mode direction <forward, reverse>")]
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
help = "Set LED mode direction <forward, reverse> (does not apply to all)"
|
||||||
|
)]
|
||||||
pub direction: Option<Direction>,
|
pub direction: Option<Direction>,
|
||||||
|
|
||||||
#[argh(
|
#[options(
|
||||||
option,
|
meta = "",
|
||||||
description = "set LED colours <hex>, specify up to 4 with repeated arg"
|
help = "Set LED colours <hex>, specify up to 4 with repeated arg"
|
||||||
)]
|
)]
|
||||||
pub colours: Vec<Colour>,
|
pub colours: Vec<Colour>,
|
||||||
|
|
||||||
#[argh(switch, description = "list available animations")]
|
#[options(help = "list available animations")]
|
||||||
pub list: bool,
|
pub list: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,37 @@
|
|||||||
use argh::FromArgs;
|
use gumdrop::Options;
|
||||||
use rog_slash::SlashMode;
|
use rog_slash::SlashMode;
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(Options)]
|
||||||
#[argh(subcommand, name = "slash", description = "slash ledbar commands")]
|
|
||||||
pub struct SlashCommand {
|
pub struct SlashCommand {
|
||||||
#[argh(switch, description = "enable the Slash Ledbar")]
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(help = "Enable the Slash Ledbar")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
#[argh(switch, description = "disable the Slash Ledbar")]
|
#[options(help = "Disable the Slash Ledbar")]
|
||||||
pub disable: bool,
|
pub disable: bool,
|
||||||
#[argh(option, short = 'l', description = "set brightness value <0-255>")]
|
#[options(short = "l", meta = "", help = "Set brightness value <0-255>")]
|
||||||
pub brightness: Option<u8>,
|
pub brightness: Option<u8>,
|
||||||
#[argh(option, description = "set interval value <0-5>")]
|
#[options(meta = "", help = "Set interval value <0-5>")]
|
||||||
pub interval: Option<u8>,
|
pub interval: Option<u8>,
|
||||||
#[argh(option, description = "set SlashMode (use 'list' for options)")]
|
#[options(meta = "", help = "Set SlashMode (so 'list' for all options)")]
|
||||||
pub mode: Option<SlashMode>,
|
pub mode: Option<SlashMode>,
|
||||||
#[argh(switch, description = "list available animations")]
|
#[options(help = "list available animations")]
|
||||||
pub list: bool,
|
pub list: bool,
|
||||||
|
|
||||||
#[argh(option, short = 'B', description = "show the animation on boot")]
|
#[options(short = "B", meta = "", help = "Show the animation on boot")]
|
||||||
pub show_on_boot: Option<bool>,
|
pub show_on_boot: Option<bool>,
|
||||||
#[argh(option, short = 'S', description = "show the animation on shutdown")]
|
#[options(short = "S", meta = "", help = "Show the animation on shutdown")]
|
||||||
pub show_on_shutdown: Option<bool>,
|
pub show_on_shutdown: Option<bool>,
|
||||||
#[argh(option, short = 's', description = "show the animation on sleep")]
|
#[options(short = "s", meta = "", help = "Show the animation on sleep")]
|
||||||
pub show_on_sleep: Option<bool>,
|
pub show_on_sleep: Option<bool>,
|
||||||
#[argh(option, short = 'b', description = "show the animation on battery")]
|
#[options(short = "b", meta = "", help = "Show the animation on battery")]
|
||||||
pub show_on_battery: Option<bool>,
|
pub show_on_battery: Option<bool>,
|
||||||
#[argh(
|
// #[options(short = "L", meta = "", help = "Show the animation on lid closed")]
|
||||||
option,
|
// pub show_on_lid_closed: Option<bool>,
|
||||||
short = 'w',
|
#[options(
|
||||||
description = "show the low-battery warning animation"
|
short = "w",
|
||||||
|
meta = "",
|
||||||
|
help = "Show the low-battery warning animation"
|
||||||
)]
|
)]
|
||||||
pub show_battery_warning: Option<bool>,
|
pub show_battery_warning: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ concat-idents.workspace = true
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cargo-husky.workspace = true
|
cargo-husky.workspace = true
|
||||||
|
tempfile = "3"
|
||||||
|
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
license-file = ["../LICENSE", "4"]
|
license-file = ["../LICENSE", "4"]
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use config_traits::StdConfig;
|
use config_traits::StdConfig;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info};
|
||||||
use rog_platform::asus_armoury::{
|
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
|
||||||
AttrValue, Attribute, FirmwareAttribute, FirmwareAttributeType, 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};
|
||||||
@@ -29,6 +27,28 @@ fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath {
|
|||||||
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into()
|
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper: return true when the attribute is effectively unsupported for
|
||||||
|
// the current power mode/device. We consider an attribute unsupported when
|
||||||
|
// its resolved min and max are equal (no available range), which indicates
|
||||||
|
// writes would be invalid. When true, callers should avoid attempting writes.
|
||||||
|
fn attr_unsupported(attr: &Attribute) -> bool {
|
||||||
|
let min = attr
|
||||||
|
.refresh_min_value()
|
||||||
|
.or(match attr.min_value() {
|
||||||
|
AttrValue::Integer(i) => Some(*i),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or(-1);
|
||||||
|
let max = attr
|
||||||
|
.refresh_max_value()
|
||||||
|
.or(match attr.max_value() {
|
||||||
|
AttrValue::Integer(i) => Some(*i),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or(-2); // different default so equality is false unless both present
|
||||||
|
min == max
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AsusArmouryAttribute {
|
pub struct AsusArmouryAttribute {
|
||||||
attr: Attribute,
|
attr: Attribute,
|
||||||
@@ -148,6 +168,14 @@ impl ArmouryAttributeRegistry {
|
|||||||
self.attrs.push(attr);
|
self.attrs.push(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.attrs.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> std::slice::Iter<'_, AsusArmouryAttribute> {
|
||||||
|
self.attrs.iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
|
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
|
||||||
let mut last_err: Option<RogError> = None;
|
let mut last_err: Option<RogError> = None;
|
||||||
for attr in &self.attrs {
|
for attr in &self.attrs {
|
||||||
@@ -170,71 +198,76 @@ impl ArmouryAttributeRegistry {
|
|||||||
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 attribute: FirmwareAttribute = self.attr.name().into();
|
let name: FirmwareAttribute = self.attr.name().into();
|
||||||
let name = self.attr.name();
|
|
||||||
|
|
||||||
let config = self.config.lock().await;
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
let apply_value = match attribute.property_type() {
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
FirmwareAttributeType::Ppt => {
|
let power_plugged = self
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
.power
|
||||||
let power_plugged = self
|
.get_online()
|
||||||
.power
|
.map_err(|e| {
|
||||||
.get_online()
|
error!("Could not get power status: {e:?}");
|
||||||
.map_err(|e| {
|
e
|
||||||
error!("Could not get power status: {e:?}");
|
})
|
||||||
e
|
.unwrap_or_default()
|
||||||
|
== 1;
|
||||||
|
|
||||||
|
let apply_value = {
|
||||||
|
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
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_default()
|
};
|
||||||
== 1;
|
|
||||||
|
|
||||||
let apply_value = {
|
if let Some(tune) = apply_value {
|
||||||
config.select_tunings_ref(power_plugged, profile).and_then(
|
// Don't attempt writes for attributes that report min==0 and max==0
|
||||||
|tuning| match tuning.enabled {
|
// (commonly means not supported in this power mode/device); skip
|
||||||
true => tuning.group.get(&self.name()).copied(),
|
// applying stored tune in that case.
|
||||||
false => None,
|
if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
|
||||||
},
|
self.attr
|
||||||
)
|
.set_current_value(&AttrValue::Integer(tune))
|
||||||
};
|
.map_err(|e| {
|
||||||
|
error!("Could not set {} value: {e:?}", self.attr.name());
|
||||||
apply_value.map_or(AttrValue::None, AttrValue::Integer)
|
self.attr.base_path_exists();
|
||||||
}
|
e
|
||||||
FirmwareAttributeType::Gpu => {
|
})?;
|
||||||
info!("Reload called on GPU attribute {name}: doing nothing");
|
info!("Set {} to {:?}", self.attr.name(), tune);
|
||||||
AttrValue::None
|
} else {
|
||||||
}
|
debug!(
|
||||||
_ => {
|
"Skipping apply for {} because attribute missing or unsupported (min==max)",
|
||||||
info!("Reload called on firmware attribute {name}");
|
self.attr.name()
|
||||||
match config.armoury_settings.get(&attribute) {
|
);
|
||||||
Some(saved_value) => AttrValue::Integer(*saved_value),
|
|
||||||
None => AttrValue::None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
// Handle non-PPT attributes (boolean and other settings)
|
||||||
match apply_value {
|
if let Some(saved_value) = self.config.lock().await.armoury_settings.get(&name) {
|
||||||
AttrValue::None => {
|
self.attr
|
||||||
|
.set_current_value(&AttrValue::Integer(*saved_value))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Could not set {} value: {e:?}", self.attr.name());
|
||||||
|
self.attr.base_path_exists();
|
||||||
|
e
|
||||||
|
})?;
|
||||||
info!(
|
info!(
|
||||||
"No saved value for attribute {}: skipping.",
|
"Restored armoury setting {} to {:?}",
|
||||||
self.attr.name()
|
self.attr.name(),
|
||||||
|
saved_value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
info!("Applying value {apply_value:?} to attribute {name}");
|
|
||||||
self.attr.set_current_value(&apply_value).map_err(|e| {
|
|
||||||
error!("Could not set {name} value: {e:?}");
|
|
||||||
self.attr.base_path_exists();
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
info!("Restored asus-armoury setting {name} to {apply_value:?}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If return is `-1` on a property then there is available value for that
|
/// If return is `-1` on a property then there is avilable value for that
|
||||||
/// property
|
/// property
|
||||||
#[interface(name = "xyz.ljones.AsusArmoury")]
|
#[interface(name = "xyz.ljones.AsusArmoury")]
|
||||||
impl AsusArmouryAttribute {
|
impl AsusArmouryAttribute {
|
||||||
@@ -284,7 +317,7 @@ impl AsusArmouryAttribute {
|
|||||||
|
|
||||||
async fn restore_default(&self) -> fdo::Result<()> {
|
async fn restore_default(&self) -> fdo::Result<()> {
|
||||||
self.attr.restore_default()?;
|
self.attr.restore_default()?;
|
||||||
if self.name().property_type() == FirmwareAttributeType::Ppt {
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
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
|
||||||
.power
|
.power
|
||||||
@@ -343,7 +376,7 @@ impl AsusArmouryAttribute {
|
|||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn current_value(&self) -> fdo::Result<i32> {
|
async fn current_value(&self) -> fdo::Result<i32> {
|
||||||
if self.name().property_type() == FirmwareAttributeType::Ppt {
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
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
|
||||||
.power
|
.power
|
||||||
@@ -376,77 +409,183 @@ impl AsusArmouryAttribute {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
|
||||||
|
if !(self.name().is_ppt() || self.name().is_dgpu()) {
|
||||||
|
return Err(fdo::Error::NotSupported(
|
||||||
|
"Stored values are only available for PPT/dGPU tunable 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() || self.name().is_dgpu()) {
|
||||||
|
return Err(fdo::Error::NotSupported(
|
||||||
|
"Setting stored values is only supported for PPT/dGPU tunable 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;
|
||||||
|
|
||||||
|
// Don't attempt writes for attributes that report min==0 and max==0
|
||||||
|
// (commonly means not supported in this power mode/device); skip
|
||||||
|
// applying stored value in that case.
|
||||||
|
if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
|
||||||
|
if power_plugged == on_ac {
|
||||||
|
self.attr
|
||||||
|
.set_current_value(&AttrValue::Integer(value))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Could not set value: {e:?}");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
"Skipping immediate apply for {} because attribute missing or unsupported (min==max)",
|
||||||
|
self.attr.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<()> {
|
||||||
let name = self.attr.name();
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
let apply_value = match self.name().property_type() {
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
FirmwareAttributeType::Ppt => {
|
let power_plugged = self
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
.power
|
||||||
let power_plugged = self
|
.get_online()
|
||||||
.power
|
.map_err(|e| {
|
||||||
.get_online()
|
error!("Could not get power status: {e:?}");
|
||||||
.map_err(|e| {
|
e
|
||||||
error!("Could not get power status: {e:?}");
|
})
|
||||||
e
|
.unwrap_or_default();
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let mut config = self.config.lock().await;
|
let mut config = self.config.lock().await;
|
||||||
let tuning = config.select_tunings(power_plugged == 1, profile);
|
let tuning = config.select_tunings(power_plugged == 1, profile);
|
||||||
|
|
||||||
if let Some(tune) = tuning.group.get_mut(&self.name()) {
|
if let Some(tune) = tuning.group.get_mut(&self.name()) {
|
||||||
*tune = value;
|
*tune = value;
|
||||||
|
} else {
|
||||||
|
tuning.group.insert(self.name(), value);
|
||||||
|
debug!("Store tuning config for {} = {:?}", self.attr.name(), value);
|
||||||
|
}
|
||||||
|
if tuning.enabled {
|
||||||
|
// Don't attempt writes for attributes that report min==0 and max==0
|
||||||
|
// (commonly means not supported in this power mode/device); skip
|
||||||
|
// applying stored value in that case.
|
||||||
|
if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
|
||||||
|
self.attr
|
||||||
|
.set_current_value(&AttrValue::Integer(value))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Could not set value: {e:?}");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
} else {
|
} else {
|
||||||
tuning.group.insert(self.name(), value);
|
debug!(
|
||||||
debug!("Store tuning config for {name} = {:?}", value);
|
"Skipping apply for {} on set_current_value because attribute missing or unsupported (min==max)",
|
||||||
}
|
self.attr.name()
|
||||||
|
);
|
||||||
match tuning.enabled {
|
|
||||||
true => {
|
|
||||||
debug!("Tuning is enabled: setting value to PPT property {name} = {value}");
|
|
||||||
AttrValue::Integer(value)
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
warn!("Tuning is disabled: skipping setting value to PPT property {name}");
|
|
||||||
AttrValue::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
} else {
|
||||||
let mut settings = self.config.lock().await;
|
self.attr
|
||||||
settings
|
.set_current_value(&AttrValue::Integer(value))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Could not set value: {e:?}");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let has_attr = self
|
||||||
|
.config
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.armoury_settings
|
||||||
|
.contains_key(&self.name());
|
||||||
|
if has_attr {
|
||||||
|
if let Some(setting) = self
|
||||||
|
.config
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
.armoury_settings
|
.armoury_settings
|
||||||
.entry(self.name())
|
.get_mut(&self.name())
|
||||||
.and_modify(|setting| {
|
{
|
||||||
debug!("Set config for {name} = {value}");
|
*setting = value
|
||||||
*setting = value;
|
}
|
||||||
})
|
} else {
|
||||||
.or_insert_with(|| {
|
debug!("Adding config for {}", self.attr.name());
|
||||||
debug!("Adding config for {name} = {value}");
|
self.config
|
||||||
value
|
.lock()
|
||||||
});
|
.await
|
||||||
|
.armoury_settings
|
||||||
AttrValue::Integer(value)
|
.insert(self.name(), value);
|
||||||
|
debug!("Set config for {} = {:?}", self.attr.name(), value);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
self.attr.set_current_value(&apply_value).map_err(|e| {
|
|
||||||
error!("Could not set value {value} to attribute {name}: {e:?}");
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// write config after setting value
|
|
||||||
self.config.lock().await.write();
|
self.config.lock().await.write();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn start_attributes_zbus(
|
pub async fn start_attributes_zbus(
|
||||||
conn: &Connection,
|
conn: Option<&Connection>,
|
||||||
platform: RogPlatform,
|
platform: RogPlatform,
|
||||||
power: AsusPower,
|
power: AsusPower,
|
||||||
attributes: FirmwareAttributes,
|
attributes: FirmwareAttributes,
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
|
enable_zbus: bool,
|
||||||
|
profile_override: Option<rog_platform::platform::PlatformProfile>,
|
||||||
|
power_plugged_override: Option<bool>,
|
||||||
) -> Result<ArmouryAttributeRegistry, RogError> {
|
) -> Result<ArmouryAttributeRegistry, RogError> {
|
||||||
let mut registry = ArmouryAttributeRegistry::default();
|
let mut registry = ArmouryAttributeRegistry::default();
|
||||||
for attr in attributes.attributes() {
|
for attr in attributes.attributes() {
|
||||||
@@ -459,34 +598,115 @@ pub async fn start_attributes_zbus(
|
|||||||
|
|
||||||
let registry_attr = attr.clone();
|
let registry_attr = attr.clone();
|
||||||
|
|
||||||
if let Err(e) = attr.reload().await {
|
// Only perform the full reload (which may query the platform/power sysfs)
|
||||||
error!(
|
// when zbus is enabled. Tests using the no-zbus mode skip the reload and
|
||||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
// emulate the reload/apply behavior to avoid depending on udev/sysfs.
|
||||||
attr.attr.name()
|
if enable_zbus {
|
||||||
);
|
if let Err(e) = attr.reload().await {
|
||||||
break;
|
error!(
|
||||||
|
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||||
|
attr.attr.name()
|
||||||
|
);
|
||||||
|
// continue with others
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let attr_name = attr.attribute_name();
|
let attr_name = attr.attribute_name();
|
||||||
|
|
||||||
let path = dbus_path_for_attr(attr_name.as_str());
|
// If zbus is enabled and a connection is provided, create the SignalEmitter,
|
||||||
match zbus::object_server::SignalEmitter::new(conn, path) {
|
// start watchers and register the object on zbus. Tests can call this function
|
||||||
Ok(sig) => {
|
// with enable_zbus=false and conn=None to skip DBus registration and watchers.
|
||||||
if let Err(e) = attr.watch_and_notify(sig).await {
|
if !enable_zbus {
|
||||||
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
|
// Emulate reload logic but prefer overrides when provided to avoid dependency on udev/sysfs in tests
|
||||||
|
let name: rog_platform::asus_armoury::FirmwareAttribute = attr.attr.name().into();
|
||||||
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
|
// determine profile
|
||||||
|
let profile = if let Some(p) = profile_override {
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
match attr.platform.get_platform_profile() {
|
||||||
|
Ok(p) => p.into(),
|
||||||
|
Err(_) => rog_platform::platform::PlatformProfile::Balanced,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// determine power plugged
|
||||||
|
let power_plugged = if let Some(v) = power_plugged_override {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
match attr.power.get_online() {
|
||||||
|
Ok(v) => v == 1,
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let apply_value = {
|
||||||
|
let config = attr.config.lock().await;
|
||||||
|
config
|
||||||
|
.select_tunings_ref(power_plugged, profile)
|
||||||
|
.and_then(|tuning| {
|
||||||
|
if tuning.enabled {
|
||||||
|
tuning.group.get(&attr.name()).copied()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(tune) = apply_value {
|
||||||
|
attr.attr
|
||||||
|
.set_current_value(&AttrValue::Integer(tune))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Could not set {} value: {e:?}", attr.attr.name());
|
||||||
|
e
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
}
|
} else if let Some(saved_value) = attr.config.lock().await.armoury_settings.get(&name) {
|
||||||
Err(e) => {
|
attr.attr
|
||||||
error!(
|
.set_current_value(&AttrValue::Integer(*saved_value))
|
||||||
"Failed to create SignalEmitter for '{}': {e:?}",
|
.map_err(|e| {
|
||||||
attr.attr.name()
|
error!("Could not set {} value: {e:?}", attr.attr.name());
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
info!(
|
||||||
|
"Restored armoury setting {} to {:?}",
|
||||||
|
attr.attr.name(),
|
||||||
|
saved_value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registry.push(registry_attr);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = attr.move_to_zbus(conn).await {
|
// If zbus is enabled and a connection is provided, create the SignalEmitter,
|
||||||
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
|
// start watchers and register the object on zbus. Tests can call this function
|
||||||
continue;
|
// with enable_zbus=false and conn=None to skip DBus registration and watchers.
|
||||||
|
if enable_zbus {
|
||||||
|
if let Some(connection) = conn {
|
||||||
|
let path = dbus_path_for_attr(attr_name.as_str());
|
||||||
|
match zbus::object_server::SignalEmitter::new(connection, path) {
|
||||||
|
Ok(sig) => {
|
||||||
|
if let Err(e) = attr.watch_and_notify(sig).await {
|
||||||
|
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"Failed to create SignalEmitter for '{}': {e:?}",
|
||||||
|
attr.attr.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = attr.move_to_zbus(connection).await {
|
||||||
|
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!("zbus enabled but no Connection provided for attribute registration");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.push(registry_attr);
|
registry.push(registry_attr);
|
||||||
@@ -502,34 +722,50 @@ pub async fn set_config_or_default(
|
|||||||
) {
|
) {
|
||||||
for attr in attrs.attributes().iter() {
|
for attr in attrs.attributes().iter() {
|
||||||
let name: FirmwareAttribute = attr.name().into();
|
let name: FirmwareAttribute = attr.name().into();
|
||||||
if name.property_type() == FirmwareAttributeType::Ppt {
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
let tuning = config.select_tunings(power_plugged, profile);
|
let tuning = config.select_tunings(power_plugged, profile);
|
||||||
if !tuning.enabled {
|
if !tuning.enabled {
|
||||||
debug!("Tuning group is not enabled, skipping");
|
debug!("Tuning group is not enabled, skipping");
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Determine once whether attribute is present and supports a writable range
|
||||||
|
let supported = attr.base_path_exists() && !attr_unsupported(attr);
|
||||||
if let Some(tune) = tuning.group.get(&name) {
|
if let Some(tune) = tuning.group.get(&name) {
|
||||||
attr.set_current_value(&AttrValue::Integer(*tune))
|
if supported {
|
||||||
.map_err(|e| {
|
attr.set_current_value(&AttrValue::Integer(*tune))
|
||||||
error!("Failed to set {}: {e}", <&str>::from(name));
|
.map_err(|e| {
|
||||||
})
|
error!("Failed to set {}: {e}", <&str>::from(name));
|
||||||
.ok();
|
})
|
||||||
} else {
|
.ok();
|
||||||
let default = attr.default_value();
|
} else {
|
||||||
attr.set_current_value(default)
|
debug!(
|
||||||
.map_err(|e| {
|
"Skipping apply for {} in set_config_or_default because attribute missing or unsupported",
|
||||||
error!("Failed to set {}: {e}", <&str>::from(name));
|
<&str>::from(name)
|
||||||
})
|
);
|
||||||
.ok();
|
}
|
||||||
if let AttrValue::Integer(i) = default {
|
} else {
|
||||||
tuning.group.insert(name, *i);
|
// Only attempt to apply defaults when the attribute supports a range
|
||||||
info!(
|
if supported {
|
||||||
"Set default tuning config for {} = {:?}",
|
let default = attr.default_value();
|
||||||
<&str>::from(name),
|
attr.set_current_value(default)
|
||||||
i
|
.map_err(|e| {
|
||||||
|
error!("Failed to set {}: {e}", <&str>::from(name));
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
if let AttrValue::Integer(i) = default {
|
||||||
|
tuning.group.insert(name, *i);
|
||||||
|
info!(
|
||||||
|
"Set default tuning config for {} = {:?}",
|
||||||
|
<&str>::from(name),
|
||||||
|
i
|
||||||
|
);
|
||||||
|
// config.write();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
"Skipping default apply for {} in set_config_or_default because attribute missing or unsupported",
|
||||||
|
<&str>::from(name)
|
||||||
);
|
);
|
||||||
// config.write();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -549,3 +785,69 @@ pub async fn set_config_or_default(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal helper to store a tuning value into the correct per-profile, per-power map.
|
||||||
|
// This centralizes the behavior so tests can validate storage semantics.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn insert_tuning_value(
|
||||||
|
config: &mut Config,
|
||||||
|
on_ac: bool,
|
||||||
|
profile: PlatformProfile,
|
||||||
|
name: rog_platform::asus_armoury::FirmwareAttribute,
|
||||||
|
value: i32,
|
||||||
|
) {
|
||||||
|
let tuning = config.select_tunings(on_ac, profile);
|
||||||
|
if let Some(t) = tuning.group.get_mut(&name) {
|
||||||
|
*t = value;
|
||||||
|
} else {
|
||||||
|
tuning.group.insert(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::config::Config;
|
||||||
|
use rog_platform::asus_armoury::FirmwareAttribute;
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_nv_tuning_is_per_profile_and_power() {
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Performance;
|
||||||
|
|
||||||
|
// Insert value for AC
|
||||||
|
insert_tuning_value(
|
||||||
|
&mut cfg,
|
||||||
|
true,
|
||||||
|
profile,
|
||||||
|
FirmwareAttribute::NvDynamicBoost,
|
||||||
|
7,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Value should be present in ac_profile_tunings
|
||||||
|
let t_ac = cfg.select_tunings_ref(true, profile).unwrap();
|
||||||
|
assert_eq!(t_ac.group.get(&FirmwareAttribute::NvDynamicBoost), Some(&7));
|
||||||
|
|
||||||
|
// Insert separate value for DC
|
||||||
|
insert_tuning_value(
|
||||||
|
&mut cfg,
|
||||||
|
false,
|
||||||
|
profile,
|
||||||
|
FirmwareAttribute::NvDynamicBoost,
|
||||||
|
3,
|
||||||
|
);
|
||||||
|
let t_dc = cfg.select_tunings_ref(false, profile).unwrap();
|
||||||
|
assert_eq!(t_dc.group.get(&FirmwareAttribute::NvDynamicBoost), Some(&3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn non_ppt_attribute_stores_in_armoury_settings() {
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
// Non-PPT/dGPU attribute, e.g., BootSound
|
||||||
|
let name = FirmwareAttribute::BootSound;
|
||||||
|
// Simulate setting armoury setting
|
||||||
|
cfg.armoury_settings.insert(name, 1);
|
||||||
|
assert_eq!(cfg.armoury_settings.get(&name), Some(&1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ pub struct AuraConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StdConfig for AuraConfig {
|
impl StdConfig for AuraConfig {
|
||||||
|
/// Detect the keyboard type and load from default DB if data available
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
panic!("This should not be used");
|
panic!("This should not be used");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,13 +71,7 @@ impl AuraZbus {
|
|||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
|
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
|
||||||
if let Some(bl) = self.0.backlight.as_ref() {
|
if let Some(bl) = self.0.backlight.as_ref() {
|
||||||
let res = bl.lock().await.set_brightness(brightness.into());
|
return Ok(bl.lock().await.set_brightness(brightness.into())?);
|
||||||
if res.is_ok() {
|
|
||||||
let mut config = self.0.config.lock().await;
|
|
||||||
config.brightness = brightness;
|
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
return Ok(res?);
|
|
||||||
}
|
}
|
||||||
Err(ZbErr::Failed("No sysfs brightness control".to_string()))
|
Err(ZbErr::Failed("No sysfs brightness control".to_string()))
|
||||||
}
|
}
|
||||||
@@ -182,6 +176,7 @@ impl AuraZbus {
|
|||||||
self.0.set_brightness(config.brightness.into()).await?;
|
self.0.set_brightness(config.brightness.into()).await?;
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
config.write();
|
config.write();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,10 +202,9 @@ impl AuraZbus {
|
|||||||
let mut config = self.0.config.lock().await;
|
let mut config = self.0.config.lock().await;
|
||||||
for opt in options.states {
|
for opt in options.states {
|
||||||
let zone = opt.zone;
|
let zone = opt.zone;
|
||||||
for state in config.enabled.states.iter_mut() {
|
for config in config.enabled.states.iter_mut() {
|
||||||
if state.zone == zone {
|
if config.zone == zone {
|
||||||
*state = opt;
|
*config = opt;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,15 +96,17 @@ pub struct AsusDevice {
|
|||||||
hid_key: Option<String>,
|
hid_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shared alias for the HidRaw handle map used throughout this module.
|
||||||
|
type HidHandleMap = Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>;
|
||||||
|
|
||||||
pub struct DeviceManager {
|
pub struct DeviceManager {
|
||||||
_dbus_connection: Connection,
|
_dbus_connection: Connection,
|
||||||
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
_hid_handles: HidHandleMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceManager {
|
impl DeviceManager {
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
async fn get_or_create_hid_handle(
|
async fn get_or_create_hid_handle(
|
||||||
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
handles: &HidHandleMap,
|
||||||
endpoint: &Device,
|
endpoint: &Device,
|
||||||
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
|
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
|
||||||
let dev_node = endpoint
|
let dev_node = endpoint
|
||||||
@@ -125,14 +127,14 @@ impl DeviceManager {
|
|||||||
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>>>>>,
|
handles: HidHandleMap,
|
||||||
) -> 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")? {
|
||||||
if let Some(usb_id) = usb_device.attribute_value("idProduct") {
|
if let Some(usb_id) = usb_device.attribute_value("idProduct") {
|
||||||
if let Some(vendor_id) = usb_device.attribute_value("idVendor") {
|
if let Some(vendor_id) = usb_device.attribute_value("idVendor") {
|
||||||
if vendor_id != "0b05" {
|
if vendor_id != "0b05" {
|
||||||
debug!("Not ASUS vendor ID: {}", vendor_id.to_string_lossy());
|
debug!("Not ASUS vendor ID");
|
||||||
return Ok(devices);
|
return Ok(devices);
|
||||||
}
|
}
|
||||||
// Almost all devices are identified by the productId.
|
// Almost all devices are identified by the productId.
|
||||||
@@ -213,7 +215,7 @@ impl DeviceManager {
|
|||||||
/// To be called on daemon startup
|
/// To be called on daemon startup
|
||||||
async fn init_all_hid(
|
async fn init_all_hid(
|
||||||
connection: &Connection,
|
connection: &Connection,
|
||||||
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
handles: HidHandleMap,
|
||||||
) -> Result<Vec<AsusDevice>, RogError> {
|
) -> 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();
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ impl DeviceHandle {
|
|||||||
Some(Arc::new(Mutex::new(k)))
|
Some(Arc::new(Mutex::new(k)))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load saved mode, colours, brightness, power from disk; apply on reload
|
|
||||||
let mut config = AuraConfig::load_and_update_config(prod_id);
|
let mut config = AuraConfig::load_and_update_config(prod_id);
|
||||||
config.led_type = aura_type;
|
config.led_type = aura_type;
|
||||||
let aura = Aura {
|
let aura = Aura {
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
const CONFIG_FILE: &str = "asusd.ron";
|
const CONFIG_FILE: &str = "asusd.ron";
|
||||||
|
|
||||||
/// Default value for base_charge_control_end_threshold when not present in config.
|
|
||||||
/// Returns 0 so restore_charge_limit() skips restoration for upgraded configs.
|
|
||||||
fn default_base_charge_limit() -> u8 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Deserialize, Serialize, PartialEq)]
|
#[derive(Default, Clone, Deserialize, Serialize, PartialEq)]
|
||||||
pub struct Tuning {
|
pub struct Tuning {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@@ -25,8 +19,8 @@ type Tunings = HashMap<PlatformProfile, Tuning>;
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
// The current charge limit applied
|
// The current charge limit applied
|
||||||
pub charge_control_end_threshold: u8,
|
pub charge_control_end_threshold: u8,
|
||||||
/// Save charge limit for restoring after one-shot full charge
|
/// Save charge limit for restoring
|
||||||
#[serde(default = "default_base_charge_limit")]
|
#[serde(skip)]
|
||||||
pub base_charge_control_end_threshold: u8,
|
pub base_charge_control_end_threshold: u8,
|
||||||
pub disable_nvidia_powerd_on_battery: bool,
|
pub disable_nvidia_powerd_on_battery: bool,
|
||||||
/// An optional command/script to run when power is changed to AC
|
/// An optional command/script to run when power is changed to AC
|
||||||
@@ -92,9 +86,6 @@ impl Default for Config {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
charge_control_end_threshold: 100,
|
charge_control_end_threshold: 100,
|
||||||
// NOTE: This is intentionally 100 (not 0 like the serde default).
|
|
||||||
// New installs get 100 (no limit). Upgraded configs missing this
|
|
||||||
// field get 0 via serde, which skips restore_charge_limit().
|
|
||||||
base_charge_control_end_threshold: 100,
|
base_charge_control_end_threshold: 100,
|
||||||
disable_nvidia_powerd_on_battery: true,
|
disable_nvidia_powerd_on_battery: true,
|
||||||
ac_command: Default::default(),
|
ac_command: Default::default(),
|
||||||
@@ -234,6 +225,8 @@ pub struct Config601 {
|
|||||||
pub nv_dynamic_boost: Option<u8>,
|
pub nv_dynamic_boost: Option<u8>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub nv_temp_target: Option<u8>,
|
pub nv_temp_target: Option<u8>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
|
pub nv_tgp: Option<u8>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub last_power_plugged: u8,
|
pub last_power_plugged: u8,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use config_traits::StdConfig;
|
use config_traits::StdConfig;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use rog_platform::asus_armoury::{
|
use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes};
|
||||||
AttrValue, FirmwareAttribute, FirmwareAttributeType, 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;
|
||||||
@@ -297,39 +295,16 @@ impl CtrlPlatform {
|
|||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
|
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
|
||||||
if !self.power.has_charge_control_end_threshold() {
|
let limit = self.power.get_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();
|
||||||
@@ -337,22 +312,12 @@ 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
|
self.power.set_charge_control_end_threshold(100)?;
|
||||||
.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();
|
||||||
}
|
}
|
||||||
@@ -461,18 +426,8 @@ impl CtrlPlatform {
|
|||||||
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
|
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
|
||||||
policy: PlatformProfile,
|
policy: PlatformProfile,
|
||||||
) -> Result<(), FdoErr> {
|
) -> Result<(), FdoErr> {
|
||||||
// If the requested profile isn't available on this platform, and it's
|
self.config.lock().await.platform_profile_on_battery = policy;
|
||||||
// `Quiet`, fall back to `LowPower` so we don't write an unavailable
|
self.set_platform_profile(ctxt, policy).await?;
|
||||||
// profile into the config file.
|
|
||||||
let mut chosen = policy;
|
|
||||||
if let Ok(choices) = self.platform.get_platform_profile_choices() {
|
|
||||||
if chosen == PlatformProfile::Quiet && !choices.contains(&PlatformProfile::Quiet) {
|
|
||||||
chosen = PlatformProfile::LowPower;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.config.lock().await.platform_profile_on_battery = chosen;
|
|
||||||
self.set_platform_profile(ctxt, chosen).await?;
|
|
||||||
self.config.lock().await.write();
|
self.config.lock().await.write();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -500,16 +455,8 @@ impl CtrlPlatform {
|
|||||||
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
|
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
|
||||||
policy: PlatformProfile,
|
policy: PlatformProfile,
|
||||||
) -> Result<(), FdoErr> {
|
) -> Result<(), FdoErr> {
|
||||||
// Mirror the same fallback behavior for AC profile changes.
|
self.config.lock().await.platform_profile_on_ac = policy;
|
||||||
let mut chosen = policy;
|
self.set_platform_profile(ctxt, policy).await?;
|
||||||
if let Ok(choices) = self.platform.get_platform_profile_choices() {
|
|
||||||
if chosen == PlatformProfile::Quiet && !choices.contains(&PlatformProfile::Quiet) {
|
|
||||||
chosen = PlatformProfile::LowPower;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.config.lock().await.platform_profile_on_ac = chosen;
|
|
||||||
self.set_platform_profile(ctxt, chosen).await?;
|
|
||||||
self.config.lock().await.write();
|
self.config.lock().await.write();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -619,7 +566,7 @@ impl CtrlPlatform {
|
|||||||
|
|
||||||
for attr in self.attributes.attributes() {
|
for attr in self.attributes.attributes() {
|
||||||
let name: FirmwareAttribute = attr.name().into();
|
let name: FirmwareAttribute = attr.name().into();
|
||||||
if name.property_type() == FirmwareAttributeType::Ppt {
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
// reset stored value
|
// reset stored value
|
||||||
if let Some(tune) = self
|
if let Some(tune) = self
|
||||||
.config
|
.config
|
||||||
|
|||||||
@@ -77,11 +77,14 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
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();
|
||||||
let armoury_registry = match start_attributes_zbus(
|
let armoury_registry = match start_attributes_zbus(
|
||||||
&server,
|
Some(&server),
|
||||||
platform.clone(),
|
platform.clone(),
|
||||||
power.clone(),
|
power.clone(),
|
||||||
attributes.clone(),
|
attributes.clone(),
|
||||||
config.clone(),
|
config.clone(),
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
68
asusd/tests/attr_unsupported_min_eq_max.rs
Normal file
68
asusd/tests/attr_unsupported_min_eq_max.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use asusd::asus_armoury::set_config_or_default;
|
||||||
|
use asusd::config::Config;
|
||||||
|
use rog_platform::asus_armoury::FirmwareAttributes;
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
|
fn write_attr_dir_with_min_max(base: &PathBuf, name: &str, default: &str, min: &str, max: &str) {
|
||||||
|
let attr_dir = base.join(name);
|
||||||
|
create_dir_all(&attr_dir).unwrap();
|
||||||
|
|
||||||
|
let mut f = File::create(attr_dir.join("default_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("display_name")).unwrap();
|
||||||
|
write!(f, "{}", name).unwrap();
|
||||||
|
// create current_value file so set_current_value can open for write
|
||||||
|
let mut f = File::create(attr_dir.join("current_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
// write explicit min and max
|
||||||
|
let mut f = File::create(attr_dir.join("min_value")).unwrap();
|
||||||
|
write!(f, "{}", min).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("max_value")).unwrap();
|
||||||
|
write!(f, "{}", max).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attribute_with_min_eq_max_is_unsupported_and_skipped() {
|
||||||
|
let td = tempdir().unwrap();
|
||||||
|
let base = td.path().join("attributes");
|
||||||
|
create_dir_all(&base).unwrap();
|
||||||
|
|
||||||
|
// create an attribute where min == max (no range)
|
||||||
|
write_attr_dir_with_min_max(&base, "nv_dynamic_boost", "5", "10", "10");
|
||||||
|
|
||||||
|
let attrs = FirmwareAttributes::from_dir(&base);
|
||||||
|
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Performance;
|
||||||
|
|
||||||
|
// set stored tuning that would normally be applied
|
||||||
|
{
|
||||||
|
let ac = cfg.select_tunings(true, profile);
|
||||||
|
ac.enabled = true;
|
||||||
|
ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
|
||||||
|
9,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
|
// apply AC
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, true, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Since min==max the attribute is considered unsupported and the current_value should remain the default (5)
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"5"
|
||||||
|
);
|
||||||
|
}
|
||||||
173
asusd/tests/sysfs_full_service.rs
Normal file
173
asusd/tests/sysfs_full_service.rs
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use asusd::asus_armoury::start_attributes_zbus;
|
||||||
|
use asusd::config::Config;
|
||||||
|
use rog_platform::asus_armoury::FirmwareAttributes;
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
use rog_platform::platform::RogPlatform;
|
||||||
|
use rog_platform::power::AsusPower;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio::sync::Mutex as TokioMutex;
|
||||||
|
|
||||||
|
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
|
||||||
|
let attr_dir = base.join(name);
|
||||||
|
create_dir_all(&attr_dir).unwrap();
|
||||||
|
|
||||||
|
let mut f = File::create(attr_dir.join("default_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("display_name")).unwrap();
|
||||||
|
write!(f, "{}", display).unwrap();
|
||||||
|
// create current_value file so set_current_value can open for write
|
||||||
|
let mut f = File::create(attr_dir.join("current_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn full_service_handles_boot_sound_and_nv_tgp() {
|
||||||
|
let td = tempdir().unwrap();
|
||||||
|
let base = td.path().join("attributes");
|
||||||
|
create_dir_all(&base).unwrap();
|
||||||
|
|
||||||
|
// create fake attributes (ppt and nv related)
|
||||||
|
write_attr_dir(&base, "boot_sound", "0", "boot_sound");
|
||||||
|
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt_pl1_spl");
|
||||||
|
write_attr_dir(&base, "ppt_pl2_sppt", "50", "ppt_pl2_sppt");
|
||||||
|
write_attr_dir(&base, "ppt_pl3_fppt", "75", "ppt_pl3_fppt");
|
||||||
|
write_attr_dir(&base, "ppt_apu_sppt", "20", "ppt_apu_sppt");
|
||||||
|
write_attr_dir(&base, "ppt_platform_sppt", "30", "ppt_platform_sppt");
|
||||||
|
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv_dynamic_boost");
|
||||||
|
write_attr_dir(&base, "nv_temp_target", "0", "nv_temp_target");
|
||||||
|
write_attr_dir(&base, "nv_base_tgp", "10", "nv_base_tgp");
|
||||||
|
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
|
||||||
|
|
||||||
|
// Ensure FirmwareAttributes reads from our fake sysfs
|
||||||
|
let attrs = FirmwareAttributes::from_dir(&base);
|
||||||
|
|
||||||
|
// Build config and set nv_tgp tuning for the platform default (Balanced) on AC
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Balanced;
|
||||||
|
{
|
||||||
|
let tuning_ac = cfg.select_tunings(true, profile);
|
||||||
|
tuning_ac.enabled = true;
|
||||||
|
tuning_ac
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 42);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
|
||||||
|
43,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
|
||||||
|
44,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptApuSppt,
|
||||||
|
45,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPlatformSppt,
|
||||||
|
46,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
|
||||||
|
11,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvTempTarget,
|
||||||
|
66,
|
||||||
|
);
|
||||||
|
tuning_ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::DgpuBaseTgp,
|
||||||
|
12,
|
||||||
|
);
|
||||||
|
tuning_ac
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 77);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use default platform/power stubs (they expect to find udev sysfs, so use Defaults)
|
||||||
|
let platform = RogPlatform::default();
|
||||||
|
let power = AsusPower::default();
|
||||||
|
|
||||||
|
// Start attributes without DBus
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
let cfg_arc = Arc::new(TokioMutex::new(cfg));
|
||||||
|
let attrs_clone = attrs.clone();
|
||||||
|
rt.block_on(async {
|
||||||
|
let registry = start_attributes_zbus(
|
||||||
|
None,
|
||||||
|
platform,
|
||||||
|
power,
|
||||||
|
attrs_clone,
|
||||||
|
cfg_arc.clone(),
|
||||||
|
false,
|
||||||
|
Some(PlatformProfile::Balanced),
|
||||||
|
Some(true),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
// registry now contains AsusArmouryAttribute objects that have been reloaded and applied
|
||||||
|
assert!(!registry.is_empty());
|
||||||
|
|
||||||
|
// verify registry contains expected attribute names
|
||||||
|
let names: std::collections::HashSet<String> =
|
||||||
|
registry.iter().map(|a| a.attribute_name()).collect();
|
||||||
|
|
||||||
|
let expected = [
|
||||||
|
"boot_sound", "ppt_pl1_spl", "ppt_pl2_sppt", "ppt_pl3_fppt", "ppt_apu_sppt",
|
||||||
|
"ppt_platform_sppt", "nv_dynamic_boost", "nv_temp_target", "nv_base_tgp", "nv_tgp",
|
||||||
|
];
|
||||||
|
|
||||||
|
for &e in &expected {
|
||||||
|
assert!(names.contains(e), "Registry missing expected attr: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that PPT and NV attributes current_value exist and were applied
|
||||||
|
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
|
||||||
|
let boot_val_path = base.join("boot_sound").join("current_value");
|
||||||
|
let ppt1_val_path = base.join("ppt_pl1_spl").join("current_value");
|
||||||
|
let ppt2_val_path = base.join("ppt_pl2_sppt").join("current_value");
|
||||||
|
let ppt3_val_path = base.join("ppt_pl3_fppt").join("current_value");
|
||||||
|
let apu_val_path = base.join("ppt_apu_sppt").join("current_value");
|
||||||
|
let plat_val_path = base.join("ppt_platform_sppt").join("current_value");
|
||||||
|
let nv_dyn_path = base.join("nv_dynamic_boost").join("current_value");
|
||||||
|
let nv_temp_path = base.join("nv_temp_target").join("current_value");
|
||||||
|
let nv_base_path = base.join("nv_base_tgp").join("current_value");
|
||||||
|
|
||||||
|
let nv = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
|
||||||
|
assert_eq!(nv.trim(), "77");
|
||||||
|
|
||||||
|
// PPTs
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(&ppt1_val_path).unwrap().trim(),
|
||||||
|
"42"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(&ppt2_val_path).unwrap().trim(),
|
||||||
|
"43"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(&ppt3_val_path).unwrap().trim(),
|
||||||
|
"44"
|
||||||
|
);
|
||||||
|
assert_eq!(std::fs::read_to_string(&apu_val_path).unwrap().trim(), "45");
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(&plat_val_path).unwrap().trim(),
|
||||||
|
"46"
|
||||||
|
);
|
||||||
|
|
||||||
|
// NVs
|
||||||
|
assert_eq!(std::fs::read_to_string(&nv_dyn_path).unwrap().trim(), "11");
|
||||||
|
assert_eq!(std::fs::read_to_string(&nv_temp_path).unwrap().trim(), "66");
|
||||||
|
assert_eq!(std::fs::read_to_string(&nv_base_path).unwrap().trim(), "12");
|
||||||
|
|
||||||
|
// boot_sound default was 0, it should remain 0 unless config.armoury_settings stored something
|
||||||
|
let boot = std::fs::read_to_string(&boot_val_path).unwrap();
|
||||||
|
assert_eq!(boot.trim(), "0");
|
||||||
|
});
|
||||||
|
}
|
||||||
97
asusd/tests/sysfs_integration.rs
Normal file
97
asusd/tests/sysfs_integration.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use asusd::asus_armoury::set_config_or_default;
|
||||||
|
use asusd::config::Config;
|
||||||
|
use rog_platform::asus_armoury::{AttrValue, FirmwareAttributes};
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
|
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
|
||||||
|
let attr_dir = base.join(name);
|
||||||
|
create_dir_all(&attr_dir).unwrap();
|
||||||
|
|
||||||
|
let mut f = File::create(attr_dir.join("default_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("display_name")).unwrap();
|
||||||
|
write!(f, "{}", display).unwrap();
|
||||||
|
// create current_value file so set_current_value can open for write
|
||||||
|
let mut f = File::create(attr_dir.join("current_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sysfs_set_config_or_default_writes_nv_and_ppt() {
|
||||||
|
let td = tempdir().unwrap();
|
||||||
|
let base = td.path().join("attributes");
|
||||||
|
create_dir_all(&base).unwrap();
|
||||||
|
|
||||||
|
// create mock attributes: ppt_pl1_spl and nv_dynamic_boost
|
||||||
|
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt");
|
||||||
|
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv");
|
||||||
|
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
|
||||||
|
|
||||||
|
// Build FirmwareAttributes from this dir
|
||||||
|
let attrs = FirmwareAttributes::from_dir(&base);
|
||||||
|
|
||||||
|
// Create a config with a tuning enabled for Performance on AC
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Performance;
|
||||||
|
{
|
||||||
|
let tuning = cfg.select_tunings(true, profile);
|
||||||
|
tuning.enabled = true;
|
||||||
|
tuning
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 42);
|
||||||
|
tuning.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
|
||||||
|
11,
|
||||||
|
);
|
||||||
|
tuning
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply
|
||||||
|
// set_config_or_default is async, call in a small runtime
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, true, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now read files to verify values were written
|
||||||
|
let ppt_val_path = base.join("ppt_pl1_spl").join("current_value");
|
||||||
|
let nv_val_path = base.join("nv_dynamic_boost").join("current_value");
|
||||||
|
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
|
||||||
|
let ppt_val = std::fs::read_to_string(&ppt_val_path).unwrap();
|
||||||
|
let mut nv_val = std::fs::read_to_string(&nv_val_path).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(ppt_val.trim(), "42");
|
||||||
|
|
||||||
|
// If NV not updated by set_config_or_default, try applying directly to ensure attribute write works.
|
||||||
|
if nv_val.trim() != "11" {
|
||||||
|
// find the attribute and set it directly
|
||||||
|
for attr in attrs.attributes() {
|
||||||
|
if attr.name() == "nv_dynamic_boost" {
|
||||||
|
attr.set_current_value(&AttrValue::Integer(11)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nv_val = std::fs::read_to_string(&nv_val_path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(nv_val.trim(), "11");
|
||||||
|
|
||||||
|
// Verify nv_tgp updated
|
||||||
|
let mut nv_tgp_val = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
|
||||||
|
if nv_tgp_val.trim() != "99" {
|
||||||
|
for attr in attrs.attributes() {
|
||||||
|
if attr.name() == "nv_tgp" {
|
||||||
|
attr.set_current_value(&AttrValue::Integer(99)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nv_tgp_val = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
|
||||||
|
}
|
||||||
|
assert_eq!(nv_tgp_val.trim(), "99");
|
||||||
|
}
|
||||||
144
asusd/tests/sysfs_nv_and_ppt_acdc.rs
Normal file
144
asusd/tests/sysfs_nv_and_ppt_acdc.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use asusd::asus_armoury::set_config_or_default;
|
||||||
|
use asusd::config::Config;
|
||||||
|
use rog_platform::asus_armoury::FirmwareAttributes;
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
|
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
|
||||||
|
let attr_dir = base.join(name);
|
||||||
|
create_dir_all(&attr_dir).unwrap();
|
||||||
|
|
||||||
|
let mut f = File::create(attr_dir.join("default_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("display_name")).unwrap();
|
||||||
|
write!(f, "{}", display).unwrap();
|
||||||
|
// create current_value file so set_current_value can open for write
|
||||||
|
let mut f = File::create(attr_dir.join("current_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nv_dynamic_boost_and_ppt_acdc() {
|
||||||
|
let td = tempdir().unwrap();
|
||||||
|
let base = td.path().join("attributes");
|
||||||
|
create_dir_all(&base).unwrap();
|
||||||
|
|
||||||
|
// create mock attributes: several PPTs and nv_dynamic_boost
|
||||||
|
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt_pl1_spl");
|
||||||
|
write_attr_dir(&base, "ppt_pl2_sppt", "50", "ppt_pl2_sppt");
|
||||||
|
write_attr_dir(&base, "ppt_pl3_fppt", "75", "ppt_pl3_fppt");
|
||||||
|
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv_dynamic_boost");
|
||||||
|
|
||||||
|
let attrs = FirmwareAttributes::from_dir(&base);
|
||||||
|
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Performance;
|
||||||
|
|
||||||
|
// set different values for AC and DC
|
||||||
|
{
|
||||||
|
let ac = cfg.select_tunings(true, profile);
|
||||||
|
ac.enabled = true;
|
||||||
|
ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
|
||||||
|
101,
|
||||||
|
);
|
||||||
|
ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
|
||||||
|
102,
|
||||||
|
);
|
||||||
|
ac.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
|
||||||
|
9,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let dc = cfg.select_tunings(false, profile);
|
||||||
|
dc.enabled = true;
|
||||||
|
dc.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 10);
|
||||||
|
dc.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
|
||||||
|
11,
|
||||||
|
);
|
||||||
|
dc.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
|
||||||
|
12,
|
||||||
|
);
|
||||||
|
dc.group.insert(
|
||||||
|
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
|
||||||
|
3,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
|
// apply AC
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, true, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl1_spl").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"100"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl2_sppt").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"101"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl3_fppt").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"102"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"9"
|
||||||
|
);
|
||||||
|
|
||||||
|
// apply DC
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, false, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl1_spl").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"10"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl2_sppt").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("ppt_pl3_fppt").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"12"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
|
||||||
|
.unwrap()
|
||||||
|
.trim(),
|
||||||
|
"3"
|
||||||
|
);
|
||||||
|
}
|
||||||
71
asusd/tests/sysfs_nv_tgp_acdc.rs
Normal file
71
asusd/tests/sysfs_nv_tgp_acdc.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use asusd::asus_armoury::set_config_or_default;
|
||||||
|
use asusd::config::Config;
|
||||||
|
use rog_platform::asus_armoury::FirmwareAttributes;
|
||||||
|
use rog_platform::platform::PlatformProfile;
|
||||||
|
|
||||||
|
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
|
||||||
|
let attr_dir = base.join(name);
|
||||||
|
create_dir_all(&attr_dir).unwrap();
|
||||||
|
|
||||||
|
let mut f = File::create(attr_dir.join("default_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
let mut f = File::create(attr_dir.join("display_name")).unwrap();
|
||||||
|
write!(f, "{}", display).unwrap();
|
||||||
|
// create current_value file so set_current_value can open for write
|
||||||
|
let mut f = File::create(attr_dir.join("current_value")).unwrap();
|
||||||
|
write!(f, "{}", default).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nv_tgp_ac_dc_applies_different_values() {
|
||||||
|
let td = tempdir().unwrap();
|
||||||
|
let base = td.path().join("attributes");
|
||||||
|
create_dir_all(&base).unwrap();
|
||||||
|
|
||||||
|
// create mock attribute nv_tgp
|
||||||
|
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
|
||||||
|
|
||||||
|
// Build FirmwareAttributes from this dir
|
||||||
|
let attrs = FirmwareAttributes::from_dir(&base);
|
||||||
|
|
||||||
|
// Create a config with different AC/DC tunings for Performance profile
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
let profile = PlatformProfile::Performance;
|
||||||
|
{
|
||||||
|
let tuning_ac = cfg.select_tunings(true, profile);
|
||||||
|
tuning_ac.enabled = true;
|
||||||
|
tuning_ac
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 123);
|
||||||
|
|
||||||
|
let tuning_dc = cfg.select_tunings(false, profile);
|
||||||
|
tuning_dc.enabled = true;
|
||||||
|
tuning_dc
|
||||||
|
.group
|
||||||
|
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply for AC
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, true, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
|
||||||
|
let val_ac = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
|
||||||
|
assert_eq!(val_ac.trim(), "123");
|
||||||
|
|
||||||
|
// Now apply for DC
|
||||||
|
rt.block_on(async {
|
||||||
|
set_config_or_default(&attrs, &mut cfg, false, profile).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
let val_dc = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
|
||||||
|
assert_eq!(val_dc.trim(), "45");
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ 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 Air*", GOTO="asusd_start"
|
||||||
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
|
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
|
||||||
ENV{DMI_FAMILY}=="*EXPERTBOOK*", GOTO="asusd_start"
|
|
||||||
# No match so
|
# No match so
|
||||||
GOTO="asusd_end"
|
GOTO="asusd_end"
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ After=nvidia-powerd.service systemd-udevd.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment=IS_SERVICE=1
|
Environment=IS_SERVICE=1
|
||||||
# Reduce noisy span logs while keeping useful debug info for asusd and related crates.
|
Environment=RUST_LOG="debug"
|
||||||
# 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,zbus::object_server=error,zbus::connection::handshake::common=error,zbus::connection::handshake::client=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
|
||||||
|
|||||||
87
distro-packaging/asusctl.spec
Normal file → Executable file
87
distro-packaging/asusctl.spec
Normal file → Executable file
@@ -20,9 +20,9 @@
|
|||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%define version 6.3.2
|
%define version 6.1.17
|
||||||
%define specrelease %{?dist}
|
%define specrelease %{?dist}
|
||||||
%define pkg_release 1%{specrelease}
|
%define pkg_release 9%{specrelease}
|
||||||
|
|
||||||
# Use hardening ldflags.
|
# Use hardening ldflags.
|
||||||
%global rustflags -Clink-arg=-Wl,-z,relro,-z,now
|
%global rustflags -Clink-arg=-Wl,-z,relro,-z,now
|
||||||
@@ -31,6 +31,7 @@ Version: %{version}
|
|||||||
Release: %{pkg_release}
|
Release: %{pkg_release}
|
||||||
Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks
|
Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks
|
||||||
License: MPLv2
|
License: MPLv2
|
||||||
|
Requires: power-profiles-daemon
|
||||||
|
|
||||||
Group: System Environment/Kernel
|
Group: System Environment/Kernel
|
||||||
|
|
||||||
@@ -55,7 +56,6 @@ BuildRequires: pkgconfig(libseat)
|
|||||||
BuildRequires: pkgconfig(libudev)
|
BuildRequires: pkgconfig(libudev)
|
||||||
BuildRequires: pkgconfig(xkbcommon)
|
BuildRequires: pkgconfig(xkbcommon)
|
||||||
BuildRequires: pkgconfig(libzstd)
|
BuildRequires: pkgconfig(libzstd)
|
||||||
BuildRequires: pkgconfig(fontconfig)
|
|
||||||
BuildRequires: desktop-file-utils
|
BuildRequires: desktop-file-utils
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@@ -68,7 +68,6 @@ asus-nb-ctrl enables third-party apps to use the above with dbus methods.
|
|||||||
|
|
||||||
%package rog-gui
|
%package rog-gui
|
||||||
Summary: An experimental GUI for %{name}
|
Summary: An experimental GUI for %{name}
|
||||||
Requires: %{name} = %{version}-%{release}
|
|
||||||
|
|
||||||
%description rog-gui
|
%description rog-gui
|
||||||
A one-stop-shop GUI tool for asusd/asusctl. It aims to provide most controls,
|
A one-stop-shop GUI tool for asusd/asusctl. It aims to provide most controls,
|
||||||
@@ -76,6 +75,11 @@ a notification service, and ability to run in the background.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%autosetup
|
%autosetup
|
||||||
|
%if %{defined fedora}
|
||||||
|
%cargo_prep
|
||||||
|
sed -i 's|offline = true|offline = false|' .cargo/config.toml
|
||||||
|
sed -i 's|source.crates-io|source.ignore_this|' .cargo/config.toml
|
||||||
|
%else
|
||||||
mkdir -p .cargo
|
mkdir -p .cargo
|
||||||
cat > .cargo/config.toml << 'EOF'
|
cat > .cargo/config.toml << 'EOF'
|
||||||
[term]
|
[term]
|
||||||
@@ -83,78 +87,28 @@ verbose = true
|
|||||||
[net]
|
[net]
|
||||||
offline = false
|
offline = false
|
||||||
EOF
|
EOF
|
||||||
|
%endif
|
||||||
|
|
||||||
%build
|
%build
|
||||||
export RUSTFLAGS="%{rustflags}"
|
export RUSTFLAGS="%{rustflags}"
|
||||||
%if %{defined fedora}
|
%if %{defined fedora}
|
||||||
/usr/bin/cargo build --release --locked
|
%# 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 --locked
|
/usr/bin/cargo auditable build --release
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%install
|
%install
|
||||||
export RUSTFLAGS="%{rustflags}"
|
export RUSTFLAGS="%{rustflags}"
|
||||||
|
mkdir -p "%{buildroot}/%{_bindir}" "%{buildroot}%{_docdir}"
|
||||||
|
%make_install
|
||||||
|
|
||||||
%define _target_dir target/release
|
install -D -m 0644 README.md %{buildroot}/%{_docdir}/%{name}/README.md
|
||||||
|
install -D -m 0644 rog-anime/README.md %{buildroot}/%{_docdir}/%{name}/README-anime.md
|
||||||
|
install -D -m 0644 rog-anime/data/diagonal-template.png %{buildroot}/%{_docdir}/%{name}/diagonal-template.png
|
||||||
|
|
||||||
# Install binaries
|
desktop-file-validate %{buildroot}/%{_datadir}/applications/rog-control-center.desktop
|
||||||
install -D -m 0755 %{_target_dir}/asusd %{buildroot}%{_bindir}/asusd
|
|
||||||
install -D -m 0755 %{_target_dir}/asusd-user %{buildroot}%{_bindir}/asusd-user
|
|
||||||
install -D -m 0755 %{_target_dir}/asusctl %{buildroot}%{_bindir}/asusctl
|
|
||||||
install -D -m 0755 %{_target_dir}/rog-control-center %{buildroot}%{_bindir}/rog-control-center
|
|
||||||
|
|
||||||
# Install systemd units
|
|
||||||
install -D -m 0644 data/asusd.service %{buildroot}%{_unitdir}/asusd.service
|
|
||||||
install -D -m 0644 data/asusd-user.service %{buildroot}%{_userunitdir}/asusd-user.service
|
|
||||||
|
|
||||||
# Install udev rules
|
|
||||||
install -D -m 0644 data/asusd.rules %{buildroot}%{_udevrulesdir}/99-asusd.rules
|
|
||||||
|
|
||||||
# Install dbus config
|
|
||||||
install -D -m 0644 data/asusd.conf %{buildroot}%{_datadir}/dbus-1/system.d/asusd.conf
|
|
||||||
|
|
||||||
# Install asusd data
|
|
||||||
install -D -m 0644 rog-aura/data/aura_support.ron %{buildroot}%{_datadir}/asusd/aura_support.ron
|
|
||||||
cp -r rog-anime/data/anime %{buildroot}%{_datadir}/asusd/
|
|
||||||
|
|
||||||
# Install rog-gui data
|
|
||||||
install -D -m 0644 rog-control-center/data/rog-control-center.desktop %{buildroot}%{_datadir}/applications/rog-control-center.desktop
|
|
||||||
install -D -m 0644 rog-control-center/data/rog-control-center.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/rog-control-center.png
|
|
||||||
mkdir -p %{buildroot}%{_datadir}/rog-gui/layouts
|
|
||||||
cp -r rog-aura/data/layouts/*.ron %{buildroot}%{_datadir}/rog-gui/layouts/
|
|
||||||
|
|
||||||
# Install icons
|
|
||||||
install -D -m 0644 data/icons/asus_notif_yellow.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
|
|
||||||
install -D -m 0644 data/icons/asus_notif_green.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
|
|
||||||
install -D -m 0644 data/icons/asus_notif_blue.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_blue.png
|
|
||||||
install -D -m 0644 data/icons/asus_notif_red.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_red.png
|
|
||||||
install -D -m 0644 data/icons/asus_notif_orange.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_orange.png
|
|
||||||
install -D -m 0644 data/icons/asus_notif_white.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_white.png
|
|
||||||
install -D -m 0644 data/icons/scalable/gpu-compute.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-compute.svg
|
|
||||||
install -D -m 0644 data/icons/scalable/gpu-hybrid.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-hybrid.svg
|
|
||||||
install -D -m 0644 data/icons/scalable/gpu-integrated.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-integrated.svg
|
|
||||||
install -D -m 0644 data/icons/scalable/gpu-nvidia.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-nvidia.svg
|
|
||||||
install -D -m 0644 data/icons/scalable/gpu-vfio.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
|
|
||||||
install -D -m 0644 data/icons/scalable/notification-reboot.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
|
|
||||||
|
|
||||||
# Install docs
|
|
||||||
install -D -m 0644 README.md %{buildroot}%{_docdir}/%{name}/README.md
|
|
||||||
install -D -m 0644 rog-anime/README.md %{buildroot}%{_docdir}/%{name}/README-anime.md
|
|
||||||
install -D -m 0644 rog-anime/data/diagonal-template.png %{buildroot}%{_docdir}/%{name}/diagonal-template.png
|
|
||||||
|
|
||||||
# Install LICENSE to asusctl datadir
|
|
||||||
install -D -m 0644 LICENSE %{buildroot}%{_datadir}/asusctl/LICENSE
|
|
||||||
|
|
||||||
desktop-file-validate %{buildroot}%{_datadir}/applications/rog-control-center.desktop
|
|
||||||
|
|
||||||
%post
|
|
||||||
%systemd_post asusd.service
|
|
||||||
|
|
||||||
%preun
|
|
||||||
%systemd_preun asusd.service
|
|
||||||
|
|
||||||
%postun
|
|
||||||
%systemd_postun_with_restart asusd.service
|
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
@@ -164,6 +118,8 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/rog-control-center.de
|
|||||||
%{_unitdir}/asusd.service
|
%{_unitdir}/asusd.service
|
||||||
%{_userunitdir}/asusd-user.service
|
%{_userunitdir}/asusd-user.service
|
||||||
%{_udevrulesdir}/99-asusd.rules
|
%{_udevrulesdir}/99-asusd.rules
|
||||||
|
#%dir %{_sysconfdir}/asusd/
|
||||||
|
%{_datadir}/asusd/aura_support.ron
|
||||||
%{_datadir}/dbus-1/system.d/asusd.conf
|
%{_datadir}/dbus-1/system.d/asusd.conf
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
|
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
|
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
|
||||||
@@ -178,7 +134,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/rog-control-center.de
|
|||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
|
%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
|
||||||
%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
|
%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
|
||||||
%{_docdir}/%{name}/
|
%{_docdir}/%{name}/
|
||||||
%{_datadir}/asusctl/
|
|
||||||
%{_datadir}/asusd/
|
%{_datadir}/asusd/
|
||||||
|
|
||||||
%files rog-gui
|
%files rog-gui
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
||||||
<title>asusctl docs</title>
|
|
||||||
<!-- Redirect to the generated crate docs -->
|
|
||||||
<meta http-equiv="refresh" content="0;url=asusctl/index.html">
|
|
||||||
<link rel="canonical" href="asusctl/index.html">
|
|
||||||
<style>
|
|
||||||
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; color:#222; display:flex; align-items:center; justify-content:center; height:100vh; margin:0 }
|
|
||||||
.box { text-align:center }
|
|
||||||
a { color: #0366d6 }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="box">
|
|
||||||
<h1>asusctl documentation</h1>
|
|
||||||
<p>Redirecting to the generated docs — if your browser doesn't redirect automatically, <a href="asusctl/index.html">click here</a>.</p>
|
|
||||||
<p>If you expected a different landing page, update <code>extra/index.html</code> accordingly.</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 518 B |
@@ -63,8 +63,6 @@ pub enum AnimeType {
|
|||||||
GA401,
|
GA401,
|
||||||
GA402,
|
GA402,
|
||||||
GU604,
|
GU604,
|
||||||
G635L,
|
|
||||||
G835L,
|
|
||||||
#[default]
|
#[default]
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
@@ -73,21 +71,12 @@ impl FromStr for AnimeType {
|
|||||||
type Err = AnimeError;
|
type Err = AnimeError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
let dmi = s.to_uppercase();
|
Ok(match s {
|
||||||
|
"ga401" | "GA401" => Self::GA401,
|
||||||
if dmi.contains("GA401") {
|
"ga402" | "GA402" => Self::GA402,
|
||||||
return Ok(Self::GA401);
|
"gu604" | "GU604" => Self::GU604,
|
||||||
} else if dmi.contains("GA402") {
|
_ => Self::Unsupported,
|
||||||
return Ok(Self::GA402);
|
})
|
||||||
} else if dmi.contains("GU604") {
|
|
||||||
return Ok(Self::GU604);
|
|
||||||
} else if dmi.contains("G635L") {
|
|
||||||
return Ok(Self::G635L);
|
|
||||||
} else if dmi.contains("G835L") {
|
|
||||||
return Ok(Self::G835L);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self::Unsupported)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,17 +85,10 @@ impl AnimeType {
|
|||||||
let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase();
|
let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase();
|
||||||
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
||||||
AnimeType::GA401
|
AnimeType::GA401
|
||||||
} else if board_name.contains("GA402R")
|
} else if board_name.contains("GA402R") || board_name.contains("GA402X") {
|
||||||
|| board_name.contains("GA402X")
|
|
||||||
|| board_name.contains("GA402N")
|
|
||||||
{
|
|
||||||
AnimeType::GA402
|
AnimeType::GA402
|
||||||
} else if board_name.contains("GU604V") {
|
} else if board_name.contains("GU604V") {
|
||||||
AnimeType::GU604
|
AnimeType::GU604
|
||||||
} else if board_name.contains("G635L") {
|
|
||||||
AnimeType::G635L
|
|
||||||
} else if board_name.contains("G835L") {
|
|
||||||
AnimeType::G835L
|
|
||||||
} else {
|
} else {
|
||||||
AnimeType::Unsupported
|
AnimeType::Unsupported
|
||||||
}
|
}
|
||||||
@@ -116,9 +98,6 @@ impl AnimeType {
|
|||||||
pub fn width(&self) -> usize {
|
pub fn width(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
AnimeType::GU604 => 70,
|
AnimeType::GU604 => 70,
|
||||||
// TODO: Find G635L W*H
|
|
||||||
AnimeType::G635L => 68,
|
|
||||||
AnimeType::G835L => 68,
|
|
||||||
_ => 74,
|
_ => 74,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,8 +107,6 @@ impl AnimeType {
|
|||||||
match self {
|
match self {
|
||||||
AnimeType::GA401 => 36,
|
AnimeType::GA401 => 36,
|
||||||
AnimeType::GU604 => 43,
|
AnimeType::GU604 => 43,
|
||||||
AnimeType::G635L => 34,
|
|
||||||
AnimeType::G835L => 34,
|
|
||||||
_ => 39,
|
_ => 39,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,9 +115,7 @@ impl AnimeType {
|
|||||||
pub fn data_length(&self) -> usize {
|
pub fn data_length(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
AnimeType::GA401 => PANE_LEN * 2,
|
AnimeType::GA401 => PANE_LEN * 2,
|
||||||
// G835L has 810 LEDs: 210 (triangle) + 600 (staggered rectangle)
|
AnimeType::GU604 => PANE_LEN * 3,
|
||||||
AnimeType::G635L => 810, // TODO: This is provisional until we have a G635L to test on
|
|
||||||
AnimeType::G835L => 810,
|
|
||||||
_ => PANE_LEN * 3,
|
_ => PANE_LEN * 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,29 +179,13 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut buffers = match anime.anime {
|
let mut buffers = match anime.anime {
|
||||||
AnimeType::GA401 | AnimeType::G635L | AnimeType::G835L => vec![[0; 640]; 2],
|
AnimeType::GA401 => vec![[0; 640]; 2],
|
||||||
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported => {
|
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported => vec![[0; 640]; 3],
|
||||||
vec![[0; 640]; 3]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// G835L has different packing: 627 bytes in pane 1, 183 bytes in pane 2
|
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
|
||||||
if anime.anime == AnimeType::G835L || anime.anime == AnimeType::G635L {
|
buffers[idx][BLOCK_START..BLOCK_END].copy_from_slice(chunk);
|
||||||
let data = anime.data.as_slice();
|
|
||||||
// Pane 1: first 627 bytes
|
|
||||||
let pane1_len = PANE_LEN.min(data.len());
|
|
||||||
buffers[0][BLOCK_START..BLOCK_START + pane1_len].copy_from_slice(&data[..pane1_len]);
|
|
||||||
// Pane 2: remaining bytes (183)
|
|
||||||
if data.len() > PANE_LEN {
|
|
||||||
let pane2_len = data.len() - PANE_LEN;
|
|
||||||
buffers[1][BLOCK_START..BLOCK_START + pane2_len].copy_from_slice(&data[PANE_LEN..]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
|
|
||||||
buffers[idx][BLOCK_START..BLOCK_START + chunk.len()].copy_from_slice(chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers[0][..7].copy_from_slice(&USB_PREFIX1);
|
buffers[0][..7].copy_from_slice(&USB_PREFIX1);
|
||||||
buffers[1][..7].copy_from_slice(&USB_PREFIX2);
|
buffers[1][..7].copy_from_slice(&USB_PREFIX2);
|
||||||
|
|
||||||
|
|||||||
@@ -146,8 +146,6 @@ impl AnimeDiagonal {
|
|||||||
match anime_type {
|
match anime_type {
|
||||||
AnimeType::GA401 => self.to_ga401_packets(),
|
AnimeType::GA401 => self.to_ga401_packets(),
|
||||||
AnimeType::GU604 => self.to_gu604_packets(),
|
AnimeType::GU604 => self.to_gu604_packets(),
|
||||||
AnimeType::G635L => self.to_g835l_packets(), // TODO: Verify with G635L model
|
|
||||||
AnimeType::G835L => self.to_g835l_packets(),
|
|
||||||
_ => self.to_ga402_packets(),
|
_ => self.to_ga402_packets(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,80 +381,4 @@ impl AnimeDiagonal {
|
|||||||
|
|
||||||
AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf)
|
AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// G835L diagonal packing - inverted geometry (rows grow then constant)
|
|
||||||
/// Triangle (rows 0-27): pairs grow from 1→14 LEDs
|
|
||||||
/// Rectangle (rows 28-67): constant 15 LEDs
|
|
||||||
///
|
|
||||||
/// Diagonal PNG layout for G835L:
|
|
||||||
/// - Image height = 34 (row pairs)
|
|
||||||
/// - Image width = 68 (half-step X grid)
|
|
||||||
/// - Even/odd rows are interleaved in X (staggered by 0.5 LED = 1 px)
|
|
||||||
fn to_g835l_packets(&self) -> Result<AnimeDataBuffer> {
|
|
||||||
use log::debug;
|
|
||||||
|
|
||||||
let mut buf = vec![0u8; AnimeType::G835L.data_length()];
|
|
||||||
let mut buf_idx = 0usize;
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"G835L packing: image dimensions {}x{}, buffer size {}",
|
|
||||||
self.1.first().map(|r| r.len()).unwrap_or(0),
|
|
||||||
self.1.len(),
|
|
||||||
buf.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Helper: get row length for G835L
|
|
||||||
fn row_length(row: usize) -> usize {
|
|
||||||
if row < 28 {
|
|
||||||
row / 2 + 1
|
|
||||||
} else {
|
|
||||||
15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper: starting X (in LED units) for the row
|
|
||||||
fn first_x(row: usize) -> usize {
|
|
||||||
if row < 28 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(row - 28) / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process all 68 rows
|
|
||||||
for row in 0..68 {
|
|
||||||
let len = row_length(row);
|
|
||||||
let img_y = row / 2;
|
|
||||||
let base_x = first_x(row);
|
|
||||||
let stagger = row % 2;
|
|
||||||
|
|
||||||
for i in 0..len {
|
|
||||||
// Half-step X grid: even rows on even pixels, odd rows on odd pixels.
|
|
||||||
let img_x = (base_x + i) * 2 + stagger;
|
|
||||||
|
|
||||||
// Read from image, clamp to bounds
|
|
||||||
let val = if img_y < self.1.len() && img_x < self.1[img_y].len() {
|
|
||||||
self.1[img_y][img_x]
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log first LED of each row for debugging
|
|
||||||
if i == 0 {
|
|
||||||
debug!(
|
|
||||||
"Row {}: len={}, first LED at img[{}][{}] = {}",
|
|
||||||
row, len, img_y, img_x, val
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if buf_idx < buf.len() {
|
|
||||||
buf[buf_idx] = val;
|
|
||||||
}
|
|
||||||
buf_idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("G835L packing complete: {} bytes written", buf_idx);
|
|
||||||
AnimeDataBuffer::from_vec(AnimeType::G835L, buf)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ impl AnimeImage {
|
|||||||
fn scale_y(anime_type: AnimeType) -> f32 {
|
fn scale_y(anime_type: AnimeType) -> f32 {
|
||||||
match anime_type {
|
match anime_type {
|
||||||
AnimeType::GA401 => 0.3,
|
AnimeType::GA401 => 0.3,
|
||||||
AnimeType::GA402 => 0.283,
|
AnimeType::GU604 => 0.28,
|
||||||
_ => 0.28,
|
_ => 0.283,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +149,6 @@ impl AnimeImage {
|
|||||||
/// square grid, so `first_x` is the x position on that grid where the
|
/// square grid, so `first_x` is the x position on that grid where the
|
||||||
/// LED is actually positioned in relation to the Y.
|
/// LED is actually positioned in relation to the Y.
|
||||||
///
|
///
|
||||||
/// For GA401/GA402/GU604 (shrinking pattern - diagonal cuts in from left):
|
|
||||||
/// ```text
|
/// ```text
|
||||||
/// +------------+
|
/// +------------+
|
||||||
/// | |
|
/// | |
|
||||||
@@ -163,19 +162,6 @@ impl AnimeImage {
|
|||||||
/// ^ ------+
|
/// ^ ------+
|
||||||
/// first_x
|
/// first_x
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
/// For G835L/G635L (inverted pattern - triangle grows then rectangle shifts):
|
|
||||||
/// ```text
|
|
||||||
/// ● <- Row 0: first_x = 0, width = 1
|
|
||||||
/// ● <- Row 1: first_x = 0 (stagger), width = 1
|
|
||||||
/// ● ● <- Row 2: first_x = 0, width = 2
|
|
||||||
/// ● ● <- Row 3: first_x = 0 (stagger), width = 2
|
|
||||||
/// ... <- Triangle continues, first_x = 0 for rows 0-27
|
|
||||||
/// ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● <- Row 28+: first_x grows
|
|
||||||
/// ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● <- Rectangle shifts right
|
|
||||||
/// ```
|
|
||||||
/// Triangle (rows 0-27): first_x = 0 (no cumulative shift)
|
|
||||||
/// Rectangle (rows 28-67): first_x = (y - 28) / 2 (shifts right)
|
|
||||||
fn first_x(anime_type: AnimeType, y: u32) -> u32 {
|
fn first_x(anime_type: AnimeType, y: u32) -> u32 {
|
||||||
match anime_type {
|
match anime_type {
|
||||||
AnimeType::GA401 => {
|
AnimeType::GA401 => {
|
||||||
@@ -193,16 +179,6 @@ impl AnimeImage {
|
|||||||
// and then their offset grows by one every two rows
|
// and then their offset grows by one every two rows
|
||||||
(y - 9) / 2
|
(y - 9) / 2
|
||||||
}
|
}
|
||||||
AnimeType::G635L | AnimeType::G835L => {
|
|
||||||
// G835L/G635L have inverted geometry - triangle at top-left, rectangle shifts right
|
|
||||||
// Triangle (rows 0-27): no cumulative shift, just alternating stagger
|
|
||||||
// Rectangle (rows 28-67): shifts right by ~0.5px per row
|
|
||||||
if y < 28 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(y - 28) / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
// first 11 rows start at zero
|
// first 11 rows start at zero
|
||||||
if y <= 11 {
|
if y <= 11 {
|
||||||
@@ -245,16 +221,6 @@ impl AnimeImage {
|
|||||||
}
|
}
|
||||||
38 - Self::first_x(anime_type, y) + y % 2
|
38 - Self::first_x(anime_type, y) + y % 2
|
||||||
}
|
}
|
||||||
AnimeType::G635L | AnimeType::G835L => {
|
|
||||||
// G835L/G635L rows GROW then stay constant (inverted from other devices)
|
|
||||||
// Triangle (rows 0-27): pairs of rows with same length, 1→14
|
|
||||||
// Rectangle (rows 28-67): constant 15 LEDs
|
|
||||||
if y < 28 {
|
|
||||||
y / 2 + 1
|
|
||||||
} else {
|
|
||||||
15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if y <= 11 {
|
if y <= 11 {
|
||||||
return 34;
|
return 34;
|
||||||
@@ -269,9 +235,8 @@ impl AnimeImage {
|
|||||||
match anime_type {
|
match anime_type {
|
||||||
// 33.0 = Longest row LED count (physical) plus half-pixel offset
|
// 33.0 = Longest row LED count (physical) plus half-pixel offset
|
||||||
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
|
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
|
||||||
|
|
||||||
AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type),
|
AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type),
|
||||||
AnimeType::G635L => (33.0 + 0.5) * Self::scale_x(anime_type),
|
|
||||||
AnimeType::G835L => (33.0 + 0.5) * Self::scale_x(anime_type),
|
|
||||||
_ => (35.0 + 0.5) * Self::scale_x(anime_type),
|
_ => (35.0 + 0.5) * Self::scale_x(anime_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,8 +246,6 @@ impl AnimeImage {
|
|||||||
match anime_type {
|
match anime_type {
|
||||||
AnimeType::GA401 => 55,
|
AnimeType::GA401 => 55,
|
||||||
AnimeType::GU604 => 62,
|
AnimeType::GU604 => 62,
|
||||||
AnimeType::G635L => 68,
|
|
||||||
AnimeType::G835L => 68,
|
|
||||||
_ => 61,
|
_ => 61,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,8 +256,6 @@ impl AnimeImage {
|
|||||||
// 54.0 = End column LED count (physical) plus one dead pixel
|
// 54.0 = End column LED count (physical) plus one dead pixel
|
||||||
AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type),
|
AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type),
|
||||||
AnimeType::GU604 => 62.0 * Self::scale_y(anime_type),
|
AnimeType::GU604 => 62.0 * Self::scale_y(anime_type),
|
||||||
AnimeType::G635L => 68.0 * Self::scale_y(anime_type),
|
|
||||||
AnimeType::G835L => 68.0 * Self::scale_y(anime_type),
|
|
||||||
// GA402 may not have dead pixels and require only the physical LED count
|
// GA402 may not have dead pixels and require only the physical LED count
|
||||||
_ => 61.0 * Self::scale_y(anime_type),
|
_ => 61.0 * Self::scale_y(anime_type),
|
||||||
}
|
}
|
||||||
@@ -308,8 +269,8 @@ impl AnimeImage {
|
|||||||
1 | 3 => 35, // Some rows are padded
|
1 | 3 => 35, // Some rows are padded
|
||||||
_ => 36 - y / 2,
|
_ => 36 - y / 2,
|
||||||
},
|
},
|
||||||
|
AnimeType::GU604 => AnimeImage::width(anime_type, y),
|
||||||
// Other devices don't have dead pixels
|
// GA402 does not have padding, equivalent to width
|
||||||
_ => AnimeImage::width(anime_type, y),
|
_ => AnimeImage::width(anime_type, y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,35 +405,13 @@ impl AnimeImage {
|
|||||||
let transform =
|
let transform =
|
||||||
Mat3::from_scale_angle_translation(self.scale, self.angle, self.translation);
|
Mat3::from_scale_angle_translation(self.scale, self.angle, self.translation);
|
||||||
|
|
||||||
let pos_in_leds = Mat3::from_translation(self.led_center());
|
let pos_in_leds = Mat3::from_translation(Vec2::new(20.0, 20.0));
|
||||||
// Get LED-to-image coords
|
// Get LED-to-image coords
|
||||||
let led_from_px = pos_in_leds * led_from_cm * transform * cm_from_px * center;
|
let led_from_px = pos_in_leds * led_from_cm * transform * cm_from_px * center;
|
||||||
|
|
||||||
led_from_px.inverse()
|
led_from_px.inverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn led_center(&self) -> Vec2 {
|
|
||||||
if !matches!(self.anime_type, AnimeType::G635L | AnimeType::G835L) {
|
|
||||||
return Vec2::new(20.0, 20.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut min = Vec2::splat(f32::INFINITY);
|
|
||||||
let mut max = Vec2::splat(f32::NEG_INFINITY);
|
|
||||||
for led in self.led_pos.iter().flatten() {
|
|
||||||
let pos = Vec2::new(led.x(), led.y());
|
|
||||||
min = min.min(pos);
|
|
||||||
max = max.max(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if min.x.is_finite() {
|
|
||||||
let mut center = (min + max) * 0.5;
|
|
||||||
center.y += 1.0;
|
|
||||||
center
|
|
||||||
} else {
|
|
||||||
Vec2::new(20.0, 20.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate the base image from inputs. The result can be displayed as is
|
/// Generate the base image from inputs. The result can be displayed as is
|
||||||
/// or updated via scale, position, or angle then displayed again after
|
/// or updated via scale, position, or angle then displayed again after
|
||||||
/// `update()`.
|
/// `update()`.
|
||||||
|
|||||||
@@ -243,21 +243,14 @@ impl From<AnimShutdown> for i32 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_anime_type() -> AnimeType {
|
pub fn get_anime_type() -> AnimeType {
|
||||||
let dmi = DMIID::new().unwrap_or_default();
|
let dmi = DMIID::new().unwrap_or_default();
|
||||||
let board_name = dmi.board_name.to_uppercase();
|
let board_name = dmi.board_name;
|
||||||
|
|
||||||
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
||||||
AnimeType::GA401
|
AnimeType::GA401
|
||||||
} else if board_name.contains("GA402R")
|
} else if board_name.contains("GA402R") || board_name.contains("GA402X") {
|
||||||
|| board_name.contains("GA402X")
|
|
||||||
|| board_name.contains("GA402N")
|
|
||||||
{
|
|
||||||
AnimeType::GA402
|
AnimeType::GA402
|
||||||
} else if board_name.contains("GU604V") {
|
} else if board_name.contains("GU604V") {
|
||||||
AnimeType::GU604
|
AnimeType::GU604
|
||||||
} else if board_name.contains("G635L") {
|
|
||||||
AnimeType::G635L
|
|
||||||
} else if board_name.contains("G835L") {
|
|
||||||
AnimeType::G835L
|
|
||||||
} else {
|
} else {
|
||||||
AnimeType::Unsupported
|
AnimeType::Unsupported
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 205 B |
Binary file not shown.
|
Before Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 156 B |
@@ -1,556 +0,0 @@
|
|||||||
// TODO: This is a provisional copy paste of GA401
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use rog_anime::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn g835l_image_edge_packet_check() {
|
|
||||||
let pkt0_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt1_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut matrix = AnimeImage::new(
|
|
||||||
Vec2::new(1.0, 1.0),
|
|
||||||
0.0,
|
|
||||||
Vec2::default(),
|
|
||||||
0.0,
|
|
||||||
vec![Pixel::default(); 1000],
|
|
||||||
100,
|
|
||||||
AnimeType::G835L,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
matrix.edge_outline();
|
|
||||||
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
|
|
||||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(pkt[0], pkt0_check);
|
|
||||||
assert_eq!(pkt[1], pkt1_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn g835l_diagonal_packet_check() {
|
|
||||||
let pkt0_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt1_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
path.push("tests/data/g835l-diagonal.png");
|
|
||||||
|
|
||||||
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::G835L).unwrap();
|
|
||||||
let data = matrix.into_data_buffer(AnimeType::G835L).unwrap();
|
|
||||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(pkt[0], pkt0_check);
|
|
||||||
assert_eq!(pkt[1], pkt1_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn g835l_diagonal_fullbright_packet_check() {
|
|
||||||
let pkt0_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt1_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
path.push("tests/data/g835l-diagonal-fullbright.png");
|
|
||||||
|
|
||||||
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::G835L).unwrap();
|
|
||||||
let data = matrix.into_data_buffer(AnimeType::G835L).unwrap();
|
|
||||||
let pkt = AnimePacketType::try_from(data).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(pkt[0], pkt0_check);
|
|
||||||
assert_eq!(pkt[1], pkt1_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn g835l_diagonal_gif_wave_packet_check() {
|
|
||||||
let pkt0_frame0_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x7f, 0x92, 0x84, 0xa2, 0x95, 0xac, 0x8a,
|
|
||||||
0xa0, 0xaf, 0x97, 0xa4, 0xa8, 0x91, 0x9c, 0x9e, 0x99, 0x98, 0x98, 0x91, 0x82, 0x99,
|
|
||||||
0x97, 0x8d, 0x7c, 0x67, 0x99, 0x8d, 0x7a, 0x63, 0x4a, 0xa0, 0x92, 0x7d, 0x63, 0x48,
|
|
||||||
0x2e, 0x9a, 0x83, 0x67, 0x4a, 0x2e, 0x17, 0xa6, 0x8d, 0x70, 0x50, 0x32, 0x19, 0x08,
|
|
||||||
0x9a, 0x7b, 0x5a, 0x3b, 0x20, 0x0c, 0x02, 0xa8, 0x89, 0x67, 0x46, 0x2a, 0x15, 0x09,
|
|
||||||
0x07, 0x97, 0x75, 0x54, 0x37, 0x21, 0x13, 0x10, 0x16, 0xa6, 0x84, 0x63, 0x45, 0x2e,
|
|
||||||
0x20, 0x1c, 0x21, 0x2e, 0x91, 0x71, 0x54, 0x3d, 0x2f, 0x2a, 0x2e, 0x3a, 0x4c, 0x9d,
|
|
||||||
0x7d, 0x61, 0x4c, 0x3e, 0x39, 0x3d, 0x49, 0x5a, 0x6d, 0x87, 0x6d, 0x58, 0x4c, 0x48,
|
|
||||||
0x4c, 0x58, 0x69, 0x7c, 0x8e, 0x8e, 0x75, 0x63, 0x58, 0x55, 0x5a, 0x67, 0x78, 0x8b,
|
|
||||||
0x9d, 0xab, 0x7a, 0x69, 0x60, 0x5f, 0x66, 0x74, 0x86, 0x9a, 0xac, 0xba, 0xc1, 0x7a,
|
|
||||||
0x6c, 0x65, 0x66, 0x6f, 0x7f, 0x93, 0xa7, 0xba, 0xc9, 0xd0, 0xce, 0x6a, 0x65, 0x69,
|
|
||||||
0x74, 0x86, 0x9c, 0xb2, 0xc7, 0xd6, 0xde, 0xdd, 0xd2, 0x63, 0x61, 0x67, 0x75, 0x89,
|
|
||||||
0xa1, 0xba, 0xd0, 0xe1, 0xea, 0xea, 0xe0, 0xcc, 0x59, 0x61, 0x71, 0x88, 0xa2, 0xbd,
|
|
||||||
0xd5, 0xe8, 0xf3, 0xf4, 0xec, 0xd9, 0xbf, 0x4e, 0x58, 0x6a, 0x82, 0x9e, 0xbc, 0xd6,
|
|
||||||
0xeb, 0xf8, 0xfc, 0xf4, 0xe4, 0xca, 0xac, 0x4b, 0x5f, 0x79, 0x97, 0xb6, 0xd3, 0xea,
|
|
||||||
0xf9, 0xfe, 0xf9, 0xea, 0xd3, 0xb6, 0x96, 0x3d, 0x51, 0x6c, 0x8c, 0xad, 0xcb, 0xe4,
|
|
||||||
0xf6, 0xfd, 0xfa, 0xed, 0xd8, 0xbd, 0x9f, 0x82, 0x43, 0x5e, 0x7f, 0xa1, 0xc0, 0xdb,
|
|
||||||
0xee, 0xf7, 0xf6, 0xeb, 0xd8, 0xc0, 0xa4, 0x89, 0x71, 0x50, 0x70, 0x92, 0xb3, 0xcf,
|
|
||||||
0xe3, 0xee, 0xee, 0xe6, 0xd5, 0xbe, 0xa4, 0x8c, 0x76, 0x67, 0x62, 0x84, 0xa5, 0xc1,
|
|
||||||
0xd5, 0xe1, 0xe3, 0xdc, 0xcd, 0xb8, 0xa1, 0x8a, 0x77, 0x6a, 0x64, 0x76, 0x96, 0xb2,
|
|
||||||
0xc7, 0xd3, 0xd5, 0xcf, 0xc1, 0xae, 0x99, 0x84, 0x73, 0x68, 0x65, 0x6a, 0x89, 0xa4,
|
|
||||||
0xb8, 0xc4, 0xc6, 0xc0, 0xb3, 0xa1, 0x8d, 0x7a, 0x6b, 0x63, 0x62, 0x69, 0x78, 0x98,
|
|
||||||
0xab, 0xb5, 0xb8, 0xb1, 0xa4, 0x93, 0x7f, 0x6e, 0x60, 0x59, 0x5b, 0x64, 0x75, 0x8c,
|
|
||||||
0xa0, 0xa9, 0xaa, 0xa3, 0x95, 0x83, 0x70, 0x5f, 0x53, 0x4d, 0x50, 0x5b, 0x6e, 0x87,
|
|
||||||
0xa4, 0xa0, 0x9f, 0x96, 0x87, 0x74, 0x61, 0x50, 0x44, 0x3f, 0x42, 0x4f, 0x64, 0x7e,
|
|
||||||
0x9d, 0xbc, 0x97, 0x8c, 0x7c, 0x68, 0x53, 0x41, 0x34, 0x2f, 0x33, 0x41, 0x56, 0x73,
|
|
||||||
0x93, 0xb3, 0xd1, 0x86, 0x74, 0x5e, 0x47, 0x34, 0x27, 0x21, 0x25, 0x32, 0x48, 0x65,
|
|
||||||
0x86, 0xa7, 0xc6, 0xe0, 0x70, 0x57, 0x3f, 0x2a, 0x1b, 0x14, 0x17, 0x24, 0x39, 0x56,
|
|
||||||
0x77, 0x99, 0xb9, 0xd4, 0xe6, 0x56, 0x3b, 0x24, 0x13, 0x0a, 0x0c, 0x17, 0x2c, 0x48,
|
|
||||||
0x69, 0x8b, 0xab, 0xc6, 0xd9, 0xe3, 0x3b, 0x22, 0x0f, 0x04, 0x04, 0x0e, 0x21, 0x3c,
|
|
||||||
0x5b, 0x7d, 0x9c, 0xb7, 0xca, 0xd5, 0xd6, 0x25, 0x0f, 0x03, 0x00, 0x08, 0x19, 0x32,
|
|
||||||
0x50, 0x70, 0x8f, 0xa9, 0xbc, 0xc6, 0xc7, 0xc0, 0x14, 0x05, 0x01, 0x06, 0x15, 0x2c,
|
|
||||||
0x49, 0x67, 0x84, 0x9c, 0xae, 0xb7, 0xb8, 0xb0, 0xa2, 0x0c, 0x05, 0x09, 0x16, 0x2b,
|
|
||||||
0x45, 0x61, 0x7c, 0x93, 0xa3, 0xab, 0xaa, 0xa2, 0x93, 0x81, 0x0e, 0x10, 0x1b, 0x2e,
|
|
||||||
0x46, 0x60, 0x78, 0x8d, 0x9b, 0xa1, 0x9e, 0x94, 0x85, 0x72, 0x5f, 0x1b, 0x24, 0x35,
|
|
||||||
0x4b, 0x62, 0x79, 0x8b, 0x96, 0x9a, 0x96, 0x8a, 0x79, 0x65, 0x50, 0x3f, 0x30, 0x40,
|
|
||||||
0x54, 0x6a, 0x7e, 0x8d, 0x97, 0x98, 0x91, 0x84, 0x70, 0x5a, 0x44, 0x32, 0x26, 0x4d,
|
|
||||||
0x60, 0x74, 0x87, 0x94, 0x9b, 0x9a, 0x91, 0x81, 0x6c, 0x53, 0x3c, 0x28, 0x1a, 0x15,
|
|
||||||
0x6e, 0x82, 0x93, 0x9f, 0xa4, 0xa1, 0x96, 0x83, 0x6b, 0x51, 0x37, 0x21, 0x11, 0x0a,
|
|
||||||
0x0e, 0x91, 0xa1, 0xac, 0xb0, 0xab, 0x9e, 0x89, 0x6f, 0x53, 0x37, 0x1e, 0x0d, 0x04,
|
|
||||||
0x05, 0x11, 0xb0, 0xbb, 0xbe, 0xb8, 0xaa, 0x93, 0x77, 0x59, 0x3a, 0x20, 0x0c, 0x01,
|
|
||||||
0x01, 0x0a, 0x1d, 0xca, 0xcd, 0xc7, 0xb7, 0xa0, 0x83, 0x62, 0x42, 0x26, 0x10, 0x03,
|
|
||||||
0x01, 0x08, 0x19, 0x31, 0xdc, 0xd6, 0xc6, 0xae, 0x90, 0x6f, 0x4e, 0x30, 0x18, 0x0a,
|
|
||||||
0x05, 0x0a, 0x19, 0x2f, 0x4a, 0xe4, 0xd4, 0xbd, 0x9f, 0x7d, 0x5b, 0x3c, 0x24, 0x14,
|
|
||||||
0x0d, 0x11, 0x1e, 0x32, 0x4a, 0x64, 0xe1, 0xcb, 0xad, 0x8c, 0x6a, 0x4b, 0x31, 0x20,
|
|
||||||
0x19, 0x1b, 0x26, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt1_frame0_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x4f, 0x66, 0x7c, 0xd6, 0xba, 0x99, 0x78,
|
|
||||||
0x59, 0x40, 0x2f, 0x27, 0x28, 0x32, 0x42, 0x57, 0x6d, 0x80, 0x8f, 0xc4, 0xa5, 0x85,
|
|
||||||
0x67, 0x4f, 0x3e, 0x35, 0x37, 0x40, 0x4f, 0x63, 0x77, 0x89, 0x96, 0x9b, 0xad, 0x8f,
|
|
||||||
0x73, 0x5c, 0x4c, 0x44, 0x46, 0x4f, 0x5e, 0x71, 0x84, 0x94, 0xa0, 0xa3, 0x9f, 0x96,
|
|
||||||
0x7b, 0x66, 0x58, 0x52, 0x54, 0x5e, 0x6e, 0x80, 0x93, 0xa2, 0xac, 0xaf, 0xa9, 0x9a,
|
|
||||||
0x80, 0x6d, 0x61, 0x5c, 0x60, 0x6c, 0x7c, 0x8f, 0xa2, 0xb2, 0xbb, 0xbd, 0xb5, 0xa5,
|
|
||||||
0x8e, 0x70, 0x66, 0x64, 0x6a, 0x77, 0x89, 0x9d, 0xb1, 0xc1, 0xca, 0xcb, 0xc4, 0xb3,
|
|
||||||
0x9a, 0x7c, 0x66, 0x67, 0x6f, 0x7e, 0x92, 0xa8, 0xbd, 0xce, 0xd9, 0xda, 0xd3, 0xc1,
|
|
||||||
0xa8, 0x8a, 0x68, 0x65, 0x70, 0x82, 0x98, 0xb0, 0xc7, 0xd9, 0xe5, 0xe8, 0xe1, 0xd0,
|
|
||||||
0xb7, 0x98, 0x76, 0x54, 0x6d, 0x81, 0x99, 0xb3, 0xcd, 0xe1, 0xee, 0xf3, 0xed, 0xdd,
|
|
||||||
0xc5, 0xa6, 0x85, 0x63, 0x45, 0x7b, 0x96, 0xb3, 0xce, 0xe5, 0xf4, 0xfa, 0xf6, 0xe8,
|
|
||||||
0xd1, 0xb4, 0x93, 0x71, 0x53, 0x3b, 0x8f, 0xad, 0xcb, 0xe4, 0xf5, 0xfe, 0xfc, 0xef,
|
|
||||||
0xda, 0xbe, 0x9f, 0x7f, 0x61, 0x4a, 0x3b, 0xa5, 0xc4, 0xdf, 0xf2, 0xfd, 0xfd, 0xf2,
|
|
||||||
0xdf, 0xc5, 0xa8, 0x89, 0x6e, 0x57, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt0_frame16_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x95, 0x88, 0x92, 0x75, 0x81, 0x60, 0x8f,
|
|
||||||
0x6d, 0x4c, 0x7c, 0x5a, 0x3c, 0x8a, 0x69, 0x4a, 0x32, 0x77, 0x59, 0x41, 0x32, 0x83,
|
|
||||||
0x66, 0x50, 0x40, 0x3a, 0x72, 0x5c, 0x4e, 0x49, 0x4c, 0x79, 0x66, 0x59, 0x56, 0x5a,
|
|
||||||
0x65, 0x6c, 0x61, 0x5f, 0x66, 0x72, 0x84, 0x6d, 0x66, 0x66, 0x6e, 0x7d, 0x90, 0xa5,
|
|
||||||
0x65, 0x68, 0x72, 0x83, 0x99, 0xaf, 0xc5, 0x61, 0x65, 0x72, 0x86, 0x9d, 0xb6, 0xcd,
|
|
||||||
0xdf, 0x5f, 0x6e, 0x84, 0x9d, 0xb9, 0xd2, 0xe6, 0xf2, 0x55, 0x66, 0x7d, 0x99, 0xb7,
|
|
||||||
0xd2, 0xe8, 0xf7, 0xfc, 0x5a, 0x73, 0x91, 0xb1, 0xce, 0xe6, 0xf7, 0xfe, 0xfb, 0x4c,
|
|
||||||
0x67, 0x86, 0xa7, 0xc6, 0xe0, 0xf3, 0xfc, 0xfb, 0xf0, 0x58, 0x78, 0x9a, 0xbb, 0xd6,
|
|
||||||
0xeb, 0xf6, 0xf7, 0xed, 0xdc, 0x4a, 0x6a, 0x8c, 0xad, 0xca, 0xdf, 0xec, 0xee, 0xe7,
|
|
||||||
0xd7, 0xc1, 0x5b, 0x7d, 0x9f, 0xbc, 0xd2, 0xdf, 0xe3, 0xdd, 0xcf, 0xbb, 0xa4, 0x4f,
|
|
||||||
0x70, 0x90, 0xad, 0xc3, 0xd0, 0xd5, 0xd0, 0xc3, 0xb1, 0x9b, 0x87, 0x64, 0x83, 0x9f,
|
|
||||||
0xb4, 0xc1, 0xc6, 0xc1, 0xb5, 0xa3, 0x90, 0x7c, 0x6d, 0x5c, 0x79, 0x93, 0xa7, 0xb3,
|
|
||||||
0xb7, 0xb2, 0xa6, 0x95, 0x81, 0x6f, 0x61, 0x59, 0x73, 0x8b, 0x9d, 0xa7, 0xa9, 0xa3,
|
|
||||||
0x97, 0x85, 0x72, 0x60, 0x53, 0x4c, 0x4e, 0x70, 0x86, 0x96, 0x9e, 0x9f, 0x97, 0x89,
|
|
||||||
0x77, 0x63, 0x51, 0x44, 0x3e, 0x40, 0x4b, 0x86, 0x93, 0x99, 0x97, 0x8e, 0x7e, 0x6a,
|
|
||||||
0x55, 0x43, 0x35, 0x2f, 0x31, 0x3d, 0x51, 0x8a, 0x95, 0x99, 0x94, 0x88, 0x76, 0x61,
|
|
||||||
0x4a, 0x36, 0x27, 0x20, 0x22, 0x2e, 0x43, 0x5f, 0x9b, 0x9c, 0x96, 0x87, 0x73, 0x5b,
|
|
||||||
0x43, 0x2d, 0x1c, 0x14, 0x15, 0x20, 0x34, 0x50, 0x71, 0xa4, 0x9b, 0x8b, 0x74, 0x5a,
|
|
||||||
0x3f, 0x27, 0x15, 0x0b, 0x0a, 0x14, 0x27, 0x42, 0x62, 0x84, 0xa5, 0x92, 0x7a, 0x5d,
|
|
||||||
0x40, 0x26, 0x11, 0x05, 0x03, 0x0b, 0x1d, 0x36, 0x55, 0x76, 0x96, 0x9d, 0x83, 0x64,
|
|
||||||
0x45, 0x29, 0x12, 0x04, 0x00, 0x06, 0x15, 0x2d, 0x4b, 0x6a, 0x89, 0xa4, 0x8f, 0x6f,
|
|
||||||
0x4e, 0x30, 0x18, 0x07, 0x01, 0x05, 0x12, 0x28, 0x44, 0x62, 0x7f, 0x98, 0xab, 0x7c,
|
|
||||||
0x5a, 0x3b, 0x21, 0x0f, 0x06, 0x08, 0x14, 0x27, 0x41, 0x5c, 0x77, 0x8f, 0xa0, 0xa9,
|
|
||||||
0x68, 0x48, 0x2d, 0x1a, 0x10, 0x10, 0x19, 0x2b, 0x42, 0x5c, 0x74, 0x89, 0x98, 0xa0,
|
|
||||||
0x9e, 0x57, 0x3b, 0x27, 0x1c, 0x1b, 0x23, 0x33, 0x48, 0x5f, 0x76, 0x88, 0x95, 0x9a,
|
|
||||||
0x97, 0x8c, 0x4a, 0x36, 0x2a, 0x28, 0x2f, 0x3e, 0x51, 0x67, 0x7b, 0x8c, 0x96, 0x99,
|
|
||||||
0x93, 0x86, 0x73, 0x44, 0x39, 0x37, 0x3e, 0x4b, 0x5e, 0x72, 0x85, 0x93, 0x9b, 0x9c,
|
|
||||||
0x94, 0x84, 0x6f, 0x57, 0x48, 0x46, 0x4d, 0x5b, 0x6c, 0x80, 0x91, 0x9e, 0xa4, 0xa3,
|
|
||||||
0x99, 0x87, 0x70, 0x55, 0x3b, 0x54, 0x5c, 0x6a, 0x7c, 0x8f, 0xa0, 0xac, 0xb1, 0xad,
|
|
||||||
0xa1, 0x8e, 0x74, 0x58, 0x3b, 0x22, 0x69, 0x78, 0x8b, 0x9e, 0xaf, 0xbb, 0xbf, 0xbb,
|
|
||||||
0xad, 0x98, 0x7d, 0x5e, 0x40, 0x24, 0x0f, 0x84, 0x98, 0xac, 0xbe, 0xca, 0xce, 0xc9,
|
|
||||||
0xbb, 0xa5, 0x89, 0x68, 0x48, 0x2b, 0x14, 0x05, 0xa2, 0xb8, 0xcb, 0xd8, 0xdd, 0xd8,
|
|
||||||
0xca, 0xb3, 0x96, 0x75, 0x54, 0x35, 0x1c, 0x0c, 0x05, 0xc0, 0xd5, 0xe3, 0xea, 0xe6,
|
|
||||||
0xd8, 0xc2, 0xa5, 0x84, 0x61, 0x42, 0x28, 0x16, 0x0e, 0x10, 0xdb, 0xec, 0xf4, 0xf1,
|
|
||||||
0xe5, 0xd0, 0xb3, 0x92, 0x70, 0x50, 0x36, 0x23, 0x1a, 0x1b, 0x24, 0xf0, 0xfa, 0xfa,
|
|
||||||
0xef, 0xdb, 0xc0, 0xa0, 0x7e, 0x5f, 0x45, 0x32, 0x28, 0x28, 0x31, 0x40, 0xfc, 0xfe,
|
|
||||||
0xf5, 0xe3, 0xc9, 0xab, 0x8b, 0x6c, 0x53, 0x41, 0x37, 0x37, 0x3f, 0x4e, 0x61, 0xfd,
|
|
||||||
0xf7, 0xe7, 0xcf, 0xb3, 0x94, 0x78, 0x60, 0x4f, 0x46, 0x46, 0x4e, 0x5d, 0x6f, 0x82,
|
|
||||||
0xf4, 0xe7, 0xd1, 0xb7, 0x9b, 0x80, 0x6a, 0x5a, 0x53, 0x54, 0x5d, 0x6c, 0x7e, 0x91,
|
|
||||||
0xa1, 0xe2, 0xce, 0xb6, 0x9c, 0x84, 0x70, 0x62, 0x5d, 0x60, 0x6a, 0x7a, 0x8d, 0xa0,
|
|
||||||
0xb1, 0xbb, 0xc8, 0xb2, 0x9a, 0x84, 0x72, 0x67, 0x64, 0x69, 0x75, 0x86, 0x9b, 0xaf,
|
|
||||||
0xbf, 0xca, 0xcd, 0xa9, 0x93, 0x7f, 0x70, 0x67, 0x66, 0x6d, 0x7c, 0x8f, 0xa5, 0xbb,
|
|
||||||
0xcd, 0xd8, 0xdc, 0xd5, 0x89, 0x76, 0x69, 0x63, 0x64, 0x6e, 0x7e, 0x94, 0xac, 0xc4,
|
|
||||||
0xd8, 0xe5, 0xe9, 0xe3, 0xd4, 0x6b, 0x5f, 0x5a, 0x5e, 0x6a, 0x7d, 0x95, 0xaf, 0xc9,
|
|
||||||
0xdf, 0xed, 0xf3, 0xef, 0xe1, 0xca, 0x52, 0x4f, 0x54, 0x62, 0x77, 0x91, 0xae, 0xca,
|
|
||||||
0xe1, 0xf2, 0xfa, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
let pkt1_frame16_check = [
|
|
||||||
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0xeb, 0xd6, 0xb9, 0x41, 0x47, 0x56, 0x6d,
|
|
||||||
0x89, 0xa8, 0xc6, 0xe0, 0xf3, 0xfd, 0xfd, 0xf2, 0xde, 0xc4, 0xa4, 0x39, 0x49, 0x61,
|
|
||||||
0x7e, 0x9f, 0xbe, 0xda, 0xef, 0xfb, 0xfd, 0xf5, 0xe3, 0xca, 0xad, 0x8f, 0x3a, 0x53,
|
|
||||||
0x71, 0x92, 0xb3, 0xd1, 0xe7, 0xf5, 0xf9, 0xf3, 0xe3, 0xcd, 0xb2, 0x95, 0x7b, 0x44,
|
|
||||||
0x62, 0x84, 0xa6, 0xc4, 0xdc, 0xec, 0xf1, 0xed, 0xdf, 0xcb, 0xb2, 0x98, 0x80, 0x6d,
|
|
||||||
0x54, 0x76, 0x97, 0xb6, 0xcf, 0xdf, 0xe6, 0xe3, 0xd7, 0xc5, 0xae, 0x96, 0x80, 0x6f,
|
|
||||||
0x66, 0x68, 0x89, 0xa7, 0xc0, 0xd1, 0xd8, 0xd6, 0xcc, 0xbb, 0xa6, 0x90, 0x7c, 0x6e,
|
|
||||||
0x66, 0x67, 0x7c, 0x9a, 0xb2, 0xc2, 0xc9, 0xc8, 0xbe, 0xae, 0x9a, 0x86, 0x74, 0x68,
|
|
||||||
0x63, 0x65, 0x70, 0x8e, 0xa4, 0xb4, 0xba, 0xb8, 0xaf, 0x9f, 0x8c, 0x79, 0x69, 0x5e,
|
|
||||||
0x5b, 0x60, 0x6d, 0x81, 0x9a, 0xa8, 0xad, 0xaa, 0x9f, 0x90, 0x7d, 0x6a, 0x5b, 0x52,
|
|
||||||
0x50, 0x57, 0x66, 0x7c, 0x96, 0x9e, 0xa2, 0x9d, 0x92, 0x81, 0x6e, 0x5b, 0x4c, 0x43,
|
|
||||||
0x42, 0x4a, 0x5b, 0x73, 0x8f, 0xae, 0x9a, 0x94, 0x86, 0x74, 0x60, 0x4c, 0x3d, 0x34,
|
|
||||||
0x33, 0x3c, 0x4d, 0x66, 0x85, 0xa5, 0xc4, 0x8e, 0x7f, 0x6a, 0x54, 0x40, 0x2f, 0x25,
|
|
||||||
0x24, 0x2d, 0x3f, 0x58, 0x78, 0x99, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
path.push("tests/data/g835l-diagonal.gif");
|
|
||||||
|
|
||||||
let gif =
|
|
||||||
AnimeGif::from_diagonal_gif(&path, AnimTime::Count(1), 1.0, AnimeType::G835L).unwrap();
|
|
||||||
assert_eq!(gif.frame_count(), 48);
|
|
||||||
|
|
||||||
let pkt = AnimePacketType::try_from(gif.frames()[0].frame().clone()).unwrap();
|
|
||||||
assert_eq!(pkt[0], pkt0_frame0_check);
|
|
||||||
assert_eq!(pkt[1], pkt1_frame0_check);
|
|
||||||
|
|
||||||
let pkt = AnimePacketType::try_from(gif.frames()[16].frame().clone()).unwrap();
|
|
||||||
assert_eq!(pkt[0], pkt0_frame16_check);
|
|
||||||
assert_eq!(pkt[1], pkt1_frame16_check);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -38,34 +38,7 @@
|
|||||||
(
|
(
|
||||||
device_name: "FA617NS",
|
device_name: "FA617NS",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
layout_name: "fa507",
|
layout_name: "fx505d",
|
||||||
basic_modes: [Static, Breathe, Pulse],
|
|
||||||
basic_zones: [],
|
|
||||||
advanced_type: r#None,
|
|
||||||
power_zones: [Keyboard],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
device_name: "FA617NT",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "fa507",
|
|
||||||
basic_modes: [Static, Breathe, Pulse],
|
|
||||||
basic_zones: [],
|
|
||||||
advanced_type: r#None,
|
|
||||||
power_zones: [Keyboard],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
device_name: "FA617XS",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "fa507",
|
|
||||||
basic_modes: [Static, Breathe, Pulse],
|
|
||||||
basic_zones: [],
|
|
||||||
advanced_type: r#None,
|
|
||||||
power_zones: [Keyboard],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
device_name: "FA617XT",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "fa507",
|
|
||||||
basic_modes: [Static, Breathe, Pulse],
|
basic_modes: [Static, Breathe, Pulse],
|
||||||
basic_zones: [],
|
basic_zones: [],
|
||||||
advanced_type: r#None,
|
advanced_type: r#None,
|
||||||
@@ -125,15 +98,6 @@
|
|||||||
advanced_type: r#None,
|
advanced_type: r#None,
|
||||||
power_zones: [Keyboard],
|
power_zones: [Keyboard],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "FX607V",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "fa506i",
|
|
||||||
basic_modes: [Static, Breathe, RainbowCycle, Pulse],
|
|
||||||
basic_zones: [],
|
|
||||||
advanced_type: Zoned([SingleZone]),
|
|
||||||
power_zones: [Keyboard],
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
device_name: "FX617X",
|
device_name: "FX617X",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -278,15 +242,6 @@
|
|||||||
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: "",
|
||||||
@@ -314,15 +269,6 @@
|
|||||||
advanced_type: r#None,
|
advanced_type: r#None,
|
||||||
power_zones: [Keyboard, Lightbar],
|
power_zones: [Keyboard, Lightbar],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "G614JU",
|
|
||||||
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: "G614JZ",
|
device_name: "G614JZ",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -332,15 +278,6 @@
|
|||||||
advanced_type: r#None,
|
advanced_type: r#None,
|
||||||
power_zones: [Keyboard, Lightbar],
|
power_zones: [Keyboard, Lightbar],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "G615LR",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "g634j-per-key",
|
|
||||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave],
|
|
||||||
basic_zones: [Key1, Key2, Key3, Key4],
|
|
||||||
advanced_type: r#None,
|
|
||||||
power_zones: [Keyboard, Lightbar],
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
device_name: "G634J",
|
device_name: "G634J",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -350,15 +287,6 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "G635L",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "g635l-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: "G712LI",
|
device_name: "G712LI",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -557,15 +485,6 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar],
|
power_zones: [Keyboard, Lightbar],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "G815L",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "g814ji-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],
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
device_name: "G834J",
|
device_name: "G834J",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -575,15 +494,6 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||||
),
|
),
|
||||||
(
|
|
||||||
device_name: "G835L",
|
|
||||||
product_id: "",
|
|
||||||
layout_name: "g814ji-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: "GA401I",
|
device_name: "GA401I",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
|
|||||||
@@ -1,375 +0,0 @@
|
|||||||
(
|
|
||||||
locale: "US",
|
|
||||||
key_shapes: {
|
|
||||||
"regular": Led(
|
|
||||||
width: 1.0,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"regular_spacing": Blank(
|
|
||||||
width: 1.2,
|
|
||||||
height: 0.0,
|
|
||||||
),
|
|
||||||
"rog_row": Led(
|
|
||||||
width: 1.0,
|
|
||||||
height: 0.7,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.6,
|
|
||||||
),
|
|
||||||
"rog_row_blocking": Blank(
|
|
||||||
width: 1.2,
|
|
||||||
height: 0.0,
|
|
||||||
),
|
|
||||||
"func_space": Blank(
|
|
||||||
width: 0.6,
|
|
||||||
height: 0.0,
|
|
||||||
),
|
|
||||||
"backspace": Led(
|
|
||||||
width: 2.2,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"tab": Led(
|
|
||||||
width: 1.6,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"backslash": Led(
|
|
||||||
width: 1.6,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"capsplonk": Led(
|
|
||||||
width: 2.0,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"return": Led(
|
|
||||||
width: 2.4,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"lshift": Led(
|
|
||||||
width: 2.6,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"rshift": Led(
|
|
||||||
width: 3.0,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"lctrl": Led(
|
|
||||||
width: 1.4,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"spacebar": Led(
|
|
||||||
width: 5.8,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"rctrl": Led(
|
|
||||||
width: 1.2,
|
|
||||||
height: 1.0,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"up_arrow": Led(
|
|
||||||
width: 0.8,
|
|
||||||
height: 0.8,
|
|
||||||
pad_left: 1.1,
|
|
||||||
pad_right: 1.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"arrows_spacer": Blank(
|
|
||||||
width: 15.0,
|
|
||||||
height: 0.0,
|
|
||||||
),
|
|
||||||
"arrows": Led(
|
|
||||||
width: 0.8,
|
|
||||||
height: 0.8,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: -0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
),
|
|
||||||
"row_end_spacing": Blank(
|
|
||||||
width: 0.4,
|
|
||||||
height: 0.0,
|
|
||||||
),
|
|
||||||
"lid_logo": Led(
|
|
||||||
width: 2.6,
|
|
||||||
height: 1.2,
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.8,
|
|
||||||
pad_bottom: 0.0,
|
|
||||||
),
|
|
||||||
"lightbar_left": Led(
|
|
||||||
width: 0.6,
|
|
||||||
height: 3.6,
|
|
||||||
pad_left: -1.2,
|
|
||||||
pad_right: 0.2,
|
|
||||||
pad_top: -3.0,
|
|
||||||
pad_bottom: 0.3,
|
|
||||||
),
|
|
||||||
"lightbar_corner_left": Led(
|
|
||||||
width: 0.8,
|
|
||||||
height: 0.6,
|
|
||||||
pad_left: -0.6,
|
|
||||||
pad_right: 0.2,
|
|
||||||
pad_top: 0.8,
|
|
||||||
pad_bottom: 0.0,
|
|
||||||
),
|
|
||||||
"lightbar_bottom": Led(
|
|
||||||
width: 12.6,
|
|
||||||
height: 0.5,
|
|
||||||
pad_left: -0.1,
|
|
||||||
pad_right: -0.1,
|
|
||||||
pad_top: 0.8,
|
|
||||||
pad_bottom: 0.0,
|
|
||||||
),
|
|
||||||
"lightbar_corner_right": Led(
|
|
||||||
width: 0.8,
|
|
||||||
height: 0.6,
|
|
||||||
pad_left: 0.0,
|
|
||||||
pad_right: 0.2,
|
|
||||||
pad_top: 0.8,
|
|
||||||
pad_bottom: 0.0,
|
|
||||||
),
|
|
||||||
"lightbar_right": Led(
|
|
||||||
width: 0.6,
|
|
||||||
height: 3.6,
|
|
||||||
pad_left: -0.8,
|
|
||||||
pad_right: 0.2,
|
|
||||||
pad_top: -3.0,
|
|
||||||
pad_bottom: 0.3,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
key_rows: [
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Blocking, "rog_row_blocking"),
|
|
||||||
(Blocking, "rog_row_blocking"),
|
|
||||||
(VolDown, "rog_row"),
|
|
||||||
(VolUp, "rog_row"),
|
|
||||||
(MicMute, "rog_row"),
|
|
||||||
(RogFan, "rog_row"),
|
|
||||||
(RogApp, "rog_row"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Esc, "regular"),
|
|
||||||
(Spacing, "regular_spacing"),
|
|
||||||
(F1, "regular"),
|
|
||||||
(F2, "regular"),
|
|
||||||
(F3, "regular"),
|
|
||||||
(F4, "regular"),
|
|
||||||
(Spacing, "func_space"),
|
|
||||||
(F5, "regular"),
|
|
||||||
(F6, "regular"),
|
|
||||||
(F7, "regular"),
|
|
||||||
(F8, "regular"),
|
|
||||||
(Spacing, "func_space"),
|
|
||||||
(F9, "regular"),
|
|
||||||
(F10, "regular"),
|
|
||||||
(F11, "regular"),
|
|
||||||
(F12, "regular"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(Del, "regular"), // Should be super/insert
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Tilde, "regular"),
|
|
||||||
(N1, "regular"),
|
|
||||||
(N2, "regular"),
|
|
||||||
(N3, "regular"),
|
|
||||||
(N4, "regular"),
|
|
||||||
(N5, "regular"),
|
|
||||||
(N6, "regular"),
|
|
||||||
(N7, "regular"),
|
|
||||||
(N8, "regular"),
|
|
||||||
(N9, "regular"),
|
|
||||||
(N0, "regular"),
|
|
||||||
(Hyphen, "regular"),
|
|
||||||
(Equals, "regular"),
|
|
||||||
(Backspace, "backspace"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(MediaPlay, "regular"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Tab, "tab"),
|
|
||||||
(Q, "regular"),
|
|
||||||
(W, "regular"),
|
|
||||||
(E, "regular"),
|
|
||||||
(R, "regular"),
|
|
||||||
(T, "regular"),
|
|
||||||
(Y, "regular"),
|
|
||||||
(U, "regular"),
|
|
||||||
(I, "regular"),
|
|
||||||
(O, "regular"),
|
|
||||||
(P, "regular"),
|
|
||||||
(LBracket, "regular"),
|
|
||||||
(RBracket, "regular"),
|
|
||||||
(BackSlash, "backslash"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(MediaStop, "regular"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Caps, "capsplonk"),
|
|
||||||
(A, "regular"),
|
|
||||||
(S, "regular"),
|
|
||||||
(D, "regular"),
|
|
||||||
(F, "regular"),
|
|
||||||
(G, "regular"),
|
|
||||||
(H, "regular"),
|
|
||||||
(J, "regular"),
|
|
||||||
(K, "regular"),
|
|
||||||
(L, "regular"),
|
|
||||||
(SemiColon, "regular"),
|
|
||||||
(Quote, "regular"),
|
|
||||||
(Return, "return"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(MediaNext, "regular"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(LShift, "lshift"),
|
|
||||||
(Z, "regular"),
|
|
||||||
(X, "regular"),
|
|
||||||
(C, "regular"),
|
|
||||||
(V, "regular"),
|
|
||||||
(B, "regular"),
|
|
||||||
(N, "regular"),
|
|
||||||
(M, "regular"),
|
|
||||||
(Comma, "regular"),
|
|
||||||
(Period, "regular"),
|
|
||||||
(FwdSlash, "regular"),
|
|
||||||
(Rshift, "rshift"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(MediaPrev, "regular"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(LCtrl, "lctrl"),
|
|
||||||
(LFn, "regular"),
|
|
||||||
(Meta, "regular"),
|
|
||||||
(LAlt, "regular"),
|
|
||||||
(Spacebar, "spacebar"),
|
|
||||||
(RAlt, "regular"),
|
|
||||||
(PrtSc, "regular"),
|
|
||||||
(RCtrl, "rctrl"),
|
|
||||||
(Up, "up_arrow"),
|
|
||||||
(Spacing, "row_end_spacing"),
|
|
||||||
(PrtSc, "regular"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(Spacing, "arrows_spacer"),
|
|
||||||
(Left, "arrows"),
|
|
||||||
(Down, "arrows"),
|
|
||||||
(Right, "arrows"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 6.5,
|
|
||||||
pad_right: 6.5,
|
|
||||||
pad_top: 0.2,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(LidLogo, "lid_logo"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
pad_left: 0.1,
|
|
||||||
pad_right: 0.1,
|
|
||||||
pad_top: 0.1,
|
|
||||||
pad_bottom: 0.1,
|
|
||||||
row: [
|
|
||||||
(LightbarLeft, "lightbar_left"),
|
|
||||||
(LightbarLeftCorner, "lightbar_corner_left"),
|
|
||||||
(LightbarLeftBottom, "lightbar_bottom"),
|
|
||||||
(LightbarRightBottom, "lightbar_bottom"),
|
|
||||||
(LightbarRightCorner, "lightbar_corner_right"),
|
|
||||||
(LightbarRight, "lightbar_right"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@@ -164,26 +164,29 @@ impl LedSupportFile {
|
|||||||
return Some(data);
|
return Some(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the system-wide files were not found (typical in CI or
|
// If the system-wide support files were not available (e.g. running
|
||||||
// development environments), attempt to load the bundled
|
// tests in CI or a development environment) try to load the
|
||||||
// `data/aura_support.ron` from the crate so tests and local runs
|
// bundled test data shipped with the crate under `data/aura_support.ron`.
|
||||||
// behave the same as when the package is installed.
|
// This allows unit tests to run without requiring files to be installed
|
||||||
// Attempt to load a bundled `aura_support.ron` included at compile time.
|
// to `/usr/share/asusd`.
|
||||||
// Using `include_str!` ensures the data is available regardless of
|
let mut bundled = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
// runtime `CARGO_MANIFEST_DIR` or CI environment differences.
|
bundled.push("data/aura_support.ron");
|
||||||
let bundled_buf = include_str!("../data/aura_support.ron");
|
if let Ok(buf) = std::fs::read_to_string(&bundled) {
|
||||||
if !bundled_buf.is_empty() {
|
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&buf) {
|
||||||
if let Ok(tmp) = ron::from_str::<LedSupportFile>(bundled_buf) {
|
data.0.append(&mut tmp.0);
|
||||||
data.0.append(&mut tmp.0.clone());
|
|
||||||
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
|
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
|
||||||
info!("Loaded bundled LED support data (embedded)");
|
info!("Loaded bundled LED support data from {}", bundled.display());
|
||||||
return Some(data);
|
return Some(data);
|
||||||
} else {
|
} else {
|
||||||
warn!("Could not parse embedded bundled data file");
|
warn!(
|
||||||
|
"Bundled aura_support.ron present but failed to parse: {}",
|
||||||
|
bundled.display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,12 +359,6 @@ impl From<AuraEffect> for AuraModeNum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dbus")]
|
|
||||||
impl zbus::zvariant::Basic for AuraModeNum {
|
|
||||||
const SIGNATURE_CHAR: char = 'u';
|
|
||||||
const SIGNATURE_STR: &'static str = "u";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Base effects have no zoning, while multizone is 1-4
|
/// Base effects have no zoning, while multizone is 1-4
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "dbus",
|
feature = "dbus",
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ mocking = []
|
|||||||
x11 = ["slint/backend-winit-x11"]
|
x11 = ["slint/backend-winit-x11"]
|
||||||
# Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
|
# Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
|
||||||
tokio-debug = ["console-subscriber"]
|
tokio-debug = ["console-subscriber"]
|
||||||
rog_ally = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
console-subscriber = { version = "^0.4", optional = true }
|
console-subscriber = { version = "^0.4", optional = true }
|
||||||
|
|||||||
@@ -24,4 +24,6 @@ pub struct CliStart {
|
|||||||
that might match your laptop"
|
that might match your laptop"
|
||||||
)]
|
)]
|
||||||
pub layout_viewing: bool,
|
pub layout_viewing: bool,
|
||||||
|
#[options(help = "start in tray mode - main window hidden")]
|
||||||
|
pub tray_mode: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,16 +24,11 @@ use tokio::runtime::Runtime;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// Ensure tracing spans are quiet by default unless user overrides
|
|
||||||
if std::env::var_os("RUST_LOG").is_none() {
|
|
||||||
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
|
|
||||||
}
|
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
logger
|
logger
|
||||||
|
.filter_level(LevelFilter::Warn)
|
||||||
.parse_default_env()
|
.parse_default_env()
|
||||||
.filter_level(LevelFilter::Info)
|
.target(env_logger::Target::Stdout)
|
||||||
.parse_default_env()
|
|
||||||
.target(env_logger::Target::Stderr)
|
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
@@ -107,6 +102,7 @@ async fn main() -> Result<()> {
|
|||||||
let board_name = dmi.board_name;
|
let board_name = dmi.board_name;
|
||||||
let prod_family = dmi.product_family;
|
let prod_family = dmi.product_family;
|
||||||
info!("Running on {board_name}, product: {prod_family}");
|
info!("Running on {board_name}, product: {prod_family}");
|
||||||
|
let is_rog_ally = board_name == "RC71L" || board_name == "RC72L" || prod_family == "ROG Ally";
|
||||||
|
|
||||||
let args: Vec<String> = args().skip(1).collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
|
|
||||||
@@ -137,24 +133,6 @@ async fn main() -> Result<()> {
|
|||||||
config.start_fullscreen = false;
|
config.start_fullscreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_rog_ally = {
|
|
||||||
#[cfg(feature = "rog_ally")]
|
|
||||||
{
|
|
||||||
board_name == "RC71L" || board_name == "RC72L" || prod_family == "ROG Ally"
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "rog_ally"))]
|
|
||||||
{
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_tuf = {
|
|
||||||
let b = board_name.to_lowercase();
|
|
||||||
let p = prod_family.to_lowercase();
|
|
||||||
b.contains("tuf") || p.contains("tuf")
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "rog_ally")]
|
|
||||||
if is_rog_ally {
|
if is_rog_ally {
|
||||||
config.notifications.enabled = false;
|
config.notifications.enabled = false;
|
||||||
config.enable_tray_icon = false;
|
config.enable_tray_icon = false;
|
||||||
@@ -163,12 +141,21 @@ async fn main() -> Result<()> {
|
|||||||
config.start_fullscreen = true;
|
config.start_fullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cli_parsed.tray_mode {
|
||||||
|
config.enable_tray_icon = true;
|
||||||
|
config.run_in_background = true;
|
||||||
|
config.startup_in_background = true;
|
||||||
|
}
|
||||||
|
|
||||||
config.write();
|
config.write();
|
||||||
|
|
||||||
let enable_tray_icon = config.enable_tray_icon;
|
let enable_tray_icon = config.enable_tray_icon;
|
||||||
let startup_in_background = config.startup_in_background;
|
let startup_in_background = config.startup_in_background;
|
||||||
let config = Arc::new(Mutex::new(config));
|
let config = Arc::new(Mutex::new(config));
|
||||||
|
|
||||||
|
// shared weak handle to the UI so other threads can request UI updates
|
||||||
|
let ui_handle: Arc<Mutex<Option<slint::Weak<MainWindow>>>> = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
start_notifications(config.clone(), &rt)?;
|
start_notifications(config.clone(), &rt)?;
|
||||||
|
|
||||||
if enable_tray_icon {
|
if enable_tray_icon {
|
||||||
@@ -193,18 +180,14 @@ async fn main() -> Result<()> {
|
|||||||
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
|
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefetch supported Aura modes once at startup and move into the
|
let config_for_ui = config.clone();
|
||||||
// spawned UI thread so the UI uses a stable, immutable list.
|
let ui_handle_for_thread = ui_handle.clone();
|
||||||
let prefetched_supported: std::sync::Arc<Option<Vec<i32>>> = std::sync::Arc::new(
|
|
||||||
rog_control_center::ui::setup_aura::prefetch_supported_basic_modes().await,
|
|
||||||
);
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut state = AppState::StartingUp;
|
let mut state = AppState::StartingUp;
|
||||||
loop {
|
loop {
|
||||||
if is_rog_ally {
|
if is_rog_ally {
|
||||||
let config_copy_2 = config.clone();
|
let config_copy_2 = config_for_ui.clone();
|
||||||
let newui = setup_window(config.clone(), prefetched_supported.clone(), is_tuf);
|
let newui = setup_window(config_for_ui.clone());
|
||||||
newui.window().on_close_requested(move || {
|
newui.window().on_close_requested(move || {
|
||||||
exit(0);
|
exit(0);
|
||||||
});
|
});
|
||||||
@@ -227,91 +210,153 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
} else {
|
||||||
continue;
|
// save as a var, don't hold the lock the entire time or deadlocks happen
|
||||||
}
|
if let Ok(app_state) = app_state.lock() {
|
||||||
|
state = *app_state;
|
||||||
// save as a var, don't hold the lock the entire time or deadlocks happen
|
|
||||||
if let Ok(app_state) = app_state.lock() {
|
|
||||||
state = *app_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This sleep is required to give the event loop time to react
|
|
||||||
sleep(Duration::from_millis(300));
|
|
||||||
if state == AppState::MainWindowShouldOpen {
|
|
||||||
if let Ok(mut app_state) = app_state.lock() {
|
|
||||||
*app_state = AppState::MainWindowOpen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let config_copy = config.clone();
|
// This sleep is required to give the event loop time to react
|
||||||
let app_state_copy = app_state.clone();
|
sleep(Duration::from_millis(300));
|
||||||
// Avoid moving the original `prefetched_supported` into the
|
if state == AppState::MainWindowShouldOpen {
|
||||||
// closure — clone an Arc for the closure to capture.
|
if let Ok(mut app_state) = app_state.lock() {
|
||||||
let pref_for_invoke = prefetched_supported.clone();
|
*app_state = AppState::MainWindowOpen;
|
||||||
slint::invoke_from_event_loop(move || {
|
}
|
||||||
UI.with(|ui| {
|
|
||||||
let app_state_copy = app_state_copy.clone();
|
|
||||||
let mut ui = ui.borrow_mut();
|
|
||||||
if let Some(ui) = ui.as_mut() {
|
|
||||||
ui.window().show().unwrap();
|
|
||||||
ui.window().on_close_requested(move || {
|
|
||||||
if let Ok(mut app_state) = app_state_copy.lock() {
|
|
||||||
*app_state = AppState::MainWindowClosed;
|
|
||||||
}
|
|
||||||
slint::CloseRequestResponse::HideWindow
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let config_copy_2 = config_copy.clone();
|
|
||||||
let newui = setup_window(config_copy, pref_for_invoke.clone(), is_tuf);
|
|
||||||
newui.window().on_close_requested(move || {
|
|
||||||
if let Ok(mut app_state) = app_state_copy.lock() {
|
|
||||||
*app_state = AppState::MainWindowClosed;
|
|
||||||
}
|
|
||||||
slint::CloseRequestResponse::HideWindow
|
|
||||||
});
|
|
||||||
|
|
||||||
let ui_copy = newui.as_weak();
|
let config_copy = config_for_ui.clone();
|
||||||
newui
|
let app_state_copy = app_state.clone();
|
||||||
.window()
|
let ui_handle_for_ui = ui_handle_for_thread.clone();
|
||||||
.set_rendering_notifier(move |s, _| {
|
slint::invoke_from_event_loop(move || {
|
||||||
if let slint::RenderingState::RenderingSetup = s {
|
let ui_handle_for_ui = ui_handle_for_ui.clone();
|
||||||
let config = config_copy_2.clone();
|
UI.with(|ui| {
|
||||||
ui_copy
|
let app_state_copy = app_state_copy.clone();
|
||||||
.upgrade_in_event_loop(move |w| {
|
let mut ui = ui.borrow_mut();
|
||||||
let fullscreen =
|
if let Some(ui) = ui.as_mut() {
|
||||||
config.lock().is_ok_and(|c| c.start_fullscreen);
|
// store weak handle so other threads can update UI globals
|
||||||
if fullscreen && !w.window().is_fullscreen() {
|
if let Ok(mut h) = ui_handle_for_ui.lock() {
|
||||||
w.window().set_fullscreen(fullscreen);
|
*h = Some(ui.as_weak());
|
||||||
}
|
}
|
||||||
})
|
ui.window().show().unwrap();
|
||||||
.ok();
|
ui.window().on_close_requested(move || {
|
||||||
|
if let Ok(mut app_state) = app_state_copy.lock() {
|
||||||
|
*app_state = AppState::MainWindowClosed;
|
||||||
}
|
}
|
||||||
})
|
slint::CloseRequestResponse::HideWindow
|
||||||
.ok();
|
});
|
||||||
ui.replace(newui);
|
} else {
|
||||||
|
let config_copy_2 = config_copy.clone();
|
||||||
|
let newui = setup_window(config_copy);
|
||||||
|
// store weak handle for the newly created UI
|
||||||
|
if let Ok(mut h) = ui_handle_for_ui.lock() {
|
||||||
|
*h = Some(newui.as_weak());
|
||||||
|
}
|
||||||
|
newui.window().on_close_requested(move || {
|
||||||
|
if let Ok(mut app_state) = app_state_copy.lock() {
|
||||||
|
*app_state = AppState::MainWindowClosed;
|
||||||
|
}
|
||||||
|
slint::CloseRequestResponse::HideWindow
|
||||||
|
});
|
||||||
|
|
||||||
|
let ui_copy = newui.as_weak();
|
||||||
|
newui
|
||||||
|
.window()
|
||||||
|
.set_rendering_notifier(move |s, _| {
|
||||||
|
if let slint::RenderingState::RenderingSetup = s {
|
||||||
|
let config = config_copy_2.clone();
|
||||||
|
ui_copy
|
||||||
|
.upgrade_in_event_loop(move |w| {
|
||||||
|
let fullscreen = config
|
||||||
|
.lock()
|
||||||
|
.is_ok_and(|c| c.start_fullscreen);
|
||||||
|
if fullscreen && !w.window().is_fullscreen() {
|
||||||
|
w.window().set_fullscreen(fullscreen);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
ui.replace(newui);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
} else if state == AppState::QuitApp {
|
||||||
|
slint::quit_event_loop().unwrap();
|
||||||
|
exit(0);
|
||||||
|
} else if state != AppState::MainWindowOpen {
|
||||||
|
if let Ok(cfg) = config_for_ui.lock() {
|
||||||
|
if !cfg.run_in_background {
|
||||||
|
slint::quit_event_loop().unwrap();
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
} else if state == AppState::QuitApp {
|
|
||||||
slint::quit_event_loop().unwrap();
|
|
||||||
exit(0);
|
|
||||||
} else if state != AppState::MainWindowOpen {
|
|
||||||
if let Ok(config) = config.lock() {
|
|
||||||
if !config.run_in_background {
|
|
||||||
slint::quit_event_loop().unwrap();
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// start config watcher to pick up external edits
|
||||||
|
spawn_config_watcher(config.clone(), ui_handle.clone());
|
||||||
|
|
||||||
slint::run_event_loop_until_quit().unwrap();
|
slint::run_event_loop_until_quit().unwrap();
|
||||||
rt.shutdown_background();
|
rt.shutdown_background();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spawn a watcher thread that polls the config file and reloads it when modified.
|
||||||
|
// This keeps the running rogcc instance in sync with manual edits to the config file.
|
||||||
|
fn spawn_config_watcher(
|
||||||
|
config: Arc<Mutex<Config>>,
|
||||||
|
ui_handle: Arc<Mutex<Option<slint::Weak<MainWindow>>>>,
|
||||||
|
) {
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
use std::time::SystemTime;
|
||||||
|
let cfg_path = Config::config_dir().join(Config::new().file_name());
|
||||||
|
let mut last_mtime: Option<SystemTime> = None;
|
||||||
|
loop {
|
||||||
|
if let Ok(meta) = std::fs::metadata(&cfg_path) {
|
||||||
|
if let Ok(m) = meta.modified() {
|
||||||
|
if last_mtime.is_none() {
|
||||||
|
last_mtime = Some(m);
|
||||||
|
} else if last_mtime.is_some_and(|t| t < m) {
|
||||||
|
// file changed, reload
|
||||||
|
last_mtime = Some(m);
|
||||||
|
let new_cfg = Config::new().load();
|
||||||
|
if let Ok(mut lock) = config.lock() {
|
||||||
|
*lock = new_cfg.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update UI app settings globals if UI is present
|
||||||
|
if let Ok(maybe_weak) = ui_handle.lock() {
|
||||||
|
if let Some(weak) = maybe_weak.clone() {
|
||||||
|
let config_for_ui = config.clone();
|
||||||
|
weak.upgrade_in_event_loop(move |w| {
|
||||||
|
if let Ok(lock) = config_for_ui.lock() {
|
||||||
|
let cfg = lock.clone();
|
||||||
|
w.global::<rog_control_center::AppSettingsPageData>()
|
||||||
|
.set_run_in_background(cfg.run_in_background);
|
||||||
|
w.global::<rog_control_center::AppSettingsPageData>()
|
||||||
|
.set_startup_in_background(cfg.startup_in_background);
|
||||||
|
w.global::<rog_control_center::AppSettingsPageData>()
|
||||||
|
.set_enable_tray_icon(cfg.enable_tray_icon);
|
||||||
|
w.global::<rog_control_center::AppSettingsPageData>()
|
||||||
|
.set_enable_dgpu_notifications(
|
||||||
|
cfg.notifications.enabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn do_cli_help(parsed: &CliStart) -> bool {
|
fn do_cli_help(parsed: &CliStart) -> bool {
|
||||||
if parsed.help {
|
if parsed.help {
|
||||||
println!("{}", CliStart::usage());
|
println!("{}", CliStart::usage());
|
||||||
|
|||||||
@@ -100,6 +100,31 @@ impl Bios {
|
|||||||
pub fn set_panel_od(&self, _b: bool) -> Result<()> {
|
pub fn set_panel_od(&self, _b: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mock NV/dGPU tunables
|
||||||
|
pub fn nv_dynamic_boost(&self) -> Result<i16> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nv_dynamic_boost(&self, _v: i16) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nv_temp_target(&self) -> Result<i16> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nv_temp_target(&self, _v: i16) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nv_tgp(&self) -> Result<i16> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nv_tgp(&self, _v: i16) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Profile;
|
pub struct Profile;
|
||||||
|
|||||||
@@ -9,11 +9,15 @@ use std::process::Command;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use futures_util::StreamExt;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use notify_rust::{Hint, Notification, Timeout};
|
use notify_rust::{Hint, Notification, Timeout, Urgency};
|
||||||
|
use rog_platform::platform::GpuMode;
|
||||||
use rog_platform::power::AsusPower;
|
use rog_platform::power::AsusPower;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use supergfxctl::pci_device::GfxPower;
|
use supergfxctl::actions::UserActionRequired as GfxUserAction;
|
||||||
|
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
||||||
|
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
@@ -141,8 +145,12 @@ pub fn start_notifications(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
info!("Attempting to start plain dgpu status monitor");
|
let enabled_notifications_copy = config.clone();
|
||||||
start_dpu_status_mon(config.clone());
|
let no_supergfx = move |e: &zbus::Error| {
|
||||||
|
error!("zbus signal: receive_notify_gfx_status: {e}");
|
||||||
|
warn!("Attempting to start plain dgpu status monitor");
|
||||||
|
start_dpu_status_mon(enabled_notifications_copy.clone());
|
||||||
|
};
|
||||||
|
|
||||||
// GPU MUX Mode notif
|
// GPU MUX Mode notif
|
||||||
// TODO: need to get armoury attrs and iter to find
|
// TODO: need to get armoury attrs and iter to find
|
||||||
@@ -181,9 +189,95 @@ pub fn start_notifications(
|
|||||||
// Ok::<(), zbus::Error>(())
|
// Ok::<(), zbus::Error>(())
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
let enabled_notifications_copy = config.clone();
|
||||||
|
// GPU Mode change/action notif
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let conn = zbus::Connection::system().await.inspect_err(|e| {
|
||||||
|
no_supergfx(e);
|
||||||
|
})?;
|
||||||
|
let proxy = SuperProxy::builder(&conn).build().await.inspect_err(|e| {
|
||||||
|
no_supergfx(e);
|
||||||
|
})?;
|
||||||
|
let _ = proxy.mode().await.inspect_err(|e| {
|
||||||
|
no_supergfx(e);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let proxy_copy = proxy.clone();
|
||||||
|
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
|
||||||
|
let mut p = proxy.receive_notify_action().await?;
|
||||||
|
tokio::spawn(async move {
|
||||||
|
info!("Started zbus signal thread: receive_notify_action");
|
||||||
|
while let Some(e) = p.next().await {
|
||||||
|
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 mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
|
||||||
|
match action {
|
||||||
|
supergfxctl::actions::UserActionRequired::Reboot => {
|
||||||
|
do_mux_notification("Graphics mode change requires reboot", &mode)
|
||||||
|
}
|
||||||
|
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
|
||||||
|
}
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("zbus signal: do_gfx_action_notif: {e}");
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut p = proxy_copy.receive_notify_gfx_status().await?;
|
||||||
|
tokio::spawn(async move {
|
||||||
|
info!("Started zbus signal thread: receive_notify_gfx_status");
|
||||||
|
let mut last_status = GfxPower::Unknown;
|
||||||
|
while let Some(e) = p.next().await {
|
||||||
|
if let Ok(out) = e.args() {
|
||||||
|
let status = out.status;
|
||||||
|
if status != GfxPower::Unknown && status != last_status {
|
||||||
|
if let Ok(config) = enabled_notifications_copy.lock() {
|
||||||
|
if !config.notifications.receive_notify_gfx_status
|
||||||
|
|| !config.notifications.enabled
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Required check because status cycles through
|
||||||
|
// active/unknown/suspended
|
||||||
|
do_gpu_status_notif("dGPU status changed:", &status)
|
||||||
|
.show_async()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.on_close(|_| ());
|
||||||
|
}
|
||||||
|
last_status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok::<(), zbus::Error>(())
|
||||||
|
});
|
||||||
|
|
||||||
Ok(vec![blocking])
|
Ok(vec![blocking])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
|
||||||
|
match gfx {
|
||||||
|
GfxMode::Hybrid => GpuMode::Optimus,
|
||||||
|
GfxMode::Integrated => GpuMode::Integrated,
|
||||||
|
GfxMode::NvidiaNoModeset => GpuMode::Optimus,
|
||||||
|
GfxMode::Vfio => GpuMode::Vfio,
|
||||||
|
GfxMode::AsusEgpu => GpuMode::Egpu,
|
||||||
|
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
|
||||||
|
GfxMode::None => GpuMode::Error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn base_notification<T>(message: &str, data: &T) -> Notification
|
fn base_notification<T>(message: &str, data: &T) -> Notification
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -209,3 +303,97 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Notification {
|
|||||||
notif.icon(icon);
|
notif.icon(icon);
|
||||||
notif
|
notif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
|
||||||
|
if matches!(action, GfxUserAction::Reboot) {
|
||||||
|
do_mux_notification("Graphics mode change requires reboot", &mode).ok();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut notif = Notification::new();
|
||||||
|
notif
|
||||||
|
.appname(NOTIF_HEADER)
|
||||||
|
.summary(&format!("Changing to {mode}. {message}"))
|
||||||
|
//.hint(Hint::Resident(true))
|
||||||
|
.hint(Hint::Category("device".into()))
|
||||||
|
.urgency(Urgency::Critical)
|
||||||
|
// 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")
|
||||||
|
.hint(Hint::Transient(true));
|
||||||
|
|
||||||
|
if matches!(action, GfxUserAction::Logout) {
|
||||||
|
notif.action("gfx-mode-session-action", "Logout");
|
||||||
|
let handle = notif.show()?;
|
||||||
|
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
|
||||||
|
if desktop.to_lowercase() == "gnome" {
|
||||||
|
handle.wait_for_action(|id| {
|
||||||
|
if id == "gfx-mode-session-action" {
|
||||||
|
let mut cmd = Command::new("gnome-session-quit");
|
||||||
|
cmd.spawn().ok();
|
||||||
|
} else if id == "__closed" {
|
||||||
|
// TODO: cancel the switching
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if desktop.to_lowercase() == "kde" {
|
||||||
|
handle.wait_for_action(|id| {
|
||||||
|
if id == "gfx-mode-session-action" {
|
||||||
|
let mut cmd = Command::new("qdbus");
|
||||||
|
cmd.args([
|
||||||
|
"org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0",
|
||||||
|
]);
|
||||||
|
cmd.spawn().ok();
|
||||||
|
} else if id == "__closed" {
|
||||||
|
// TODO: cancel the switching
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// todo: handle alternatives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notif.show()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actual `GpuMode` unused as data is never correct until switched by reboot
|
||||||
|
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
|
||||||
|
let mut notif = base_notification(message, &m.to_string());
|
||||||
|
notif
|
||||||
|
.action("gfx-mode-session-action", "Reboot")
|
||||||
|
.urgency(Urgency::Critical)
|
||||||
|
.icon("system-reboot-symbolic")
|
||||||
|
.hint(Hint::Transient(true));
|
||||||
|
let handle = notif.show()?;
|
||||||
|
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
|
||||||
|
if desktop.to_lowercase() == "gnome" {
|
||||||
|
handle.wait_for_action(|id| {
|
||||||
|
if id == "gfx-mode-session-action" {
|
||||||
|
let mut cmd = Command::new("gnome-session-quit");
|
||||||
|
cmd.arg("--reboot");
|
||||||
|
cmd.spawn().ok();
|
||||||
|
} else if id == "__closed" {
|
||||||
|
// TODO: cancel the switching
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if desktop.to_lowercase() == "kde" {
|
||||||
|
handle.wait_for_action(|id| {
|
||||||
|
if id == "gfx-mode-session-action" {
|
||||||
|
let mut cmd = Command::new("qdbus");
|
||||||
|
cmd.args([
|
||||||
|
"org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0",
|
||||||
|
]);
|
||||||
|
cmd.spawn().ok();
|
||||||
|
} else if id == "__closed" {
|
||||||
|
// TODO: cancel the switching
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ pub fn init_tray(_supported_properties: Vec<Properties>, config: Arc<Mutex<Confi
|
|||||||
|
|
||||||
// TODO: return an error to the UI
|
// TODO: return an error to the UI
|
||||||
let mut tray;
|
let mut tray;
|
||||||
match tray_init.disable_dbus_name(true).spawn().await {
|
match tray_init.spawn_without_dbus_name().await {
|
||||||
Ok(t) => tray = t,
|
Ok(t) => tray = t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
pub mod setup_anime;
|
pub mod setup_anime;
|
||||||
pub mod setup_aura;
|
pub mod setup_aura;
|
||||||
pub mod setup_fans;
|
pub mod setup_fans;
|
||||||
pub mod setup_gpu;
|
|
||||||
pub mod setup_system;
|
pub mod setup_system;
|
||||||
|
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
static TOAST_SEQ: AtomicU64 = AtomicU64::new(0);
|
|
||||||
|
|
||||||
use config_traits::StdConfig;
|
use config_traits::StdConfig;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
@@ -75,61 +70,25 @@ pub fn show_toast(
|
|||||||
handle: Weak<MainWindow>,
|
handle: Weak<MainWindow>,
|
||||||
result: zbus::Result<()>,
|
result: zbus::Result<()>,
|
||||||
) {
|
) {
|
||||||
// bump sequence so that any previously spawned timers won't clear newer toasts
|
|
||||||
let seq = TOAST_SEQ.fetch_add(1, Ordering::SeqCst) + 1;
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let delayed_handle = handle.clone();
|
slint::invoke_from_event_loop(move || handle.unwrap().invoke_show_toast(success)).ok()
|
||||||
let delayed_text = success.clone();
|
|
||||||
slint::invoke_from_event_loop(move || handle.unwrap().invoke_show_toast(success)).ok();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
||||||
if TOAST_SEQ.load(Ordering::SeqCst) == seq {
|
|
||||||
slint::invoke_from_event_loop(move || {
|
|
||||||
delayed_handle
|
|
||||||
.unwrap()
|
|
||||||
.invoke_clear_toast_if_matches(delayed_text)
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let delayed_handle = handle.clone();
|
|
||||||
let delayed_text = fail.clone();
|
|
||||||
slint::invoke_from_event_loop(move || {
|
|
||||||
log::warn!("{fail}: {e}");
|
|
||||||
handle.unwrap().invoke_show_toast(fail)
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
||||||
if TOAST_SEQ.load(Ordering::SeqCst) == seq {
|
|
||||||
slint::invoke_from_event_loop(move || {
|
|
||||||
delayed_handle
|
|
||||||
.unwrap()
|
|
||||||
.invoke_clear_toast_if_matches(delayed_text)
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
Err(e) => slint::invoke_from_event_loop(move || {
|
||||||
|
log::warn!("{fail}: {e}");
|
||||||
|
handle.unwrap().invoke_show_toast(fail)
|
||||||
|
})
|
||||||
|
.ok(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_window(
|
pub fn setup_window(config: Arc<Mutex<Config>>) -> MainWindow {
|
||||||
config: Arc<Mutex<Config>>,
|
|
||||||
prefetched_supported: std::sync::Arc<Option<Vec<i32>>>,
|
|
||||||
is_tuf: bool,
|
|
||||||
) -> MainWindow {
|
|
||||||
slint::set_xdg_app_id("rog-control-center")
|
slint::set_xdg_app_id("rog-control-center")
|
||||||
.map_err(|e| warn!("Couldn't set application ID: {e:?}"))
|
.map_err(|e| warn!("Couldn't set application ID: {e:?}"))
|
||||||
.ok();
|
.ok();
|
||||||
let ui = MainWindow::new()
|
let ui = MainWindow::new()
|
||||||
.map_err(|e| warn!("Couldn't create main window: {e:?}"))
|
.map_err(|e| warn!("Couldn't create main window: {e:?}"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// propagate TUF flag to the UI so the sidebar can swap logo branding
|
|
||||||
ui.set_is_tuf(is_tuf);
|
|
||||||
ui.window()
|
ui.window()
|
||||||
.show()
|
.show()
|
||||||
.map_err(|e| warn!("Couldn't show main window: {e:?}"))
|
.map_err(|e| warn!("Couldn't show main window: {e:?}"))
|
||||||
@@ -143,9 +102,8 @@ pub fn setup_window(
|
|||||||
available.contains(&"xyz.ljones.Aura".to_string()),
|
available.contains(&"xyz.ljones.Aura".to_string()),
|
||||||
available.contains(&"xyz.ljones.Anime".to_string()),
|
available.contains(&"xyz.ljones.Anime".to_string()),
|
||||||
available.contains(&"xyz.ljones.FanCurves".to_string()),
|
available.contains(&"xyz.ljones.FanCurves".to_string()),
|
||||||
true, // GPU Configuration
|
true,
|
||||||
true, // App Settings
|
true,
|
||||||
true, // About
|
|
||||||
]
|
]
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
@@ -160,18 +118,15 @@ pub fn setup_window(
|
|||||||
setup_system_page_callbacks(&ui, config.clone());
|
setup_system_page_callbacks(&ui, config.clone());
|
||||||
}
|
}
|
||||||
if available.contains(&"xyz.ljones.Aura".to_string()) {
|
if available.contains(&"xyz.ljones.Aura".to_string()) {
|
||||||
setup_aura_page(&ui, config.clone(), prefetched_supported.as_ref().clone());
|
setup_aura_page(&ui, config.clone());
|
||||||
}
|
}
|
||||||
if available.contains(&"xyz.ljones.Anime".to_string()) {
|
if available.contains(&"xyz.ljones.Anime".to_string()) {
|
||||||
setup_anime_page(&ui, config.clone());
|
setup_anime_page(&ui, config.clone());
|
||||||
}
|
}
|
||||||
if available.contains(&"xyz.ljones.FanCurves".to_string()) {
|
if available.contains(&"xyz.ljones.FanCurves".to_string()) {
|
||||||
setup_fan_curve_page(&ui, config.clone());
|
setup_fan_curve_page(&ui, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate GPU page choices and callbacks
|
|
||||||
setup_gpu::setup_gpu_page(&ui);
|
|
||||||
|
|
||||||
ui
|
ui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,103 +34,63 @@ fn decode_hex(s: &str) -> RgbaColor<u8> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the first available Aura interface
|
||||||
|
// TODO: return all
|
||||||
async fn find_aura_iface() -> Result<AuraProxy<'static>, Box<dyn std::error::Error>> {
|
async fn find_aura_iface() -> Result<AuraProxy<'static>, Box<dyn std::error::Error>> {
|
||||||
let conn = zbus::Connection::system().await?;
|
let conn = zbus::Connection::system().await?;
|
||||||
let mgr = zbus::fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/").await?;
|
let f = zbus::fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/").await?;
|
||||||
let objs = mgr.get_managed_objects().await?;
|
let interfaces = f.get_managed_objects().await?;
|
||||||
let mut paths: Vec<zbus::zvariant::OwnedObjectPath> = objs
|
let mut aura_paths = Vec::new();
|
||||||
.iter()
|
for v in interfaces.iter() {
|
||||||
.filter(|(_, ifaces)| ifaces.keys().any(|k| k.as_str() == "xyz.ljones.Aura"))
|
for k in v.1.keys() {
|
||||||
.map(|(p, _)| p.clone())
|
if k.as_str() == "xyz.ljones.Aura" {
|
||||||
.collect();
|
println!("Found aura device at {}, {}", v.0, k);
|
||||||
if paths.len() > 1 {
|
aura_paths.push(v.0.clone());
|
||||||
log::debug!("Multiple aura devices: {paths:?}");
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let path = paths.pop().ok_or("No Aura interface")?;
|
if aura_paths.len() > 1 {
|
||||||
AuraProxy::builder(&conn)
|
println!("Multiple aura devices found: {aura_paths:?}");
|
||||||
.path(path)?
|
println!("TODO: enable selection");
|
||||||
.destination("xyz.ljones.Asusd")?
|
}
|
||||||
.build()
|
if let Some(path) = aura_paths.first() {
|
||||||
.await
|
return Ok(AuraProxy::builder(&conn)
|
||||||
.map_err(Into::into)
|
.path(path.clone())?
|
||||||
|
.destination("xyz.ljones.Asusd")?
|
||||||
|
.build()
|
||||||
|
.await?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err("No Aura interface".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn prefetch_supported_basic_modes() -> Option<Vec<i32>> {
|
pub fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
|
||||||
let proxy = find_aura_iface().await.ok()?;
|
ui.global::<AuraPageData>().on_cb_hex_from_colour(|c| {
|
||||||
let modes = proxy.supported_basic_modes().await.ok()?;
|
|
||||||
Some(modes.iter().map(|n| (*n).into()).collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_aura_page(
|
|
||||||
ui: &MainWindow,
|
|
||||||
_states: Arc<Mutex<Config>>,
|
|
||||||
prefetched_supported: Option<Vec<i32>>,
|
|
||||||
) {
|
|
||||||
let g = ui.global::<AuraPageData>();
|
|
||||||
g.on_cb_hex_from_colour(|c| {
|
|
||||||
format!("#{:02X}{:02X}{:02X}", c.red(), c.green(), c.blue()).into()
|
format!("#{:02X}{:02X}{:02X}", c.red(), c.green(), c.blue()).into()
|
||||||
});
|
});
|
||||||
g.on_cb_hex_to_colour(|s| decode_hex(s.as_str()).into());
|
|
||||||
|
ui.global::<AuraPageData>()
|
||||||
|
.on_cb_hex_to_colour(|s| decode_hex(s.as_str()).into());
|
||||||
|
|
||||||
let handle = ui.as_weak();
|
let handle = ui.as_weak();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let Ok(aura) = find_aura_iface().await else {
|
let Ok(aura) = find_aura_iface().await else {
|
||||||
info!("No aura interfaces");
|
info!("This device appears to have no aura interfaces");
|
||||||
return Ok::<(), zbus::Error>(());
|
return Ok::<(), zbus::Error>(());
|
||||||
};
|
};
|
||||||
|
|
||||||
set_ui_props_async!(handle, aura, AuraPageData, brightness);
|
set_ui_props_async!(handle, aura, AuraPageData, brightness);
|
||||||
|
set_ui_props_async!(handle, aura, AuraPageData, led_mode);
|
||||||
|
set_ui_props_async!(handle, aura, AuraPageData, led_mode_data);
|
||||||
set_ui_props_async!(handle, aura, AuraPageData, led_power);
|
set_ui_props_async!(handle, aura, AuraPageData, led_power);
|
||||||
set_ui_props_async!(handle, aura, AuraPageData, device_type);
|
set_ui_props_async!(handle, aura, AuraPageData, device_type);
|
||||||
|
|
||||||
let modes_vec: Vec<i32> = match prefetched_supported {
|
|
||||||
Some(p) => p,
|
|
||||||
None => aura
|
|
||||||
.supported_basic_modes()
|
|
||||||
.await
|
|
||||||
.ok()
|
|
||||||
.map(|m| m.iter().map(|n| (*n).into()).collect())
|
|
||||||
.unwrap_or_default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Restore saved mode, colours, zone, speed, direction from asusd (persisted to disk).
|
|
||||||
// Use effect.mode as single source — avoid led_mode() which can fail (try_lock).
|
|
||||||
let restore = aura.led_mode_data().await.ok();
|
|
||||||
let raw_mode: Option<i32> = restore.as_ref().map(|d| d.mode.into());
|
|
||||||
let d_slint = restore.map(|d| d.into());
|
|
||||||
handle
|
|
||||||
.upgrade_in_event_loop(move |h| {
|
|
||||||
let names = h.global::<AuraPageData>().get_mode_names();
|
|
||||||
let mut raws = Vec::new();
|
|
||||||
let mut mode_names = Vec::new();
|
|
||||||
for (i, name) in names.iter().enumerate() {
|
|
||||||
let raw = i as i32;
|
|
||||||
if modes_vec.contains(&raw) && i != 9 {
|
|
||||||
raws.push(raw);
|
|
||||||
mode_names.push(name.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.global::<AuraPageData>()
|
|
||||||
.set_supported_basic_modes(raws.as_slice().into());
|
|
||||||
h.global::<AuraPageData>()
|
|
||||||
.set_available_mode_names(mode_names.as_slice().into());
|
|
||||||
if let Some(d) = d_slint {
|
|
||||||
h.global::<AuraPageData>().invoke_update_led_mode_data(d);
|
|
||||||
if let Some(cm) = raw_mode {
|
|
||||||
let idx = raws.iter().position(|&r| r == cm).unwrap_or(0) as i32;
|
|
||||||
h.global::<AuraPageData>().set_current_available_mode(idx);
|
|
||||||
}
|
|
||||||
h.invoke_external_colour_change();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map_err(|e| error!("{e}"))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
if let Ok(mut pow3r) = aura.supported_power_zones().await {
|
if let Ok(mut pow3r) = aura.supported_power_zones().await {
|
||||||
let dev = aura
|
let dev_type = aura
|
||||||
.device_type()
|
.device_type()
|
||||||
.await
|
.await
|
||||||
.unwrap_or(AuraDeviceType::LaptopKeyboard2021);
|
.unwrap_or(AuraDeviceType::LaptopKeyboard2021);
|
||||||
|
log::debug!("Available LED power modes {pow3r:?}");
|
||||||
handle
|
handle
|
||||||
.upgrade_in_event_loop(move |handle| {
|
.upgrade_in_event_loop(move |handle| {
|
||||||
let names: Vec<SharedString> = handle
|
let names: Vec<SharedString> = handle
|
||||||
@@ -138,103 +98,135 @@ pub fn setup_aura_page(
|
|||||||
.get_power_zone_names()
|
.get_power_zone_names()
|
||||||
.iter()
|
.iter()
|
||||||
.collect();
|
.collect();
|
||||||
if dev.is_old_laptop() {
|
|
||||||
|
if dev_type.is_old_laptop() {
|
||||||
|
// Need to add the specific KeyboardAndLightbar
|
||||||
if pow3r.contains(&PowerZones::Keyboard)
|
if pow3r.contains(&PowerZones::Keyboard)
|
||||||
&& pow3r.contains(&PowerZones::Lightbar)
|
&& pow3r.contains(&PowerZones::Lightbar)
|
||||||
{
|
{
|
||||||
pow3r.push(PowerZones::KeyboardAndLightbar);
|
pow3r.push(PowerZones::KeyboardAndLightbar);
|
||||||
}
|
}
|
||||||
let n: Vec<SharedString> =
|
let names: Vec<SharedString> =
|
||||||
pow3r.iter().map(|z| names[(*z) as usize].clone()).collect();
|
pow3r.iter().map(|n| names[(*n) as usize].clone()).collect();
|
||||||
handle
|
handle
|
||||||
.global::<AuraPageData>()
|
.global::<AuraPageData>()
|
||||||
.set_power_zone_names_old(n.as_slice().into());
|
.set_power_zone_names_old(names.as_slice().into());
|
||||||
} else {
|
} else {
|
||||||
let p: Vec<SlintPowerZones> = pow3r.iter().map(|z| (*z).into()).collect();
|
let power: Vec<SlintPowerZones> =
|
||||||
|
pow3r.iter().map(|p| (*p).into()).collect();
|
||||||
|
|
||||||
handle
|
handle
|
||||||
.global::<AuraPageData>()
|
.global::<AuraPageData>()
|
||||||
.set_supported_power_zones(p.as_slice().into());
|
.set_supported_power_zones(power.as_slice().into());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let proxy = aura.clone();
|
if let Ok(modes) = aura.supported_basic_modes().await {
|
||||||
let weak = handle.clone();
|
log::debug!("Available LED modes {modes:?}");
|
||||||
|
handle
|
||||||
|
.upgrade_in_event_loop(move |handle| {
|
||||||
|
let m: Vec<i32> = modes.iter().map(|n| (*n).into()).collect();
|
||||||
|
handle
|
||||||
|
.global::<AuraPageData>()
|
||||||
|
.set_supported_basic_modes(m.as_slice().into());
|
||||||
|
// Get the translated names
|
||||||
|
let names = handle.global::<AuraPageData>().get_mode_names();
|
||||||
|
|
||||||
|
let res: Vec<SharedString> = names
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(n, _)| modes.contains(&(*n as i32).into()) && *n != 9)
|
||||||
|
.map(|(_, i)| i)
|
||||||
|
.collect();
|
||||||
|
handle
|
||||||
|
.global::<AuraPageData>()
|
||||||
|
.set_available_mode_names(res.as_slice().into());
|
||||||
|
})
|
||||||
|
.map_err(|e| error!("{e:}"))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
let proxy_copy = aura.clone();
|
||||||
handle
|
handle
|
||||||
.upgrade_in_event_loop(move |h| {
|
.upgrade_in_event_loop(move |handle| {
|
||||||
set_ui_callbacks!(h,
|
set_ui_callbacks!(handle,
|
||||||
AuraPageData(.into()),
|
AuraPageData(.into()),
|
||||||
proxy.brightness(.into()),
|
proxy_copy.brightness(.into()),
|
||||||
"Brightness set to {}",
|
"Keyboard LED brightness successfully set to {}",
|
||||||
"Brightness failed"
|
"Setting keyboard LED brightness failed"
|
||||||
);
|
);
|
||||||
|
|
||||||
let p = proxy.clone();
|
set_ui_callbacks!(handle,
|
||||||
let w = weak.clone();
|
AuraPageData(.into()),
|
||||||
h.global::<AuraPageData>().on_apply_led_mode_data(move || {
|
proxy_copy.led_mode(.into()),
|
||||||
let Some(ui) = w.upgrade() else { return };
|
"Keyboard LED mode successfully set to {}",
|
||||||
let slint_effect = ui.global::<AuraPageData>().get_led_mode_data();
|
"Setting keyboard LEDmode failed"
|
||||||
let raw: rog_aura::AuraEffect = slint_effect.into();
|
);
|
||||||
let pp = p.clone();
|
|
||||||
let t = w.clone();
|
set_ui_callbacks!(handle,
|
||||||
tokio::spawn(async move {
|
AuraPageData(.into()),
|
||||||
let r = pp.set_led_mode_data(raw).await;
|
proxy_copy.led_mode_data(.into()),
|
||||||
show_toast("LED mode applied".into(), "LED mode failed".into(), t, r);
|
"Keyboard LED mode set to {:?}",
|
||||||
});
|
"Setting keyboard LED mode failed"
|
||||||
});
|
);
|
||||||
h.invoke_external_colour_change();
|
|
||||||
|
// set_ui_callbacks!(handle,
|
||||||
|
// AuraPageData(.clone().into()),
|
||||||
|
// proxy_copy.led_power(.into()),
|
||||||
|
// "Keyboard LED power successfully set to {:?}",
|
||||||
|
// "Setting keyboard power failed"
|
||||||
|
// );
|
||||||
|
|
||||||
|
handle.invoke_external_colour_change();
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let weak_power = handle.clone();
|
let handle_copy = handle.clone();
|
||||||
let proxy_power = aura.clone();
|
let proxy_copy = aura.clone();
|
||||||
handle
|
handle
|
||||||
.upgrade_in_event_loop(|h| {
|
.upgrade_in_event_loop(|handle| {
|
||||||
h.global::<AuraPageData>().on_cb_led_power(move |power| {
|
handle
|
||||||
let w = weak_power.clone();
|
.global::<AuraPageData>()
|
||||||
let p = proxy_power.clone();
|
.on_cb_led_power(move |power| {
|
||||||
let pw: LaptopAuraPower = power.into();
|
let handle_copy = handle_copy.clone();
|
||||||
tokio::spawn(async move {
|
let proxy_copy = aura.clone();
|
||||||
show_toast(
|
let power: LaptopAuraPower = power.into();
|
||||||
"Aura power updated".into(),
|
tokio::spawn(async move {
|
||||||
"Aura power failed".into(),
|
show_toast(
|
||||||
w,
|
"Aura power settings changed".into(),
|
||||||
p.set_led_power(pw).await,
|
"Failed to set Aura power settings".into(),
|
||||||
);
|
handle_copy,
|
||||||
|
proxy_copy.set_led_power(power).await,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.map_err(|e| error!("{e}"))
|
.map_err(|e| error!("{e:}"))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let stream_handle = handle.clone();
|
// Need to update the UI if the mode changes
|
||||||
let aura_stream = aura.clone();
|
let handle_copy = handle.clone();
|
||||||
|
// spawn required since the while let never exits
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
let mut x = proxy_copy.receive_led_mode_data_changed().await;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
let mut stream = aura_stream.receive_led_mode_data_changed().await;
|
while let Some(e) = x.next().await {
|
||||||
while let Some(e) = stream.next().await {
|
|
||||||
if let Ok(out) = e.get().await {
|
if let Ok(out) = e.get().await {
|
||||||
let raw: i32 = out.mode.into();
|
handle_copy
|
||||||
let data = out.into();
|
.upgrade_in_event_loop(move |handle| {
|
||||||
stream_handle
|
handle
|
||||||
.upgrade_in_event_loop(move |h| {
|
|
||||||
h.global::<AuraPageData>().invoke_update_led_mode_data(data);
|
|
||||||
let supported: Vec<i32> = h
|
|
||||||
.global::<AuraPageData>()
|
.global::<AuraPageData>()
|
||||||
.get_supported_basic_modes()
|
.invoke_update_led_mode_data(out.into());
|
||||||
.iter()
|
handle.invoke_external_colour_change();
|
||||||
.collect();
|
|
||||||
let idx = supported.iter().position(|&x| x == raw).unwrap_or(0) as i32;
|
|
||||||
h.global::<AuraPageData>().set_current_available_mode(idx);
|
|
||||||
h.invoke_external_colour_change();
|
|
||||||
})
|
})
|
||||||
.map_err(|e| error!("{e}"))
|
.map_err(|e| error!("{e:}"))
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
debug!("Aura setup done");
|
debug!("Aura setup tasks complete");
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,24 +168,15 @@ pub fn setup_fan_curve_page(ui: &MainWindow, _config: Arc<Mutex<Config>>) {
|
|||||||
|
|
||||||
update_fan_data(handle, balanced, perf, quiet);
|
update_fan_data(handle, balanced, perf, quiet);
|
||||||
|
|
||||||
let choices_for_ui = platform_profile_choices.clone();
|
|
||||||
let handle_next1 = handle_copy.clone();
|
let handle_next1 = handle_copy.clone();
|
||||||
if let Err(e) = handle_copy.upgrade_in_event_loop(move |handle| {
|
if let Err(e) = handle_copy.upgrade_in_event_loop(move |handle| {
|
||||||
let global = handle.global::<FanPageData>();
|
let global = handle.global::<FanPageData>();
|
||||||
let fans1 = fans.clone();
|
let fans1 = fans.clone();
|
||||||
let choices = choices_for_ui.clone();
|
|
||||||
global.on_set_profile_default(move |profile| {
|
global.on_set_profile_default(move |profile| {
|
||||||
let fans = fans1.clone();
|
let fans = fans1.clone();
|
||||||
let handle_next = handle_next1.clone();
|
let handle_next = handle_next1.clone();
|
||||||
let choices = choices.clone();
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut target: PlatformProfile = profile.into();
|
if fans.set_curves_to_defaults(profile.into()).await.is_err() {
|
||||||
if target == PlatformProfile::Quiet
|
|
||||||
&& !choices.contains(&PlatformProfile::Quiet)
|
|
||||||
{
|
|
||||||
target = PlatformProfile::LowPower;
|
|
||||||
}
|
|
||||||
if fans.set_curves_to_defaults(target).await.is_err() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Ok(balanced) = fans
|
let Ok(balanced) = fans
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
use log::error;
|
|
||||||
use rog_platform::asus_armoury::{AttrValue, FirmwareAttributes};
|
|
||||||
use slint::{ComponentHandle, ModelRc, SharedString};
|
|
||||||
|
|
||||||
use crate::{GPUPageData, MainWindow};
|
|
||||||
|
|
||||||
// Populate GPU page choices and wire the `cb_set_gpu_mode` callback
|
|
||||||
pub fn setup_gpu_page(ui: &MainWindow) {
|
|
||||||
let handle = ui.as_weak();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
// Read available attributes
|
|
||||||
let attrs = FirmwareAttributes::new();
|
|
||||||
let gpu_mux_available = attrs
|
|
||||||
.gpu_mux_mode()
|
|
||||||
.map(|a| a.base_path_exists())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
// Prepare choice strings
|
|
||||||
let mut choices: Vec<SharedString> = Vec::new();
|
|
||||||
choices.push(SharedString::from("Integrated"));
|
|
||||||
if gpu_mux_available {
|
|
||||||
choices.push(SharedString::from("Ultimate"));
|
|
||||||
}
|
|
||||||
choices.push(SharedString::from("Hybrid"));
|
|
||||||
|
|
||||||
// Read current attribute values to initialise UI state
|
|
||||||
let current_dgpu = attrs
|
|
||||||
.dgpu_disable()
|
|
||||||
.and_then(|a| a.current_value().ok())
|
|
||||||
.unwrap_or(AttrValue::Integer(0));
|
|
||||||
let current_mux = attrs
|
|
||||||
.gpu_mux_mode()
|
|
||||||
.and_then(|a| a.current_value().ok())
|
|
||||||
.unwrap_or(AttrValue::Integer(1));
|
|
||||||
|
|
||||||
// Convert to UI-able values
|
|
||||||
let dgpu_disabled = matches!(current_dgpu, AttrValue::Integer(v) if v == 1);
|
|
||||||
// Determine initial index for gpu_mux_mode property
|
|
||||||
let initial_index: i32 = if gpu_mux_available {
|
|
||||||
// If mux attr says 0 -> Ultimate, else try dgpu to refine
|
|
||||||
match current_mux {
|
|
||||||
AttrValue::Integer(0) => 1, // Ultimate
|
|
||||||
_ => {
|
|
||||||
match current_dgpu {
|
|
||||||
AttrValue::Integer(1) => 0, // Integrated
|
|
||||||
_ => 2, // Hybrid/Optimus fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Only Integrated / Hybrid
|
|
||||||
match current_dgpu {
|
|
||||||
AttrValue::Integer(1) => 0,
|
|
||||||
_ => 1,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let handle_copy = handle.clone();
|
|
||||||
if let Err(e) = handle.upgrade_in_event_loop(move |handle| {
|
|
||||||
let global = handle.global::<GPUPageData>();
|
|
||||||
|
|
||||||
// set choices model
|
|
||||||
let model: ModelRc<SharedString> = choices.as_slice().into();
|
|
||||||
global.set_gpu_modes_choises(model);
|
|
||||||
global.set_gpu_mux_available(gpu_mux_available);
|
|
||||||
|
|
||||||
// set initial state
|
|
||||||
global.set_dgpu_disabled(if dgpu_disabled { 1 } else { 0 });
|
|
||||||
global.set_gpu_mux_mode(initial_index);
|
|
||||||
|
|
||||||
// register callback
|
|
||||||
let handle_cb = handle_copy.clone();
|
|
||||||
global.on_cb_set_gpu_mode(move |index: i32| {
|
|
||||||
// show a blue toast informing user a reboot is required (auto-clears)
|
|
||||||
let toast_handle = handle_cb.clone();
|
|
||||||
crate::ui::show_toast(
|
|
||||||
SharedString::from(
|
|
||||||
"GPU mode change scheduled — reboot required for changes to apply.",
|
|
||||||
),
|
|
||||||
SharedString::from("Failed to set GPU mode"),
|
|
||||||
toast_handle.clone(),
|
|
||||||
Ok(()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let handle_next = handle_cb.clone();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let attrs = FirmwareAttributes::new();
|
|
||||||
let mux_avail = attrs
|
|
||||||
.gpu_mux_mode()
|
|
||||||
.map(|a| a.base_path_exists())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
// helper to set attribute ignoring errors
|
|
||||||
if mux_avail {
|
|
||||||
match index {
|
|
||||||
0 => {
|
|
||||||
// Integrated
|
|
||||||
if let Some(attr) = attrs.dgpu_disable() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(1));
|
|
||||||
}
|
|
||||||
if let Some(attr) = attrs.gpu_mux_mode() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
// Ultimate
|
|
||||||
if let Some(attr) = attrs.dgpu_disable() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(0));
|
|
||||||
}
|
|
||||||
if let Some(attr) = attrs.gpu_mux_mode() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
// Dynamic
|
|
||||||
if let Some(attr) = attrs.dgpu_disable() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(0));
|
|
||||||
}
|
|
||||||
if let Some(attr) = attrs.gpu_mux_mode() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match index {
|
|
||||||
0 => {
|
|
||||||
if let Some(attr) = attrs.dgpu_disable() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
if let Some(attr) = attrs.dgpu_disable() {
|
|
||||||
let _ = attr.set_current_value(&AttrValue::Integer(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// After attempting write(s), refresh UI from attributes
|
|
||||||
let attrs2 = FirmwareAttributes::new();
|
|
||||||
let cur_dgpu = attrs2
|
|
||||||
.dgpu_disable()
|
|
||||||
.and_then(|a| a.current_value().ok())
|
|
||||||
.unwrap_or(AttrValue::Integer(0));
|
|
||||||
let cur_mux = attrs2
|
|
||||||
.gpu_mux_mode()
|
|
||||||
.and_then(|a| a.current_value().ok())
|
|
||||||
.unwrap_or(AttrValue::Integer(1));
|
|
||||||
|
|
||||||
let dgpu_disabled = matches!(cur_dgpu, AttrValue::Integer(v) if v == 1);
|
|
||||||
let new_index: i32 = if mux_avail {
|
|
||||||
match cur_mux {
|
|
||||||
AttrValue::Integer(0) => 1,
|
|
||||||
_ => match cur_dgpu {
|
|
||||||
AttrValue::Integer(1) => 0,
|
|
||||||
_ => 2,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match cur_dgpu {
|
|
||||||
AttrValue::Integer(1) => 0,
|
|
||||||
_ => 1,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = handle_next.upgrade_in_event_loop(move |h| {
|
|
||||||
let g = h.global::<GPUPageData>();
|
|
||||||
g.set_dgpu_disabled(if dgpu_disabled { 1 } else { 0 });
|
|
||||||
g.set_gpu_mux_mode(new_index);
|
|
||||||
}) {
|
|
||||||
error!("setup_gpu callback: upgrade_in_event_loop: {e:?}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}) {
|
|
||||||
error!("setup_gpu_page: upgrade_in_event_loop: {e:?}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -130,6 +130,51 @@ macro_rules! init_minmax_property {
|
|||||||
|
|
||||||
// For handling callbacks from UI value changes
|
// For handling callbacks from UI value changes
|
||||||
macro_rules! setup_callback {
|
macro_rules! setup_callback {
|
||||||
|
// Minmax (AttrMinMax) variant - pass an extra `minmax` token
|
||||||
|
($property:ident, $handle:expr, $attr:expr, $type:tt, minmax) => {
|
||||||
|
let handle_copy = $handle.as_weak();
|
||||||
|
let proxy_copy = $attr.clone();
|
||||||
|
concat_idents!(on_callback = on_cb_, $property {
|
||||||
|
$handle
|
||||||
|
.global::<SystemPageData>()
|
||||||
|
.on_callback(move |v| {
|
||||||
|
let handle_copy = handle_copy.clone();
|
||||||
|
let proxy_copy = proxy_copy.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let res = proxy_copy
|
||||||
|
.set_current_value(convert_to_dbus!($type, v))
|
||||||
|
.await;
|
||||||
|
show_toast(
|
||||||
|
format!("{} successfully set to {}", stringify!($property), v).into(),
|
||||||
|
format!("Setting {} failed", stringify!($property)).into(),
|
||||||
|
handle_copy.clone(),
|
||||||
|
res.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
|
let min_v = proxy_copy.min_value().await.unwrap_or(-1);
|
||||||
|
let max_v = proxy_copy.max_value().await.unwrap_or(-1);
|
||||||
|
if let Ok(cur_val) = proxy_copy.current_value().await {
|
||||||
|
let cur_f = cur_val as f32;
|
||||||
|
handle_copy
|
||||||
|
.upgrade_in_event_loop(move |handle| {
|
||||||
|
concat_idents!(setter = set_, $property {
|
||||||
|
handle.global::<SystemPageData>().setter(AttrMinMax {
|
||||||
|
min: min_v,
|
||||||
|
max: max_v,
|
||||||
|
current: cur_f,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scalar variant (i32/bool/f32) - update scalar setter with authoritative value
|
||||||
($property:ident, $handle:expr, $attr:expr, $type:tt) => {
|
($property:ident, $handle:expr, $attr:expr, $type:tt) => {
|
||||||
let handle_copy = $handle.as_weak();
|
let handle_copy = $handle.as_weak();
|
||||||
let proxy_copy = $attr.clone();
|
let proxy_copy = $attr.clone();
|
||||||
@@ -140,12 +185,28 @@ macro_rules! setup_callback {
|
|||||||
let handle_copy = handle_copy.clone();
|
let handle_copy = handle_copy.clone();
|
||||||
let proxy_copy = proxy_copy.clone();
|
let proxy_copy = proxy_copy.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
let res = proxy_copy
|
||||||
|
.set_current_value(convert_to_dbus!($type, v))
|
||||||
|
.await;
|
||||||
show_toast(
|
show_toast(
|
||||||
format!("{} successfully set to {}", stringify!($property), v).into(),
|
format!("{} successfully set to {}", stringify!($property), v).into(),
|
||||||
format!("Setting {} failed", stringify!($property)).into(),
|
format!("Setting {} failed", stringify!($property)).into(),
|
||||||
handle_copy,
|
handle_copy.clone(),
|
||||||
proxy_copy.set_current_value(convert_to_dbus!($type, v)).await,
|
res.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
|
// Query authoritative value and set scalar global
|
||||||
|
if let Ok(cur_val) = proxy_copy.current_value().await {
|
||||||
|
handle_copy.upgrade_in_event_loop(move |handle| {
|
||||||
|
concat_idents!(setter = set_, $property {
|
||||||
|
handle
|
||||||
|
.global::<SystemPageData>()
|
||||||
|
.setter(convert_value!($type, cur_val));
|
||||||
|
});
|
||||||
|
}).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -615,49 +676,49 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
|
|||||||
}
|
}
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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, minmax);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if paths.len() > 1 {
|
if paths.len() > 1 {
|
||||||
log::warn!("Multiple asusd interfaces devices found");
|
println!("Multiple asusd interfaces devices found");
|
||||||
}
|
}
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let mut ctrl = Vec::new();
|
let mut ctrl = Vec::new();
|
||||||
@@ -129,7 +129,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if paths.len() > 1 {
|
if paths.len() > 1 {
|
||||||
log::warn!("Multiple asusd interfaces devices found");
|
println!("Multiple asusd interfaces devices found");
|
||||||
}
|
}
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let mut ctrl = Vec::new();
|
let mut ctrl = Vec::new();
|
||||||
|
|||||||
Binary file not shown.
@@ -1,810 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: rog-control-center\n"
|
|
||||||
"POT-Creation-Date: 2026-01-16 22:25+0000\n"
|
|
||||||
"PO-Revision-Date: 2024-07-28 12:00+0300\n"
|
|
||||||
"Last-Translator: Mykola Shevchenko\n"
|
|
||||||
"Language-Team: Ukrainian\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: uk_UA\n"
|
|
||||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:55
|
|
||||||
msgctxt "MainWindow"
|
|
||||||
msgid "ROG"
|
|
||||||
msgstr "ROG"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:57
|
|
||||||
msgctxt "Menu1"
|
|
||||||
msgid "System Control"
|
|
||||||
msgstr "Системні"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:58
|
|
||||||
msgctxt "Menu2"
|
|
||||||
msgid "Keyboard Aura"
|
|
||||||
msgstr "Aura клавіатури"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:59
|
|
||||||
msgctxt "Menu3"
|
|
||||||
msgid "AniMe Matrix"
|
|
||||||
msgstr "AniMe матриця"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:60
|
|
||||||
msgctxt "Menu4"
|
|
||||||
msgid "Fan Curves"
|
|
||||||
msgstr "Криві вентиляторів"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:61
|
|
||||||
msgctxt "Menu5"
|
|
||||||
msgid "App Settings"
|
|
||||||
msgstr "Налаштування"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:62
|
|
||||||
msgctxt "Menu6"
|
|
||||||
msgid "About"
|
|
||||||
msgstr "Про додаток"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/main_window.slint:74
|
|
||||||
msgctxt "MainWindow"
|
|
||||||
msgid "Quit App"
|
|
||||||
msgstr "Вийти"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:6
|
|
||||||
msgctxt "Anime Brightness"
|
|
||||||
msgid "Off"
|
|
||||||
msgstr "Вимкнено"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:7
|
|
||||||
msgctxt "Anime Brightness"
|
|
||||||
msgid "Low"
|
|
||||||
msgstr "Низька"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:8
|
|
||||||
msgctxt "Anime Brightness"
|
|
||||||
msgid "Med"
|
|
||||||
msgstr "Середня"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:9
|
|
||||||
msgctxt "Anime Brightness"
|
|
||||||
msgid "High"
|
|
||||||
msgstr "Висока"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:23
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Glitch Construction"
|
|
||||||
msgstr "Збій конструкції"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:23
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Static Emergence"
|
|
||||||
msgstr "Статична поява"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:25
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Binary Banner Scroll"
|
|
||||||
msgstr "Прокрутка бінарного банера"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:25
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Rog Logo Glitch"
|
|
||||||
msgstr "Збій логотипу Rog"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:27
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Banner Swipe"
|
|
||||||
msgstr "Прогортання банера"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:27
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Starfield"
|
|
||||||
msgstr "Зоряне поле"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:29
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "Glitch Out"
|
|
||||||
msgstr "Збій"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:29
|
|
||||||
msgctxt "AnimePageData"
|
|
||||||
msgid "See Ya"
|
|
||||||
msgstr "Бувай"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:50
|
|
||||||
msgctxt "Anime Brightness"
|
|
||||||
msgid "Brightness"
|
|
||||||
msgstr "Яскравість"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:66
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Enable display"
|
|
||||||
msgstr "Увімкнути показ"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:74 rog-control-center/ui/pages/anime.slint:97
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Розширені"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:89
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Use built-in animations"
|
|
||||||
msgstr "Використовувати вбудовані анімації"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:146
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Set which builtin animations are played"
|
|
||||||
msgstr "Встановити, які вбудовані анімації відтворювати"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:150
|
|
||||||
msgctxt "Anime built-in selection"
|
|
||||||
msgid "Boot Animation"
|
|
||||||
msgstr "Анімація завантаження"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:160
|
|
||||||
msgctxt "Anime built-in selection"
|
|
||||||
msgid "Running Animation"
|
|
||||||
msgstr "Анімація роботи"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:170
|
|
||||||
msgctxt "Anime built-in selection"
|
|
||||||
msgid "Sleep Animation"
|
|
||||||
msgstr "Анімація сну"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:180
|
|
||||||
msgctxt "Anime built-in selection"
|
|
||||||
msgid "Shutdown Animation"
|
|
||||||
msgstr "Анімація вимкнення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:220
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Advanced Display Settings"
|
|
||||||
msgstr "Розширені налаштування показу"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:225
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Off when lid closed"
|
|
||||||
msgstr "Вимикати при закритій кришці"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:234
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Off when suspended"
|
|
||||||
msgstr "Вимикати в режимі сну"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/anime.slint:243
|
|
||||||
msgctxt "PageAnime"
|
|
||||||
msgid "Off when on battery"
|
|
||||||
msgstr "Вимикати при роботі від батареї"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:20
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "Balanced"
|
|
||||||
msgstr "Збалансований"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:20 rog-control-center/ui/pages/system.slint:27
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "Performance"
|
|
||||||
msgstr "Продуктивний"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:20
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "Quiet"
|
|
||||||
msgstr "Тихий"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:20
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "LowPower"
|
|
||||||
msgstr "Низьке споживання"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:26
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "Default"
|
|
||||||
msgstr "За замовчуванням"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:28
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "BalancePerformance"
|
|
||||||
msgstr "Баланс-Продуктивність"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:29
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "BalancePower"
|
|
||||||
msgstr "Баланс-Енергозбереження"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:30
|
|
||||||
msgctxt "SystemPageData"
|
|
||||||
msgid "Power"
|
|
||||||
msgstr "Енергозбереження"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:159
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Power settings"
|
|
||||||
msgstr "Налаштування живлення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:164
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Charge limit"
|
|
||||||
msgstr "Ліміт заряду"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:179
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Platform Profile"
|
|
||||||
msgstr "Профіль платформи"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:189
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Розширені"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:209
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Screenpad brightness"
|
|
||||||
msgstr "Яскравість екранної панелі"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:233
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Sync with primary"
|
|
||||||
msgstr "Синхронізувати з основним"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:253
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Armoury settings"
|
|
||||||
msgstr "Налаштування Armoury"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:253
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Keyboard Power Management"
|
|
||||||
msgstr "Керування живленням клавіатури"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:263
|
|
||||||
msgctxt "no_asus_armoury_driver_1"
|
|
||||||
msgid "The asus-armoury driver is not loaded"
|
|
||||||
msgstr "Драйвер asus-armoury не завантажено"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:269
|
|
||||||
msgctxt "no_asus_armoury_driver_2"
|
|
||||||
msgid "For advanced features you will require a kernel with this driver added."
|
|
||||||
msgstr "Для розширених функцій вам знадобиться ядро з доданим цим драйвером."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:280
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Panel Overdrive"
|
|
||||||
msgstr "Розгін матриці"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:288
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "MiniLED Mode"
|
|
||||||
msgstr "Режим MiniLED"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:296
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "POST boot sound"
|
|
||||||
msgstr "Звук при завантаженні"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:312
|
|
||||||
msgctxt "ppt_warning"
|
|
||||||
msgid "The following settings are not applied until the toggle is enabled."
|
|
||||||
msgstr "Наступні налаштування не застосовуються, доки перемикач не буде увімкнено."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:317 rog-control-center/ui/pages/system.slint:324
|
|
||||||
msgctxt "ppt_group_enabled"
|
|
||||||
msgid "Enable Tuning"
|
|
||||||
msgstr "Увімкнути налаштування"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:334 rog-control-center/ui/pages/system.slint:335
|
|
||||||
msgctxt "ppt_pl1_spl"
|
|
||||||
msgid "CPU Sustained Power Limit"
|
|
||||||
msgstr "Тривалий ліміт потужності CPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:336
|
|
||||||
msgctxt "ppt_pl1_spl_help"
|
|
||||||
msgid ""
|
|
||||||
"Long-term CPU power limit that affects sustained workload performance. "
|
|
||||||
"Higher values may increase heat and power consumption."
|
|
||||||
msgstr ""
|
|
||||||
"Довготривалий ліміт потужності CPU, що впливає на продуктивність при тривалих навантаженнях."
|
|
||||||
"Вищі значення можуть збільшити нагрівання та споживання енергії."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:352 rog-control-center/ui/pages/system.slint:353
|
|
||||||
msgctxt "ppt_pl2_sppt"
|
|
||||||
msgid "CPU Turbo Power Limit"
|
|
||||||
msgstr "Турбо ліміт потужності CPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:354
|
|
||||||
msgctxt "ppt_pl2_sppt_help"
|
|
||||||
msgid ""
|
|
||||||
"Short-term CPU power limit for boost periods. Controls maximum power during "
|
|
||||||
"brief high-performance bursts."
|
|
||||||
msgstr ""
|
|
||||||
"Короткочасний ліміт потужності CPU для періодів прискорення. Контролює максимальну"
|
|
||||||
"потужність під час коротких сплесків високої продуктивності."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:370 rog-control-center/ui/pages/system.slint:371
|
|
||||||
msgctxt "ppt_pl3_fppt"
|
|
||||||
msgid "CPU Fast Burst Power Limit"
|
|
||||||
msgstr "Швидкий ліміт потужності CPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:372
|
|
||||||
msgctxt "ppt_pl3_fppt_help"
|
|
||||||
msgid ""
|
|
||||||
"Ultra-short duration power limit for instantaneous CPU bursts. Affects "
|
|
||||||
"responsiveness during sudden workload spikes."
|
|
||||||
msgstr ""
|
|
||||||
"Надкороткий ліміт потужності для миттєвих сплесків CPU."
|
|
||||||
"Впливає на чутливість під час раптових піків навантаження."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:387 rog-control-center/ui/pages/system.slint:388
|
|
||||||
msgctxt "ppt_fppt"
|
|
||||||
msgid "Fast Package Power Limit"
|
|
||||||
msgstr "Швидкий ліміт потужності пакета"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:389
|
|
||||||
msgctxt "ppt_fppt_help"
|
|
||||||
msgid ""
|
|
||||||
"Ultra-short duration power limit for system package. Controls maximum power "
|
|
||||||
"during millisecond-scale load spikes."
|
|
||||||
msgstr ""
|
|
||||||
"Надкороткий ліміт потужності для системного пакета. Контролює максимальну"
|
|
||||||
"потужність під час пікових навантажень мілісекундного масштабу."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:405 rog-control-center/ui/pages/system.slint:406
|
|
||||||
msgctxt "ppt_apu_sppt"
|
|
||||||
msgid "APU Sustained Power Limit"
|
|
||||||
msgstr "Тривалий ліміт потужності APU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:407
|
|
||||||
msgctxt "ppt_apu_sppt_help"
|
|
||||||
msgid ""
|
|
||||||
"Long-term power limit for integrated graphics and CPU combined. Affects "
|
|
||||||
"sustained performance of APU-based workloads."
|
|
||||||
msgstr ""
|
|
||||||
"Довготривалий ліміт потужності для інтегрованої графіки та CPU разом."
|
|
||||||
"Впливає на тривалу продуктивність навантажень на базі APU."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:423 rog-control-center/ui/pages/system.slint:424
|
|
||||||
msgctxt "ppt_platform_sppt"
|
|
||||||
msgid "Platform Sustained Power Limit"
|
|
||||||
msgstr "Тривалий ліміт потужності платформи"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:425
|
|
||||||
msgctxt "ppt_platform_sppt_help"
|
|
||||||
msgid ""
|
|
||||||
"Overall system power limit for sustained operations. Controls total platform "
|
|
||||||
"power consumption over extended periods."
|
|
||||||
msgstr ""
|
|
||||||
"Загальний ліміт потужності системи для тривалих операцій. Контролює загальне"
|
|
||||||
"споживання енергії платформою протягом тривалих періодів."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:441 rog-control-center/ui/pages/system.slint:442
|
|
||||||
msgctxt "nv_dynamic_boost"
|
|
||||||
msgid "GPU Power Boost"
|
|
||||||
msgstr "Прискорення потужності GPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:443
|
|
||||||
msgctxt "nv_dynamic_boost_help"
|
|
||||||
msgid ""
|
|
||||||
"Additional power allocation for GPU dynamic boost. Higher values increase "
|
|
||||||
"GPU performance but generate more heat."
|
|
||||||
msgstr ""
|
|
||||||
"Додаткове виділення потужності для динамічного прискорення GPU. Вищі значення"
|
|
||||||
"збільшують продуктивність GPU, але генерують більше тепла."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:459 rog-control-center/ui/pages/system.slint:460
|
|
||||||
msgctxt "nv_temp_target"
|
|
||||||
msgid "GPU Temperature Limit"
|
|
||||||
msgstr "Ліміт температури GPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:461
|
|
||||||
msgctxt "nv_temp_target_help"
|
|
||||||
msgid ""
|
|
||||||
"Maximum GPU temperature threshold in Celsius. GPU will throttle to maintain "
|
|
||||||
"temperature below this limit."
|
|
||||||
msgstr ""
|
|
||||||
"Максимальний поріг температури GPU у градусах Цельсія. GPU буде знижувати"
|
|
||||||
"частоту для підтримки температури нижче цього ліміту."
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:513
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Energy Performance Preference linked to Throttle Policy"
|
|
||||||
msgstr "Перевага енергоефективності пов'язана з Політикою Тротлінгу"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:517
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Change EPP based on Throttle Policy"
|
|
||||||
msgstr "Змінювати EPP на основі Політики Тротлінгу"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:525
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "EPP for Balanced Policy"
|
|
||||||
msgstr "EPP для Збалансованої Політики"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:535
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "EPP for Performance Policy"
|
|
||||||
msgstr "EPP для Політики Продуктивності"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:545
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "EPP for Quiet Policy"
|
|
||||||
msgstr "EPP для Тихої Політики"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:563
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Throttle Policy for power state"
|
|
||||||
msgstr "Політика Тротлінгу для стану живлення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:569
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Throttle Policy on Battery"
|
|
||||||
msgstr "Політика Тротлінгу при живленні від батареї"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:579 rog-control-center/ui/pages/system.slint:600
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Enabled"
|
|
||||||
msgstr "Увімкнено"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/system.slint:590
|
|
||||||
msgctxt "PageSystem"
|
|
||||||
msgid "Throttle Policy on AC"
|
|
||||||
msgstr "Політика Тротлінгу при живленні від мережі"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:28
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Brightness"
|
|
||||||
msgstr "Яскравість"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:39
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Aura mode"
|
|
||||||
msgstr "Режим Aura"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:59
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Colour 1"
|
|
||||||
msgstr "Колір 1"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:85
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Colour 2"
|
|
||||||
msgstr "Колір 2"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:119
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Zone"
|
|
||||||
msgstr "Зона"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:142
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Direction"
|
|
||||||
msgstr "Напрямок"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:164
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Speed"
|
|
||||||
msgstr "Швидкість"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:185
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Power Settings"
|
|
||||||
msgstr "Налаштування живлення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/aura.slint:270
|
|
||||||
msgctxt "PageAura"
|
|
||||||
msgid "Power Zones"
|
|
||||||
msgstr "Зони живлення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/app_settings.slint:26
|
|
||||||
msgctxt "PageAppSettings"
|
|
||||||
msgid "Run in background after closing"
|
|
||||||
msgstr "Працювати у фоні після закриття"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/app_settings.slint:34
|
|
||||||
msgctxt "PageAppSettings"
|
|
||||||
msgid "Start app in background (UI closed)"
|
|
||||||
msgstr "Запускати у фоні (без інтерфейсу)"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/app_settings.slint:42
|
|
||||||
msgctxt "PageAppSettings"
|
|
||||||
msgid "Enable system tray icon"
|
|
||||||
msgstr "Увімкнути іконку в треї"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/app_settings.slint:50
|
|
||||||
msgctxt "PageAppSettings"
|
|
||||||
msgid "Enable dGPU notifications"
|
|
||||||
msgstr "Увімкнути сповіщення про dGPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:26
|
|
||||||
msgctxt "FanTab"
|
|
||||||
msgid "This fan is not avilable on this machine"
|
|
||||||
msgstr "Цей вентилятор недоступний на цьому пристрої"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:34
|
|
||||||
msgctxt "FanTab"
|
|
||||||
msgid "Enabled"
|
|
||||||
msgstr "Увімкнено"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:43
|
|
||||||
msgctxt "FanTab"
|
|
||||||
msgid "Apply"
|
|
||||||
msgstr "Застосувати"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:51
|
|
||||||
msgctxt "FanTab"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Скасувати"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:59
|
|
||||||
msgctxt "FanTab"
|
|
||||||
msgid "Factory Default (all fans)"
|
|
||||||
msgstr "Заводські налаштування (всі вентилятори)"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:72
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "Balanced"
|
|
||||||
msgstr "Збалансований"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:75 rog-control-center/ui/pages/fans.slint:134 rog-control-center/ui/pages/fans.slint:193
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "CPU"
|
|
||||||
msgstr "CPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:93 rog-control-center/ui/pages/fans.slint:152 rog-control-center/ui/pages/fans.slint:211
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "Mid"
|
|
||||||
msgstr "Середній"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:111 rog-control-center/ui/pages/fans.slint:170 rog-control-center/ui/pages/fans.slint:229
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "GPU"
|
|
||||||
msgstr "GPU"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:131
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "Performance"
|
|
||||||
msgstr "Продуктивний"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/pages/fans.slint:190
|
|
||||||
msgctxt "PageFans"
|
|
||||||
msgid "Quiet"
|
|
||||||
msgstr "Тихий"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/common.slint:126
|
|
||||||
msgctxt "confirm_reset"
|
|
||||||
msgid "Are you sure you want to reset this?"
|
|
||||||
msgstr "Ви впевнені, що хочете скинути це?"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:33
|
|
||||||
msgctxt "AuraPowerGroup"
|
|
||||||
msgid "Boot"
|
|
||||||
msgstr "Запуск"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:43
|
|
||||||
msgctxt "AuraPowerGroup"
|
|
||||||
msgid "Awake"
|
|
||||||
msgstr "Робота"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:53
|
|
||||||
msgctxt "AuraPowerGroup"
|
|
||||||
msgid "Sleep"
|
|
||||||
msgstr "Сон"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:63
|
|
||||||
msgctxt "AuraPowerGroup"
|
|
||||||
msgid "Shutdown"
|
|
||||||
msgstr "Вимкнення"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:102
|
|
||||||
msgctxt "AuraPowerGroupOld"
|
|
||||||
msgid "Zone Selection"
|
|
||||||
msgstr "Вибір зони"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:114
|
|
||||||
msgctxt "AuraPowerGroupOld"
|
|
||||||
msgid "Boot"
|
|
||||||
msgstr "Завантаження"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:124
|
|
||||||
msgctxt "AuraPowerGroupOld"
|
|
||||||
msgid "Awake"
|
|
||||||
msgstr "Робота"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/widgets/aura_power.slint:134
|
|
||||||
msgctxt "AuraPowerGroupOld"
|
|
||||||
msgid "Sleep"
|
|
||||||
msgstr "Сон"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:52
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Logo"
|
|
||||||
msgstr "Логотип"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:53 rog-control-center/ui/types/aura_types.slint:63
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Keyboard"
|
|
||||||
msgstr "Клавіатура"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:54 rog-control-center/ui/types/aura_types.slint:64
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Lightbar"
|
|
||||||
msgstr "Світлова панель"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:55
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Lid"
|
|
||||||
msgstr "Кришка"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:56
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Rear Glow"
|
|
||||||
msgstr "Заднє світіння"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:57 rog-control-center/ui/types/aura_types.slint:65
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Keyboard and Lightbar"
|
|
||||||
msgstr "Клавіатура та світлова панель"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:58
|
|
||||||
msgctxt "Aura power zone"
|
|
||||||
msgid "Ally"
|
|
||||||
msgstr "Ally"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:68
|
|
||||||
msgctxt "Aura brightness"
|
|
||||||
msgid "Off"
|
|
||||||
msgstr "Вимкнено"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:69
|
|
||||||
msgctxt "Aura brightness"
|
|
||||||
msgid "Low"
|
|
||||||
msgstr "Низька"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:70
|
|
||||||
msgctxt "Aura brightness"
|
|
||||||
msgid "Med"
|
|
||||||
msgstr "Середня"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:71
|
|
||||||
msgctxt "Aura brightness"
|
|
||||||
msgid "High"
|
|
||||||
msgstr "Висока"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:76 rog-control-center/ui/types/aura_types.slint:91
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Static"
|
|
||||||
msgstr "Статичний"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:77 rog-control-center/ui/types/aura_types.slint:92
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Breathe"
|
|
||||||
msgstr "Дихання"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:78 rog-control-center/ui/types/aura_types.slint:93
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Strobe"
|
|
||||||
msgstr "Стробоскоп"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:79
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Rainbow"
|
|
||||||
msgstr "Веселка"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:80
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Star"
|
|
||||||
msgstr "Зірка"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:81
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Rain"
|
|
||||||
msgstr "Дощ"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:82
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Highlight"
|
|
||||||
msgstr "Підсвічування"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:83
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Laser"
|
|
||||||
msgstr "Лазер"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:84
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Ripple"
|
|
||||||
msgstr "Хвиля"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:85
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Nothing"
|
|
||||||
msgstr "Нічого"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:86
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Pulse"
|
|
||||||
msgstr "Пульс"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:87
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Comet"
|
|
||||||
msgstr "Комета"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:88
|
|
||||||
msgctxt "Basic aura mode"
|
|
||||||
msgid "Flash"
|
|
||||||
msgstr "Спалах"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:100
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "None"
|
|
||||||
msgstr "Немає"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:101
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Key1"
|
|
||||||
msgstr "Клавіша 1"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:102
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Key2"
|
|
||||||
msgstr "Клавіша 2"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:103
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Key3"
|
|
||||||
msgstr "Клавіша 3"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:104
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Key4"
|
|
||||||
msgstr "Клавіша 4"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:105
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Logo"
|
|
||||||
msgstr "Логотип"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:106
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Lightbar Left"
|
|
||||||
msgstr "Світлова панель зліва"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:107
|
|
||||||
msgctxt "Aura zone"
|
|
||||||
msgid "Lightbar Right"
|
|
||||||
msgstr "Світлова панель справа"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:111
|
|
||||||
msgctxt "Aura direction"
|
|
||||||
msgid "Right"
|
|
||||||
msgstr "Вправо"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:112
|
|
||||||
msgctxt "Aura direction"
|
|
||||||
msgid "Left"
|
|
||||||
msgstr "Вліво"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:113
|
|
||||||
msgctxt "Aura direction"
|
|
||||||
msgid "Up"
|
|
||||||
msgstr "Вгору"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:114
|
|
||||||
msgctxt "Aura direction"
|
|
||||||
msgid "Down"
|
|
||||||
msgstr "Вниз"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:118
|
|
||||||
msgctxt "Aura speed"
|
|
||||||
msgid "Low"
|
|
||||||
msgstr "Низька"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:119
|
|
||||||
msgctxt "Aura speed"
|
|
||||||
msgid "Medium"
|
|
||||||
msgstr "Середня"
|
|
||||||
|
|
||||||
#: rog-control-center/ui/types/aura_types.slint:120
|
|
||||||
msgctxt "Aura speed"
|
|
||||||
msgid "High"
|
|
||||||
msgstr "Висока"
|
|
||||||
|
|
||||||
@@ -7,7 +7,6 @@ import { PageFans } from "pages/fans.slint";
|
|||||||
import { PageAnime, AnimePageData } from "pages/anime.slint";
|
import { PageAnime, AnimePageData } from "pages/anime.slint";
|
||||||
import { RogItem } from "widgets/common.slint";
|
import { RogItem } from "widgets/common.slint";
|
||||||
import { PageAura } from "pages/aura.slint";
|
import { PageAura } from "pages/aura.slint";
|
||||||
import { PageGPU, GPUPageData } from "pages/gpu.slint";
|
|
||||||
import { Node } from "widgets/graph.slint";
|
import { Node } from "widgets/graph.slint";
|
||||||
export { Node }
|
export { Node }
|
||||||
import { FanPageData, FanType, Profile } from "types/fan_types.slint";
|
import { FanPageData, FanType, Profile } from "types/fan_types.slint";
|
||||||
@@ -16,7 +15,7 @@ import { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones,
|
|||||||
export { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect }
|
export { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect }
|
||||||
import { PageAppSettings, AppSettingsPageData } from "pages/app_settings.slint";
|
import { PageAppSettings, AppSettingsPageData } from "pages/app_settings.slint";
|
||||||
|
|
||||||
export { AppSize, AttrMinMax, SystemPageData, AnimePageData, AppSettingsPageData, GPUPageData }
|
export { AppSize, AttrMinMax, SystemPageData, AnimePageData, AppSettingsPageData }
|
||||||
|
|
||||||
export component MainWindow inherits Window {
|
export component MainWindow inherits Window {
|
||||||
title: "ROG Control";
|
title: "ROG Control";
|
||||||
@@ -25,18 +24,8 @@ export component MainWindow inherits Window {
|
|||||||
default-font-size: 14px;
|
default-font-size: 14px;
|
||||||
default-font-weight: 400;
|
default-font-weight: 400;
|
||||||
icon: @image-url("../data/rog-control-center.png");
|
icon: @image-url("../data/rog-control-center.png");
|
||||||
in property <[bool]> sidebar_items_avilable: [
|
in property <[bool]> sidebar_items_avilable: [true, true, true, true, true, true];
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true, // GPU Configuration
|
|
||||||
true, // App Settings
|
|
||||||
true, // About
|
|
||||||
];
|
|
||||||
private property <bool> show_notif;
|
private property <bool> show_notif;
|
||||||
// TODO: change if TUF on the logo in the menu on the main page
|
|
||||||
in property <bool> is_tuf: false;
|
|
||||||
private property <bool> fade_cover;
|
private property <bool> fade_cover;
|
||||||
private property <bool> toast: false;
|
private property <bool> toast: false;
|
||||||
private property <string> toast_text: "I show when something is waiting";
|
private property <string> toast_text: "I show when something is waiting";
|
||||||
@@ -45,13 +34,6 @@ export component MainWindow inherits Window {
|
|||||||
toast = text != "";
|
toast = text != "";
|
||||||
toast_text = text;
|
toast_text = text;
|
||||||
}
|
}
|
||||||
callback clear_toast_if_matches(string);
|
|
||||||
clear_toast_if_matches(text) => {
|
|
||||||
if (toast && toast_text == text) {
|
|
||||||
toast = false;
|
|
||||||
toast_text = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback exit-app();
|
callback exit-app();
|
||||||
callback show_notification(bool);
|
callback show_notification(bool);
|
||||||
show_notification(yes) => {
|
show_notification(yes) => {
|
||||||
@@ -65,32 +47,37 @@ export component MainWindow inherits Window {
|
|||||||
}
|
}
|
||||||
min-height: AppSize.height;
|
min-height: AppSize.height;
|
||||||
min-width: AppSize.width;
|
min-width: AppSize.width;
|
||||||
background: Palette.alternate-background;
|
background: Colors.black;
|
||||||
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 0px;
|
|
||||||
side-bar := SideBar {
|
side-bar := SideBar {
|
||||||
|
title: @tr("ROG");
|
||||||
model: [
|
model: [
|
||||||
@tr("Menu1" => "System Control"),
|
@tr("Menu1" => "System Control"),
|
||||||
@tr("Menu2" => "Keyboard Aura"),
|
@tr("Menu2" => "Keyboard Aura"),
|
||||||
@tr("Menu3" => "AniMe Matrix"),
|
@tr("Menu3" => "AniMe Matrix"),
|
||||||
@tr("Menu4" => "Fan Curves"),
|
@tr("Menu4" => "Fan Curves"),
|
||||||
@tr("Menu5" => "GPU Configuration"),
|
@tr("Menu5" => "App Settings"),
|
||||||
@tr("Menu6" => "App Settings"),
|
@tr("Menu6" => "About"),
|
||||||
@tr("Menu7" => "About"),
|
|
||||||
];
|
];
|
||||||
available: root.sidebar_items_avilable;
|
available: root.sidebar_items_avilable;
|
||||||
is_tuf: root.is_tuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Rectangle {
|
||||||
height: 40px;
|
max-height: 40px;
|
||||||
width: side-bar.width;
|
width: side-bar.width;
|
||||||
text: @tr("Quit App");
|
background: Palette.control-background;
|
||||||
clicked() => {
|
Text {
|
||||||
root.exit-app();
|
vertical-alignment: center;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
text: @tr("Quit App");
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchArea {
|
||||||
|
clicked => {
|
||||||
|
root.exit-app();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,67 +89,26 @@ export component MainWindow inherits Window {
|
|||||||
height: root.height + 12px;
|
height: root.height + 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if(side-bar.current-item == 1):*/ aura := PageAura {
|
aura := PageAura {
|
||||||
width: root.width - side-bar.width;
|
width: root.width - side-bar.width;
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 1;
|
visible: side-bar.current-item == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side-bar.current-item == 2): PageAnime {
|
if(side-bar.current-item == 2): PageAnime {
|
||||||
width: root.width - side-bar.width;
|
width: root.width - side-bar.width;
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side-bar.current-item == 3): fans := PageFans {
|
fans := PageFans {
|
||||||
width: root.width - side-bar.width;
|
width: root.width - side-bar.width;
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 3;
|
visible: side-bar.current-item == 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side-bar.current-item == 4): PageGPU {
|
if(side-bar.current-item == 4): PageAppSettings {
|
||||||
width: root.width - side-bar.width;
|
width: root.width - side-bar.width;
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side-bar.current-item == 5): PageAppSettings {
|
if(side-bar.current-item == 5): PageAbout {
|
||||||
width: root.width - side-bar.width;
|
width: root.width - side-bar.width;
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(side-bar.current-item == 6): PageAbout {
|
|
||||||
width: root.width - side-bar.width;
|
|
||||||
height: root.height + 12px;
|
|
||||||
visible: side-bar.current-item == 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if toast: Rectangle {
|
|
||||||
x: 0px;
|
|
||||||
y: root.height - self.height;
|
|
||||||
width: root.width - side-bar.width;
|
|
||||||
height: 40px;
|
|
||||||
opacity: 1.0;
|
|
||||||
background: Palette.selection-background;
|
|
||||||
clip: true;
|
|
||||||
TouchArea {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
clicked => {
|
|
||||||
toast = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background: Palette.control-background;
|
|
||||||
Text {
|
|
||||||
color: Palette.control-foreground;
|
|
||||||
text: root.toast_text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,6 +133,31 @@ export component MainWindow inherits Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if toast: Rectangle {
|
||||||
|
x: 0px;
|
||||||
|
y: 0px;
|
||||||
|
width: root.width;
|
||||||
|
height: 32px;
|
||||||
|
opacity: 1.0;
|
||||||
|
background: Colors.grey;
|
||||||
|
TouchArea {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
clicked => {
|
||||||
|
toast = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: Palette.control-background;
|
||||||
|
Text {
|
||||||
|
color: Palette.control-foreground;
|
||||||
|
text: root.toast_text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// // TODO: or use Dialogue
|
// // TODO: or use Dialogue
|
||||||
if show_notif: Rectangle {
|
if show_notif: Rectangle {
|
||||||
@@ -219,6 +190,10 @@ export component MainWindow inherits Window {
|
|||||||
y: 0px;
|
y: 0px;
|
||||||
width: root.width;
|
width: root.width;
|
||||||
height: root.height;
|
height: root.height;
|
||||||
|
|
||||||
|
//padding only has effect on layout elements
|
||||||
|
//padding: 10px;
|
||||||
|
|
||||||
background: Palette.background;
|
background: Palette.background;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
|
|||||||
@@ -1,77 +1,66 @@
|
|||||||
import {
|
import { AboutSlint, VerticalBox, HorizontalBox } from "std-widgets.slint";
|
||||||
AboutSlint,
|
|
||||||
VerticalBox,
|
|
||||||
HorizontalBox,
|
|
||||||
ScrollView,
|
|
||||||
} from "std-widgets.slint";
|
|
||||||
|
|
||||||
export component PageAbout inherits VerticalLayout {
|
export component PageAbout inherits VerticalLayout {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
ScrollView {
|
Text {
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
text: "A UI for asusctl made with slint";
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
HorizontalBox {
|
HorizontalBox {
|
||||||
|
alignment: LayoutAlignment.center;
|
||||||
|
VerticalBox {
|
||||||
alignment: LayoutAlignment.center;
|
alignment: LayoutAlignment.center;
|
||||||
VerticalBox {
|
|
||||||
alignment: LayoutAlignment.center;
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
wrap: TextWrap.word-wrap;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
text: "You will require a kernel built with my work from here: https://github.com/flukejones/linux";
|
||||||
text: "ROG Control Center";
|
}
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
wrap: TextWrap.word-wrap;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
text: "\nA powerful graphical interface for managing ASUS ROG, TUF, and ProArt laptops on Linux. It acts as the official GUI for the asusctl toolset, allowing for seamless hardware tuning without the command line.";
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
}
|
text: "Todo:";
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
font-weight: 900;
|
text: "- [ ] Theme the widgets";
|
||||||
text: "Key Features:";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: " • Performance: Switch power profiles and customize fan curves.\n • Aura Sync: Control keyboard backlighting and LED effects.\n • Battery Health: Set charge limits to extend battery longevity.\n • Display: Toggle Panel Overdrive and refresh rates.\n • AniMe Matrix: Control AniMe Matrix displays.";
|
text: "- [ ] Add a cpu/gpu temp/fan speed info bar";
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
font-weight: 900;
|
text: "- [ ] Include fan speeds, temps in a bottom bar";
|
||||||
text: "Requirements:";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: " • This software requires kernel version 6.19.";
|
text: "- [ ] Slash control";
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
font-weight: 900;
|
text: "- [ ] Supergfx control";
|
||||||
text: "Work in progress:";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: " • Theme the widgets\n • Add a cpu/gpu temp/fan speed info bar\n • Include fan speeds, temps in a bottom bar\n • Slash control\n • Screenpad controls\n • ROG Ally specific settings";
|
text: "- [ ] Screenpad controls";
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
font-weight: 900;
|
text: "- [ ] ROG Ally specific settings";
|
||||||
text: "License:";
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: " This project is open-source software licensed under the Mozilla Public License 2.0 (MPL-2.0).";
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
font-weight: 900;
|
|
||||||
text: "Links:";
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: " Source Code: https://gitlab.com/asus-linux/asusctl\n Website: https://asus-linux.org/";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
text: "Work in progress";
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,12 @@ export component PageAnime inherits Rectangle {
|
|||||||
property <bool> show_display_advanced: false;
|
property <bool> show_display_advanced: false;
|
||||||
property <bool> show_builtin_advanced: false;
|
property <bool> show_builtin_advanced: false;
|
||||||
clip: true;
|
clip: true;
|
||||||
|
// TODO: slow with border-radius
|
||||||
VerticalLayout {
|
//padding only has effect on layout elements
|
||||||
|
//padding: 8px;
|
||||||
|
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
|
||||||
|
// TODO: border-radius: 8px;
|
||||||
|
VerticalLayout {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
@@ -128,9 +132,8 @@ export component PageAnime inherits Rectangle {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background: Palette.background;
|
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 4px;
|
padding: 50px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
GroupBox {
|
GroupBox {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
@@ -138,7 +141,7 @@ export component PageAnime inherits Rectangle {
|
|||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
text: @tr("Set which builtin animations are played");
|
text: @tr("Set which builtin animations are played");
|
||||||
@@ -190,8 +193,8 @@ export component PageAnime inherits Rectangle {
|
|||||||
Button {
|
Button {
|
||||||
x: root.width - self.width - 6px;
|
x: root.width - self.width - 6px;
|
||||||
y: 6px;
|
y: 6px;
|
||||||
text: "✕";
|
text: "X";
|
||||||
height: 36px;
|
height: 40px;
|
||||||
clicked => {
|
clicked => {
|
||||||
root.show_builtin_advanced = false;
|
root.show_builtin_advanced = false;
|
||||||
root.show_fade_cover = false;
|
root.show_fade_cover = false;
|
||||||
@@ -203,9 +206,8 @@ export component PageAnime inherits Rectangle {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background: Palette.background;
|
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 4px;
|
padding: 50px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
GroupBox {
|
GroupBox {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
@@ -213,7 +215,7 @@ export component PageAnime inherits Rectangle {
|
|||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
text: @tr("Advanced Display Settings");
|
text: @tr("Advanced Display Settings");
|
||||||
@@ -252,8 +254,8 @@ export component PageAnime inherits Rectangle {
|
|||||||
Button {
|
Button {
|
||||||
x: root.width - self.width - 6px;
|
x: root.width - self.width - 6px;
|
||||||
y: 6px;
|
y: 6px;
|
||||||
text: "✕";
|
text: "X";
|
||||||
height: 36px;
|
height: 40px;
|
||||||
clicked => {
|
clicked => {
|
||||||
root.show_display_advanced = false;
|
root.show_display_advanced = false;
|
||||||
root.show_fade_cover = false;
|
root.show_fade_cover = false;
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ export global AppSettingsPageData {
|
|||||||
export component PageAppSettings inherits VerticalLayout {
|
export component PageAppSettings inherits VerticalLayout {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
clip: true;
|
clip: true;
|
||||||
|
// TODO: slow with border-radius
|
||||||
|
//padding only has effect on layout elements
|
||||||
|
//padding: 8px;
|
||||||
|
|
||||||
|
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
|
||||||
|
// TODO: border-radius: 8px;
|
||||||
mainview := VerticalLayout {
|
mainview := VerticalLayout {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
@@ -52,8 +57,7 @@ export component PageAppSettings inherits VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
color: Palette.accent-background;
|
text: "WIP: some features like notifications are not complete";
|
||||||
text: " WIP: some features like notifications are not complete";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export component PageAura inherits Rectangle {
|
|||||||
c2.final_colour = AuraPageData.led_mode_data.colour2;
|
c2.final_colour = AuraPageData.led_mode_data.colour2;
|
||||||
c2.external_colour_change();
|
c2.external_colour_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -42,14 +41,10 @@ export component PageAura inherits Rectangle {
|
|||||||
current_value: AuraPageData.available_mode_names[self.current-index];
|
current_value: AuraPageData.available_mode_names[self.current-index];
|
||||||
model <=> AuraPageData.available_mode_names;
|
model <=> AuraPageData.available_mode_names;
|
||||||
selected => {
|
selected => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.mode = AuraPageData.led_mode;
|
||||||
mode: AuraPageData.supported_basic_modes[self.current-index],
|
AuraPageData.led_mode_data.mode = AuraPageData.current_available_mode;
|
||||||
zone: AuraPageData.led_mode_data.zone,
|
self.current_value = AuraPageData.available_mode_names[self.current-index];
|
||||||
colour1: AuraPageData.led_mode_data.colour1,
|
AuraPageData.cb_led_mode(AuraPageData.current_available_mode);
|
||||||
colour2: AuraPageData.led_mode_data.colour2,
|
|
||||||
speed: AuraPageData.led_mode_data.speed,
|
|
||||||
direction: AuraPageData.led_mode_data.direction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +53,6 @@ export component PageAura inherits Rectangle {
|
|||||||
min-height: 220px;
|
min-height: 220px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
padding-top: 5px;
|
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text {
|
Text {
|
||||||
@@ -66,44 +60,47 @@ export component PageAura inherits Rectangle {
|
|||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalBox {
|
HorizontalBox {
|
||||||
c1 := ColourSlider {
|
c1 := ColourSlider {
|
||||||
enabled: AuraPageData.colour1_enabled;
|
enabled: AuraPageData.led_mode == 0 || AuraPageData.led_mode == 1 || AuraPageData.led_mode == 4 || AuraPageData.led_mode == 6 || AuraPageData.led_mode == 7 || AuraPageData.led_mode == 8 || AuraPageData.led_mode == 10 || AuraPageData.led_mode == 11 || AuraPageData.led_mode == 12;
|
||||||
final_colour <=> AuraPageData.color1;
|
final_colour <=> AuraPageData.color1;
|
||||||
colourbox <=> AuraPageData.colorbox1;
|
colourbox <=> AuraPageData.colorbox1;
|
||||||
set_hex_from_colour(c) => { return AuraPageData.cb_hex_from_colour(c); }
|
set_hex_from_colour(c1) => {
|
||||||
hex_to_colour(s) => { return AuraPageData.cb_hex_to_colour(s); }
|
return AuraPageData.cb_hex_from_colour(c1);
|
||||||
|
}
|
||||||
|
hex_to_colour(s) => {
|
||||||
|
return AuraPageData.cb_hex_to_colour(s);
|
||||||
|
}
|
||||||
released => {
|
released => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.colour1 = AuraPageData.color1;
|
||||||
mode: AuraPageData.led_mode_data.mode,
|
AuraPageData.cb_led_mode_data(AuraPageData.led_mode_data);
|
||||||
zone: AuraPageData.led_mode_data.zone,
|
|
||||||
colour1: AuraPageData.color1,
|
|
||||||
colour2: AuraPageData.led_mode_data.colour2,
|
|
||||||
speed: AuraPageData.led_mode_data.speed,
|
|
||||||
direction: AuraPageData.led_mode_data.direction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text { text: @tr("Colour 2"); vertical-alignment: TextVerticalAlignment.center; horizontal-alignment: TextHorizontalAlignment.center; }
|
Text {
|
||||||
|
text: @tr("Colour 2");
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
}
|
||||||
|
|
||||||
HorizontalBox {
|
HorizontalBox {
|
||||||
c2 := ColourSlider {
|
c2 := ColourSlider {
|
||||||
enabled: AuraPageData.colour2_enabled;
|
enabled: AuraPageData.led_mode == 1 || AuraPageData.led_mode == 4;
|
||||||
final_colour <=> AuraPageData.color2;
|
final_colour <=> AuraPageData.color2;
|
||||||
colourbox <=> AuraPageData.colorbox2;
|
colourbox <=> AuraPageData.colorbox2;
|
||||||
set_hex_from_colour(c) => { return AuraPageData.cb_hex_from_colour(c); }
|
set_hex_from_colour(c1) => {
|
||||||
hex_to_colour(s) => { return AuraPageData.cb_hex_to_colour(s); }
|
return AuraPageData.cb_hex_from_colour(c1);
|
||||||
|
}
|
||||||
|
hex_to_colour(s) => {
|
||||||
|
return AuraPageData.cb_hex_to_colour(s);
|
||||||
|
}
|
||||||
released => {
|
released => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.colour2 = AuraPageData.color2;
|
||||||
mode: AuraPageData.led_mode_data.mode,
|
AuraPageData.cb_led_mode_data(AuraPageData.led_mode_data);
|
||||||
zone: AuraPageData.led_mode_data.zone,
|
|
||||||
colour1: AuraPageData.led_mode_data.colour1,
|
|
||||||
colour2: AuraPageData.color2,
|
|
||||||
speed: AuraPageData.led_mode_data.speed,
|
|
||||||
direction: AuraPageData.led_mode_data.direction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,64 +113,70 @@ export component PageAura inherits Rectangle {
|
|||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
max-height: 90px;
|
max-height: 90px;
|
||||||
RogItem {
|
RogItem {
|
||||||
|
//padding only has effect on layout elements
|
||||||
|
//padding: 0px;
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text { text: @tr("Zone"); vertical-alignment: TextVerticalAlignment.center; horizontal-alignment: TextHorizontalAlignment.center; }
|
Text {
|
||||||
|
text: @tr("Zone");
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
}
|
||||||
|
|
||||||
ComboBox {
|
ComboBox {
|
||||||
enabled: false;
|
// enabled: AuraPageData.led_mode == ;
|
||||||
|
enabled: false;
|
||||||
current_index <=> AuraPageData.zone;
|
current_index <=> AuraPageData.zone;
|
||||||
current_value: AuraPageData.zone_names[self.current-index];
|
current_value: AuraPageData.zone_names[self.current-index];
|
||||||
model <=> AuraPageData.zone_names;
|
model <=> AuraPageData.zone_names;
|
||||||
selected => {
|
selected => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.zone = self.current-index;
|
||||||
mode: AuraPageData.led_mode_data.mode,
|
AuraPageData.cb_led_mode_data(AuraPageData.led_mode_data);
|
||||||
zone: self.current-index,
|
|
||||||
colour1: AuraPageData.led_mode_data.colour1,
|
|
||||||
colour2: AuraPageData.led_mode_data.colour2,
|
|
||||||
speed: AuraPageData.led_mode_data.speed,
|
|
||||||
direction: AuraPageData.led_mode_data.direction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RogItem {
|
RogItem {
|
||||||
|
//padding only has effect on layout elements
|
||||||
|
//padding: 0px;
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text { text: @tr("Direction"); vertical-alignment: TextVerticalAlignment.center; horizontal-alignment: TextHorizontalAlignment.center; }
|
Text {
|
||||||
|
text: @tr("Direction");
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
}
|
||||||
|
|
||||||
ComboBox {
|
ComboBox {
|
||||||
enabled: AuraPageData.direction_enabled;
|
enabled: AuraPageData.led_mode == 3;
|
||||||
current_index <=> AuraPageData.direction;
|
current_index <=> AuraPageData.direction;
|
||||||
current_value: AuraPageData.direction_names[self.current-index];
|
current_value: AuraPageData.direction_names[self.current-index];
|
||||||
model <=> AuraPageData.direction_names;
|
model <=> AuraPageData.direction_names;
|
||||||
selected => {
|
selected => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.direction = self.current-index;
|
||||||
mode: AuraPageData.led_mode_data.mode,
|
AuraPageData.cb_led_mode_data(AuraPageData.led_mode_data);
|
||||||
zone: AuraPageData.led_mode_data.zone,
|
|
||||||
colour1: AuraPageData.led_mode_data.colour1,
|
|
||||||
colour2: AuraPageData.led_mode_data.colour2,
|
|
||||||
speed: AuraPageData.led_mode_data.speed,
|
|
||||||
direction: self.current-index,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RogItem {
|
RogItem {
|
||||||
|
//padding only has effect on layout elements
|
||||||
|
//padding: 0px;
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text { text: @tr("Speed"); vertical-alignment: TextVerticalAlignment.center; horizontal-alignment: TextHorizontalAlignment.center; }
|
Text {
|
||||||
|
text: @tr("Speed");
|
||||||
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
|
}
|
||||||
|
|
||||||
ComboBox {
|
ComboBox {
|
||||||
enabled: AuraPageData.speed_enabled;
|
enabled: AuraPageData.led_mode == 1 || AuraPageData.led_mode == 2 || AuraPageData.led_mode == 3 || AuraPageData.led_mode == 4 || AuraPageData.led_mode == 5 || AuraPageData.led_mode == 6 || AuraPageData.led_mode == 7 || AuraPageData.led_mode == 8;
|
||||||
current_index <=> AuraPageData.speed;
|
current_index <=> AuraPageData.speed;
|
||||||
current_value: AuraPageData.speed_names[self.current-index];
|
current_value: AuraPageData.speed_names[self.current-index];
|
||||||
model <=> AuraPageData.speed_names;
|
model <=> AuraPageData.speed_names;
|
||||||
selected => {
|
selected => {
|
||||||
AuraPageData.apply_effect({
|
AuraPageData.led_mode_data.speed = self.current-index;
|
||||||
mode: AuraPageData.led_mode_data.mode,
|
AuraPageData.cb_led_mode_data(AuraPageData.led_mode_data);
|
||||||
zone: AuraPageData.led_mode_data.zone,
|
|
||||||
colour1: AuraPageData.led_mode_data.colour1,
|
|
||||||
colour2: AuraPageData.led_mode_data.colour2,
|
|
||||||
speed: self.current-index,
|
|
||||||
direction: AuraPageData.led_mode_data.direction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +205,6 @@ export component PageAura inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if root.show_aura_power && AuraPageData.device_type == AuraDevType.New: Rectangle {
|
if root.show_aura_power && AuraPageData.device_type == AuraDevType.New: Rectangle {
|
||||||
background: Palette.background;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -238,54 +240,21 @@ export component PageAura inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TUF devices: show the same configurable power groups as `New`, since
|
Button {
|
||||||
// `setup_aura` fills `AuraPageData.supported_power_zones` and `led_power`
|
x: root.width - self.width - 6px;
|
||||||
// appropriately for TUF devices. This ensures the Power Settings panel
|
y: 6px;
|
||||||
// reflects what the firmware reports for TUF models.
|
text: "X";
|
||||||
if root.show_aura_power && AuraPageData.device_type == AuraDevType.Tuf: Rectangle {
|
height: 40px;
|
||||||
background: Palette.background;
|
clicked => {
|
||||||
width: 100%;
|
root.show_aura_power = false;
|
||||||
height: 100%;
|
root.show_fade_cover = false;
|
||||||
opacity: 1;
|
|
||||||
ScrollView {
|
|
||||||
VerticalLayout {
|
|
||||||
padding: 30px;
|
|
||||||
padding-top: 10px;
|
|
||||||
spacing: 10px;
|
|
||||||
alignment: LayoutAlignment.start;
|
|
||||||
|
|
||||||
for state[idx] in AuraPageData.led_power.states: tuf_zone := AuraPowerGroup {
|
|
||||||
group-title: AuraPageData.power_zone_names[state.zone_name_idx];
|
|
||||||
boot_checked: state.boot;
|
|
||||||
boot_toggled => {
|
|
||||||
AuraPageData.led_power.states[idx].boot = tuf_zone.boot_checked;
|
|
||||||
AuraPageData.cb_led_power(AuraPageData.led_power);
|
|
||||||
}
|
|
||||||
awake_checked: state.awake;
|
|
||||||
awake_toggled => {
|
|
||||||
AuraPageData.led_power.states[idx].awake = tuf_zone.awake_checked;
|
|
||||||
AuraPageData.cb_led_power(AuraPageData.led_power);
|
|
||||||
}
|
|
||||||
sleep_checked: state.sleep;
|
|
||||||
sleep_toggled => {
|
|
||||||
AuraPageData.led_power.states[idx].sleep = tuf_zone.sleep_checked;
|
|
||||||
AuraPageData.cb_led_power(AuraPageData.led_power);
|
|
||||||
}
|
|
||||||
shutdown_checked: state.shutdown;
|
|
||||||
shutdown_toggled => {
|
|
||||||
AuraPageData.led_power.states[idx].shutdown = tuf_zone.shutdown_checked;
|
|
||||||
AuraPageData.cb_led_power(AuraPageData.led_power);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if root.show_aura_power && AuraPageData.device_type == AuraDevType.Old: Rectangle {
|
if root.show_aura_power && AuraPageData.device_type == AuraDevType.Old: Rectangle {
|
||||||
background: Palette.background;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -324,17 +293,17 @@ export component PageAura inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.show_aura_power: Button {
|
Button {
|
||||||
x: root.width - self.width - 6px;
|
x: root.width - self.width - 6px;
|
||||||
y: 6px;
|
y: 6px;
|
||||||
text: "✕";
|
text: "X";
|
||||||
height: 36px;
|
height: 40px;
|
||||||
clicked => {
|
clicked => {
|
||||||
root.show_aura_power = false;
|
root.show_aura_power = false;
|
||||||
root.show_fade_cover = false;
|
root.show_fade_cover = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,28 +16,20 @@ component FanTab inherits Rectangle {
|
|||||||
in-out property <[Node]> nodes;
|
in-out property <[Node]> nodes;
|
||||||
|
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 5px;
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
if root.tab_enabled: Graph {
|
if root.tab_enabled: Graph {
|
||||||
nodes <=> root.nodes;
|
nodes <=> root.nodes;
|
||||||
}
|
}
|
||||||
if !root.tab_enabled: Rectangle {
|
if !root.tab_enabled: Rectangle {
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 24px;
|
||||||
text: @tr("This fan is not avilable on this machine");
|
text: @tr("This fan is not avilable on this machine");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
background: Palette.border;
|
|
||||||
height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
alignment: LayoutAlignment.end;
|
alignment: LayoutAlignment.end;
|
||||||
spacing: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
CheckBox {
|
CheckBox {
|
||||||
text: @tr("Enabled");
|
text: @tr("Enabled");
|
||||||
checked <=> root.enabled;
|
checked <=> root.enabled;
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
import { Palette, TabWidget, Button, CheckBox, ScrollView } from "std-widgets.slint";
|
|
||||||
import { Graph, Node } from "../widgets/graph.slint";
|
|
||||||
import { SystemToggle, SystemDropdown } from "../widgets/common.slint";
|
|
||||||
import { Profile, FanType, FanPageData } from "../types/fan_types.slint";
|
|
||||||
|
|
||||||
export global GPUPageData {
|
|
||||||
// GPU mode and device state
|
|
||||||
in-out property <int> gpu_mux_mode: 1; // 0 = Ultra/Discreet, 1 = Integrated/Optimus
|
|
||||||
in-out property <int> dgpu_disabled: 0; // 1 == dGPU disabled
|
|
||||||
in-out property <int> egpu_enabled: 0; // 1 == eGPU (XGMobile) enabled
|
|
||||||
in-out property <[string]> gpu_modes_choises: [@tr("Integrated"), @tr("Hybrid")];
|
|
||||||
in-out property <bool> gpu_mux_available: false;
|
|
||||||
callback cb_set_gpu_mode(int);
|
|
||||||
}
|
|
||||||
|
|
||||||
export component PageGPU inherits Rectangle {
|
|
||||||
clip: true;
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
VerticalLayout {
|
|
||||||
padding: 12px;
|
|
||||||
spacing: 8px;
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
background: Palette.alternate-background;
|
|
||||||
border-color: Palette.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 2px;
|
|
||||||
height: 36px;
|
|
||||||
Text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: Palette.control-foreground;
|
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
|
||||||
text: @tr("Coming Soon: GPU Configuration");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Rectangle {
|
|
||||||
background: Palette.alternate-background;
|
|
||||||
border-color: Palette.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 2px;
|
|
||||||
height: 36px;
|
|
||||||
Text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: Palette.control-foreground;
|
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
|
||||||
text: @tr("Internal/Discrete GPU");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalLayout {
|
|
||||||
padding-right: 10px;
|
|
||||||
padding-left: 10px;
|
|
||||||
alignment: LayoutAlignment.space-between;
|
|
||||||
Rectangle {
|
|
||||||
height: 32px;
|
|
||||||
Text {
|
|
||||||
font-size: 16px;
|
|
||||||
text: @tr("Note: Changes take effect after a reboot. The dropdown always shows the current mode.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalLayout {
|
|
||||||
SystemDropdown {
|
|
||||||
text: @tr("GPU mode");
|
|
||||||
model <=> GPUPageData.gpu_modes_choises;
|
|
||||||
current_index <=> GPUPageData.gpu_mux_mode;
|
|
||||||
current_value: GPUPageData.gpu_modes_choises[GPUPageData.gpu_mux_mode];
|
|
||||||
selected => {
|
|
||||||
GPUPageData.cb_set_gpu_mode(GPUPageData.gpu_mux_mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -144,20 +144,21 @@ 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 only has effect on layout elements
|
||||||
|
//padding: 8px;
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
padding: 12px;
|
padding: 10px;
|
||||||
spacing: 8px;
|
spacing: 10px;
|
||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
Rectangle {
|
Rectangle {
|
||||||
background: Palette.alternate-background;
|
background: Palette.alternate-background;
|
||||||
border-color: Palette.border;
|
border-color: Palette.accent-background;
|
||||||
border-width: 1px;
|
border-width: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 10px;
|
||||||
height: 36px;
|
height: 40px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
text: @tr("Power settings");
|
text: @tr("Power settings");
|
||||||
@@ -203,11 +204,11 @@ export component PageSystem inherits Rectangle {
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
width: 40%;
|
width: 38%;
|
||||||
alignment: LayoutAlignment.space-between;
|
alignment: LayoutAlignment.space-between;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
text: @tr("Screenpad brightness");
|
text: @tr("Screenpad brightness");
|
||||||
@@ -231,7 +232,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
padding-left: 14px;
|
padding-left: 10px;
|
||||||
alignment: LayoutAlignment.stretch;
|
alignment: LayoutAlignment.stretch;
|
||||||
Switch {
|
Switch {
|
||||||
text: @tr("Sync with primary");
|
text: @tr("Sync with primary");
|
||||||
@@ -246,12 +247,12 @@ export component PageSystem inherits Rectangle {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
background: Palette.alternate-background;
|
background: Palette.alternate-background;
|
||||||
border-color: Palette.border;
|
border-color: Palette.accent-background;
|
||||||
border-width: 1px;
|
border-width: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 10px;
|
||||||
height: 36px;
|
height: 40px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
text: @tr("Armoury settings");
|
text: @tr("Armoury settings");
|
||||||
@@ -259,21 +260,19 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !SystemPageData.asus_armoury_loaded: Rectangle {
|
if !SystemPageData.asus_armoury_loaded: Rectangle {
|
||||||
background: maroon;
|
border-width: 3px;
|
||||||
// background: darkred;
|
border-color: red;
|
||||||
max-height: 30px;
|
max-height: 30px;
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
Text {
|
Text {
|
||||||
text: @tr("no_asus_armoury_driver_1" => "The asus-armoury driver is not loaded");
|
text: @tr("no_asus_armoury_driver_1" => "The asus-armoury driver is not loaded");
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: white;
|
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: @tr("no_asus_armoury_driver_2" => "For advanced features you will require a kernel with this driver added.");
|
text: @tr("no_asus_armoury_driver_2" => "For advanced features you will require a kernel with this driver added.");
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: white;
|
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,22 +515,20 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if root.show_throttle_advanced: Rectangle {
|
if root.show_throttle_advanced: Rectangle {
|
||||||
background: Palette.background;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
alignment: start;
|
padding: 50px;
|
||||||
padding: 5px;
|
padding-top: 5px;
|
||||||
padding-top: 15px;
|
padding-bottom: 100px;
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
GroupBox {
|
GroupBox {
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
alignment: start;
|
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
text: @tr("Energy Performance Preference linked to Throttle Policy");
|
text: @tr("Energy Performance Preference linked to Throttle Policy");
|
||||||
@@ -566,7 +563,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemDropdown {
|
SystemDropdown {
|
||||||
text: @tr("EPP for ") + SystemPageData.platform_profile_choices[2] + @tr(" Policy");
|
text: @tr("EPP for Quiet Policy");
|
||||||
current_index <=> SystemPageData.profile_quiet_epp;
|
current_index <=> SystemPageData.profile_quiet_epp;
|
||||||
current_value: SystemPageData.energy_performance_choices[SystemPageData.profile_quiet_epp];
|
current_value: SystemPageData.energy_performance_choices[SystemPageData.profile_quiet_epp];
|
||||||
model <=> SystemPageData.energy_performance_choices;
|
model <=> SystemPageData.energy_performance_choices;
|
||||||
@@ -579,10 +576,9 @@ export component PageSystem inherits Rectangle {
|
|||||||
|
|
||||||
GroupBox {
|
GroupBox {
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
alignment: start;
|
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
text: @tr("Throttle Policy for power state");
|
text: @tr("Throttle Policy for power state");
|
||||||
@@ -637,8 +633,8 @@ export component PageSystem inherits Rectangle {
|
|||||||
Button {
|
Button {
|
||||||
x: root.width - self.width - 6px;
|
x: root.width - self.width - 6px;
|
||||||
y: 6px;
|
y: 6px;
|
||||||
text: "✕";
|
text: "X";
|
||||||
height: 34px;
|
height: 40px;
|
||||||
clicked => {
|
clicked => {
|
||||||
root.show_throttle_advanced = false;
|
root.show_throttle_advanced = false;
|
||||||
root.show_fade_cover = false;
|
root.show_fade_cover = false;
|
||||||
|
|||||||
@@ -46,10 +46,8 @@ export struct LaptopAuraPower {
|
|||||||
states: [AuraPowerState],
|
states: [AuraPowerState],
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modes with colour1: Static,Breathe,Star,Rain,Highlight,Laser,Ripple,Pulse,Comet,Flash (excl. Strobe,Rainbow,Nothing)
|
|
||||||
// Modes with colour2: Breathe, Star only.
|
|
||||||
// Speed: Breathe,Strobe,Rainbow,Star,Rain,Highlight,Laser,Ripple. Direction: Rainbow only.
|
|
||||||
export global AuraPageData {
|
export global AuraPageData {
|
||||||
|
// The ordering must match the rog-aura crate
|
||||||
in-out property <[string]> power_zone_names: [
|
in-out property <[string]> power_zone_names: [
|
||||||
@tr("Aura power zone" => "Logo"),
|
@tr("Aura power zone" => "Logo"),
|
||||||
@tr("Aura power zone" => "Keyboard"),
|
@tr("Aura power zone" => "Keyboard"),
|
||||||
@@ -89,9 +87,15 @@ export global AuraPageData {
|
|||||||
@tr("Basic aura mode" => "Comet"),
|
@tr("Basic aura mode" => "Comet"),
|
||||||
@tr("Basic aura mode" => "Flash"),
|
@tr("Basic aura mode" => "Flash"),
|
||||||
];
|
];
|
||||||
in-out property <[string]> available_mode_names: [ @tr("Basic aura mode" => "Static"), @tr("Basic aura mode" => "Breathe"), @tr("Basic aura mode" => "Strobe") ];
|
in-out property <[string]> available_mode_names: [
|
||||||
|
@tr("Basic aura mode" => "Static"),
|
||||||
|
@tr("Basic aura mode" => "Breathe"),
|
||||||
|
@tr("Basic aura mode" => "Strobe"),
|
||||||
|
];
|
||||||
in-out property <int> current_available_mode: 0;
|
in-out property <int> current_available_mode: 0;
|
||||||
in-out property <[int]> supported_basic_modes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12];
|
in-out property <[int]> supported_basic_modes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12];
|
||||||
|
in-out property <int> led_mode;
|
||||||
|
callback cb_led_mode(int);
|
||||||
in-out property <[string]> zone_names: [
|
in-out property <[string]> zone_names: [
|
||||||
@tr("Aura zone" => "None"),
|
@tr("Aura zone" => "None"),
|
||||||
@tr("Aura zone" => "Key1"),
|
@tr("Aura zone" => "Key1"),
|
||||||
@@ -102,57 +106,51 @@ export global AuraPageData {
|
|||||||
@tr("Aura zone" => "Lightbar Left"),
|
@tr("Aura zone" => "Lightbar Left"),
|
||||||
@tr("Aura zone" => "Lightbar Right"),
|
@tr("Aura zone" => "Lightbar Right"),
|
||||||
];
|
];
|
||||||
|
in-out property <int> zone;
|
||||||
in-out property <[string]> direction_names: [
|
in-out property <[string]> direction_names: [
|
||||||
@tr("Aura direction" => "Right"),
|
@tr("Aura direction" => "Right"),
|
||||||
@tr("Aura direction" => "Left"),
|
@tr("Aura direction" => "Left"),
|
||||||
@tr("Aura direction" => "Up"),
|
@tr("Aura direction" => "Up"),
|
||||||
@tr("Aura direction" => "Down"),
|
@tr("Aura direction" => "Down"),
|
||||||
];
|
];
|
||||||
|
in-out property <int> direction;
|
||||||
in-out property <[string]> speed_names: [
|
in-out property <[string]> speed_names: [
|
||||||
@tr("Aura speed" => "Low"),
|
@tr("Aura speed" => "Low"),
|
||||||
@tr("Aura speed" => "Medium"),
|
@tr("Aura speed" => "Medium"),
|
||||||
@tr("Aura speed" => "High"),
|
@tr("Aura speed" => "High"),
|
||||||
];
|
];
|
||||||
|
in-out property <int> speed;
|
||||||
in-out property <AuraEffect> led_mode_data: {
|
in-out property <AuraEffect> led_mode_data: {
|
||||||
mode: 0,
|
mode: 0,
|
||||||
zone: 0,
|
zone: 0,
|
||||||
colour1: Colors.aquamarine,
|
colour1: Colors.aquamarine,
|
||||||
|
colourbox1: Colors.aquamarine,
|
||||||
colour2: Colors.hotpink,
|
colour2: Colors.hotpink,
|
||||||
|
colourbox2: Colors.hotpink,
|
||||||
speed: 0,
|
speed: 0,
|
||||||
direction: 0,
|
direction: 0,
|
||||||
};
|
};
|
||||||
|
callback cb_led_mode_data(AuraEffect);
|
||||||
in-out property <color> color1;
|
in-out property <color> color1;
|
||||||
in-out property <brush> colorbox1;
|
in-out property <brush> colorbox1;
|
||||||
in-out property <color> color2;
|
in-out property <color> color2;
|
||||||
in-out property <brush> colorbox2;
|
in-out property <brush> colorbox2;
|
||||||
|
|
||||||
out property <bool> colour1_enabled: led_mode_data.mode == 0 || led_mode_data.mode == 1 || led_mode_data.mode == 4 || led_mode_data.mode == 6 || led_mode_data.mode == 7 || led_mode_data.mode == 8 || led_mode_data.mode == 10 || led_mode_data.mode == 11 || led_mode_data.mode == 12;
|
|
||||||
out property <bool> colour2_enabled: led_mode_data.mode == 1 || led_mode_data.mode == 4;
|
|
||||||
out property <bool> speed_enabled: led_mode_data.mode == 1 || led_mode_data.mode == 2 || led_mode_data.mode == 3 || led_mode_data.mode == 4 || led_mode_data.mode == 5 || led_mode_data.mode == 6 || led_mode_data.mode == 7 || led_mode_data.mode == 8;
|
|
||||||
out property <bool> direction_enabled: led_mode_data.mode == 3;
|
|
||||||
|
|
||||||
callback apply_led_mode_data();
|
|
||||||
callback apply_effect(AuraEffect);
|
|
||||||
apply_effect(e) => { led_mode_data = e; apply_led_mode_data(); }
|
|
||||||
in-out property <int> zone;
|
|
||||||
in-out property <int> speed;
|
|
||||||
in-out property <int> direction;
|
|
||||||
|
|
||||||
callback update_led_mode_data(AuraEffect);
|
callback update_led_mode_data(AuraEffect);
|
||||||
update_led_mode_data(d) => {
|
update_led_mode_data(data) => {
|
||||||
led_mode_data = d;
|
led_mode_data = data;
|
||||||
zone = d.zone;
|
current_available_mode = data.mode;
|
||||||
speed = d.speed;
|
zone = data.zone;
|
||||||
direction = d.direction;
|
speed = data.speed;
|
||||||
color1 = d.colour1;
|
direction = data.direction;
|
||||||
color2 = d.colour2;
|
color1 = data.colour1;
|
||||||
colorbox1 = d.colour1;
|
color2 = data.colour2;
|
||||||
colorbox2 = d.colour2;
|
colorbox1 = data.colour1;
|
||||||
|
colorbox2 = data.colour2;
|
||||||
}
|
}
|
||||||
callback cb_hex_from_colour(color) -> string;
|
callback cb_hex_from_colour(color) -> string;
|
||||||
callback cb_hex_to_colour(string) -> color;
|
callback cb_hex_to_colour(string) -> color;
|
||||||
in-out property <AuraDevType> device_type: AuraDevType.Old;
|
in-out property <AuraDevType> device_type: AuraDevType.Old;
|
||||||
|
// List of indexes to power_zone_names. Must correspond to rog-aura crate
|
||||||
in-out property <[PowerZones]> supported_power_zones: [
|
in-out property <[PowerZones]> supported_power_zones: [
|
||||||
PowerZones.Keyboard,
|
PowerZones.Keyboard,
|
||||||
PowerZones.Lightbar,
|
PowerZones.Lightbar,
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { PowerZones } from "../types/aura_types.slint";
|
|||||||
|
|
||||||
export component AuraPowerGroup inherits Rectangle {
|
export component AuraPowerGroup inherits Rectangle {
|
||||||
min-width: row.min-width;
|
min-width: row.min-width;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: Palette.alternate-background;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
in-out property <string> group-title;
|
in-out property <string> group-title;
|
||||||
in-out property <bool> boot_checked;
|
in-out property <bool> boot_checked;
|
||||||
@@ -14,7 +16,6 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
callback awake_toggled(bool);
|
callback awake_toggled(bool);
|
||||||
callback sleep_toggled(bool);
|
callback sleep_toggled(bool);
|
||||||
callback shutdown_toggled(bool);
|
callback shutdown_toggled(bool);
|
||||||
|
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
Text {
|
Text {
|
||||||
@@ -27,7 +28,7 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
row := HorizontalBox {
|
row := HorizontalBox {
|
||||||
alignment: LayoutAlignment.center;
|
alignment: LayoutAlignment.center;
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Boot");
|
text: @tr("Boot");
|
||||||
checked <=> root.boot_checked;
|
checked <=> root.boot_checked;
|
||||||
@@ -37,7 +38,7 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Awake");
|
text: @tr("Awake");
|
||||||
checked <=> root.awake_checked;
|
checked <=> root.awake_checked;
|
||||||
@@ -47,7 +48,7 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Sleep");
|
text: @tr("Sleep");
|
||||||
checked <=> root.sleep_checked;
|
checked <=> root.sleep_checked;
|
||||||
@@ -57,7 +58,7 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Shutdown");
|
text: @tr("Shutdown");
|
||||||
checked <=> root.shutdown_checked;
|
checked <=> root.shutdown_checked;
|
||||||
@@ -71,6 +72,8 @@ export component AuraPowerGroup inherits Rectangle {
|
|||||||
|
|
||||||
export component AuraPowerGroupOld inherits Rectangle {
|
export component AuraPowerGroupOld inherits Rectangle {
|
||||||
min-width: row.min-width;
|
min-width: row.min-width;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: Palette.alternate-background;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
in-out property <int> current_zone;
|
in-out property <int> current_zone;
|
||||||
in-out property <[int]> zones;
|
in-out property <[int]> zones;
|
||||||
@@ -83,7 +86,6 @@ export component AuraPowerGroupOld inherits Rectangle {
|
|||||||
callback awake_toggled(bool);
|
callback awake_toggled(bool);
|
||||||
callback sleep_toggled(bool);
|
callback sleep_toggled(bool);
|
||||||
callback selected_zone(int);
|
callback selected_zone(int);
|
||||||
|
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
spacing: 10px;
|
spacing: 10px;
|
||||||
Text {
|
Text {
|
||||||
@@ -107,7 +109,7 @@ export component AuraPowerGroupOld inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Boot");
|
text: @tr("Boot");
|
||||||
checked <=> root.boot_checked;
|
checked <=> root.boot_checked;
|
||||||
@@ -117,7 +119,7 @@ export component AuraPowerGroupOld inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Awake");
|
text: @tr("Awake");
|
||||||
checked <=> root.awake_checked;
|
checked <=> root.awake_checked;
|
||||||
@@ -127,7 +129,7 @@ export component AuraPowerGroupOld inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemToggleVert {
|
SystemToggleVert {
|
||||||
min-width: 128px;
|
min-width: 96px;
|
||||||
max-height: 42px;
|
max-height: 42px;
|
||||||
text: @tr("Sleep");
|
text: @tr("Sleep");
|
||||||
checked <=> root.sleep_checked;
|
checked <=> root.sleep_checked;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Palette, Slider, HorizontalBox, Button, LineEdit } from "std-widgets.slint";
|
import { Palette, Slider, HorizontalBox, Button, LineEdit } from "std-widgets.slint";
|
||||||
|
|
||||||
export component ColourSlider inherits VerticalLayout {
|
export component ColourSlider inherits VerticalLayout {
|
||||||
spacing: 12px;
|
spacing: 10px;
|
||||||
in-out property <bool> enabled;
|
in-out property <bool> enabled;
|
||||||
property <string> hex: "#FF0000";
|
property <string> hex: "#FF0000";
|
||||||
in-out property <float> c1value <=> c1.value;
|
in-out property <float> c1value <=> c1.value;
|
||||||
@@ -102,9 +102,9 @@ export component ColourSlider inherits VerticalLayout {
|
|||||||
hex = set_hex_from_colour(final_colour);
|
hex = set_hex_from_colour(final_colour);
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 28px;
|
height: 32px;
|
||||||
border-width: 1px;
|
border-width: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 7px;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
// 13 colours
|
// 13 colours
|
||||||
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_colours[0], base_colours[1], base_colours[2], base_colours[3], base_colours[4], base_colours[5], base_colours[6], base_colours[7], base_colours[8], base_colours[9], base_colours[10], base_colours[11], base_colours[12], base_colours[13], base_colours[14], base_colours[15], base_colours[16], base_colours[17], base_colours[18], base_colours[19], base_colours[20], base_colours[21], base_colours[22], base_colours[23], base_colours[24], base_colours[25], base_colours[26], base_colours[27], base_colours[28], base_colours[29], base_colours[30], base_colours[31], base_colours[32], base_colours[33], base_colours[34], base_colours[35]);
|
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_colours[0], base_colours[1], base_colours[2], base_colours[3], base_colours[4], base_colours[5], base_colours[6], base_colours[7], base_colours[8], base_colours[9], base_colours[10], base_colours[11], base_colours[12], base_colours[13], base_colours[14], base_colours[15], base_colours[16], base_colours[17], base_colours[18], base_colours[19], base_colours[20], base_colours[21], base_colours[22], base_colours[23], base_colours[24], base_colours[25], base_colours[26], base_colours[27], base_colours[28], base_colours[29], base_colours[30], base_colours[31], base_colours[32], base_colours[33], base_colours[34], base_colours[35]);
|
||||||
@@ -127,9 +127,9 @@ export component ColourSlider inherits VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 28px;
|
height: 32px;
|
||||||
border-width: 1px;
|
border-width: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 7px;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
// 11 colours
|
// 11 colours
|
||||||
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_saturation[0], base_saturation[1], base_saturation[2], base_saturation[3], base_saturation[4], base_saturation[5], base_saturation[6], base_saturation[7], base_saturation[8], base_saturation[9], base_saturation[10]);
|
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_saturation[0], base_saturation[1], base_saturation[2], base_saturation[3], base_saturation[4], base_saturation[5], base_saturation[6], base_saturation[7], base_saturation[8], base_saturation[9], base_saturation[10]);
|
||||||
@@ -151,9 +151,9 @@ export component ColourSlider inherits VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 28px;
|
height: 32px;
|
||||||
border-width: 1px;
|
border-width: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 7px;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
// 11 colours
|
// 11 colours
|
||||||
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_value[0], base_value[1], base_value[2], base_value[3], base_value[4], base_value[5], base_value[6], base_value[7], base_value[8], base_value[9], base_value[10]);
|
background: !root.enabled ? Palette.alternate-background : @linear-gradient(90deg, base_value[0], base_value[1], base_value[2], base_value[3], base_value[4], base_value[5], base_value[6], base_value[7], base_value[8], base_value[9], base_value[10]);
|
||||||
@@ -191,8 +191,8 @@ export component ColourSlider inherits VerticalLayout {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: self.height;
|
width: self.height;
|
||||||
border-width: 1px;
|
border-width: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 7px;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
background <=> root.colourbox;
|
background <=> root.colourbox;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Palette, VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint";
|
import { Palette, VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint";
|
||||||
|
|
||||||
export component RogItem inherits Rectangle {
|
export component RogItem inherits Rectangle {
|
||||||
|
background: Palette.control-background;
|
||||||
border-color: Palette.border;
|
border-color: Palette.border;
|
||||||
border-width: 1px;
|
border-width: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 10px;
|
||||||
min-height: 44px;
|
min-height: 48px;
|
||||||
max-height: 44px;
|
max-height: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
export component SystemSlider inherits RogItem {
|
export component SystemSlider inherits RogItem {
|
||||||
@@ -29,14 +30,14 @@ export component SystemSlider inherits RogItem {
|
|||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
spacing: 6px;
|
spacing: 6px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
text: root.text;
|
text: root.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
horizontal-alignment: TextHorizontalAlignment.right;
|
horizontal-alignment: TextHorizontalAlignment.right;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
@@ -46,7 +47,7 @@ export component SystemSlider inherits RogItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HorizontalBox {
|
HorizontalBox {
|
||||||
padding-right: 10px;
|
padding-right: 20px;
|
||||||
slider := Slider {
|
slider := Slider {
|
||||||
enabled: root.enabled;
|
enabled: root.enabled;
|
||||||
maximum: root.maximum;
|
maximum: root.maximum;
|
||||||
@@ -161,7 +162,7 @@ export component SystemToggle inherits RogItem {
|
|||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
text: root.text;
|
text: root.text;
|
||||||
@@ -192,7 +193,7 @@ export component SystemToggleInt inherits RogItem {
|
|||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
text: root.text;
|
text: root.text;
|
||||||
@@ -222,7 +223,7 @@ export component SystemToggleVert inherits RogItem {
|
|||||||
alignment: LayoutAlignment.space-around;
|
alignment: LayoutAlignment.space-around;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.bottom;
|
vertical-alignment: TextVerticalAlignment.bottom;
|
||||||
horizontal-alignment: TextHorizontalAlignment.center;
|
horizontal-alignment: TextHorizontalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
@@ -253,7 +254,7 @@ export component SystemDropdown inherits RogItem {
|
|||||||
alignment: LayoutAlignment.start;
|
alignment: LayoutAlignment.start;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
Text {
|
Text {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
vertical-alignment: TextVerticalAlignment.center;
|
vertical-alignment: TextVerticalAlignment.center;
|
||||||
color: Palette.control-foreground;
|
color: Palette.control-foreground;
|
||||||
text: root.text;
|
text: root.text;
|
||||||
@@ -290,7 +291,11 @@ export component PopupNotification {
|
|||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-color: Palette.accent-background;
|
border-color: Palette.accent-background;
|
||||||
background: Palette.background;
|
background: Palette.background;
|
||||||
|
// TODO: drop shadows slow
|
||||||
|
// drop-shadow-offset-x: 7px;
|
||||||
|
// drop-shadow-offset-y: 7px;
|
||||||
|
// drop-shadow-color: black;
|
||||||
|
// drop-shadow-blur: 30px;
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
Dialog {
|
Dialog {
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
|
|||||||
@@ -191,11 +191,10 @@ export component Graph inherits Rectangle {
|
|||||||
tip := Rectangle {
|
tip := Rectangle {
|
||||||
background: Palette.control-foreground;
|
background: Palette.control-foreground;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
border-radius: 12px;
|
|
||||||
x: final_x_pos();
|
x: final_x_pos();
|
||||||
y: final_y_pos();
|
y: final_y_pos();
|
||||||
width: label.preferred-width + 14px;
|
width: label.preferred-width;
|
||||||
height: label.preferred-height + 4px;
|
height: label.preferred-height;
|
||||||
function x_pos() -> length {
|
function x_pos() -> length {
|
||||||
scale_x_to_graph(n.x) - label.preferred-width - 8px
|
scale_x_to_graph(n.x) - label.preferred-width - 8px
|
||||||
}
|
}
|
||||||
@@ -226,7 +225,7 @@ export component Graph inherits Rectangle {
|
|||||||
//
|
//
|
||||||
label := Text {
|
label := Text {
|
||||||
color: Palette.accent-foreground;
|
color: Palette.accent-foreground;
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
text: "\{Math.floor(n.x / 1px)}c, \{fan_pct()}%";
|
text: "\{Math.floor(n.x / 1px)}c, \{fan_pct()}%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +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 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;
|
||||||
@@ -24,16 +26,18 @@ component SideBarItem inherits Rectangle {
|
|||||||
state.opacity: 0.8;
|
state.opacity: 0.8;
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
state := Rectangle {
|
state := Rectangle {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background: Palette.selection-background;
|
border-width: 2px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-color: Palette.accent-background;
|
||||||
|
background: Palette.alternate-background;
|
||||||
animate opacity { duration: 150ms; }
|
animate opacity { duration: 150ms; }
|
||||||
|
animate border-width { duration: 150ms; }
|
||||||
height: l.preferred-height;
|
height: l.preferred-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
l := HorizontalBox {
|
l := HorizontalBox {
|
||||||
x: 4px;
|
|
||||||
y: (parent.height - self.height) / 2;
|
y: (parent.height - self.height) / 2;
|
||||||
spacing: 0px;
|
spacing: 0px;
|
||||||
label := Text {
|
label := Text {
|
||||||
@@ -52,17 +56,20 @@ component SideBarItem inherits Rectangle {
|
|||||||
export component SideBar inherits Rectangle {
|
export component SideBar inherits Rectangle {
|
||||||
in property <[string]> model: [];
|
in property <[string]> model: [];
|
||||||
in property <[bool]> available: [];
|
in property <[bool]> available: [];
|
||||||
in property <bool> is_tuf: false;
|
in property <string> title <=> label.text;
|
||||||
out property <int> current-item: 0;
|
out property <int> current-item: 0;
|
||||||
out property <int> current-focused: fs.has-focus ? fs.focused-tab : -1;
|
out property <int> current-focused: fs.has-focus ? fs.focused-tab : -1;
|
||||||
|
|
||||||
// The currently focused tab
|
// The currently focused tab
|
||||||
width: 180px;
|
width: 160px;
|
||||||
forward-focus: fs;
|
forward-focus: fs;
|
||||||
accessible-role: tab;
|
accessible-role: tab;
|
||||||
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
|
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
|
||||||
Rectangle {
|
Rectangle {
|
||||||
background: Palette.alternate-background;
|
border-width: 2px;
|
||||||
|
border-color: Palette.accent-background;
|
||||||
|
border-radius: 0px;
|
||||||
|
background: Palette.background.darker(0.2);
|
||||||
fs := FocusScope {
|
fs := FocusScope {
|
||||||
key-pressed(event) => {
|
key-pressed(event) => {
|
||||||
if (event.text == "\n") {
|
if (event.text == "\n") {
|
||||||
@@ -95,22 +102,10 @@ export component SideBar inherits Rectangle {
|
|||||||
|
|
||||||
VerticalBox {
|
VerticalBox {
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
padding: 0px;
|
|
||||||
alignment: start;
|
alignment: start;
|
||||||
|
label := Text {
|
||||||
Image {
|
font-size: 16px;
|
||||||
height: 100px;
|
|
||||||
// TODO: change if TUF on the logo in the menu on the main page
|
|
||||||
// If running on a TUF model, replace the ROG red with TUF orange
|
|
||||||
// (add data/tuf-control-center.png and switch here when available)
|
|
||||||
source: @image-url("../../data/rog-control-center.png");
|
|
||||||
horizontal-alignment: center;
|
horizontal-alignment: center;
|
||||||
image-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
height: 1px;
|
|
||||||
background: Palette.border;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
navigation := VerticalLayout {
|
navigation := VerticalLayout {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use zbus::proxy;
|
|||||||
#[proxy(
|
#[proxy(
|
||||||
interface = "xyz.ljones.Anime",
|
interface = "xyz.ljones.Anime",
|
||||||
default_service = "xyz.ljones.Asusd",
|
default_service = "xyz.ljones.Asusd",
|
||||||
default_path = "/xyz/ljones/aura/anime"
|
default_path = "/xyz/ljones"
|
||||||
)]
|
)]
|
||||||
pub trait Anime {
|
pub trait Anime {
|
||||||
/// DeviceState method
|
/// DeviceState method
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl Attribute {
|
|||||||
_ => return Err(PlatformError::InvalidValue),
|
_ => return Err(PlatformError::InvalidValue),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut file = OpenOptions::new().write(true).open(&path)?;
|
let mut file = OpenOptions::new().write(true).truncate(true).open(&path)?;
|
||||||
file.write_all(value_str.as_bytes())?;
|
file.write_all(value_str.as_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -244,6 +244,37 @@ impl FirmwareAttributes {
|
|||||||
Self { attrs }
|
Self { attrs }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create attributes collection from an arbitrary base directory. Intended for tests
|
||||||
|
/// where a fake sysfs-like layout can be supplied.
|
||||||
|
pub fn from_dir(base_dir: &std::path::Path) -> Self {
|
||||||
|
let mut attrs = Vec::new();
|
||||||
|
if let Ok(dir) = read_dir(base_dir) {
|
||||||
|
for entry in dir.flatten() {
|
||||||
|
let base_path = entry.path();
|
||||||
|
let name = base_path.file_name().unwrap().to_string_lossy().to_string();
|
||||||
|
if name == "pending_reboot" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let help = read_string(&base_path.join("display_name")).unwrap_or_default();
|
||||||
|
|
||||||
|
let (default_value, possible_values, min_value, max_value, scalar_increment) =
|
||||||
|
Attribute::read_base_values(&base_path);
|
||||||
|
|
||||||
|
attrs.push(Attribute {
|
||||||
|
name,
|
||||||
|
help,
|
||||||
|
default_value,
|
||||||
|
possible_values,
|
||||||
|
min_value,
|
||||||
|
max_value,
|
||||||
|
scalar_increment,
|
||||||
|
base_path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self { attrs }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn attributes(&self) -> &Vec<Attribute> {
|
pub fn attributes(&self) -> &Vec<Attribute> {
|
||||||
&self.attrs
|
&self.attrs
|
||||||
}
|
}
|
||||||
@@ -253,18 +284,8 @@ impl FirmwareAttributes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
||||||
pub enum FirmwareAttributeType {
|
|
||||||
#[default]
|
|
||||||
Immediate,
|
|
||||||
Ppt,
|
|
||||||
Gpu,
|
|
||||||
Bios,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! define_attribute_getters {
|
macro_rules! define_attribute_getters {
|
||||||
// Accept a list of attribute idents and an optional `types { .. }` block
|
($($attr:ident),*) => {
|
||||||
( $( $attr:ident ),* $(,)? $( ; types { $( $tattr:ident : $ptype:ident ),* $(,)? } )? ) => {
|
|
||||||
impl FirmwareAttributes {
|
impl FirmwareAttributes {
|
||||||
$(
|
$(
|
||||||
pub fn $attr(&self) -> Option<&Attribute> {
|
pub fn $attr(&self) -> Option<&Attribute> {
|
||||||
@@ -278,17 +299,6 @@ macro_rules! define_attribute_getters {
|
|||||||
});
|
});
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirmwareAttribute {
|
|
||||||
pub fn property_type(&self) -> FirmwareAttributeType {
|
|
||||||
match <&str>::from(*self) {
|
|
||||||
$(
|
|
||||||
$( stringify!($tattr) => FirmwareAttributeType::$ptype, )*
|
|
||||||
)?
|
|
||||||
_ => FirmwareAttributeType::Immediate,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,14 +313,10 @@ define_attribute_getters!(
|
|||||||
ppt_fppt,
|
ppt_fppt,
|
||||||
nv_dynamic_boost,
|
nv_dynamic_boost,
|
||||||
nv_temp_target,
|
nv_temp_target,
|
||||||
dgpu_base_tgp,
|
nv_base_tgp,
|
||||||
dgpu_tgp,
|
nv_tgp,
|
||||||
charge_mode,
|
charge_mode,
|
||||||
boot_sound,
|
boot_sound,
|
||||||
kbd_leds_awake,
|
|
||||||
kbd_leds_sleep,
|
|
||||||
kbd_leds_boot,
|
|
||||||
kbd_leds_shutdown,
|
|
||||||
mcu_powersave,
|
mcu_powersave,
|
||||||
panel_od,
|
panel_od,
|
||||||
panel_hd_mode,
|
panel_hd_mode,
|
||||||
@@ -320,38 +326,12 @@ define_attribute_getters!(
|
|||||||
gpu_mux_mode,
|
gpu_mux_mode,
|
||||||
mini_led_mode,
|
mini_led_mode,
|
||||||
screen_auto_brightness
|
screen_auto_brightness
|
||||||
; types {
|
|
||||||
ppt_pl1_spl: Ppt,
|
|
||||||
ppt_pl2_sppt: Ppt,
|
|
||||||
ppt_apu_sppt: Ppt,
|
|
||||||
ppt_platform_sppt: Ppt,
|
|
||||||
ppt_fppt: Ppt,
|
|
||||||
nv_dynamic_boost: Ppt,
|
|
||||||
nv_temp_target: Ppt,
|
|
||||||
dgpu_base_tgp: Ppt,
|
|
||||||
dgpu_tgp: Ppt,
|
|
||||||
|
|
||||||
gpu_mux_mode: Gpu,
|
|
||||||
egpu_connected: Gpu,
|
|
||||||
egpu_enable: Gpu,
|
|
||||||
dgpu_disable: Gpu,
|
|
||||||
|
|
||||||
boot_sound: Bios,
|
|
||||||
|
|
||||||
mcu_powersave: Immediate,
|
|
||||||
|
|
||||||
screen_auto_brightness: Immediate,
|
|
||||||
mini_led_mode: Immediate,
|
|
||||||
panel_hd_mode: Immediate,
|
|
||||||
panel_od: Immediate,
|
|
||||||
|
|
||||||
charge_mode: Immediate,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/// CamelCase names of the properties. Intended for use with DBUS
|
/// CamelCase names of the properties. Intended for use with DBUS
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(
|
#[derive(
|
||||||
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
Copy,
|
Copy,
|
||||||
Serialize,
|
Serialize,
|
||||||
@@ -396,6 +376,30 @@ pub enum FirmwareAttribute {
|
|||||||
ScreenAutoBrightness = 26,
|
ScreenAutoBrightness = 26,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FirmwareAttribute {
|
||||||
|
pub fn is_ppt(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
FirmwareAttribute::PptPl1Spl
|
||||||
|
| FirmwareAttribute::PptPl2Sppt
|
||||||
|
| FirmwareAttribute::PptPl3Fppt
|
||||||
|
| FirmwareAttribute::PptFppt
|
||||||
|
| FirmwareAttribute::PptApuSppt
|
||||||
|
| FirmwareAttribute::PptPlatformSppt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dgpu(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
FirmwareAttribute::NvDynamicBoost
|
||||||
|
| FirmwareAttribute::NvTempTarget
|
||||||
|
| FirmwareAttribute::DgpuBaseTgp
|
||||||
|
| FirmwareAttribute::DgpuTgp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&str> for FirmwareAttribute {
|
impl From<&str> for FirmwareAttribute {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
match s {
|
match s {
|
||||||
@@ -411,8 +415,11 @@ impl From<&str> for FirmwareAttribute {
|
|||||||
"ppt_platform_sppt" => Self::PptPlatformSppt,
|
"ppt_platform_sppt" => Self::PptPlatformSppt,
|
||||||
"nv_dynamic_boost" => Self::NvDynamicBoost,
|
"nv_dynamic_boost" => Self::NvDynamicBoost,
|
||||||
"nv_temp_target" => Self::NvTempTarget,
|
"nv_temp_target" => Self::NvTempTarget,
|
||||||
"nv_base_tgp" => Self::DgpuBaseTgp,
|
|
||||||
"nv_tgp" => Self::DgpuTgp,
|
"nv_tgp" => Self::DgpuTgp,
|
||||||
|
"nv_base_tgp" => Self::DgpuBaseTgp,
|
||||||
|
/* Backwards compatibility: some kernels expose these attributes with a dgpu_* prefix */
|
||||||
|
"dgpu_tgp" => Self::DgpuTgp,
|
||||||
|
"dgpu_base_tgp" => Self::DgpuBaseTgp,
|
||||||
"charge_mode" => Self::ChargeMode,
|
"charge_mode" => Self::ChargeMode,
|
||||||
"boot_sound" => Self::BootSound,
|
"boot_sound" => Self::BootSound,
|
||||||
"mcu_powersave" => Self::McuPowersave,
|
"mcu_powersave" => Self::McuPowersave,
|
||||||
@@ -448,7 +455,7 @@ impl From<FirmwareAttribute> for &str {
|
|||||||
FirmwareAttribute::PptPlatformSppt => "ppt_platform_sppt",
|
FirmwareAttribute::PptPlatformSppt => "ppt_platform_sppt",
|
||||||
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
|
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
|
||||||
FirmwareAttribute::NvTempTarget => "nv_temp_target",
|
FirmwareAttribute::NvTempTarget => "nv_temp_target",
|
||||||
FirmwareAttribute::DgpuBaseTgp => "dgpu_base_tgp",
|
FirmwareAttribute::DgpuBaseTgp => "nv_base_tgp",
|
||||||
FirmwareAttribute::DgpuTgp => "nv_tgp",
|
FirmwareAttribute::DgpuTgp => "nv_tgp",
|
||||||
FirmwareAttribute::ChargeMode => "charge_mode",
|
FirmwareAttribute::ChargeMode => "charge_mode",
|
||||||
FirmwareAttribute::BootSound => "boot_sound",
|
FirmwareAttribute::BootSound => "boot_sound",
|
||||||
@@ -548,3 +555,28 @@ mod tests {
|
|||||||
attr.set_current_value(&val).unwrap();
|
attr.set_current_value(&val).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod alias_tests {
|
||||||
|
use super::FirmwareAttribute;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tgp_aliases_map_to_same_variant() {
|
||||||
|
let nv = FirmwareAttribute::from("nv_tgp");
|
||||||
|
let dgpu = FirmwareAttribute::from("dgpu_tgp");
|
||||||
|
assert_eq!(nv, dgpu);
|
||||||
|
|
||||||
|
let nv_base = FirmwareAttribute::from("nv_base_tgp");
|
||||||
|
let dgpu_base = FirmwareAttribute::from("dgpu_base_tgp");
|
||||||
|
assert_eq!(nv_base, dgpu_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tgp_canonical_output_is_nv_tgp() {
|
||||||
|
let s: &str = FirmwareAttribute::DgpuTgp.into();
|
||||||
|
assert_eq!(s, "nv_tgp");
|
||||||
|
|
||||||
|
let s_base: &str = FirmwareAttribute::DgpuBaseTgp.into();
|
||||||
|
assert_eq!(s_base, "nv_base_tgp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,15 +101,18 @@ impl AsusPower {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// No battery found. Return an AsusPower with an empty battery path so
|
Err(PlatformError::MissingFunction(
|
||||||
// callers can still be constructed and query `has_*` methods which
|
"Did not find a battery".to_owned(),
|
||||||
// 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,
|
impl Default for AsusPower {
|
||||||
battery: PathBuf::new(),
|
fn default() -> Self {
|
||||||
usb,
|
Self {
|
||||||
})
|
mains: PathBuf::from("/this_shouldNeVErr_exisid"),
|
||||||
|
battery: PathBuf::from("/this_shouldNeVErr_exisid"),
|
||||||
|
usb: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,12 +177,6 @@ pub enum AuraMode {
|
|||||||
DoubleFade = 14,
|
DoubleFade = 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dbus")]
|
|
||||||
impl zbus::zvariant::Basic for AuraMode {
|
|
||||||
const SIGNATURE_CHAR: char = 'u';
|
|
||||||
const SIGNATURE_STR: &'static str = "u";
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuraMode {
|
impl AuraMode {
|
||||||
pub fn list() -> [String; 15] {
|
pub fn list() -> [String; 15] {
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -12,13 +12,9 @@ use crate::usb::{PROD_ID1, PROD_ID1_STR, PROD_ID2, PROD_ID2_STR};
|
|||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum SlashType {
|
pub enum SlashType {
|
||||||
GA403_2024,
|
GA403,
|
||||||
GA403_2025,
|
GA605,
|
||||||
GA605_2024,
|
GU605,
|
||||||
GA605_2025,
|
|
||||||
GU605_2024,
|
|
||||||
GU605_2025,
|
|
||||||
G614_2025,
|
|
||||||
#[default]
|
#[default]
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
@@ -26,51 +22,30 @@ pub enum SlashType {
|
|||||||
impl SlashType {
|
impl SlashType {
|
||||||
pub const fn prod_id(&self) -> u16 {
|
pub const fn prod_id(&self) -> u16 {
|
||||||
match self {
|
match self {
|
||||||
SlashType::GA403_2025 => PROD_ID2,
|
SlashType::GA403 => PROD_ID1,
|
||||||
SlashType::GA403_2024 => PROD_ID1,
|
SlashType::GA605 => PROD_ID2,
|
||||||
SlashType::GA605_2025 => PROD_ID2,
|
SlashType::GU605 => PROD_ID1,
|
||||||
SlashType::GA605_2024 => PROD_ID2,
|
|
||||||
SlashType::GU605_2025 => PROD_ID2,
|
|
||||||
SlashType::GU605_2024 => PROD_ID1,
|
|
||||||
SlashType::G614_2025 => PROD_ID2,
|
|
||||||
SlashType::Unsupported => 0,
|
SlashType::Unsupported => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn prod_id_str(&self) -> &str {
|
pub const fn prod_id_str(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
SlashType::GA403_2025 => PROD_ID2_STR,
|
SlashType::GA403 => PROD_ID1_STR,
|
||||||
SlashType::GA403_2024 => PROD_ID1_STR,
|
SlashType::GA605 => PROD_ID2_STR,
|
||||||
SlashType::GA605_2025 => PROD_ID2_STR,
|
SlashType::GU605 => PROD_ID1_STR,
|
||||||
SlashType::GA605_2024 => PROD_ID2_STR,
|
|
||||||
SlashType::GU605_2025 => PROD_ID2_STR,
|
|
||||||
SlashType::GU605_2024 => PROD_ID1_STR,
|
|
||||||
SlashType::G614_2025 => PROD_ID2_STR,
|
|
||||||
SlashType::Unsupported => "",
|
SlashType::Unsupported => "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_dmi() -> Self {
|
pub fn from_dmi() -> Self {
|
||||||
let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase();
|
let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase();
|
||||||
if board_name.contains("G614F") {
|
if board_name.contains("GA403") {
|
||||||
SlashType::G614_2025
|
SlashType::GA403
|
||||||
} else if [
|
|
||||||
"GA403W", "GA403UH", "GA403UM", "GA403UP",
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.any(|s| board_name.contains(s))
|
|
||||||
{
|
|
||||||
SlashType::GA403_2025
|
|
||||||
} else if board_name.contains("GA403") {
|
|
||||||
SlashType::GA403_2024
|
|
||||||
} else if board_name.contains("GA605K") {
|
|
||||||
SlashType::GA605_2025
|
|
||||||
} else if board_name.contains("GA605") {
|
} else if board_name.contains("GA605") {
|
||||||
SlashType::GA605_2024
|
SlashType::GA605
|
||||||
} else if board_name.contains("GU605C") {
|
|
||||||
SlashType::GU605_2025
|
|
||||||
} else if board_name.contains("GU605") {
|
} else if board_name.contains("GU605") {
|
||||||
SlashType::GU605_2024
|
SlashType::GU605
|
||||||
} else {
|
} else {
|
||||||
SlashType::Unsupported
|
SlashType::Unsupported
|
||||||
}
|
}
|
||||||
@@ -81,14 +56,10 @@ impl FromStr for SlashType {
|
|||||||
type Err = SlashError;
|
type Err = SlashError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
Ok(match s.to_uppercase().as_str() {
|
Ok(match s {
|
||||||
"GA403_2025" => Self::GA403_2025,
|
"ga403" | "GA403" => Self::GA403,
|
||||||
"GA403_2024" => Self::GA403_2024,
|
"ga605" | "GA605" => Self::GA605,
|
||||||
"GA605_2025" => Self::GA605_2025,
|
"gu605" | "GU605" => Self::GU605,
|
||||||
"GA605_2024" => Self::GA605_2024,
|
|
||||||
"GU605_2025" => Self::GU605_2025,
|
|
||||||
"GU605_2024" => Self::GU605_2024,
|
|
||||||
"G614_2025" => Self::G614_2025,
|
|
||||||
_ => Self::Unsupported,
|
_ => Self::Unsupported,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -97,7 +68,6 @@ impl FromStr for SlashType {
|
|||||||
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
|
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
|
||||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||||
pub enum SlashMode {
|
pub enum SlashMode {
|
||||||
Static = 0x06,
|
|
||||||
Bounce = 0x10,
|
Bounce = 0x10,
|
||||||
Slash = 0x12,
|
Slash = 0x12,
|
||||||
Loading = 0x13,
|
Loading = 0x13,
|
||||||
@@ -121,7 +91,6 @@ impl FromStr for SlashMode {
|
|||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, SlashError> {
|
fn from_str(s: &str) -> Result<Self, SlashError> {
|
||||||
match s {
|
match s {
|
||||||
"Static" => Ok(SlashMode::Static),
|
|
||||||
"Bounce" => Ok(SlashMode::Bounce),
|
"Bounce" => Ok(SlashMode::Bounce),
|
||||||
"Slash" => Ok(SlashMode::Slash),
|
"Slash" => Ok(SlashMode::Slash),
|
||||||
"Loading" => Ok(SlashMode::Loading),
|
"Loading" => Ok(SlashMode::Loading),
|
||||||
@@ -145,7 +114,6 @@ impl FromStr for SlashMode {
|
|||||||
impl Display for SlashMode {
|
impl Display for SlashMode {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let str = match &self {
|
let str = match &self {
|
||||||
SlashMode::Static => String::from("Static"),
|
|
||||||
SlashMode::Bounce => String::from("Bounce"),
|
SlashMode::Bounce => String::from("Bounce"),
|
||||||
SlashMode::Slash => String::from("Slash"),
|
SlashMode::Slash => String::from("Slash"),
|
||||||
SlashMode::Loading => String::from("Loading"),
|
SlashMode::Loading => String::from("Loading"),
|
||||||
@@ -167,9 +135,8 @@ impl Display for SlashMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SlashMode {
|
impl SlashMode {
|
||||||
pub fn list() -> [String; 16] {
|
pub fn list() -> [String; 15] {
|
||||||
[
|
[
|
||||||
SlashMode::Static.to_string(),
|
|
||||||
SlashMode::Bounce.to_string(),
|
SlashMode::Bounce.to_string(),
|
||||||
SlashMode::Slash.to_string(),
|
SlashMode::Slash.to_string(),
|
||||||
SlashMode::Loading.to_string(),
|
SlashMode::Loading.to_string(),
|
||||||
|
|||||||
@@ -37,26 +37,14 @@ pub fn get_slash_type() -> SlashType {
|
|||||||
let dmi = DMIID::new()
|
let dmi = DMIID::new()
|
||||||
.map_err(|_| SlashError::NoDevice)
|
.map_err(|_| SlashError::NoDevice)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let board_name = dmi.board_name.to_uppercase();
|
let board_name = dmi.board_name;
|
||||||
if board_name.contains("G614F") {
|
|
||||||
SlashType::G614_2025
|
if board_name.contains("GA403") {
|
||||||
} else if [
|
SlashType::GA403
|
||||||
"GA403W", "GA403UH", "GA403UM", "GA403UP",
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.any(|s| board_name.contains(s))
|
|
||||||
{
|
|
||||||
SlashType::GA403_2025
|
|
||||||
} else if board_name.contains("GA403") {
|
|
||||||
SlashType::GA403_2024
|
|
||||||
} else if board_name.contains("GA605K") {
|
|
||||||
SlashType::GA605_2025
|
|
||||||
} else if board_name.contains("GA605") {
|
} else if board_name.contains("GA605") {
|
||||||
SlashType::GA605_2024
|
SlashType::GA605
|
||||||
} else if board_name.contains("GU605C") {
|
|
||||||
SlashType::GU605_2025
|
|
||||||
} else if board_name.contains("GU605") {
|
} else if board_name.contains("GU605") {
|
||||||
SlashType::GU605_2024
|
SlashType::GU605
|
||||||
} else {
|
} else {
|
||||||
SlashType::Unsupported
|
SlashType::Unsupported
|
||||||
}
|
}
|
||||||
@@ -64,13 +52,9 @@ pub fn get_slash_type() -> SlashType {
|
|||||||
|
|
||||||
pub const fn report_id(slash_type: SlashType) -> u8 {
|
pub const fn report_id(slash_type: SlashType) -> u8 {
|
||||||
match slash_type {
|
match slash_type {
|
||||||
SlashType::GA403_2025 => REPORT_ID_19B6,
|
SlashType::GA403 => REPORT_ID_193B,
|
||||||
SlashType::GA403_2024 => REPORT_ID_193B,
|
SlashType::GA605 => REPORT_ID_19B6,
|
||||||
SlashType::GA605_2025 => REPORT_ID_19B6,
|
SlashType::GU605 => REPORT_ID_193B,
|
||||||
SlashType::GA605_2024 => REPORT_ID_19B6,
|
|
||||||
SlashType::GU605_2025 => REPORT_ID_19B6,
|
|
||||||
SlashType::GU605_2024 => REPORT_ID_193B,
|
|
||||||
SlashType::G614_2025 => REPORT_ID_19B6,
|
|
||||||
SlashType::Unsupported => REPORT_ID_19B6,
|
SlashType::Unsupported => REPORT_ID_19B6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
stable
|
|
||||||
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "stable"
|
||||||
|
components = ["rustfmt", "clippy"]
|
||||||
|
profile = "minimal"
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
use super::Row;
|
|
||||||
|
|
||||||
// TODO: This is a placeholder for G635L map
|
|
||||||
pub const G635L: [Row; 63] = [
|
|
||||||
Row(0x01, 7, 32, 0),
|
|
||||||
Row(0x01, 7 + 34, 32, 0),
|
|
||||||
Row(0x01, 7 + 68, 32, 0),
|
|
||||||
Row(0x01, 7 + 102, 32, 0), // 34 len
|
|
||||||
Row(0x01, 7 + 136, 32, 0),
|
|
||||||
Row(0x01, 7 + 170, 34, 0),
|
|
||||||
Row(0x01, 7 + 204, 34, 0),
|
|
||||||
Row(0x01, 7 + 238, 34, 0),
|
|
||||||
Row(0x01, 7 + 272, 34, 0),
|
|
||||||
Row(0x01, 7 + 306, 34, 0),
|
|
||||||
Row(0x01, 7 + 340, 34, 0),
|
|
||||||
Row(0x01, 7 + 374, 34, 0),
|
|
||||||
Row(0x01, 7 + 408, 33, 1),
|
|
||||||
Row(0x01, 7 + 441, 33, 1),
|
|
||||||
Row(0x01, 7 + 474, 32, 2),
|
|
||||||
Row(0x01, 7 + 506, 32, 2),
|
|
||||||
Row(0x01, 7 + 538, 31, 3),
|
|
||||||
Row(0x01, 7 + 569, 31, 3),
|
|
||||||
Row(0x01, 7 + 600, 28, 4),
|
|
||||||
//
|
|
||||||
Row(0x74, 7 + 1, 3, 28 + 4), // adds to end of previous
|
|
||||||
Row(0x74, 7 + 3, 30, 4),
|
|
||||||
Row(0x74, 7 + 33, 29, 5),
|
|
||||||
Row(0x74, 7 + 62, 29, 5),
|
|
||||||
Row(0x74, 7 + 91, 28, 6),
|
|
||||||
Row(0x74, 7 + 119, 28, 6),
|
|
||||||
Row(0x74, 7 + 147, 27, 7),
|
|
||||||
Row(0x74, 7 + 174, 27, 7),
|
|
||||||
Row(0x74, 7 + 202, 26, 9),
|
|
||||||
Row(0x74, 7 + 228, 26, 9),
|
|
||||||
Row(0x74, 7 + 254, 25, 10),
|
|
||||||
Row(0x74, 7 + 278, 25, 9), // WEIRD OFFSET
|
|
||||||
Row(0x74, 7 + 303, 24, 10),
|
|
||||||
Row(0x74, 7 + 327, 24, 10),
|
|
||||||
Row(0x74, 7 + 351, 23, 11),
|
|
||||||
Row(0x74, 7 + 374, 23, 11),
|
|
||||||
Row(0x74, 7 + 397, 22, 12),
|
|
||||||
Row(0x74, 7 + 419, 22, 12),
|
|
||||||
Row(0x74, 7 + 441, 21, 13),
|
|
||||||
Row(0x74, 7 + 462, 21, 13),
|
|
||||||
Row(0x74, 7 + 483, 20, 14),
|
|
||||||
Row(0x74, 7 + 503, 20, 14),
|
|
||||||
Row(0x74, 7 + 523, 19, 15),
|
|
||||||
Row(0x74, 7 + 542, 19, 15),
|
|
||||||
Row(0x74, 7 + 561, 18, 16),
|
|
||||||
Row(0x74, 7 + 579, 18, 16),
|
|
||||||
Row(0x74, 7 + 597, 17, 17),
|
|
||||||
Row(0x74, 7 + 614, 13, 17),
|
|
||||||
//
|
|
||||||
Row(0xe7, 7 + 1, 4, 13 + 18), // adds to end of previous
|
|
||||||
Row(0xe7, 7 + 4, 16, 18),
|
|
||||||
Row(0xe7, 7 + 20, 16, 18),
|
|
||||||
Row(0xe7, 7 + 36, 15, 19),
|
|
||||||
Row(0xe7, 7 + 51, 15, 19),
|
|
||||||
Row(0xe7, 7 + 66, 14, 20),
|
|
||||||
Row(0xe7, 7 + 80, 12, 20), // too long? 14
|
|
||||||
Row(0xe7, 7 + 94, 13, 21),
|
|
||||||
Row(0xe7, 7 + 107, 13, 21),
|
|
||||||
Row(0xe7, 7 + 120, 12, 12), // Actual display end
|
|
||||||
Row(0xe7, 7 + 132, 12, 22),
|
|
||||||
Row(0xe7, 7 + 144, 11, 23),
|
|
||||||
Row(0xe7, 7 + 155, 11, 23),
|
|
||||||
Row(0xe7, 7 + 166, 10, 24),
|
|
||||||
Row(0xe7, 7 + 176, 10, 24),
|
|
||||||
Row(0xe7, 7 + 186, 9, 25),
|
|
||||||
];
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
use super::Row;
|
|
||||||
|
|
||||||
// G835L layout: 68 rows (triangle + rectangle), 2 packets
|
|
||||||
pub const G835L: [Row; 69] = [
|
|
||||||
Row(0x01, 7, 0, 0),
|
|
||||||
Row(0x01, 8, 0, 0),
|
|
||||||
Row(0x01, 9, 1, 0),
|
|
||||||
Row(0x01, 11, 1, 0),
|
|
||||||
Row(0x01, 13, 2, 0),
|
|
||||||
Row(0x01, 16, 2, 0),
|
|
||||||
Row(0x01, 19, 3, 0),
|
|
||||||
Row(0x01, 23, 3, 0),
|
|
||||||
Row(0x01, 27, 4, 0),
|
|
||||||
Row(0x01, 32, 4, 0),
|
|
||||||
Row(0x01, 37, 5, 0),
|
|
||||||
Row(0x01, 43, 5, 0),
|
|
||||||
Row(0x01, 49, 6, 0),
|
|
||||||
Row(0x01, 56, 6, 0),
|
|
||||||
Row(0x01, 63, 7, 0),
|
|
||||||
Row(0x01, 71, 7, 0),
|
|
||||||
Row(0x01, 79, 8, 0),
|
|
||||||
Row(0x01, 88, 8, 0),
|
|
||||||
Row(0x01, 97, 9, 0),
|
|
||||||
Row(0x01, 107, 9, 0),
|
|
||||||
Row(0x01, 117, 10, 0),
|
|
||||||
Row(0x01, 128, 10, 0),
|
|
||||||
Row(0x01, 139, 11, 0),
|
|
||||||
Row(0x01, 151, 11, 0),
|
|
||||||
Row(0x01, 163, 12, 0),
|
|
||||||
Row(0x01, 176, 12, 0),
|
|
||||||
Row(0x01, 189, 13, 0),
|
|
||||||
Row(0x01, 203, 13, 0),
|
|
||||||
Row(0x01, 217, 14, 0),
|
|
||||||
Row(0x01, 232, 14, 0),
|
|
||||||
Row(0x01, 247, 14, 1),
|
|
||||||
Row(0x01, 262, 14, 1),
|
|
||||||
Row(0x01, 277, 14, 2),
|
|
||||||
Row(0x01, 292, 14, 2),
|
|
||||||
Row(0x01, 307, 14, 3),
|
|
||||||
Row(0x01, 322, 14, 3),
|
|
||||||
Row(0x01, 337, 14, 4),
|
|
||||||
Row(0x01, 352, 14, 4),
|
|
||||||
Row(0x01, 367, 14, 5),
|
|
||||||
Row(0x01, 382, 14, 5),
|
|
||||||
Row(0x01, 397, 14, 6),
|
|
||||||
Row(0x01, 412, 14, 6),
|
|
||||||
Row(0x01, 427, 14, 7),
|
|
||||||
Row(0x01, 442, 14, 7),
|
|
||||||
Row(0x01, 457, 14, 8),
|
|
||||||
Row(0x01, 472, 14, 8),
|
|
||||||
Row(0x01, 487, 14, 9),
|
|
||||||
Row(0x01, 502, 14, 9),
|
|
||||||
Row(0x01, 517, 14, 10),
|
|
||||||
Row(0x01, 532, 14, 10),
|
|
||||||
Row(0x01, 547, 14, 11),
|
|
||||||
Row(0x01, 562, 14, 11),
|
|
||||||
Row(0x01, 577, 14, 12),
|
|
||||||
Row(0x01, 592, 14, 12),
|
|
||||||
Row(0x01, 607, 14, 13),
|
|
||||||
Row(0x01, 622, 11, 13),
|
|
||||||
Row(0x74, 7, 2, 25),
|
|
||||||
Row(0x74, 10, 14, 14),
|
|
||||||
Row(0x74, 25, 14, 14),
|
|
||||||
Row(0x74, 40, 14, 15),
|
|
||||||
Row(0x74, 55, 14, 15),
|
|
||||||
Row(0x74, 70, 14, 16),
|
|
||||||
Row(0x74, 85, 14, 16),
|
|
||||||
Row(0x74, 100, 14, 17),
|
|
||||||
Row(0x74, 115, 14, 17),
|
|
||||||
Row(0x74, 130, 14, 18),
|
|
||||||
Row(0x74, 145, 14, 18),
|
|
||||||
Row(0x74, 160, 14, 19),
|
|
||||||
Row(0x74, 175, 14, 19),
|
|
||||||
];
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
use rog_anime::AnimeType;
|
use rog_anime::AnimeType;
|
||||||
|
|
||||||
use self::map_g635l::G635L;
|
|
||||||
use self::map_g835l::G835L;
|
|
||||||
use self::map_ga401::GA401;
|
use self::map_ga401::GA401;
|
||||||
use self::map_ga402::GA402;
|
use self::map_ga402::GA402;
|
||||||
use self::map_gu604::GU604;
|
use self::map_gu604::GU604;
|
||||||
|
|
||||||
mod map_g635l;
|
|
||||||
mod map_g835l;
|
|
||||||
mod map_ga401;
|
mod map_ga401;
|
||||||
mod map_ga402;
|
mod map_ga402;
|
||||||
mod map_gu604;
|
mod map_gu604;
|
||||||
@@ -42,9 +38,19 @@ pub struct AniMatrix {
|
|||||||
|
|
||||||
impl AniMatrix {
|
impl AniMatrix {
|
||||||
pub fn new(model: AnimeType) -> Self {
|
pub fn new(model: AnimeType) -> Self {
|
||||||
let led_shape = LedShape {
|
let led_shape = match model {
|
||||||
vertical: 2,
|
AnimeType::GA401 => LedShape {
|
||||||
horizontal: 5,
|
vertical: 2,
|
||||||
|
horizontal: 5,
|
||||||
|
},
|
||||||
|
AnimeType::GA402 | AnimeType::Unsupported => LedShape {
|
||||||
|
vertical: 2,
|
||||||
|
horizontal: 5,
|
||||||
|
},
|
||||||
|
AnimeType::GU604 => LedShape {
|
||||||
|
vertical: 2,
|
||||||
|
horizontal: 5,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Do a hard mapping of each (derived from wireshardk captures)
|
// Do a hard mapping of each (derived from wireshardk captures)
|
||||||
@@ -52,8 +58,6 @@ impl AniMatrix {
|
|||||||
AnimeType::GA401 => GA401.to_vec(),
|
AnimeType::GA401 => GA401.to_vec(),
|
||||||
AnimeType::GA402 | AnimeType::Unsupported => GA402.to_vec(),
|
AnimeType::GA402 | AnimeType::Unsupported => GA402.to_vec(),
|
||||||
AnimeType::GU604 => GU604.to_vec(),
|
AnimeType::GU604 => GU604.to_vec(),
|
||||||
AnimeType::G635L => G635L.to_vec(),
|
|
||||||
AnimeType::G835L => G835L.to_vec(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Self { rows, led_shape }
|
Self { rows, led_shape }
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::env;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use log::error;
|
||||||
use rog_anime::usb::{PROD_ID, VENDOR_ID};
|
use rog_anime::usb::{PROD_ID, VENDOR_ID};
|
||||||
use rog_anime::{AnimeType, USB_PREFIX2};
|
use rog_anime::{AnimeType, USB_PREFIX2};
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
@@ -19,7 +20,6 @@ pub struct VirtAnimeMatrix {
|
|||||||
animatrix: AniMatrix,
|
animatrix: AniMatrix,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This isn't working
|
|
||||||
impl VirtAnimeMatrix {
|
impl VirtAnimeMatrix {
|
||||||
pub fn new(model: AnimeType) -> Self {
|
pub fn new(model: AnimeType) -> Self {
|
||||||
VirtAnimeMatrix {
|
VirtAnimeMatrix {
|
||||||
@@ -86,12 +86,8 @@ impl VirtAnimeMatrix {
|
|||||||
]
|
]
|
||||||
.to_vec(),
|
.to_vec(),
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|err| {
|
.map_err(|err| error!("Could not create virtual device: {:?}", err))
|
||||||
panic!(
|
.expect("Could not create virtual device"),
|
||||||
"Could not create virtual device: {err:?}. \
|
|
||||||
Try loading the uhid module and ensure you have the necessary permissions."
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +114,7 @@ impl VirtAnimeMatrix {
|
|||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() <= 1 {
|
if args.len() <= 1 {
|
||||||
println!("Must supply arg, one of <GA401, GA402, GU604, G835L>");
|
println!("Must supply arg, one of <GA401, GA402, GU604>");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let anime_type = AnimeType::from_str(&args[1])?;
|
let anime_type = AnimeType::from_str(&args[1])?;
|
||||||
@@ -161,14 +157,14 @@ 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
|
#[allow(clippy::manual_is_multiple_of)]
|
||||||
- if (y_count + y_offset as usize) % 2 != 0 {
|
if (y_count + y_offset as usize) % 2 != 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
w / 2
|
w / 2
|
||||||
}
|
}
|
||||||
+ row.3 * w;
|
} + row.3 * w;
|
||||||
let y = y_count as i32 * h - y_offset * h;
|
let y = y_count as i32 * h - y_offset * h;
|
||||||
canvas
|
canvas
|
||||||
.fill_rect(Rect::new(x, y, w as u32, h as u32))
|
.fill_rect(Rect::new(x, y, w as u32, h as u32))
|
||||||
|
|||||||
Reference in New Issue
Block a user