Compare commits

...

26 Commits

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

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

Closes #696

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

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

See merge request asus-linux/asusctl!228
2025-10-29 18:49:50 +00:00
Synby bbd03c128d Edit Makefile
add install-data-asusd_user to install-data
2025-10-29 17:23:29 +00:00
Denis Benato 132a2f3665 Chore: complete the switch back to stable 2025-10-23 14:50:40 +02:00
Denis Benato 180566e5f1 Fix: share a single HID device
Avoid opening multiple handles to the same device whenever possible.
2025-10-22 22:05:17 +02:00
34 changed files with 1107 additions and 872 deletions
+14
View File
@@ -2,6 +2,20 @@
## [Unreleased] ## [Unreleased]
## [6.1.18]
### Changed
- Add aura support for G614FR (ROG Strix G16 2025)
- all notifications now respects the timeout
- improve udev daemon-starting rule
- reduce log noise
## [v6.1.17]
### Changed
- Fix Makefile
- Share a single HID device
## [v6.1.16] ## [v6.1.16]
### Changed ### Changed
Generated
+632 -637
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace.package] [workspace.package]
version = "6.1.16" version = "6.1.18"
rust-version = "1.82" rust-version = "1.82"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
+12 -5
View File
@@ -59,10 +59,17 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
target/$(TARGET)/$(BIN_D): build target/$(TARGET)/$(BIN_D): $(SRC)
target/$(TARGET)/$(BIN_C): build $(MAKE) build
target/$(TARGET)/$(BIN_U): build
target/$(TARGET)/$(BIN_ROG): build target/$(TARGET)/$(BIN_C): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_U): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_ROG): $(SRC)
$(MAKE) build
install-asusd: target/$(TARGET)/$(BIN_D) install-asusd: target/$(TARGET)/$(BIN_D)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
@@ -113,7 +120,7 @@ install-data-asusd_user:
.PHONY: install-data-asusd install-data-asusd_user .PHONY: install-data-asusd install-data-asusd_user
install-data: install-data-asusd install-data-rog_gui install-data: install-data-asusd install-data-asusd_user install-data-rog_gui
install: install-program install-data install: install-program install-data
$(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE" $(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE"
+28 -22
View File
@@ -46,13 +46,13 @@ See the [rog-aura readme](./rog-aura/README.md) for more details.
Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar
to this: to this:
``` ```plain
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
``` ```
or or
``` ```plain
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown] Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
``` ```
@@ -74,13 +74,13 @@ The list is a bit outdated as many features have been enabled in the Linux kerne
- [x] Toggle bios setting for boot/POST sound - [x] Toggle bios setting for boot/POST sound
- [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops) - [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops)
# GUI ## GUI
A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already. A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already.
**NOTE**: Xorg is not supported. **NOTE**: Xorg is not supported.
# BUILDING ## BUILDING
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/). Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/).
@@ -88,27 +88,33 @@ Distro packaging should work with the stable toolchain. If your distro does not
**fedora:** **fedora:**
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel ```sh
make dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**openSUSE:** **openSUSE:**
Works with KDE Plasma (without GTK packages) Works with KDE Plasma (without GTK packages)
zypper in -t pattern devel_basis ```sh
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel zypper in -t pattern devel_basis
make zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**Debian(unsuported):** **Debian(unsuported):**
officially unsuported,but you can still try and test it by yourself(some features may not be available). officially unsuported,but you can still try and test it by yourself(some features may not be available).
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev ```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
make curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
sudo make install make
sudo make install
```
**Ubuntu, Popos (unsuported):** **Ubuntu, Popos (unsuported):**
@@ -135,15 +141,15 @@ You may also need to activate the service for debian install. If running Pop!\_O
If you are upgrading from a previous installed version, you will need to restart the service or reboot. If you are upgrading from a previous installed version, you will need to restart the service or reboot.
``` ```sh
$ systemctl daemon-reload && systemctl restart asusd systemctl daemon-reload && systemctl restart asusd
``` ```
## Uninstalling ## Uninstalling
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`. Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
# Contributing ## Contributing
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`). See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
@@ -151,17 +157,17 @@ Generation of the bindings with `make bindings` requires `typeshare` to be insta
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`. Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
# OTHER ## OTHER
## AniMe Matrix simulator ### AniMe Matrix simulator
A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop _with_ the display, the simulated display will be used instead of the physical display. A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop _with_ the display, the simulated display will be used instead of the physical display.
## Supporting more laptops ### Supporting more laptops
Please file a support request. Please file a support request.
# License & Trademarks ## License & Trademarks
Mozilla Public License 2 (MPL-2.0) Mozilla Public License 2 (MPL-2.0)
+8 -5
View File
@@ -21,11 +21,14 @@ fn main() {
let brightness = args[2].parse::<f32>().unwrap(); let brightness = args[2].parse::<f32>().unwrap();
let anime_type = get_anime_type(); let anime_type = get_anime_type();
let mut seq = Sequences::new(anime_type); let mut seq = Sequences::new(anime_type);
seq.insert(0, &ActionLoader::AsusAnimation { seq.insert(
file: path.into(), 0,
time: rog_anime::AnimTime::Infinite, &ActionLoader::AsusAnimation {
brightness, file: path.into(),
}) time: rog_anime::AnimTime::Infinite,
brightness,
},
)
.unwrap(); .unwrap();
loop { loop {
+2
View File
@@ -181,6 +181,7 @@ pub struct TwoColourSpeed {
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiZone { pub struct MultiZone {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -195,6 +196,7 @@ pub struct MultiZone {
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiColourSpeed { pub struct MultiColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
+10
View File
@@ -74,6 +74,16 @@ pub struct ProfileCommand {
#[options(meta = "", help = "set the active profile")] #[options(meta = "", help = "set the active profile")]
pub profile_set: Option<PlatformProfile>, pub profile_set: Option<PlatformProfile>,
#[options(short = "a", meta = "", help = "set the profile to use on AC power")]
pub profile_set_ac: Option<PlatformProfile>,
#[options(
short = "b",
meta = "",
help = "set the profile to use on battery power"
)]
pub profile_set_bat: Option<PlatformProfile>,
} }
#[derive(Options)] #[derive(Options)]
+19 -3
View File
@@ -979,7 +979,13 @@ fn handle_throttle_profile(
return Err(ProfileError::NotSupported.into()); return Err(ProfileError::NotSupported.into());
} }
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get { if !cmd.next
&& !cmd.list
&& cmd.profile_set.is_none()
&& !cmd.profile_get
&& cmd.profile_set_ac.is_none()
&& cmd.profile_set_bat.is_none()
{
if !cmd.help { if !cmd.help {
println!("Missing arg or command\n"); println!("Missing arg or command\n");
} }
@@ -999,6 +1005,10 @@ fn handle_throttle_profile(
proxy.set_platform_profile(PlatformProfile::next(current, &choices))?; proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
} else if let Some(profile) = cmd.profile_set { } else if let Some(profile) = cmd.profile_set {
proxy.set_platform_profile(profile)?; proxy.set_platform_profile(profile)?;
} else if let Some(profile) = cmd.profile_set_ac {
proxy.set_platform_profile_on_ac(profile)?;
} else if let Some(profile) = cmd.profile_set_bat {
proxy.set_platform_profile_on_battery(profile)?;
} }
if cmd.list { if cmd.list {
@@ -1009,6 +1019,11 @@ fn handle_throttle_profile(
if cmd.profile_get { if cmd.profile_get {
println!("Active profile is {current:?}"); println!("Active profile is {current:?}");
println!("Profile on AC is {:?}", proxy.platform_profile_on_ac()?);
println!(
"Profile on Battery is {:?}",
proxy.platform_profile_on_battery()?
);
} }
Ok(()) Ok(())
@@ -1169,11 +1184,12 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
Ok(()) Ok(())
} }
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)]
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
{ {
if cmd.free.is_empty() || !cmd.free.len().is_multiple_of(2) || cmd.help { if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help {
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5"; const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
if !cmd.free.len().is_multiple_of(2) { if cmd.free.len() % 2 != 0 {
println!( println!(
"Incorrect number of args, each attribute label must be paired with a setting:" "Incorrect number of args, each attribute label must be paired with a setting:"
); );
+1 -1
View File
@@ -1,12 +1,12 @@
use std::sync::Arc; use std::sync::Arc;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info}; use log::{debug, error, info};
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value}; use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value};
use zbus::{fdo, interface, Connection}; use zbus::{fdo, interface, Connection};
+2 -2
View File
@@ -8,7 +8,6 @@ use std::sync::Arc;
use std::thread::sleep; use std::thread::sleep;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_anime::usb::{ use rog_anime::usb::{
pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim, pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim,
@@ -17,6 +16,7 @@ use rog_anime::usb::{
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType}; use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw; use rog_platform::usb_raw::USBRaw;
use tokio::sync::Mutex;
use self::config::{AniMeConfig, AniMeConfigCached}; use self::config::{AniMeConfig, AniMeConfigCached};
use crate::error::RogError; use crate::error::RogError;
@@ -51,7 +51,7 @@ impl AniMe {
/// Will fail if something is already holding the config lock /// Will fail if something is already holding the config lock
async fn do_init_cache(&mut self) { async fn do_init_cache(&mut self) {
if let Some(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
if let Err(e) = self.cache.init_from_config(&config, config.anime_type) { if let Err(e) = self.cache.init_from_config(&config, config.anime_type) {
error!( error!(
"Trying to cache the Anime Config failed, will reset to default config: {e:?}" "Trying to cache the Anime Config failed, will reset to default config: {e:?}"
+7 -7
View File
@@ -85,7 +85,7 @@ impl AniMeZbus {
/// Set base brightness level /// Set base brightness level
#[zbus(property)] #[zbus(property)]
async fn brightness(&self) -> Brightness { async fn brightness(&self) -> Brightness {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.display_brightness; return config.display_brightness;
} }
Brightness::Off Brightness::Off
@@ -117,7 +117,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn builtins_enabled(&self) -> bool { async fn builtins_enabled(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims_enabled; return config.builtin_anims_enabled;
} }
false false
@@ -162,7 +162,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn builtin_animations(&self) -> Animations { async fn builtin_animations(&self) -> Animations {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims; return config.builtin_anims;
} }
Animations::default() Animations::default()
@@ -195,7 +195,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn enable_display(&self) -> bool { async fn enable_display(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.display_enabled; return config.display_enabled;
} }
false false
@@ -218,7 +218,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_unplugged(&self) -> bool { async fn off_when_unplugged(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_unplugged; return config.off_when_unplugged;
} }
false false
@@ -245,7 +245,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_suspended(&self) -> bool { async fn off_when_suspended(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_suspended; return config.off_when_suspended;
} }
false false
@@ -261,7 +261,7 @@ impl AniMeZbus {
#[zbus(property)] #[zbus(property)]
async fn off_when_lid_closed(&self) -> bool { async fn off_when_lid_closed(&self) -> bool {
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
return config.off_when_lid_closed; return config.off_when_lid_closed;
} }
false false
+74 -50
View File
@@ -309,26 +309,38 @@ mod tests {
let res = config.multizone.unwrap(); let res = config.multizone.unwrap();
let sta = res.get(&AuraModeNum::Static).unwrap(); let sta = res.get(&AuraModeNum::Static).unwrap();
assert_eq!(sta.len(), 4); assert_eq!(sta.len(), 4);
assert_eq!(sta[0].colour1, Colour { assert_eq!(
r: 0xff, sta[0].colour1,
g: 0x00, Colour {
b: 0xff r: 0xff,
}); g: 0x00,
assert_eq!(sta[1].colour1, Colour { b: 0xff
r: 0x00, }
g: 0xff, );
b: 0xff assert_eq!(
}); sta[1].colour1,
assert_eq!(sta[2].colour1, Colour { Colour {
r: 0xff, r: 0x00,
g: 0xff, g: 0xff,
b: 0x00 b: 0xff
}); }
assert_eq!(sta[3].colour1, Colour { );
r: 0x00, assert_eq!(
g: 0xff, sta[2].colour1,
b: 0x00 Colour {
}); r: 0xff,
g: 0xff,
b: 0x00
}
);
assert_eq!(
sta[3].colour1,
Colour {
r: 0x00,
g: 0xff,
b: 0x00
}
);
} }
#[test] #[test]
@@ -388,22 +400,28 @@ mod tests {
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 5); assert_eq!(config.builtins.len(), 5);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
mode: AuraModeNum::Static, config.builtins.first_entry().unwrap().get(),
zone: AuraZone::None, &AuraEffect {
colour1: Colour { r: 166, g: 0, b: 0 }, mode: AuraModeNum::Static,
colour2: Colour { r: 0, g: 0, b: 0 }, zone: AuraZone::None,
speed: Speed::Med, colour1: Colour { r: 166, g: 0, b: 0 },
direction: Direction::Right colour2: Colour { r: 0, g: 0, b: 0 },
}); speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 1); assert_eq!(config.enabled.states.len(), 1);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
zone: PowerZones::KeyboardAndLightbar, config.enabled.states[0],
boot: true, AuraPowerState {
awake: true, zone: PowerZones::KeyboardAndLightbar,
sleep: true, boot: true,
shutdown: true awake: true,
}); sleep: true,
shutdown: true
}
);
} }
#[test] #[test]
@@ -414,21 +432,27 @@ mod tests {
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 12); assert_eq!(config.builtins.len(), 12);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
mode: AuraModeNum::Static, config.builtins.first_entry().unwrap().get(),
zone: AuraZone::None, &AuraEffect {
colour1: Colour { r: 166, g: 0, b: 0 }, mode: AuraModeNum::Static,
colour2: Colour { r: 0, g: 0, b: 0 }, zone: AuraZone::None,
speed: Speed::Med, colour1: Colour { r: 166, g: 0, b: 0 },
direction: Direction::Right colour2: Colour { r: 0, g: 0, b: 0 },
}); speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 4); assert_eq!(config.enabled.states.len(), 4);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
zone: PowerZones::Keyboard, config.enabled.states[0],
boot: true, AuraPowerState {
awake: true, zone: PowerZones::Keyboard,
sleep: true, boot: true,
shutdown: true awake: true,
}); sleep: true,
shutdown: true
}
);
} }
} }
+1 -1
View File
@@ -2,13 +2,13 @@ use std::sync::Arc;
use config::AuraConfig; use config::AuraConfig;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::{Mutex, MutexGuard};
use log::info; use log::info;
use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets}; use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets};
use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET}; use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET};
use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN}; use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardBacklight; use rog_platform::keyboard_led::KeyboardBacklight;
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
+2 -2
View File
@@ -112,7 +112,7 @@ impl AuraZbus {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
// let ctrl = self.0.lock().await; // let ctrl = self.0.lock().await;
// Ok(config.current_mode) // Ok(config.current_mode)
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
Ok(config.current_mode) Ok(config.current_mode)
} else { } else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string())) Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
@@ -140,7 +140,7 @@ impl AuraZbus {
#[zbus(property)] #[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> { async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode; let mode = config.current_mode;
match config.builtins.get(&mode) { match config.builtins.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
+63 -12
View File
@@ -4,15 +4,16 @@
// - Add it to Zbus server // - Add it to Zbus server
// - If udev sees device removed then remove the zbus path // - If udev sees device removed then remove the zbus path
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use dmi_id::DMIID; use dmi_id::DMIID;
use futures_lite::future::block_on; use futures_lite::future::block_on;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use mio::{Events, Interest, Poll, Token}; use mio::{Events, Interest, Poll, Token};
use rog_platform::error::PlatformError; use rog_platform::error::PlatformError;
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use tokio::sync::Mutex;
use udev::{Device, MonitorBuilder}; use udev::{Device, MonitorBuilder};
use zbus::zvariant::{ObjectPath, OwnedObjectPath}; use zbus::zvariant::{ObjectPath, OwnedObjectPath};
use zbus::Connection; use zbus::Connection;
@@ -92,16 +93,39 @@ fn dev_prop_matches(dev: &Device, prop: &str, value: &str) -> bool {
pub struct AsusDevice { pub struct AsusDevice {
device: DeviceHandle, device: DeviceHandle,
dbus_path: OwnedObjectPath, dbus_path: OwnedObjectPath,
hid_key: Option<String>,
} }
pub struct DeviceManager { pub struct DeviceManager {
_dbus_connection: Connection, _dbus_connection: Connection,
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
} }
impl DeviceManager { impl DeviceManager {
#[allow(clippy::type_complexity)]
async fn get_or_create_hid_handle(
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
endpoint: &Device,
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
let dev_node = endpoint
.devnode()
.ok_or_else(|| RogError::MissingFunction("hidraw devnode missing".to_string()))?;
let key = dev_node.to_string_lossy().to_string();
if let Some(existing) = handles.lock().await.get(&key).cloned() {
return Ok((existing, key));
}
let hidraw = HidRaw::from_device(endpoint.clone())?;
let handle = Arc::new(Mutex::new(hidraw));
handles.lock().await.insert(key.clone(), handle.clone());
Ok((handle, key))
}
async fn init_hid_devices( async fn init_hid_devices(
connection: &Connection, connection: &Connection,
device: Device, device: Device,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> { ) -> Result<Vec<AsusDevice>, RogError> {
let mut devices = Vec::new(); let mut devices = Vec::new();
if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? { if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? {
@@ -116,9 +140,10 @@ impl DeviceManager {
// 1. Generate an interface path // 1. Generate an interface path
// 2. Create the device // 2. Create the device
// Use the top-level endpoint, not the parent // Use the top-level endpoint, not the parent
if let Ok(hidraw) = HidRaw::from_device(device) { if let Ok((dev, hid_key)) =
Self::get_or_create_hid_handle(&handles, &device).await
{
debug!("Testing device {usb_id:?}"); debug!("Testing device {usb_id:?}");
let dev = Arc::new(Mutex::new(hidraw));
// SLASH DEVICE // SLASH DEVICE
if let Ok(dev_type) = DeviceHandle::new_slash_hid( if let Ok(dev_type) = DeviceHandle::new_slash_hid(
dev.clone(), dev.clone(),
@@ -134,6 +159,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
@@ -152,6 +178,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
@@ -170,9 +197,12 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: Some(hid_key),
}); });
} }
} }
} else {
warn!("Failed to initialise shared hid handle for {usb_id:?}");
} }
} }
} }
@@ -181,7 +211,10 @@ impl DeviceManager {
} }
/// To be called on daemon startup /// To be called on daemon startup
async fn init_all_hid(connection: &Connection) -> Result<Vec<AsusDevice>, RogError> { async fn init_all_hid(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> {
// track and ensure we use only one hidraw per prod_id // track and ensure we use only one hidraw per prod_id
// let mut interfaces = HashSet::new(); // let mut interfaces = HashSet::new();
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
@@ -200,7 +233,7 @@ impl DeviceManager {
.scan_devices() .scan_devices()
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))? .map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
{ {
devices.append(&mut Self::init_hid_devices(connection, device).await?); devices.append(&mut Self::init_hid_devices(connection, device, handles.clone()).await?);
} }
Ok(devices) Ok(devices)
@@ -228,6 +261,7 @@ impl DeviceManager {
return Some(AsusDevice { return Some(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -275,10 +309,13 @@ impl DeviceManager {
Ok(devices) Ok(devices)
} }
pub async fn find_all_devices(connection: &Connection) -> Vec<AsusDevice> { pub async fn find_all_devices(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Vec<AsusDevice> {
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
// HID first, always // HID first, always
if let Ok(devs) = &mut Self::init_all_hid(connection).await { if let Ok(devs) = &mut Self::init_all_hid(connection, handles.clone()).await {
devices.append(devs); devices.append(devs);
} }
// USB after, need to check if HID picked something up and if so, skip it // USB after, need to check if HID picked something up and if so, skip it
@@ -306,6 +343,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} else { } else {
@@ -328,6 +366,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -355,6 +394,7 @@ impl DeviceManager {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path, dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -370,16 +410,19 @@ impl DeviceManager {
pub async fn new(connection: Connection) -> Result<Self, RogError> { pub async fn new(connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone(); let conn_copy = connection.clone();
let devices = Self::find_all_devices(&conn_copy).await; let hid_handles = Arc::new(Mutex::new(HashMap::new()));
let devices = Self::find_all_devices(&conn_copy, hid_handles.clone()).await;
info!("Found {} valid devices on startup", devices.len()); info!("Found {} valid devices on startup", devices.len());
let devices = Arc::new(Mutex::new(devices)); let devices = Arc::new(Mutex::new(devices));
let manager = Self { let manager = Self {
_dbus_connection: connection, _dbus_connection: connection,
_hid_handles: hid_handles.clone(),
}; };
// TODO: The /sysfs/ LEDs don't cause events, so they need to be manually // TODO: The /sysfs/ LEDs don't cause events, so they need to be manually
// checked for and added // checked for and added
let hid_handles_thread = hid_handles.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut monitor = MonitorBuilder::new()?.listen()?; let mut monitor = MonitorBuilder::new()?.listen()?;
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
@@ -408,6 +451,7 @@ impl DeviceManager {
let devices = devices.clone(); let devices = devices.clone();
let conn_copy = conn_copy.clone(); let conn_copy = conn_copy.clone();
let hid_handles = hid_handles_thread.clone();
block_on(async move { block_on(async move {
// SCSCI devs // SCSCI devs
if subsys == "block" { if subsys == "block" {
@@ -483,6 +527,7 @@ impl DeviceManager {
// Iter in reverse so as to not screw up indexing // Iter in reverse so as to not screw up indexing
for index in removals.iter().rev() { for index in removals.iter().rev() {
let dev = devices.lock().await.remove(*index); let dev = devices.lock().await.remove(*index);
let hid_key = dev.hid_key.clone();
let path = path.clone(); let path = path.clone();
let res = match dev.device { let res = match dev.device {
DeviceHandle::Aura(_) => { DeviceHandle::Aura(_) => {
@@ -512,14 +557,20 @@ impl DeviceManager {
_ => todo!(), _ => todo!(),
}; };
info!("AuraManager removed: {path:?}, {res}"); info!("AuraManager removed: {path:?}, {res}");
if let Some(key) = hid_key {
hid_handles.lock().await.remove(&key);
}
} }
} }
} else if action == "add" { } else if action == "add" {
let evdev = event.device(); let evdev = event.device();
if let Ok(mut new_devs) = if let Ok(mut new_devs) = Self::init_hid_devices(
Self::init_hid_devices(&conn_copy, evdev) &conn_copy,
.await evdev,
.map_err(|e| error!("Couldn't add new device: {e:?}")) hid_handles.clone(),
)
.await
.map_err(|e| error!("Couldn't add new device: {e:?}"))
{ {
devices.lock().await.append(&mut new_devs); devices.lock().await.append(&mut new_devs);
} }
+1 -1
View File
@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use config::ScsiConfig; use config::ScsiConfig;
use futures_util::lock::{Mutex, MutexGuard};
use rog_scsi::{AuraEffect, Device, Task}; use rog_scsi::{AuraEffect, Device, Task};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
+1 -1
View File
@@ -83,7 +83,7 @@ impl ScsiZbus {
#[zbus(property)] #[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> { async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock() // entirely possible to deadlock here, so use try instead of lock()
if let Some(config) = self.0.config.try_lock() { if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode; let mode = config.current_mode;
match config.modes.get(&mode) { match config.modes.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
+1 -1
View File
@@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use config::SlashConfig; use config::SlashConfig;
use futures_util::lock::{Mutex, MutexGuard};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw; use rog_platform::usb_raw::USBRaw;
use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode}; use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
+1 -1
View File
@@ -1,7 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use futures_util::lock::Mutex;
use log::{debug, error, info}; use log::{debug, error, info};
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_anime::usb::get_anime_type; use rog_anime::usb::get_anime_type;
@@ -13,6 +12,7 @@ use rog_platform::usb_raw::USBRaw;
use rog_scsi::{open_device, ScsiType}; use rog_scsi::{open_device, ScsiType};
use rog_slash::error::SlashError; use rog_slash::error::SlashError;
use rog_slash::SlashType; use rog_slash::SlashType;
use tokio::sync::Mutex;
use crate::aura_anime::config::AniMeConfig; use crate::aura_anime::config::AniMeConfig;
use crate::aura_anime::AniMe; use crate::aura_anime::AniMe;
+2 -2
View File
@@ -2,9 +2,9 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{info, warn}; use log::{info, warn};
use rog_platform::backlight::{Backlight, BacklightType}; use rog_platform::backlight::{Backlight, BacklightType};
use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr; use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
@@ -13,7 +13,7 @@ use crate::config::Config;
use crate::error::RogError; use crate::error::RogError;
use crate::ASUS_ZBUS_PATH; use crate::ASUS_ZBUS_PATH;
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct CtrlBacklight { pub struct CtrlBacklight {
backlights: Vec<Backlight>, backlights: Vec<Backlight>,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
+1 -1
View File
@@ -3,13 +3,13 @@ use std::sync::Arc;
use config_traits::{StdConfig, StdConfigLoad}; use config_traits::{StdConfig, StdConfigLoad};
use futures_lite::StreamExt; use futures_lite::StreamExt;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_profiles::error::ProfileError; use rog_profiles::error::ProfileError;
use rog_profiles::fan_curve_set::CurveData; use rog_profiles::fan_curve_set::CurveData;
use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles}; use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
+38 -4
View File
@@ -3,12 +3,12 @@ use std::process::Command;
use std::sync::Arc; use std::sync::Arc;
use config_traits::StdConfig; use config_traits::StdConfig;
use futures_util::lock::Mutex;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttributes};
use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP}; use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP};
use rog_platform::platform::{PlatformProfile, Properties, RogPlatform}; use rog_platform::platform::{PlatformProfile, Properties, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr; use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
@@ -51,6 +51,7 @@ pub struct CtrlPlatform {
} }
impl CtrlPlatform { impl CtrlPlatform {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
@@ -294,16 +295,39 @@ impl CtrlPlatform {
#[zbus(property)] #[zbus(property)]
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> { fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
let limit = self.power.get_charge_control_end_threshold()?; if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let limit = self.power.get_charge_control_end_threshold().map_err(|e| {
FdoErr::Failed(format!(
"Could not read charge_control_end_threshold: {e:?}"
))
})?;
Ok(limit) Ok(limit)
} }
#[zbus(property)] #[zbus(property)]
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> { async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
if !(20..=100).contains(&limit) { if !(20..=100).contains(&limit) {
return Err(RogError::ChargeLimit(limit))?; return Err(RogError::ChargeLimit(limit))?;
} }
self.power.set_charge_control_end_threshold(limit)?;
self.power
.set_charge_control_end_threshold(limit)
.map_err(|e| {
FdoErr::Failed(format!("Could not set charge_control_end_threshold: {e:?}"))
})?;
self.config.lock().await.charge_control_end_threshold = limit; self.config.lock().await.charge_control_end_threshold = limit;
self.config.lock().await.base_charge_control_end_threshold = limit; self.config.lock().await.base_charge_control_end_threshold = limit;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -311,12 +335,22 @@ impl CtrlPlatform {
} }
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> { async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let base_limit = std::mem::replace( let base_limit = std::mem::replace(
&mut self.config.lock().await.charge_control_end_threshold, &mut self.config.lock().await.charge_control_end_threshold,
100, 100,
); );
if base_limit != 100 { if base_limit != 100 {
self.power.set_charge_control_end_threshold(100)?; self.power
.set_charge_control_end_threshold(100)
.map_err(|e| {
FdoErr::Failed(format!("Could not set one_shot_full_charge: {e:?}"))
})?;
self.config.lock().await.base_charge_control_end_threshold = base_limit; self.config.lock().await.base_charge_control_end_threshold = base_limit;
self.config.lock().await.write(); self.config.lock().await.write();
} }
+1 -1
View File
@@ -11,11 +11,11 @@ use asusd::ctrl_fancurves::CtrlFanCurveZbus;
use asusd::ctrl_platform::CtrlPlatform; use asusd::ctrl_platform::CtrlPlatform;
use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME}; use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME};
use config_traits::{StdConfig, StdConfigLoad2}; use config_traits::{StdConfig, StdConfigLoad2};
use futures_util::lock::Mutex;
use log::{error, info}; use log::{error, info};
use rog_platform::asus_armoury::FirmwareAttributes; use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::RogPlatform; use rog_platform::platform::RogPlatform;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use tokio::sync::Mutex;
use zbus::fdo::ObjectManager; use zbus::fdo::ObjectManager;
#[tokio::main] #[tokio::main]
+2 -2
View File
@@ -15,7 +15,7 @@ ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
GOTO="asusd_end" GOTO="asusd_end"
LABEL="asusd_start" LABEL="asusd_start"
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service" ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", RUN+="/usr/bin/systemctl restart asusd.service" ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
LABEL="asusd_end" LABEL="asusd_end"
+4 -1
View File
@@ -6,7 +6,10 @@ After=nvidia-powerd.service systemd-udevd.service
[Service] [Service]
Environment=IS_SERVICE=1 Environment=IS_SERVICE=1
Environment=RUST_LOG="debug" # Reduce noisy span logs while keeping useful debug info for asusd and related crates.
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error"
# required to prevent init issues with hid_asus and MCU # required to prevent init issues with hid_asus and MCU
ExecStartPre=/bin/sleep 1 ExecStartPre=/bin/sleep 1
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd
+4 -2
View File
@@ -20,7 +20,7 @@
%global debug_package %{nil} %global debug_package %{nil}
%endif %endif
%define version 6.1.16 %define version 6.1.18
%define specrelease %{?dist} %define specrelease %{?dist}
%define pkg_release 9%{specrelease} %define pkg_release 9%{specrelease}
@@ -92,7 +92,9 @@ EOF
%build %build
export RUSTFLAGS="%{rustflags}" export RUSTFLAGS="%{rustflags}"
%if %{defined fedora} %if %{defined fedora}
%cargo_build %# Use an explicit cargo invocation for Fedora to avoid the macro adding `--locked`.
%# `--locked` breaks Fedora builds because the lockfile may not be appropriate for the distro buildroot.
/usr/bin/cargo auditable build --release
%else %else
/usr/bin/cargo auditable build --release /usr/bin/cargo auditable build --release
%endif %endif
+19 -1
View File
@@ -44,6 +44,15 @@
advanced_type: r#None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "FA617XS",
product_id: "",
layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
( (
device_name: "FX505", device_name: "FX505",
product_id: "", product_id: "",
@@ -242,6 +251,15 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "G614FR",
product_id: "",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G614J", device_name: "G614J",
product_id: "", product_id: "",
@@ -908,4 +926,4 @@
advanced_type: r#None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
]) ])
+5 -3
View File
@@ -207,12 +207,14 @@ mod tests {
fn single_key_next_state_then_create() { fn single_key_next_state_then_create() {
let layout = KeyLayout::default_layout(); let layout = KeyLayout::default_layout();
let mut seq = AdvancedEffects::new(false); let mut seq = AdvancedEffects::new(false);
seq.effects seq.effects.push(Effect::Static(Static::new(
.push(Effect::Static(Static::new(LedCode::F, Colour { LedCode::F,
Colour {
r: 255, r: 255,
g: 127, g: 127,
b: 0, b: 0,
}))); },
)));
seq.next_state(&layout); seq.next_state(&layout);
let packets = seq.create_packets(); let packets = seq.create_packets();
+111 -87
View File
@@ -335,93 +335,117 @@ impl KeyLayout {
KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1), KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1),
)]), )]),
key_rows: vec![ key_rows: vec![
KeyRow::new(0.1, 0.1, vec![ KeyRow::new(
(LedCode::Esc, "regular".to_owned()), 0.1,
(LedCode::F1, "regular".to_owned()), 0.1,
(LedCode::F2, "regular".to_owned()), vec![
(LedCode::F3, "regular".to_owned()), (LedCode::Esc, "regular".to_owned()),
(LedCode::F4, "regular".to_owned()), (LedCode::F1, "regular".to_owned()),
// not sure which key to put here (LedCode::F2, "regular".to_owned()),
(LedCode::F5, "regular".to_owned()), (LedCode::F3, "regular".to_owned()),
(LedCode::F6, "regular".to_owned()), (LedCode::F4, "regular".to_owned()),
(LedCode::F7, "regular".to_owned()), // not sure which key to put here
(LedCode::F8, "regular".to_owned()), (LedCode::F5, "regular".to_owned()),
(LedCode::F9, "regular".to_owned()), (LedCode::F6, "regular".to_owned()),
(LedCode::F10, "regular".to_owned()), (LedCode::F7, "regular".to_owned()),
(LedCode::F11, "regular".to_owned()), (LedCode::F8, "regular".to_owned()),
(LedCode::F12, "regular".to_owned()), (LedCode::F9, "regular".to_owned()),
]), (LedCode::F10, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::F11, "regular".to_owned()),
(LedCode::Tilde, "regular".to_owned()), (LedCode::F12, "regular".to_owned()),
(LedCode::N1, "regular".to_owned()), ],
(LedCode::N2, "regular".to_owned()), ),
(LedCode::N3, "regular".to_owned()), KeyRow::new(
(LedCode::N4, "regular".to_owned()), 0.1,
(LedCode::N5, "regular".to_owned()), 0.1,
(LedCode::N6, "regular".to_owned()), vec![
(LedCode::N7, "regular".to_owned()), (LedCode::Tilde, "regular".to_owned()),
(LedCode::N8, "regular".to_owned()), (LedCode::N1, "regular".to_owned()),
(LedCode::N9, "regular".to_owned()), (LedCode::N2, "regular".to_owned()),
(LedCode::N0, "regular".to_owned()), (LedCode::N3, "regular".to_owned()),
(LedCode::Hyphen, "regular".to_owned()), (LedCode::N4, "regular".to_owned()),
(LedCode::Equals, "regular".to_owned()), (LedCode::N5, "regular".to_owned()),
(LedCode::Backspace, "regular".to_owned()), (LedCode::N6, "regular".to_owned()),
]), (LedCode::N7, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::N8, "regular".to_owned()),
(LedCode::Tab, "regular".to_owned()), (LedCode::N9, "regular".to_owned()),
(LedCode::Q, "regular".to_owned()), (LedCode::N0, "regular".to_owned()),
(LedCode::W, "regular".to_owned()), (LedCode::Hyphen, "regular".to_owned()),
(LedCode::E, "regular".to_owned()), (LedCode::Equals, "regular".to_owned()),
(LedCode::R, "regular".to_owned()), (LedCode::Backspace, "regular".to_owned()),
(LedCode::T, "regular".to_owned()), ],
(LedCode::Y, "regular".to_owned()), ),
(LedCode::U, "regular".to_owned()), KeyRow::new(
(LedCode::I, "regular".to_owned()), 0.1,
(LedCode::O, "regular".to_owned()), 0.1,
(LedCode::P, "regular".to_owned()), vec![
(LedCode::LBracket, "regular".to_owned()), (LedCode::Tab, "regular".to_owned()),
(LedCode::RBracket, "regular".to_owned()), (LedCode::Q, "regular".to_owned()),
(LedCode::BackSlash, "regular".to_owned()), (LedCode::W, "regular".to_owned()),
]), (LedCode::E, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ (LedCode::R, "regular".to_owned()),
(LedCode::Caps, "regular".to_owned()), (LedCode::T, "regular".to_owned()),
(LedCode::A, "regular".to_owned()), (LedCode::Y, "regular".to_owned()),
(LedCode::S, "regular".to_owned()), (LedCode::U, "regular".to_owned()),
(LedCode::D, "regular".to_owned()), (LedCode::I, "regular".to_owned()),
(LedCode::F, "regular".to_owned()), (LedCode::O, "regular".to_owned()),
(LedCode::G, "regular".to_owned()), (LedCode::P, "regular".to_owned()),
(LedCode::H, "regular".to_owned()), (LedCode::LBracket, "regular".to_owned()),
(LedCode::J, "regular".to_owned()), (LedCode::RBracket, "regular".to_owned()),
(LedCode::K, "regular".to_owned()), (LedCode::BackSlash, "regular".to_owned()),
(LedCode::L, "regular".to_owned()), ],
(LedCode::SemiColon, "regular".to_owned()), ),
(LedCode::Quote, "regular".to_owned()), KeyRow::new(
(LedCode::Return, "regular".to_owned()), 0.1,
]), 0.1,
KeyRow::new(0.1, 0.1, vec![ vec![
(LedCode::LShift, "regular".to_owned()), (LedCode::Caps, "regular".to_owned()),
(LedCode::Z, "regular".to_owned()), (LedCode::A, "regular".to_owned()),
(LedCode::X, "regular".to_owned()), (LedCode::S, "regular".to_owned()),
(LedCode::C, "regular".to_owned()), (LedCode::D, "regular".to_owned()),
(LedCode::V, "regular".to_owned()), (LedCode::F, "regular".to_owned()),
(LedCode::B, "regular".to_owned()), (LedCode::G, "regular".to_owned()),
(LedCode::N, "regular".to_owned()), (LedCode::H, "regular".to_owned()),
(LedCode::M, "regular".to_owned()), (LedCode::J, "regular".to_owned()),
(LedCode::Comma, "regular".to_owned()), (LedCode::K, "regular".to_owned()),
(LedCode::Period, "regular".to_owned()), (LedCode::L, "regular".to_owned()),
(LedCode::FwdSlash, "regular".to_owned()), (LedCode::SemiColon, "regular".to_owned()),
(LedCode::Rshift, "regular".to_owned()), (LedCode::Quote, "regular".to_owned()),
]), (LedCode::Return, "regular".to_owned()),
KeyRow::new(0.1, 0.1, vec![ ],
(LedCode::LCtrl, "regular".to_owned()), ),
(LedCode::LFn, "regular".to_owned()), KeyRow::new(
(LedCode::Meta, "regular".to_owned()), 0.1,
(LedCode::LAlt, "regular".to_owned()), 0.1,
(LedCode::Spacebar, "regular".to_owned()), vec![
(LedCode::RAlt, "regular".to_owned()), (LedCode::LShift, "regular".to_owned()),
(LedCode::PrtSc, "regular".to_owned()), (LedCode::Z, "regular".to_owned()),
(LedCode::RCtrl, "regular".to_owned()), (LedCode::X, "regular".to_owned()),
]), (LedCode::C, "regular".to_owned()),
(LedCode::V, "regular".to_owned()),
(LedCode::B, "regular".to_owned()),
(LedCode::N, "regular".to_owned()),
(LedCode::M, "regular".to_owned()),
(LedCode::Comma, "regular".to_owned()),
(LedCode::Period, "regular".to_owned()),
(LedCode::FwdSlash, "regular".to_owned()),
(LedCode::Rshift, "regular".to_owned()),
],
),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::LCtrl, "regular".to_owned()),
(LedCode::LFn, "regular".to_owned()),
(LedCode::Meta, "regular".to_owned()),
(LedCode::LAlt, "regular".to_owned()),
(LedCode::Spacebar, "regular".to_owned()),
(LedCode::RAlt, "regular".to_owned()),
(LedCode::PrtSc, "regular".to_owned()),
(LedCode::RCtrl, "regular".to_owned()),
],
),
], ],
} }
} }
+11 -1
View File
@@ -203,11 +203,19 @@ pub fn start_notifications(
})?; })?;
let proxy_copy = proxy.clone(); let proxy_copy = proxy.clone();
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
let mut p = proxy.receive_notify_action().await?; let mut p = proxy.receive_notify_action().await?;
tokio::spawn(async move { tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_action"); info!("Started zbus signal thread: receive_notify_action");
while let Some(e) = p.next().await { while let Some(e) = p.next().await {
if let Ok(out) = e.args() { if let Ok(out) = e.args() {
// Respect user notification settings for gpu actions
if let Ok(cfg) = enabled_notifications_copy_action.lock() {
if !cfg.notifications.enabled || !cfg.notifications.receive_notify_gfx {
continue;
}
}
let action = out.action(); let action = out.action();
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default()); let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
match action { match action {
@@ -309,7 +317,9 @@ fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> R
//.hint(Hint::Resident(true)) //.hint(Hint::Resident(true))
.hint(Hint::Category("device".into())) .hint(Hint::Category("device".into()))
.urgency(Urgency::Critical) .urgency(Urgency::Critical)
.timeout(Timeout::Never) // For user-action notifications keep them visible if they require interaction
// but for non-interactive actions we prefer they auto-hide like other notifs.
.timeout(Timeout::Milliseconds(6000))
.icon("dialog-warning") .icon("dialog-warning")
.hint(Hint::Transient(true)); .hint(Hint::Transient(true));
+17 -11
View File
@@ -267,18 +267,24 @@ mod tests {
fn check_cpu() { fn check_cpu() {
let cpu = CPUControl::new().unwrap(); let cpu = CPUControl::new().unwrap();
assert_eq!(cpu.get_governor().unwrap(), CPUGovernor::Powersave); assert_eq!(cpu.get_governor().unwrap(), CPUGovernor::Powersave);
assert_eq!(cpu.get_available_governors().unwrap(), vec![ assert_eq!(
CPUGovernor::Performance, cpu.get_available_governors().unwrap(),
CPUGovernor::Powersave vec![
]); CPUGovernor::Performance,
CPUGovernor::Powersave
]
);
assert_eq!(cpu.get_epp().unwrap(), CPUEPP::BalancePower); assert_eq!(cpu.get_epp().unwrap(), CPUEPP::BalancePower);
assert_eq!(cpu.get_available_epp().unwrap(), vec![ assert_eq!(
CPUEPP::Default, cpu.get_available_epp().unwrap(),
CPUEPP::Performance, vec![
CPUEPP::BalancePerformance, CPUEPP::Default,
CPUEPP::BalancePower, CPUEPP::Performance,
CPUEPP::Power, CPUEPP::BalancePerformance,
]); CPUEPP::BalancePower,
CPUEPP::Power,
]
);
} }
} }
+10 -3
View File
@@ -101,8 +101,15 @@ impl AsusPower {
}); });
} }
Err(PlatformError::MissingFunction( // No battery found. Return an AsusPower with an empty battery path so
"Did not find a battery".to_owned(), // callers can still be constructed and query `has_*` methods which
)) // will correctly report absence. This avoids hard-failing on systems
// where the asus-nb-wmi driver loads on desktops with no battery.
info!("Did not find a battery, continuing without battery support");
Ok(Self {
mains,
battery: PathBuf::new(),
usb,
})
} }
} }
+2 -1
View File
@@ -157,8 +157,9 @@ fn main() -> Result<(), Box<dyn Error>> {
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() { for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
canvas.set_draw_color(Color::RGB(*b, *b, *b)); canvas.set_draw_color(Color::RGB(*b, *b, *b));
#[allow(clippy::manual_is_multiple_of)]
let x: i32 = w + x_count as i32 * w let x: i32 = w + x_count as i32 * w
- if !(y_count + y_offset as usize).is_multiple_of(2) { - if (y_count + y_offset as usize) % 2 != 0 {
0 0
} else { } else {
w / 2 w / 2