mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
43 Commits
6.1.15
...
devel-dyna
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e5cebc781 | ||
|
|
def691f9d0 | ||
|
|
80eeafd9e1 | ||
|
|
bf173300e0 | ||
|
|
07874d7452 | ||
|
|
894a0d2b11 | ||
|
|
11dc02612e | ||
|
|
fccb233e9e | ||
|
|
c13612e02c | ||
|
|
80147966a9 | ||
|
|
a1815ac40c | ||
|
|
ad051bd7b8 | ||
|
|
90676b390e | ||
|
|
974f2acafa | ||
|
|
6ae3ae5284 | ||
|
|
34699a7021 | ||
|
|
ef311689ec | ||
|
|
8ee0281b4f | ||
|
|
d8504b5430 | ||
|
|
5c4d833fbd | ||
|
|
698999e828 | ||
|
|
0eae9e55c6 | ||
|
|
07171888a1 | ||
|
|
9321fde6af | ||
|
|
f90d0a6673 | ||
|
|
bbd03c128d | ||
|
|
132a2f3665 | ||
|
|
180566e5f1 | ||
|
|
c9e76f3273 | ||
|
|
2997ae83ff | ||
|
|
151d681e16 | ||
|
|
90b3f43a36 | ||
|
|
a345b09ce1 | ||
|
|
f26b0d8de5 | ||
|
|
9366b0ec04 | ||
|
|
415712143b | ||
|
|
60fce30a06 | ||
|
|
d8f06230fa | ||
|
|
834464a527 | ||
|
|
4faa96298a | ||
|
|
78c574b761 | ||
|
|
9785eafd53 | ||
|
|
51cad9ea7e |
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo '+cargo +nightly fmt --all -- --check'
|
||||
cargo +nightly fmt --all -- --check
|
||||
echo '+cargo fmt --all -- --check'
|
||||
cargo fmt --all -- --check
|
||||
git add -u
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
set -e
|
||||
|
||||
echo '+cargo +nightly fmt --all -- --check'
|
||||
cargo +nightly fmt --all -- --check
|
||||
echo '+cargo fmt --all -- --check'
|
||||
cargo fmt --all -- --check
|
||||
echo '+cargo clippy --all -- -D warnings'
|
||||
cargo clippy --all -- -D warnings
|
||||
echo '+cargo cranky'
|
||||
|
||||
@@ -31,8 +31,7 @@ format:
|
||||
- tags
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- echo "nightly" > rust-toolchain
|
||||
- rustup component add rustfmt
|
||||
- rustup component add rustfmt || true
|
||||
- cargo fmt --check
|
||||
|
||||
check:
|
||||
@@ -40,8 +39,8 @@ check:
|
||||
- tags
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- rustup component add clippy
|
||||
- cargo check
|
||||
- rustup component add clippy || true
|
||||
- cargo check --locked --workspace
|
||||
# deny currently catches too much
|
||||
#- cargo install cargo-deny && cargo deny
|
||||
- cargo install cargo-cranky && cargo cranky
|
||||
@@ -52,7 +51,7 @@ test:
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- mkdir -p .git/hooks > /dev/null
|
||||
- cargo test --all -- --test-threads=1
|
||||
- cargo test --locked --all
|
||||
|
||||
release:
|
||||
only:
|
||||
@@ -60,7 +59,7 @@ release:
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- cargo install cargo-vendor-filterer
|
||||
- make && make vendor
|
||||
- make FROZEN=1 && make vendor
|
||||
artifacts:
|
||||
paths:
|
||||
- vendor_asusctl*.tar.xz
|
||||
@@ -72,7 +71,7 @@ pages:
|
||||
- tags
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- cargo doc --document-private-items --no-deps --workspace
|
||||
- cargo doc --locked --document-private-items --no-deps --workspace
|
||||
- rm -rf public
|
||||
- mkdir public
|
||||
- cp -R target/doc/* public
|
||||
|
||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -2,6 +2,23 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
- Make the boot process more reliable
|
||||
- tie nv_ properties to power profiles
|
||||
- Better support nv_tgp
|
||||
|
||||
## [v6.1.17]
|
||||
|
||||
### Changed
|
||||
- Fix Makefile
|
||||
- Share a single HID device
|
||||
|
||||
## [v6.1.16]
|
||||
|
||||
### Changed
|
||||
- Expose more properties via rog-control-center
|
||||
- Add support for a few more models
|
||||
|
||||
## [v6.1.15]
|
||||
|
||||
### Changed
|
||||
|
||||
1241
Cargo.lock
generated
1241
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
[workspace.package]
|
||||
version = "6.1.15"
|
||||
version = "6.1.17"
|
||||
rust-version = "1.82"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
|
||||
11
Makefile
11
Makefile
@@ -37,6 +37,15 @@ ifeq ($(X11),1)
|
||||
ARGS += --features "rog-control-center/x11"
|
||||
endif
|
||||
|
||||
# Always use the versions in Cargo.lock by default
|
||||
ARGS += --locked
|
||||
|
||||
# Allow optionally freezing the build to avoid any network access and enforce Cargo.lock strictly
|
||||
FROZEN ?= 0
|
||||
ifeq ($(FROZEN),1)
|
||||
ARGS += --frozen
|
||||
endif
|
||||
|
||||
VENDORED ?= 0
|
||||
ifeq ($(VENDORED),1)
|
||||
ARGS += --frozen
|
||||
@@ -104,7 +113,7 @@ install-data-asusd_user:
|
||||
|
||||
.PHONY: install-data-asusd install-data-asusd_user
|
||||
|
||||
install-data: install-data-asusd install-data-rog_gui
|
||||
install-data: install-data-asusd install-data-asusd_user install-data-rog_gui
|
||||
|
||||
install: install-program install-data
|
||||
$(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE"
|
||||
|
||||
54
README.md
54
README.md
@@ -46,13 +46,13 @@ See the [rog-aura readme](./rog-aura/README.md) for more details.
|
||||
Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar
|
||||
to this:
|
||||
|
||||
```
|
||||
```plain
|
||||
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
```plain
|
||||
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
|
||||
```
|
||||
|
||||
@@ -74,39 +74,47 @@ The list is a bit outdated as many features have been enabled in the Linux kerne
|
||||
- [x] Toggle bios setting for boot/POST sound
|
||||
- [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops)
|
||||
|
||||
# GUI
|
||||
## GUI
|
||||
|
||||
A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already.
|
||||
|
||||
**NOTE**: Xorg is not supported.
|
||||
|
||||
# BUILDING
|
||||
## BUILDING
|
||||
|
||||
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/) or from the distro repos if newer than 1.75.
|
||||
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/).
|
||||
|
||||
Distro packaging should work with the stable toolchain. If your distro does not provide a recent Rust toolchain, install rustup and use the stable toolchain.
|
||||
|
||||
**fedora:**
|
||||
|
||||
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
|
||||
make
|
||||
sudo make install
|
||||
```sh
|
||||
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
**openSUSE:**
|
||||
|
||||
Works with KDE Plasma (without GTK packages)
|
||||
|
||||
zypper in -t pattern devel_basis
|
||||
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
|
||||
make
|
||||
sudo make install
|
||||
```sh
|
||||
zypper in -t pattern devel_basis
|
||||
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
**Debian(unsuported):**
|
||||
|
||||
officially unsuported,but you can still try and test it by yourself(some features may not be available).
|
||||
|
||||
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
make
|
||||
sudo make install
|
||||
```sh
|
||||
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
**Ubuntu, Popos (unsuported):**
|
||||
|
||||
@@ -133,15 +141,15 @@ You may also need to activate the service for debian install. If running Pop!\_O
|
||||
|
||||
If you are upgrading from a previous installed version, you will need to restart the service or reboot.
|
||||
|
||||
```
|
||||
$ systemctl daemon-reload && systemctl restart asusd
|
||||
```sh
|
||||
systemctl daemon-reload && systemctl restart asusd
|
||||
```
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
|
||||
|
||||
# Contributing
|
||||
## Contributing
|
||||
|
||||
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
|
||||
|
||||
@@ -149,17 +157,17 @@ Generation of the bindings with `make bindings` requires `typeshare` to be insta
|
||||
|
||||
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
|
||||
|
||||
# OTHER
|
||||
## OTHER
|
||||
|
||||
## AniMe Matrix simulator
|
||||
### AniMe Matrix simulator
|
||||
|
||||
A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop _with_ the display, the simulated display will be used instead of the physical display.
|
||||
|
||||
## Supporting more laptops
|
||||
### Supporting more laptops
|
||||
|
||||
Please file a support request.
|
||||
|
||||
# License & Trademarks
|
||||
## License & Trademarks
|
||||
|
||||
Mozilla Public License 2 (MPL-2.0)
|
||||
|
||||
|
||||
@@ -21,11 +21,14 @@ fn main() {
|
||||
let brightness = args[2].parse::<f32>().unwrap();
|
||||
let anime_type = get_anime_type();
|
||||
let mut seq = Sequences::new(anime_type);
|
||||
seq.insert(0, &ActionLoader::AsusAnimation {
|
||||
file: path.into(),
|
||||
time: rog_anime::AnimTime::Infinite,
|
||||
brightness,
|
||||
})
|
||||
seq.insert(
|
||||
0,
|
||||
&ActionLoader::AsusAnimation {
|
||||
file: path.into(),
|
||||
time: rog_anime::AnimTime::Infinite,
|
||||
brightness,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
|
||||
@@ -180,6 +180,7 @@ pub struct TwoColourSpeed {
|
||||
pub zone: AuraZone,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Default, Options)]
|
||||
pub struct MultiZone {
|
||||
#[options(help = "print help message")]
|
||||
@@ -194,6 +195,7 @@ pub struct MultiZone {
|
||||
pub colour4: Colour,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Default, Options)]
|
||||
pub struct MultiColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
|
||||
@@ -74,6 +74,16 @@ pub struct ProfileCommand {
|
||||
|
||||
#[options(meta = "", help = "set the active profile")]
|
||||
pub profile_set: Option<PlatformProfile>,
|
||||
|
||||
#[options(short = "a", meta = "", help = "set the profile to use on AC power")]
|
||||
pub profile_set_ac: Option<PlatformProfile>,
|
||||
|
||||
#[options(
|
||||
short = "b",
|
||||
meta = "",
|
||||
help = "set the profile to use on battery power"
|
||||
)]
|
||||
pub profile_set_bat: Option<PlatformProfile>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
|
||||
@@ -979,7 +979,13 @@ fn handle_throttle_profile(
|
||||
return Err(ProfileError::NotSupported.into());
|
||||
}
|
||||
|
||||
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get {
|
||||
if !cmd.next
|
||||
&& !cmd.list
|
||||
&& cmd.profile_set.is_none()
|
||||
&& !cmd.profile_get
|
||||
&& cmd.profile_set_ac.is_none()
|
||||
&& cmd.profile_set_bat.is_none()
|
||||
{
|
||||
if !cmd.help {
|
||||
println!("Missing arg or command\n");
|
||||
}
|
||||
@@ -999,6 +1005,10 @@ fn handle_throttle_profile(
|
||||
proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
|
||||
} else if let Some(profile) = cmd.profile_set {
|
||||
proxy.set_platform_profile(profile)?;
|
||||
} else if let Some(profile) = cmd.profile_set_ac {
|
||||
proxy.set_platform_profile_on_ac(profile)?;
|
||||
} else if let Some(profile) = cmd.profile_set_bat {
|
||||
proxy.set_platform_profile_on_battery(profile)?;
|
||||
}
|
||||
|
||||
if cmd.list {
|
||||
@@ -1009,6 +1019,11 @@ fn handle_throttle_profile(
|
||||
|
||||
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(())
|
||||
@@ -1169,11 +1184,15 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::manual_is_multiple_of)]
|
||||
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||
{
|
||||
if cmd.free.is_empty() || !cmd.free.len().is_multiple_of(2) || cmd.help {
|
||||
// Avoid using `.is_multiple_of(2)` to satisfy the request. Use modulus check
|
||||
// and simplify the boolean expression.
|
||||
let odd_len = cmd.free.len() % 2 != 0;
|
||||
if cmd.free.is_empty() || odd_len || cmd.help {
|
||||
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
|
||||
if !cmd.free.len().is_multiple_of(2) {
|
||||
if odd_len {
|
||||
println!(
|
||||
"Incorrect number of args, each attribute label must be paired with a setting:"
|
||||
);
|
||||
|
||||
@@ -45,6 +45,7 @@ concat-idents.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
cargo-husky.workspace = true
|
||||
tempfile = "3"
|
||||
|
||||
[package.metadata.deb]
|
||||
license-file = ["../LICENSE", "4"]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use config_traits::StdConfig;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info};
|
||||
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
|
||||
use rog_platform::platform::{PlatformProfile, RogPlatform};
|
||||
use rog_platform::power::AsusPower;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::object_server::SignalEmitter;
|
||||
use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value};
|
||||
use zbus::{fdo, interface, Connection};
|
||||
@@ -27,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()
|
||||
}
|
||||
|
||||
// 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)]
|
||||
pub struct AsusArmouryAttribute {
|
||||
attr: Attribute,
|
||||
@@ -146,6 +168,14 @@ impl ArmouryAttributeRegistry {
|
||||
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> {
|
||||
let mut last_err: Option<RogError> = None;
|
||||
for attr in &self.attrs {
|
||||
@@ -170,7 +200,7 @@ impl crate::Reloadable for AsusArmouryAttribute {
|
||||
info!("Reloading {}", self.attr.name());
|
||||
let name: FirmwareAttribute = self.attr.name().into();
|
||||
|
||||
if name.is_ppt() {
|
||||
if name.is_ppt() || name.is_dgpu() {
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let power_plugged = self
|
||||
.power
|
||||
@@ -196,14 +226,24 @@ impl crate::Reloadable for AsusArmouryAttribute {
|
||||
};
|
||||
|
||||
if let Some(tune) = apply_value {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(tune))
|
||||
.map_err(|e| {
|
||||
error!("Could not set {} value: {e:?}", self.attr.name());
|
||||
self.attr.base_path_exists();
|
||||
e
|
||||
})?;
|
||||
info!("Set {} to {:?}", self.attr.name(), tune);
|
||||
// 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 tune in that case.
|
||||
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());
|
||||
self.attr.base_path_exists();
|
||||
e
|
||||
})?;
|
||||
info!("Set {} to {:?}", self.attr.name(), tune);
|
||||
} else {
|
||||
debug!(
|
||||
"Skipping apply for {} because attribute missing or unsupported (min==max)",
|
||||
self.attr.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle non-PPT attributes (boolean and other settings)
|
||||
@@ -277,7 +317,7 @@ impl AsusArmouryAttribute {
|
||||
|
||||
async fn restore_default(&self) -> fdo::Result<()> {
|
||||
self.attr.restore_default()?;
|
||||
if self.name().is_ppt() {
|
||||
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let power_plugged = self
|
||||
.power
|
||||
@@ -336,7 +376,7 @@ impl AsusArmouryAttribute {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn current_value(&self) -> fdo::Result<i32> {
|
||||
if self.name().is_ppt() {
|
||||
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let power_plugged = self
|
||||
.power
|
||||
@@ -370,9 +410,9 @@ impl AsusArmouryAttribute {
|
||||
}
|
||||
|
||||
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
|
||||
if !self.name().is_ppt() {
|
||||
if !(self.name().is_ppt() || self.name().is_dgpu()) {
|
||||
return Err(fdo::Error::NotSupported(
|
||||
"Stored values are only available for PPT attributes".to_string(),
|
||||
"Stored values are only available for PPT/dGPU tunable attributes".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -393,9 +433,10 @@ impl AsusArmouryAttribute {
|
||||
}
|
||||
|
||||
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
|
||||
if !self.name().is_ppt() {
|
||||
if !(self.name().is_ppt() || self.name().is_dgpu()) {
|
||||
return Err(fdo::Error::NotSupported(
|
||||
"Setting stored values is only supported for PPT attributes".to_string(),
|
||||
"Setting stored values is only supported for PPT/dGPU tunable attributes"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -433,13 +474,23 @@ impl AsusArmouryAttribute {
|
||||
.unwrap_or_default()
|
||||
!= 0;
|
||||
|
||||
if power_plugged == on_ac {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(value))
|
||||
.map_err(|e| {
|
||||
error!("Could not set value: {e:?}");
|
||||
e
|
||||
})?;
|
||||
// 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +499,7 @@ impl AsusArmouryAttribute {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
|
||||
if self.name().is_ppt() {
|
||||
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let power_plugged = self
|
||||
.power
|
||||
@@ -469,12 +520,22 @@ impl AsusArmouryAttribute {
|
||||
debug!("Store tuning config for {} = {:?}", self.attr.name(), value);
|
||||
}
|
||||
if tuning.enabled {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(value))
|
||||
.map_err(|e| {
|
||||
error!("Could not set value: {e:?}");
|
||||
e
|
||||
})?;
|
||||
// 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 {
|
||||
debug!(
|
||||
"Skipping apply for {} on set_current_value because attribute missing or unsupported (min==max)",
|
||||
self.attr.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.attr
|
||||
@@ -515,12 +576,16 @@ impl AsusArmouryAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn start_attributes_zbus(
|
||||
conn: &Connection,
|
||||
conn: Option<&Connection>,
|
||||
platform: RogPlatform,
|
||||
power: AsusPower,
|
||||
attributes: FirmwareAttributes,
|
||||
config: Arc<Mutex<Config>>,
|
||||
enable_zbus: bool,
|
||||
profile_override: Option<rog_platform::platform::PlatformProfile>,
|
||||
power_plugged_override: Option<bool>,
|
||||
) -> Result<ArmouryAttributeRegistry, RogError> {
|
||||
let mut registry = ArmouryAttributeRegistry::default();
|
||||
for attr in attributes.attributes() {
|
||||
@@ -533,35 +598,115 @@ pub async fn start_attributes_zbus(
|
||||
|
||||
let registry_attr = attr.clone();
|
||||
|
||||
if let Err(e) = attr.reload().await {
|
||||
error!(
|
||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||
attr.attr.name()
|
||||
);
|
||||
// continue with others
|
||||
continue;
|
||||
// Only perform the full reload (which may query the platform/power sysfs)
|
||||
// when zbus is enabled. Tests using the no-zbus mode skip the reload and
|
||||
// emulate the reload/apply behavior to avoid depending on udev/sysfs.
|
||||
if enable_zbus {
|
||||
if let Err(e) = attr.reload().await {
|
||||
error!(
|
||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||
attr.attr.name()
|
||||
);
|
||||
// continue with others
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let attr_name = attr.attribute_name();
|
||||
|
||||
let path = dbus_path_for_attr(attr_name.as_str());
|
||||
match zbus::object_server::SignalEmitter::new(conn, path) {
|
||||
Ok(sig) => {
|
||||
if let Err(e) = attr.watch_and_notify(sig).await {
|
||||
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
|
||||
// If zbus is enabled and a connection is provided, create the SignalEmitter,
|
||||
// start watchers and register the object on zbus. Tests can call this function
|
||||
// with enable_zbus=false and conn=None to skip DBus registration and watchers.
|
||||
if !enable_zbus {
|
||||
// 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
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to create SignalEmitter for '{}': {e:?}",
|
||||
attr.attr.name()
|
||||
} else if let Some(saved_value) = attr.config.lock().await.armoury_settings.get(&name) {
|
||||
attr.attr
|
||||
.set_current_value(&AttrValue::Integer(*saved_value))
|
||||
.map_err(|e| {
|
||||
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 {
|
||||
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
|
||||
continue;
|
||||
// If zbus is enabled and a connection is provided, create the SignalEmitter,
|
||||
// start watchers and register the object on zbus. Tests can call this function
|
||||
// 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);
|
||||
@@ -577,34 +722,50 @@ pub async fn set_config_or_default(
|
||||
) {
|
||||
for attr in attrs.attributes().iter() {
|
||||
let name: FirmwareAttribute = attr.name().into();
|
||||
if name.is_ppt() {
|
||||
if name.is_ppt() || name.is_dgpu() {
|
||||
let tuning = config.select_tunings(power_plugged, profile);
|
||||
if !tuning.enabled {
|
||||
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) {
|
||||
attr.set_current_value(&AttrValue::Integer(*tune))
|
||||
.map_err(|e| {
|
||||
error!("Failed to set {}: {e}", <&str>::from(name));
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
let default = attr.default_value();
|
||||
attr.set_current_value(default)
|
||||
.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
|
||||
if supported {
|
||||
attr.set_current_value(&AttrValue::Integer(*tune))
|
||||
.map_err(|e| {
|
||||
error!("Failed to set {}: {e}", <&str>::from(name));
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
debug!(
|
||||
"Skipping apply for {} in set_config_or_default because attribute missing or unsupported",
|
||||
<&str>::from(name)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Only attempt to apply defaults when the attribute supports a range
|
||||
if supported {
|
||||
let default = attr.default_value();
|
||||
attr.set_current_value(default)
|
||||
.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 {
|
||||
@@ -624,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::sync::Arc;
|
||||
use std::thread::sleep;
|
||||
|
||||
use config_traits::StdConfig;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info, warn};
|
||||
use rog_anime::usb::{
|
||||
pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim,
|
||||
@@ -17,6 +16,7 @@ use rog_anime::usb::{
|
||||
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::usb_raw::USBRaw;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use self::config::{AniMeConfig, AniMeConfigCached};
|
||||
use crate::error::RogError;
|
||||
@@ -51,7 +51,7 @@ impl AniMe {
|
||||
|
||||
/// Will fail if something is already holding the config lock
|
||||
async fn do_init_cache(&mut self) {
|
||||
if let Some(mut config) = self.config.try_lock() {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
if let Err(e) = self.cache.init_from_config(&config, config.anime_type) {
|
||||
error!(
|
||||
"Trying to cache the Anime Config failed, will reset to default config: {e:?}"
|
||||
|
||||
@@ -85,7 +85,7 @@ impl AniMeZbus {
|
||||
/// Set base brightness level
|
||||
#[zbus(property)]
|
||||
async fn brightness(&self) -> Brightness {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.display_brightness;
|
||||
}
|
||||
Brightness::Off
|
||||
@@ -117,7 +117,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn builtins_enabled(&self) -> bool {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.builtin_anims_enabled;
|
||||
}
|
||||
false
|
||||
@@ -162,7 +162,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn builtin_animations(&self) -> Animations {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.builtin_anims;
|
||||
}
|
||||
Animations::default()
|
||||
@@ -195,7 +195,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn enable_display(&self) -> bool {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.display_enabled;
|
||||
}
|
||||
false
|
||||
@@ -218,7 +218,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn off_when_unplugged(&self) -> bool {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.off_when_unplugged;
|
||||
}
|
||||
false
|
||||
@@ -245,7 +245,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn off_when_suspended(&self) -> bool {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.off_when_suspended;
|
||||
}
|
||||
false
|
||||
@@ -261,7 +261,7 @@ impl AniMeZbus {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn off_when_lid_closed(&self) -> bool {
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
return config.off_when_lid_closed;
|
||||
}
|
||||
false
|
||||
|
||||
@@ -231,6 +231,8 @@ impl AuraConfig {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::{Mutex, MutexGuard, OnceLock};
|
||||
|
||||
use rog_aura::keyboard::AuraPowerState;
|
||||
use rog_aura::{
|
||||
AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed,
|
||||
@@ -238,8 +240,20 @@ mod tests {
|
||||
|
||||
use super::AuraConfig;
|
||||
|
||||
// Global mutex to serialize tests that rely on process-wide environment
|
||||
// variables
|
||||
static TEST_MUTEX: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
|
||||
fn test_lock() -> MutexGuard<'static, ()> {
|
||||
TEST_MUTEX
|
||||
.get_or_init(|| Mutex::new(()))
|
||||
.lock()
|
||||
.expect("TEST_MUTEX poisoned")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_multizone_4key_config() {
|
||||
let _guard = test_lock();
|
||||
std::env::set_var("BOARD_NAME", "");
|
||||
let mut config = AuraConfig::new("19b6");
|
||||
|
||||
@@ -295,30 +309,43 @@ mod tests {
|
||||
let res = config.multizone.unwrap();
|
||||
let sta = res.get(&AuraModeNum::Static).unwrap();
|
||||
assert_eq!(sta.len(), 4);
|
||||
assert_eq!(sta[0].colour1, Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xff
|
||||
});
|
||||
assert_eq!(sta[1].colour1, Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0xff
|
||||
});
|
||||
assert_eq!(sta[2].colour1, Colour {
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
});
|
||||
assert_eq!(sta[3].colour1, Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
});
|
||||
assert_eq!(
|
||||
sta[0].colour1,
|
||||
Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xff
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[1].colour1,
|
||||
Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0xff
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[2].colour1,
|
||||
Colour {
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[3].colour1,
|
||||
Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_multizone_multimode_config() {
|
||||
let _guard = test_lock();
|
||||
std::env::set_var("BOARD_NAME", "");
|
||||
let mut config = AuraConfig::new("19b6");
|
||||
|
||||
@@ -367,51 +394,65 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn verify_0x1866_g531i() {
|
||||
let _guard = test_lock();
|
||||
std::env::set_var("BOARD_NAME", "G513I");
|
||||
let mut config = AuraConfig::new("1866");
|
||||
|
||||
assert_eq!(config.brightness, LedBrightness::Med);
|
||||
assert_eq!(config.builtins.len(), 5);
|
||||
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour { r: 166, g: 0, b: 0 },
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right
|
||||
});
|
||||
assert_eq!(
|
||||
config.builtins.first_entry().unwrap().get(),
|
||||
&AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour { r: 166, g: 0, b: 0 },
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right
|
||||
}
|
||||
);
|
||||
assert_eq!(config.enabled.states.len(), 1);
|
||||
assert_eq!(config.enabled.states[0], AuraPowerState {
|
||||
zone: PowerZones::KeyboardAndLightbar,
|
||||
boot: true,
|
||||
awake: true,
|
||||
sleep: true,
|
||||
shutdown: true
|
||||
});
|
||||
assert_eq!(
|
||||
config.enabled.states[0],
|
||||
AuraPowerState {
|
||||
zone: PowerZones::KeyboardAndLightbar,
|
||||
boot: true,
|
||||
awake: true,
|
||||
sleep: true,
|
||||
shutdown: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_0x19b6_g634j() {
|
||||
let _guard = test_lock();
|
||||
std::env::set_var("BOARD_NAME", "G634J");
|
||||
let mut config = AuraConfig::new("19b6");
|
||||
|
||||
assert_eq!(config.brightness, LedBrightness::Med);
|
||||
assert_eq!(config.builtins.len(), 12);
|
||||
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour { r: 166, g: 0, b: 0 },
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right
|
||||
});
|
||||
assert_eq!(
|
||||
config.builtins.first_entry().unwrap().get(),
|
||||
&AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour { r: 166, g: 0, b: 0 },
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right
|
||||
}
|
||||
);
|
||||
assert_eq!(config.enabled.states.len(), 4);
|
||||
assert_eq!(config.enabled.states[0], AuraPowerState {
|
||||
zone: PowerZones::Keyboard,
|
||||
boot: true,
|
||||
awake: true,
|
||||
sleep: true,
|
||||
shutdown: true
|
||||
});
|
||||
assert_eq!(
|
||||
config.enabled.states[0],
|
||||
AuraPowerState {
|
||||
zone: PowerZones::Keyboard,
|
||||
boot: true,
|
||||
awake: true,
|
||||
sleep: true,
|
||||
shutdown: true
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ use std::sync::Arc;
|
||||
|
||||
use config::AuraConfig;
|
||||
use config_traits::StdConfig;
|
||||
use futures_util::lock::{Mutex, MutexGuard};
|
||||
use log::info;
|
||||
use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets};
|
||||
use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET};
|
||||
use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::keyboard_led::KeyboardBacklight;
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ impl AuraZbus {
|
||||
// entirely possible to deadlock here, so use try instead of lock()
|
||||
// let ctrl = self.0.lock().await;
|
||||
// Ok(config.current_mode)
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
Ok(config.current_mode)
|
||||
} else {
|
||||
Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
|
||||
@@ -140,7 +140,7 @@ impl AuraZbus {
|
||||
#[zbus(property)]
|
||||
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
|
||||
// entirely possible to deadlock here, so use try instead of lock()
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
let mode = config.current_mode;
|
||||
match config.builtins.get(&mode) {
|
||||
Some(effect) => Ok(effect.clone()),
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
// - Add it to Zbus server
|
||||
// - If udev sees device removed then remove the zbus path
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use dmi_id::DMIID;
|
||||
use futures_lite::future::block_on;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info, warn};
|
||||
use mio::{Events, Interest, Poll, Token};
|
||||
use rog_platform::error::PlatformError;
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use tokio::sync::Mutex;
|
||||
use udev::{Device, MonitorBuilder};
|
||||
use zbus::zvariant::{ObjectPath, OwnedObjectPath};
|
||||
use zbus::Connection;
|
||||
@@ -92,16 +93,41 @@ fn dev_prop_matches(dev: &Device, prop: &str, value: &str) -> bool {
|
||||
pub struct AsusDevice {
|
||||
device: DeviceHandle,
|
||||
dbus_path: OwnedObjectPath,
|
||||
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 {
|
||||
_dbus_connection: Connection,
|
||||
_hid_handles: HidHandleMap,
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
async fn get_or_create_hid_handle(
|
||||
handles: &HidHandleMap,
|
||||
endpoint: &Device,
|
||||
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
|
||||
let dev_node = endpoint
|
||||
.devnode()
|
||||
.ok_or_else(|| RogError::MissingFunction("hidraw devnode missing".to_string()))?;
|
||||
let key = dev_node.to_string_lossy().to_string();
|
||||
|
||||
if let Some(existing) = handles.lock().await.get(&key).cloned() {
|
||||
return Ok((existing, key));
|
||||
}
|
||||
|
||||
let hidraw = HidRaw::from_device(endpoint.clone())?;
|
||||
let handle = Arc::new(Mutex::new(hidraw));
|
||||
handles.lock().await.insert(key.clone(), handle.clone());
|
||||
Ok((handle, key))
|
||||
}
|
||||
|
||||
async fn init_hid_devices(
|
||||
connection: &Connection,
|
||||
device: Device,
|
||||
handles: HidHandleMap,
|
||||
) -> Result<Vec<AsusDevice>, RogError> {
|
||||
let mut devices = Vec::new();
|
||||
if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? {
|
||||
@@ -116,9 +142,10 @@ impl DeviceManager {
|
||||
// 1. Generate an interface path
|
||||
// 2. Create the device
|
||||
// Use the top-level endpoint, not the parent
|
||||
if let Ok(hidraw) = HidRaw::from_device(device) {
|
||||
if let Ok((dev, hid_key)) =
|
||||
Self::get_or_create_hid_handle(&handles, &device).await
|
||||
{
|
||||
debug!("Testing device {usb_id:?}");
|
||||
let dev = Arc::new(Mutex::new(hidraw));
|
||||
// SLASH DEVICE
|
||||
if let Ok(dev_type) = DeviceHandle::new_slash_hid(
|
||||
dev.clone(),
|
||||
@@ -134,6 +161,7 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: Some(hid_key.clone()),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -152,6 +180,7 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: Some(hid_key.clone()),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -170,9 +199,12 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: Some(hid_key),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Failed to initialise shared hid handle for {usb_id:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +213,10 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
/// To be called on daemon startup
|
||||
async fn init_all_hid(connection: &Connection) -> Result<Vec<AsusDevice>, RogError> {
|
||||
async fn init_all_hid(
|
||||
connection: &Connection,
|
||||
handles: HidHandleMap,
|
||||
) -> Result<Vec<AsusDevice>, RogError> {
|
||||
// track and ensure we use only one hidraw per prod_id
|
||||
// let mut interfaces = HashSet::new();
|
||||
let mut devices: Vec<AsusDevice> = Vec::new();
|
||||
@@ -200,7 +235,7 @@ impl DeviceManager {
|
||||
.scan_devices()
|
||||
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
|
||||
{
|
||||
devices.append(&mut Self::init_hid_devices(connection, device).await?);
|
||||
devices.append(&mut Self::init_hid_devices(connection, device, handles.clone()).await?);
|
||||
}
|
||||
|
||||
Ok(devices)
|
||||
@@ -228,6 +263,7 @@ impl DeviceManager {
|
||||
return Some(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -275,10 +311,13 @@ impl DeviceManager {
|
||||
Ok(devices)
|
||||
}
|
||||
|
||||
pub async fn find_all_devices(connection: &Connection) -> Vec<AsusDevice> {
|
||||
pub async fn find_all_devices(
|
||||
connection: &Connection,
|
||||
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
||||
) -> Vec<AsusDevice> {
|
||||
let mut devices: Vec<AsusDevice> = Vec::new();
|
||||
// HID first, always
|
||||
if let Ok(devs) = &mut Self::init_all_hid(connection).await {
|
||||
if let Ok(devs) = &mut Self::init_all_hid(connection, handles.clone()).await {
|
||||
devices.append(devs);
|
||||
}
|
||||
// USB after, need to check if HID picked something up and if so, skip it
|
||||
@@ -306,6 +345,7 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: None,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -328,6 +368,7 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -355,6 +396,7 @@ impl DeviceManager {
|
||||
devices.push(AsusDevice {
|
||||
device: dev_type,
|
||||
dbus_path: path,
|
||||
hid_key: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -370,16 +412,19 @@ impl DeviceManager {
|
||||
|
||||
pub async fn new(connection: Connection) -> Result<Self, RogError> {
|
||||
let conn_copy = connection.clone();
|
||||
let devices = Self::find_all_devices(&conn_copy).await;
|
||||
let hid_handles = Arc::new(Mutex::new(HashMap::new()));
|
||||
let devices = Self::find_all_devices(&conn_copy, hid_handles.clone()).await;
|
||||
info!("Found {} valid devices on startup", devices.len());
|
||||
let devices = Arc::new(Mutex::new(devices));
|
||||
let manager = Self {
|
||||
_dbus_connection: connection,
|
||||
_hid_handles: hid_handles.clone(),
|
||||
};
|
||||
|
||||
// TODO: The /sysfs/ LEDs don't cause events, so they need to be manually
|
||||
// checked for and added
|
||||
|
||||
let hid_handles_thread = hid_handles.clone();
|
||||
std::thread::spawn(move || {
|
||||
let mut monitor = MonitorBuilder::new()?.listen()?;
|
||||
let mut poll = Poll::new()?;
|
||||
@@ -408,6 +453,7 @@ impl DeviceManager {
|
||||
|
||||
let devices = devices.clone();
|
||||
let conn_copy = conn_copy.clone();
|
||||
let hid_handles = hid_handles_thread.clone();
|
||||
block_on(async move {
|
||||
// SCSCI devs
|
||||
if subsys == "block" {
|
||||
@@ -483,6 +529,7 @@ impl DeviceManager {
|
||||
// Iter in reverse so as to not screw up indexing
|
||||
for index in removals.iter().rev() {
|
||||
let dev = devices.lock().await.remove(*index);
|
||||
let hid_key = dev.hid_key.clone();
|
||||
let path = path.clone();
|
||||
let res = match dev.device {
|
||||
DeviceHandle::Aura(_) => {
|
||||
@@ -512,14 +559,20 @@ impl DeviceManager {
|
||||
_ => todo!(),
|
||||
};
|
||||
info!("AuraManager removed: {path:?}, {res}");
|
||||
if let Some(key) = hid_key {
|
||||
hid_handles.lock().await.remove(&key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if action == "add" {
|
||||
let evdev = event.device();
|
||||
if let Ok(mut new_devs) =
|
||||
Self::init_hid_devices(&conn_copy, evdev)
|
||||
.await
|
||||
.map_err(|e| error!("Couldn't add new device: {e:?}"))
|
||||
if let Ok(mut new_devs) = Self::init_hid_devices(
|
||||
&conn_copy,
|
||||
evdev,
|
||||
hid_handles.clone(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| error!("Couldn't add new device: {e:?}"))
|
||||
{
|
||||
devices.lock().await.append(&mut new_devs);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use config::ScsiConfig;
|
||||
use futures_util::lock::{Mutex, MutexGuard};
|
||||
use rog_scsi::{AuraEffect, Device, Task};
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ impl ScsiZbus {
|
||||
#[zbus(property)]
|
||||
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
|
||||
// entirely possible to deadlock here, so use try instead of lock()
|
||||
if let Some(config) = self.0.config.try_lock() {
|
||||
if let Ok(config) = self.0.config.try_lock() {
|
||||
let mode = config.current_mode;
|
||||
match config.modes.get(&mode) {
|
||||
Some(effect) => Ok(effect.clone()),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use config::SlashConfig;
|
||||
use futures_util::lock::{Mutex, MutexGuard};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::usb_raw::USBRaw;
|
||||
use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode};
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info};
|
||||
use rog_anime::error::AnimeError;
|
||||
use rog_anime::usb::get_anime_type;
|
||||
@@ -13,6 +12,7 @@ use rog_platform::usb_raw::USBRaw;
|
||||
use rog_scsi::{open_device, ScsiType};
|
||||
use rog_slash::error::SlashError;
|
||||
use rog_slash::SlashType;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::aura_anime::config::AniMeConfig;
|
||||
use crate::aura_anime::AniMe;
|
||||
|
||||
@@ -225,6 +225,8 @@ pub struct Config601 {
|
||||
pub nv_dynamic_boost: Option<u8>,
|
||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||
pub nv_temp_target: Option<u8>,
|
||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||
pub nv_tgp: Option<u8>,
|
||||
#[serde(skip)]
|
||||
pub last_power_plugged: u8,
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use config_traits::StdConfig;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{info, warn};
|
||||
use rog_platform::backlight::{Backlight, BacklightType};
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::fdo::Error as FdoErr;
|
||||
use zbus::object_server::SignalEmitter;
|
||||
use zbus::{interface, Connection};
|
||||
@@ -13,7 +13,7 @@ use crate::config::Config;
|
||||
use crate::error::RogError;
|
||||
use crate::ASUS_ZBUS_PATH;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct CtrlBacklight {
|
||||
backlights: Vec<Backlight>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
|
||||
@@ -3,13 +3,13 @@ use std::sync::Arc;
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use futures_lite::StreamExt;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info, warn};
|
||||
use rog_platform::platform::{PlatformProfile, RogPlatform};
|
||||
use rog_profiles::error::ProfileError;
|
||||
use rog_profiles::fan_curve_set::CurveData;
|
||||
use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::object_server::SignalEmitter;
|
||||
use zbus::{interface, Connection};
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use config_traits::StdConfig;
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{debug, error, info, warn};
|
||||
use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes};
|
||||
use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP};
|
||||
use rog_platform::platform::{PlatformProfile, Properties, RogPlatform};
|
||||
use rog_platform::power::AsusPower;
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::fdo::Error as FdoErr;
|
||||
use zbus::object_server::SignalEmitter;
|
||||
use zbus::{interface, Connection};
|
||||
@@ -51,6 +51,7 @@ pub struct CtrlPlatform {
|
||||
}
|
||||
|
||||
impl CtrlPlatform {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
platform: RogPlatform,
|
||||
power: AsusPower,
|
||||
@@ -167,7 +168,7 @@ impl CtrlPlatform {
|
||||
.map(|s| s.to_string())
|
||||
.collect()
|
||||
};
|
||||
if prog.len() > 1 {
|
||||
if (!prog.is_empty()) && (!prog[0].is_empty()) {
|
||||
let mut cmd = Command::new(&prog[0]);
|
||||
for arg in prog.iter().skip(1) {
|
||||
cmd.arg(arg);
|
||||
@@ -565,7 +566,7 @@ impl CtrlPlatform {
|
||||
|
||||
for attr in self.attributes.attributes() {
|
||||
let name: FirmwareAttribute = attr.name().into();
|
||||
if name.is_ppt() {
|
||||
if name.is_ppt() || name.is_dgpu() {
|
||||
// reset stored value
|
||||
if let Some(tune) = self
|
||||
.config
|
||||
|
||||
@@ -11,15 +11,17 @@ use asusd::ctrl_fancurves::CtrlFanCurveZbus;
|
||||
use asusd::ctrl_platform::CtrlPlatform;
|
||||
use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME};
|
||||
use config_traits::{StdConfig, StdConfigLoad2};
|
||||
use futures_util::lock::Mutex;
|
||||
use log::{error, info};
|
||||
use rog_platform::asus_armoury::FirmwareAttributes;
|
||||
use rog_platform::platform::RogPlatform;
|
||||
use rog_platform::power::AsusPower;
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::fdo::ObjectManager;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Starting asusd daemon...");
|
||||
|
||||
// console_subscriber::init();
|
||||
let mut logger = env_logger::Builder::new();
|
||||
logger
|
||||
@@ -75,15 +77,21 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
let power = AsusPower::new()?; // TODO: maybe needs async mutex?
|
||||
let attributes = FirmwareAttributes::new();
|
||||
let armoury_registry = match start_attributes_zbus(
|
||||
&server,
|
||||
Some(&server),
|
||||
platform.clone(),
|
||||
power.clone(),
|
||||
attributes.clone(),
|
||||
config.clone(),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(registry) => registry,
|
||||
Ok(registry) => {
|
||||
info!("attribute on zbus initialized");
|
||||
registry
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to initialize firmware attributes over zbus: {e:?}");
|
||||
ArmouryAttributeRegistry::default()
|
||||
@@ -92,8 +100,10 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
match CtrlFanCurveZbus::new() {
|
||||
Ok(ctrl) => {
|
||||
info!("FanCurves: found supported fancurves");
|
||||
let sig_ctx = CtrlFanCurveZbus::signal_context(&server)?;
|
||||
start_tasks(ctrl, &mut server, sig_ctx).await?;
|
||||
info!("FanCurves: initialized");
|
||||
}
|
||||
Err(err) => {
|
||||
error!("FanCurves: {}", err);
|
||||
@@ -102,8 +112,10 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
match CtrlBacklight::new(config.clone()) {
|
||||
Ok(backlight) => {
|
||||
info!("Backlight: found supported backlight");
|
||||
backlight.start_watch_primary().await?;
|
||||
backlight.add_to_server(&mut server).await;
|
||||
info!("Backlight: initialized");
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Backlight: {}", err);
|
||||
@@ -121,8 +133,10 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
armoury_registry,
|
||||
) {
|
||||
Ok(ctrl) => {
|
||||
info!("CtrlPlatform: initialized");
|
||||
let sig_ctx = CtrlPlatform::signal_context(&server)?;
|
||||
start_tasks(ctrl, &mut server, sig_ctx).await?;
|
||||
info!("CtrlPlatform: tasks started");
|
||||
}
|
||||
Err(err) => {
|
||||
error!("CtrlPlatform: {}", err);
|
||||
@@ -131,10 +145,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let _ = DeviceManager::new(server.clone()).await?;
|
||||
|
||||
info!("DeviceManager initialized");
|
||||
|
||||
// Request dbus name after finishing initalizing all functions
|
||||
server.request_name(DBUS_NAME).await?;
|
||||
|
||||
info!("Startup success, begining dbus server loop");
|
||||
info!("Startup success on dbus name {DBUS_NAME}: begining dbus server loop");
|
||||
loop {
|
||||
// This is just a blocker to idle and ensure the reator reacts
|
||||
server.executor().tick().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");
|
||||
}
|
||||
@@ -15,7 +15,7 @@ ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
|
||||
GOTO="asusd_end"
|
||||
|
||||
LABEL="asusd_start"
|
||||
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
||||
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", RUN+="/usr/bin/systemctl restart asusd.service"
|
||||
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
|
||||
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
|
||||
|
||||
LABEL="asusd_end"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
%global debug_package %{nil}
|
||||
%endif
|
||||
|
||||
%define version 6.1.15
|
||||
%define version 6.1.17
|
||||
%define specrelease %{?dist}
|
||||
%define pkg_release 9%{specrelease}
|
||||
|
||||
@@ -92,7 +92,9 @@ EOF
|
||||
%build
|
||||
export RUSTFLAGS="%{rustflags}"
|
||||
%if %{defined fedora}
|
||||
%cargo_build
|
||||
%# Use an explicit cargo invocation for Fedora to avoid the macro adding `--locked`.
|
||||
%# `--locked` breaks Fedora builds because the lockfile may not be appropriate for the distro buildroot.
|
||||
/usr/bin/cargo auditable build --release
|
||||
%else
|
||||
/usr/bin/cargo auditable build --release
|
||||
%endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -14,7 +14,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -23,7 +23,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -32,7 +32,7 @@
|
||||
layout_name: "fa507",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -41,7 +41,7 @@
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -50,7 +50,7 @@
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -59,7 +59,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -68,7 +68,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -77,7 +77,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -86,7 +86,16 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
device_name: "FX607J",
|
||||
product_id: "",
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -95,7 +104,7 @@
|
||||
layout_name: "fa506i",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -104,16 +113,16 @@
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
(
|
||||
device_name: "FX706H",
|
||||
product_id: "",
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, RainbowCycle],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -122,7 +131,7 @@
|
||||
layout_name: "g512",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -140,7 +149,7 @@
|
||||
layout_name: "g513i",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -185,7 +194,7 @@
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -194,7 +203,7 @@
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -239,7 +248,16 @@
|
||||
layout_name: "g634j-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
device_name: "G614JIR",
|
||||
product_id: "",
|
||||
layout_name: "g513i-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -248,7 +266,7 @@
|
||||
layout_name: "g634j-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -257,7 +275,7 @@
|
||||
layout_name: "g634j-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -275,7 +293,7 @@
|
||||
layout_name: "gl503",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -284,7 +302,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -293,7 +311,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -302,7 +320,7 @@
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -311,7 +329,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -320,7 +338,7 @@
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -329,7 +347,7 @@
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -365,7 +383,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -383,7 +401,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
@@ -401,7 +419,7 @@
|
||||
layout_name: "g533q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -410,7 +428,7 @@
|
||||
layout_name: "g533q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -419,7 +437,7 @@
|
||||
layout_name: "g533q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -482,7 +500,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -491,7 +509,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -500,7 +518,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -509,7 +527,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -518,7 +536,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -527,7 +545,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -536,7 +554,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -545,7 +563,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -554,7 +572,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -563,7 +581,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -572,7 +590,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -590,7 +608,7 @@
|
||||
layout_name: "gl503",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -599,7 +617,7 @@
|
||||
layout_name: "gl503",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -608,7 +626,7 @@
|
||||
layout_name: "gl503",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -626,7 +644,7 @@
|
||||
layout_name: "g533q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -635,7 +653,7 @@
|
||||
layout_name: "gl503",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -644,7 +662,7 @@
|
||||
layout_name: "fa507",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -692,6 +710,15 @@
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
device_name: "GU605C",
|
||||
product_id: "",
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
device_name: "GU605M",
|
||||
product_id: "",
|
||||
@@ -707,7 +734,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -716,7 +743,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -725,7 +752,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -734,7 +761,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -752,7 +779,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -770,7 +797,7 @@
|
||||
layout_name: "gx531-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -824,7 +851,7 @@
|
||||
layout_name: "gx531-per-key",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -833,7 +860,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -842,7 +869,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -851,8 +878,8 @@
|
||||
layout_name: "",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [None],
|
||||
advanced_type: r#None,
|
||||
power_zones: [r#None],
|
||||
),
|
||||
(
|
||||
device_name: "GZ301Z",
|
||||
@@ -860,7 +887,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
@@ -869,7 +896,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Ally],
|
||||
),
|
||||
(
|
||||
@@ -878,7 +905,7 @@
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: r#None,
|
||||
power_zones: [Ally],
|
||||
),
|
||||
])
|
||||
])
|
||||
@@ -164,7 +164,29 @@ impl LedSupportFile {
|
||||
return Some(data);
|
||||
}
|
||||
|
||||
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
||||
// If the system-wide support files were not available (e.g. running
|
||||
// tests in CI or a development environment) try to load the
|
||||
// bundled test data shipped with the crate under `data/aura_support.ron`.
|
||||
// This allows unit tests to run without requiring files to be installed
|
||||
// to `/usr/share/asusd`.
|
||||
let mut bundled = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
bundled.push("data/aura_support.ron");
|
||||
if let Ok(buf) = std::fs::read_to_string(&bundled) {
|
||||
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&buf) {
|
||||
data.0.append(&mut tmp.0);
|
||||
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
|
||||
info!("Loaded bundled LED support data from {}", bundled.display());
|
||||
return Some(data);
|
||||
} else {
|
||||
warn!(
|
||||
"Bundled aura_support.ron present but failed to parse: {}",
|
||||
bundled.display()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,12 +207,14 @@ mod tests {
|
||||
fn single_key_next_state_then_create() {
|
||||
let layout = KeyLayout::default_layout();
|
||||
let mut seq = AdvancedEffects::new(false);
|
||||
seq.effects
|
||||
.push(Effect::Static(Static::new(LedCode::F, Colour {
|
||||
seq.effects.push(Effect::Static(Static::new(
|
||||
LedCode::F,
|
||||
Colour {
|
||||
r: 255,
|
||||
g: 127,
|
||||
b: 0,
|
||||
})));
|
||||
},
|
||||
)));
|
||||
|
||||
seq.next_state(&layout);
|
||||
let packets = seq.create_packets();
|
||||
|
||||
@@ -335,93 +335,117 @@ impl KeyLayout {
|
||||
KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1),
|
||||
)]),
|
||||
key_rows: vec![
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::Esc, "regular".to_owned()),
|
||||
(LedCode::F1, "regular".to_owned()),
|
||||
(LedCode::F2, "regular".to_owned()),
|
||||
(LedCode::F3, "regular".to_owned()),
|
||||
(LedCode::F4, "regular".to_owned()),
|
||||
// not sure which key to put here
|
||||
(LedCode::F5, "regular".to_owned()),
|
||||
(LedCode::F6, "regular".to_owned()),
|
||||
(LedCode::F7, "regular".to_owned()),
|
||||
(LedCode::F8, "regular".to_owned()),
|
||||
(LedCode::F9, "regular".to_owned()),
|
||||
(LedCode::F10, "regular".to_owned()),
|
||||
(LedCode::F11, "regular".to_owned()),
|
||||
(LedCode::F12, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::Tilde, "regular".to_owned()),
|
||||
(LedCode::N1, "regular".to_owned()),
|
||||
(LedCode::N2, "regular".to_owned()),
|
||||
(LedCode::N3, "regular".to_owned()),
|
||||
(LedCode::N4, "regular".to_owned()),
|
||||
(LedCode::N5, "regular".to_owned()),
|
||||
(LedCode::N6, "regular".to_owned()),
|
||||
(LedCode::N7, "regular".to_owned()),
|
||||
(LedCode::N8, "regular".to_owned()),
|
||||
(LedCode::N9, "regular".to_owned()),
|
||||
(LedCode::N0, "regular".to_owned()),
|
||||
(LedCode::Hyphen, "regular".to_owned()),
|
||||
(LedCode::Equals, "regular".to_owned()),
|
||||
(LedCode::Backspace, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::Tab, "regular".to_owned()),
|
||||
(LedCode::Q, "regular".to_owned()),
|
||||
(LedCode::W, "regular".to_owned()),
|
||||
(LedCode::E, "regular".to_owned()),
|
||||
(LedCode::R, "regular".to_owned()),
|
||||
(LedCode::T, "regular".to_owned()),
|
||||
(LedCode::Y, "regular".to_owned()),
|
||||
(LedCode::U, "regular".to_owned()),
|
||||
(LedCode::I, "regular".to_owned()),
|
||||
(LedCode::O, "regular".to_owned()),
|
||||
(LedCode::P, "regular".to_owned()),
|
||||
(LedCode::LBracket, "regular".to_owned()),
|
||||
(LedCode::RBracket, "regular".to_owned()),
|
||||
(LedCode::BackSlash, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::Caps, "regular".to_owned()),
|
||||
(LedCode::A, "regular".to_owned()),
|
||||
(LedCode::S, "regular".to_owned()),
|
||||
(LedCode::D, "regular".to_owned()),
|
||||
(LedCode::F, "regular".to_owned()),
|
||||
(LedCode::G, "regular".to_owned()),
|
||||
(LedCode::H, "regular".to_owned()),
|
||||
(LedCode::J, "regular".to_owned()),
|
||||
(LedCode::K, "regular".to_owned()),
|
||||
(LedCode::L, "regular".to_owned()),
|
||||
(LedCode::SemiColon, "regular".to_owned()),
|
||||
(LedCode::Quote, "regular".to_owned()),
|
||||
(LedCode::Return, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::LShift, "regular".to_owned()),
|
||||
(LedCode::Z, "regular".to_owned()),
|
||||
(LedCode::X, "regular".to_owned()),
|
||||
(LedCode::C, "regular".to_owned()),
|
||||
(LedCode::V, "regular".to_owned()),
|
||||
(LedCode::B, "regular".to_owned()),
|
||||
(LedCode::N, "regular".to_owned()),
|
||||
(LedCode::M, "regular".to_owned()),
|
||||
(LedCode::Comma, "regular".to_owned()),
|
||||
(LedCode::Period, "regular".to_owned()),
|
||||
(LedCode::FwdSlash, "regular".to_owned()),
|
||||
(LedCode::Rshift, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(0.1, 0.1, vec![
|
||||
(LedCode::LCtrl, "regular".to_owned()),
|
||||
(LedCode::LFn, "regular".to_owned()),
|
||||
(LedCode::Meta, "regular".to_owned()),
|
||||
(LedCode::LAlt, "regular".to_owned()),
|
||||
(LedCode::Spacebar, "regular".to_owned()),
|
||||
(LedCode::RAlt, "regular".to_owned()),
|
||||
(LedCode::PrtSc, "regular".to_owned()),
|
||||
(LedCode::RCtrl, "regular".to_owned()),
|
||||
]),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::Esc, "regular".to_owned()),
|
||||
(LedCode::F1, "regular".to_owned()),
|
||||
(LedCode::F2, "regular".to_owned()),
|
||||
(LedCode::F3, "regular".to_owned()),
|
||||
(LedCode::F4, "regular".to_owned()),
|
||||
// not sure which key to put here
|
||||
(LedCode::F5, "regular".to_owned()),
|
||||
(LedCode::F6, "regular".to_owned()),
|
||||
(LedCode::F7, "regular".to_owned()),
|
||||
(LedCode::F8, "regular".to_owned()),
|
||||
(LedCode::F9, "regular".to_owned()),
|
||||
(LedCode::F10, "regular".to_owned()),
|
||||
(LedCode::F11, "regular".to_owned()),
|
||||
(LedCode::F12, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::Tilde, "regular".to_owned()),
|
||||
(LedCode::N1, "regular".to_owned()),
|
||||
(LedCode::N2, "regular".to_owned()),
|
||||
(LedCode::N3, "regular".to_owned()),
|
||||
(LedCode::N4, "regular".to_owned()),
|
||||
(LedCode::N5, "regular".to_owned()),
|
||||
(LedCode::N6, "regular".to_owned()),
|
||||
(LedCode::N7, "regular".to_owned()),
|
||||
(LedCode::N8, "regular".to_owned()),
|
||||
(LedCode::N9, "regular".to_owned()),
|
||||
(LedCode::N0, "regular".to_owned()),
|
||||
(LedCode::Hyphen, "regular".to_owned()),
|
||||
(LedCode::Equals, "regular".to_owned()),
|
||||
(LedCode::Backspace, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::Tab, "regular".to_owned()),
|
||||
(LedCode::Q, "regular".to_owned()),
|
||||
(LedCode::W, "regular".to_owned()),
|
||||
(LedCode::E, "regular".to_owned()),
|
||||
(LedCode::R, "regular".to_owned()),
|
||||
(LedCode::T, "regular".to_owned()),
|
||||
(LedCode::Y, "regular".to_owned()),
|
||||
(LedCode::U, "regular".to_owned()),
|
||||
(LedCode::I, "regular".to_owned()),
|
||||
(LedCode::O, "regular".to_owned()),
|
||||
(LedCode::P, "regular".to_owned()),
|
||||
(LedCode::LBracket, "regular".to_owned()),
|
||||
(LedCode::RBracket, "regular".to_owned()),
|
||||
(LedCode::BackSlash, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::Caps, "regular".to_owned()),
|
||||
(LedCode::A, "regular".to_owned()),
|
||||
(LedCode::S, "regular".to_owned()),
|
||||
(LedCode::D, "regular".to_owned()),
|
||||
(LedCode::F, "regular".to_owned()),
|
||||
(LedCode::G, "regular".to_owned()),
|
||||
(LedCode::H, "regular".to_owned()),
|
||||
(LedCode::J, "regular".to_owned()),
|
||||
(LedCode::K, "regular".to_owned()),
|
||||
(LedCode::L, "regular".to_owned()),
|
||||
(LedCode::SemiColon, "regular".to_owned()),
|
||||
(LedCode::Quote, "regular".to_owned()),
|
||||
(LedCode::Return, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::LShift, "regular".to_owned()),
|
||||
(LedCode::Z, "regular".to_owned()),
|
||||
(LedCode::X, "regular".to_owned()),
|
||||
(LedCode::C, "regular".to_owned()),
|
||||
(LedCode::V, "regular".to_owned()),
|
||||
(LedCode::B, "regular".to_owned()),
|
||||
(LedCode::N, "regular".to_owned()),
|
||||
(LedCode::M, "regular".to_owned()),
|
||||
(LedCode::Comma, "regular".to_owned()),
|
||||
(LedCode::Period, "regular".to_owned()),
|
||||
(LedCode::FwdSlash, "regular".to_owned()),
|
||||
(LedCode::Rshift, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
KeyRow::new(
|
||||
0.1,
|
||||
0.1,
|
||||
vec![
|
||||
(LedCode::LCtrl, "regular".to_owned()),
|
||||
(LedCode::LFn, "regular".to_owned()),
|
||||
(LedCode::Meta, "regular".to_owned()),
|
||||
(LedCode::LAlt, "regular".to_owned()),
|
||||
(LedCode::Spacebar, "regular".to_owned()),
|
||||
(LedCode::RAlt, "regular".to_owned()),
|
||||
(LedCode::PrtSc, "regular".to_owned()),
|
||||
(LedCode::RCtrl, "regular".to_owned()),
|
||||
],
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ edition.workspace = true
|
||||
default = []
|
||||
mocking = []
|
||||
x11 = ["slint/backend-winit-x11"]
|
||||
# Requires RUSTFLAGS="--cfg tokio_unstable"
|
||||
# Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
|
||||
tokio-debug = ["console-subscriber"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -24,4 +24,6 @@ pub struct CliStart {
|
||||
that might match your laptop"
|
||||
)]
|
||||
pub layout_viewing: bool,
|
||||
#[options(help = "start in tray mode - main window hidden")]
|
||||
pub tray_mode: bool,
|
||||
}
|
||||
|
||||
@@ -140,12 +140,22 @@ async fn main() -> Result<()> {
|
||||
config.startup_in_background = false;
|
||||
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();
|
||||
|
||||
let enable_tray_icon = config.enable_tray_icon;
|
||||
let startup_in_background = config.startup_in_background;
|
||||
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)?;
|
||||
|
||||
if enable_tray_icon {
|
||||
@@ -170,12 +180,14 @@ async fn main() -> Result<()> {
|
||||
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
|
||||
}
|
||||
|
||||
let config_for_ui = config.clone();
|
||||
let ui_handle_for_thread = ui_handle.clone();
|
||||
thread::spawn(move || {
|
||||
let mut state = AppState::StartingUp;
|
||||
loop {
|
||||
if is_rog_ally {
|
||||
let config_copy_2 = config.clone();
|
||||
let newui = setup_window(config.clone());
|
||||
let config_copy_2 = config_for_ui.clone();
|
||||
let newui = setup_window(config_for_ui.clone());
|
||||
newui.window().on_close_requested(move || {
|
||||
exit(0);
|
||||
});
|
||||
@@ -211,13 +223,19 @@ async fn main() -> Result<()> {
|
||||
*app_state = AppState::MainWindowOpen;
|
||||
}
|
||||
|
||||
let config_copy = config.clone();
|
||||
let config_copy = config_for_ui.clone();
|
||||
let app_state_copy = app_state.clone();
|
||||
let ui_handle_for_ui = ui_handle_for_thread.clone();
|
||||
slint::invoke_from_event_loop(move || {
|
||||
let ui_handle_for_ui = ui_handle_for_ui.clone();
|
||||
UI.with(|ui| {
|
||||
let app_state_copy = app_state_copy.clone();
|
||||
let mut ui = ui.borrow_mut();
|
||||
if let Some(ui) = ui.as_mut() {
|
||||
// store weak handle so other threads can update UI globals
|
||||
if let Ok(mut h) = ui_handle_for_ui.lock() {
|
||||
*h = Some(ui.as_weak());
|
||||
}
|
||||
ui.window().show().unwrap();
|
||||
ui.window().on_close_requested(move || {
|
||||
if let Ok(mut app_state) = app_state_copy.lock() {
|
||||
@@ -228,6 +246,10 @@ async fn main() -> Result<()> {
|
||||
} 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;
|
||||
@@ -263,8 +285,8 @@ async fn main() -> Result<()> {
|
||||
slint::quit_event_loop().unwrap();
|
||||
exit(0);
|
||||
} else if state != AppState::MainWindowOpen {
|
||||
if let Ok(config) = config.lock() {
|
||||
if !config.run_in_background {
|
||||
if let Ok(cfg) = config_for_ui.lock() {
|
||||
if !cfg.run_in_background {
|
||||
slint::quit_event_loop().unwrap();
|
||||
exit(0);
|
||||
}
|
||||
@@ -274,11 +296,67 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
});
|
||||
|
||||
// start config watcher to pick up external edits
|
||||
spawn_config_watcher(config.clone(), ui_handle.clone());
|
||||
|
||||
slint::run_event_loop_until_quit().unwrap();
|
||||
rt.shutdown_background();
|
||||
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 {
|
||||
if parsed.help {
|
||||
println!("{}", CliStart::usage());
|
||||
|
||||
@@ -100,6 +100,31 @@ impl Bios {
|
||||
pub fn set_panel_od(&self, _b: bool) -> Result<()> {
|
||||
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;
|
||||
|
||||
@@ -116,26 +116,26 @@ pub fn start_notifications(
|
||||
|
||||
if p == 0 && p != last_state {
|
||||
let prog: Vec<&str> = bat.split_whitespace().collect();
|
||||
if prog.len() > 1 {
|
||||
if (!prog.is_empty()) && (!prog[0].is_empty()) {
|
||||
let mut cmd = Command::new(prog[0]);
|
||||
|
||||
for arg in prog.iter().skip(1) {
|
||||
cmd.arg(*arg);
|
||||
}
|
||||
cmd.spawn()
|
||||
.map_err(|e| error!("AC command error: {e:?}"))
|
||||
.map_err(|e| error!("Battery power command error: {e:?}"))
|
||||
.ok();
|
||||
}
|
||||
} else if p != last_state {
|
||||
let prog: Vec<&str> = ac.split_whitespace().collect();
|
||||
if prog.len() > 1 {
|
||||
if (!prog.is_empty()) && (!prog[0].is_empty()) {
|
||||
let mut cmd = Command::new(prog[0]);
|
||||
|
||||
for arg in prog.iter().skip(1) {
|
||||
cmd.arg(*arg);
|
||||
}
|
||||
cmd.spawn()
|
||||
.map_err(|e| error!("AC command error: {e:?}"))
|
||||
.map_err(|e| error!("AC power command error: {e:?}"))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
@@ -203,11 +203,19 @@ pub fn start_notifications(
|
||||
})?;
|
||||
|
||||
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 {
|
||||
@@ -309,7 +317,9 @@ fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> R
|
||||
//.hint(Hint::Resident(true))
|
||||
.hint(Hint::Category("device".into()))
|
||||
.urgency(Urgency::Critical)
|
||||
.timeout(Timeout::Never)
|
||||
// For user-action notifications keep them visible if they require interaction
|
||||
// but for non-interactive actions we prefer they auto-hide like other notifs.
|
||||
.timeout(Timeout::Milliseconds(6000))
|
||||
.icon("dialog-warning")
|
||||
.hint(Hint::Transient(true));
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ pub fn setup_system_page(ui: &MainWindow, _config: Arc<Mutex<Config>>) {
|
||||
ui.global::<SystemPageData>().set_platform_profile(-1);
|
||||
ui.global::<SystemPageData>().set_panel_overdrive(-1);
|
||||
ui.global::<SystemPageData>().set_boot_sound(-1);
|
||||
ui.global::<SystemPageData>().set_screen_auto_brightness(-1);
|
||||
ui.global::<SystemPageData>().set_mcu_powersave(-1);
|
||||
ui.global::<SystemPageData>().set_mini_led_mode(-1);
|
||||
ui.global::<SystemPageData>().set_screenpad_brightness(-1);
|
||||
ui.global::<SystemPageData>().set_ppt_pl1_spl(MINMAX);
|
||||
@@ -128,6 +130,51 @@ macro_rules! init_minmax_property {
|
||||
|
||||
// For handling callbacks from UI value changes
|
||||
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) => {
|
||||
let handle_copy = $handle.as_weak();
|
||||
let proxy_copy = $attr.clone();
|
||||
@@ -138,12 +185,28 @@ macro_rules! setup_callback {
|
||||
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,
|
||||
proxy_copy.set_current_value(convert_to_dbus!($type, v)).await,
|
||||
handle_copy.clone(),
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -308,6 +371,7 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
|
||||
|
||||
let platform_copy = platform.clone();
|
||||
if let Ok(mut value) = platform.platform_profile_choices().await {
|
||||
debug!("Available platform profile choices: {:?}", value);
|
||||
handle
|
||||
.upgrade_in_event_loop(move |handle| {
|
||||
value.sort();
|
||||
@@ -519,7 +583,7 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
|
||||
set_ui_callbacks!(handle,
|
||||
SystemPageData(as i32),
|
||||
platform_copy.platform_profile_on_battery(.into()),
|
||||
"Throttle policy on abttery set to {}",
|
||||
"Throttle policy on battery set to {}",
|
||||
"Setting Throttle policy on battery failed"
|
||||
);
|
||||
set_ui_callbacks!(handle,
|
||||
@@ -612,49 +676,49 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
|
||||
}
|
||||
FirmwareAttribute::PptPl1Spl => {
|
||||
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_minmax_external!(ppt_pl1_spl, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::PptPl2Sppt => {
|
||||
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_minmax_external!(ppt_pl2_sppt, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::PptPl3Fppt => {
|
||||
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_minmax_external!(ppt_pl3_fppt, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::PptFppt => {
|
||||
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_minmax_external!(ppt_fppt, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::PptApuSppt => {
|
||||
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_minmax_external!(ppt_apu_sppt, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::PptPlatformSppt => {
|
||||
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_minmax_external!(ppt_platform_sppt, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::NvDynamicBoost => {
|
||||
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_minmax_external!(nv_dynamic_boost, handle, attr, platform);
|
||||
}
|
||||
FirmwareAttribute::NvTempTarget => {
|
||||
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_minmax_external!(nv_temp_target, handle, attr, platform);
|
||||
}
|
||||
@@ -666,7 +730,16 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
|
||||
setup_callback!(boot_sound, handle, attr, i32);
|
||||
setup_external!(boot_sound, i32, handle, attr, value)
|
||||
}
|
||||
FirmwareAttribute::McuPowersave => {}
|
||||
FirmwareAttribute::ScreenAutoBrightness => {
|
||||
init_property!(screen_auto_brightness, handle, value, i32);
|
||||
setup_callback!(screen_auto_brightness, handle, attr, i32);
|
||||
setup_external!(screen_auto_brightness, i32, handle, attr, value)
|
||||
}
|
||||
FirmwareAttribute::McuPowersave => {
|
||||
init_property!(mcu_powersave, handle, value, i32);
|
||||
setup_callback!(mcu_powersave, handle, attr, i32);
|
||||
setup_external!(mcu_powersave, i32, handle, attr, value)
|
||||
}
|
||||
FirmwareAttribute::PanelOverdrive => {
|
||||
init_property!(panel_overdrive, handle, value, i32);
|
||||
setup_callback!(panel_overdrive, handle, attr, i32);
|
||||
|
||||
@@ -51,6 +51,10 @@ export global SystemPageData {
|
||||
callback cb_panel_overdrive(int);
|
||||
in-out property <int> boot_sound;
|
||||
callback cb_boot_sound(int);
|
||||
in-out property <int> screen_auto_brightness;
|
||||
callback cb_screen_auto_brightness(int);
|
||||
in-out property <int> mcu_powersave;
|
||||
callback cb_mcu_powersave(int);
|
||||
in-out property <int> mini_led_mode;
|
||||
callback cb_mini_led_mode(int);
|
||||
|
||||
@@ -300,6 +304,22 @@ export component PageSystem inherits Rectangle {
|
||||
SystemPageData.cb_boot_sound(SystemPageData.boot_sound)
|
||||
}
|
||||
}
|
||||
|
||||
if SystemPageData.screen_auto_brightness != -1: SystemToggleInt {
|
||||
text: @tr("Screen Auto Brightness");
|
||||
checked_int <=> SystemPageData.screen_auto_brightness;
|
||||
toggled => {
|
||||
SystemPageData.cb_screen_auto_brightness(SystemPageData.screen_auto_brightness)
|
||||
}
|
||||
}
|
||||
|
||||
if SystemPageData.mcu_powersave != -1: SystemToggleInt {
|
||||
text: @tr("MCU Powersave");
|
||||
checked_int <=> SystemPageData.mcu_powersave;
|
||||
toggled => {
|
||||
SystemPageData.cb_mcu_powersave(SystemPageData.mcu_powersave)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SystemPageData.ppt_pl1_spl.max > 0 && SystemPageData.ppt_pl1_spl.current != -1) || (SystemPageData.ppt_pl2_sppt.max > 0 && SystemPageData.ppt_pl2_sppt.current != -1) || (SystemPageData.ppt_pl3_fppt.max > 0 && SystemPageData.ppt_pl3_fppt.current != -1) || (SystemPageData.ppt_fppt.max > 0 && SystemPageData.ppt_fppt.current != -1) || (SystemPageData.ppt_apu_sppt.max > 0 && SystemPageData.ppt_apu_sppt.current != -1) || (SystemPageData.nv_temp_target.max > 0 && SystemPageData.nv_temp_target.current != -1) || (SystemPageData.nv_dynamic_boost.max > 0 && SystemPageData.nv_dynamic_boost.current != -1): HorizontalLayout {
|
||||
|
||||
@@ -95,7 +95,7 @@ impl Attribute {
|
||||
_ => 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())?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -244,6 +244,37 @@ impl FirmwareAttributes {
|
||||
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> {
|
||||
&self.attrs
|
||||
}
|
||||
@@ -272,15 +303,35 @@ macro_rules! define_attribute_getters {
|
||||
}
|
||||
|
||||
define_attribute_getters!(
|
||||
apu_mem, cores_performance, cores_efficiency, ppt_pl1_spl, ppt_pl2_sppt, ppt_apu_sppt,
|
||||
ppt_platform_sppt, ppt_fppt, nv_dynamic_boost, nv_temp_target, dgpu_base_tgp, dgpu_tgp,
|
||||
charge_mode, boot_sound, mcu_powersave, panel_od, panel_hd_mode, egpu_connected, egpu_enable,
|
||||
dgpu_disable, gpu_mux_mode, mini_led_mode
|
||||
apu_mem,
|
||||
cores_performance,
|
||||
cores_efficiency,
|
||||
ppt_pl1_spl,
|
||||
ppt_pl2_sppt,
|
||||
ppt_apu_sppt,
|
||||
ppt_platform_sppt,
|
||||
ppt_fppt,
|
||||
nv_dynamic_boost,
|
||||
nv_temp_target,
|
||||
nv_base_tgp,
|
||||
nv_tgp,
|
||||
charge_mode,
|
||||
boot_sound,
|
||||
mcu_powersave,
|
||||
panel_od,
|
||||
panel_hd_mode,
|
||||
egpu_connected,
|
||||
egpu_enable,
|
||||
dgpu_disable,
|
||||
gpu_mux_mode,
|
||||
mini_led_mode,
|
||||
screen_auto_brightness
|
||||
);
|
||||
|
||||
/// CamelCase names of the properties. Intended for use with DBUS
|
||||
#[repr(u8)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Serialize,
|
||||
@@ -322,6 +373,7 @@ pub enum FirmwareAttribute {
|
||||
PendingReboot = 23,
|
||||
PptEnabled = 24,
|
||||
None = 25,
|
||||
ScreenAutoBrightness = 26,
|
||||
}
|
||||
|
||||
impl FirmwareAttribute {
|
||||
@@ -342,6 +394,7 @@ impl FirmwareAttribute {
|
||||
self,
|
||||
FirmwareAttribute::NvDynamicBoost
|
||||
| FirmwareAttribute::NvTempTarget
|
||||
| FirmwareAttribute::DgpuBaseTgp
|
||||
| FirmwareAttribute::DgpuTgp
|
||||
)
|
||||
}
|
||||
@@ -362,8 +415,11 @@ impl From<&str> for FirmwareAttribute {
|
||||
"ppt_platform_sppt" => Self::PptPlatformSppt,
|
||||
"nv_dynamic_boost" => Self::NvDynamicBoost,
|
||||
"nv_temp_target" => Self::NvTempTarget,
|
||||
"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,
|
||||
"boot_sound" => Self::BootSound,
|
||||
"mcu_powersave" => Self::McuPowersave,
|
||||
@@ -375,6 +431,7 @@ impl From<&str> for FirmwareAttribute {
|
||||
"gpu_mux_mode" => Self::GpuMuxMode,
|
||||
"mini_led_mode" => Self::MiniLedMode,
|
||||
"pending_reboot" => Self::PendingReboot,
|
||||
"screen_auto_brightness" => Self::ScreenAutoBrightness,
|
||||
_ => {
|
||||
error!("Invalid firmware attribute: {}", s);
|
||||
Self::None
|
||||
@@ -398,8 +455,8 @@ impl From<FirmwareAttribute> for &str {
|
||||
FirmwareAttribute::PptPlatformSppt => "ppt_platform_sppt",
|
||||
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
|
||||
FirmwareAttribute::NvTempTarget => "nv_temp_target",
|
||||
FirmwareAttribute::DgpuBaseTgp => "dgpu_base_tgp",
|
||||
FirmwareAttribute::DgpuTgp => "dgpu_tgp",
|
||||
FirmwareAttribute::DgpuBaseTgp => "nv_base_tgp",
|
||||
FirmwareAttribute::DgpuTgp => "nv_tgp",
|
||||
FirmwareAttribute::ChargeMode => "charge_mode",
|
||||
FirmwareAttribute::BootSound => "boot_sound",
|
||||
FirmwareAttribute::McuPowersave => "mcu_powersave",
|
||||
@@ -411,6 +468,7 @@ impl From<FirmwareAttribute> for &str {
|
||||
FirmwareAttribute::GpuMuxMode => "gpu_mux_mode",
|
||||
FirmwareAttribute::MiniLedMode => "mini_led_mode",
|
||||
FirmwareAttribute::PendingReboot => "pending_reboot",
|
||||
FirmwareAttribute::ScreenAutoBrightness => "screen_auto_brightness",
|
||||
FirmwareAttribute::None => "none",
|
||||
}
|
||||
}
|
||||
@@ -497,3 +555,28 @@ mod tests {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,18 +267,24 @@ mod tests {
|
||||
fn check_cpu() {
|
||||
let cpu = CPUControl::new().unwrap();
|
||||
assert_eq!(cpu.get_governor().unwrap(), CPUGovernor::Powersave);
|
||||
assert_eq!(cpu.get_available_governors().unwrap(), vec![
|
||||
CPUGovernor::Performance,
|
||||
CPUGovernor::Powersave
|
||||
]);
|
||||
assert_eq!(
|
||||
cpu.get_available_governors().unwrap(),
|
||||
vec![
|
||||
CPUGovernor::Performance,
|
||||
CPUGovernor::Powersave
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(cpu.get_epp().unwrap(), CPUEPP::BalancePower);
|
||||
assert_eq!(cpu.get_available_epp().unwrap(), vec![
|
||||
CPUEPP::Default,
|
||||
CPUEPP::Performance,
|
||||
CPUEPP::BalancePerformance,
|
||||
CPUEPP::BalancePower,
|
||||
CPUEPP::Power,
|
||||
]);
|
||||
assert_eq!(
|
||||
cpu.get_available_epp().unwrap(),
|
||||
vec![
|
||||
CPUEPP::Default,
|
||||
CPUEPP::Performance,
|
||||
CPUEPP::BalancePerformance,
|
||||
CPUEPP::BalancePower,
|
||||
CPUEPP::Power,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,11 +275,16 @@ impl std::str::FromStr for PlatformProfile {
|
||||
type Err = PlatformError;
|
||||
|
||||
fn from_str(profile: &str) -> Result<Self> {
|
||||
match profile.to_ascii_lowercase().trim() {
|
||||
match profile
|
||||
.to_ascii_lowercase()
|
||||
.trim()
|
||||
.replace(|c| !char::is_alphabetic(c), "")
|
||||
.as_str()
|
||||
{
|
||||
"balanced" => Ok(PlatformProfile::Balanced),
|
||||
"performance" => Ok(PlatformProfile::Performance),
|
||||
"quiet" => Ok(PlatformProfile::Quiet),
|
||||
"low-power" => Ok(PlatformProfile::LowPower),
|
||||
"lowpower" => Ok(PlatformProfile::LowPower),
|
||||
"custom" => Ok(PlatformProfile::Custom),
|
||||
_ => Err(PlatformError::NotSupported),
|
||||
}
|
||||
@@ -288,11 +293,16 @@ impl std::str::FromStr for PlatformProfile {
|
||||
|
||||
impl From<&str> for PlatformProfile {
|
||||
fn from(profile: &str) -> Self {
|
||||
match profile.to_ascii_lowercase().trim() {
|
||||
match profile
|
||||
.to_ascii_lowercase()
|
||||
.trim()
|
||||
.replace(|c| !char::is_alphabetic(c), "")
|
||||
.as_str()
|
||||
{
|
||||
"balanced" => PlatformProfile::Balanced,
|
||||
"performance" => PlatformProfile::Performance,
|
||||
"quiet" => PlatformProfile::Quiet,
|
||||
"low-power" => PlatformProfile::LowPower,
|
||||
"lowpower" => PlatformProfile::LowPower,
|
||||
"custom" => PlatformProfile::Custom,
|
||||
_ => {
|
||||
warn!("{profile} is unknown, using ThrottlePolicy::Balanced");
|
||||
|
||||
@@ -106,3 +106,13 @@ impl AsusPower {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AsusPower {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mains: PathBuf::from("/this_shouldNeVErr_exisid"),
|
||||
battery: PathBuf::from("/this_shouldNeVErr_exisid"),
|
||||
usb: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt", "clippy"]
|
||||
profile = "minimal"
|
||||
@@ -157,13 +157,14 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
|
||||
canvas.set_draw_color(Color::RGB(*b, *b, *b));
|
||||
|
||||
let x: i32 = w + x_count as i32 * w
|
||||
- if !(y_count + y_offset as usize).is_multiple_of(2) {
|
||||
let x: i32 = w + x_count as i32 * w - {
|
||||
#[allow(clippy::manual_is_multiple_of)]
|
||||
if (y_count + y_offset as usize) % 2 != 0 {
|
||||
0
|
||||
} else {
|
||||
w / 2
|
||||
}
|
||||
+ row.3 * w;
|
||||
} + row.3 * w;
|
||||
let y = y_count as i32 * h - y_offset * h;
|
||||
canvas
|
||||
.fill_rect(Rect::new(x, y, w as u32, h as u32))
|
||||
|
||||
Reference in New Issue
Block a user