mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2cd1ee02ee | |||
| 5f4e950819 | |||
| efc752cce6 | |||
| 37553a5fdd | |||
| cd5a85a843 | |||
| 7385844a9b | |||
| 0b71104833 | |||
| 688e3a7358 | |||
| 58ff566d65 | |||
| 1332ac803c | |||
| ba1d3f045d | |||
| e0ed52092a | |||
| 921637f979 | |||
| f6498337fe | |||
| 3a640a3269 | |||
| e938f1f9ec | |||
| 600d0ae3d9 | |||
| 8569edf684 | |||
| 52af4ad2b2 | |||
| cde1b4f252 | |||
| 2a4754cfc4 | |||
| 51c97fa350 | |||
| c968dce009 |
+4
-2
@@ -1,4 +1,4 @@
|
|||||||
image: rustdocker/rust:stable
|
image: rust:latest
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update -qq && apt-get install -y -qq libdbus-1-dev libclang-dev libudev-dev libfontconfig1-dev
|
- apt-get update -qq && apt-get install -y -qq libdbus-1-dev libclang-dev libudev-dev libfontconfig1-dev
|
||||||
@@ -9,7 +9,9 @@ stages:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
script:
|
script:
|
||||||
- cargo check #+nightly check --features "clippy"
|
- rustup component add clippy
|
||||||
|
- cargo check
|
||||||
|
- cargo clippy
|
||||||
- cargo test
|
- cargo test
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
|||||||
+8
-1
@@ -22,15 +22,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `NotifyEgpuEnable`
|
- `NotifyEgpuEnable`
|
||||||
- `MainsOnline` (This is AC, check if plugged in or not)
|
- `MainsOnline` (This is AC, check if plugged in or not)
|
||||||
- `NotifyMainsOnline`
|
- `NotifyMainsOnline`
|
||||||
|
- `nvidia-powerd.service` will now enable or disable depending on the AC power state
|
||||||
|
and on resume/boot (hybrid boot). It has been proven that this nvidia daemon can be
|
||||||
|
problematic when on battery, not allowing the dgpu to suspend within decent time and
|
||||||
|
sometimes blocking it completely.
|
||||||
|
- Notification to rog-control-center of dGPU state change
|
||||||
### Changed
|
### Changed
|
||||||
- Use loops to ensure that mutex is gained for LED changes.
|
- Use loops to ensure that mutex is gained for LED changes.
|
||||||
- asusctl now uses tokio for async runtime. This helps simplify some code.
|
- asusctl now uses tokio for async runtime. This helps simplify some code.
|
||||||
|
- Properly fix notifs used in rog-control-center
|
||||||
### Breaking
|
### Breaking
|
||||||
- DBUS: all charge control methods renamed to:
|
- DBUS: all charge control methods renamed to:
|
||||||
- `ChargeControlEndThreshold`
|
- `ChargeControlEndThreshold`
|
||||||
- `SetChargeControlEndThreshold`
|
- `SetChargeControlEndThreshold`
|
||||||
- `NotifyChargeControlEndThreshold`
|
- `NotifyChargeControlEndThreshold`
|
||||||
- `PanelOd` (form PanelOverdrive)
|
- DBUS: all panel overdrive methods renamed to:
|
||||||
|
- `PanelOd` (from PanelOverdrive)
|
||||||
- `SetPanelOd`
|
- `SetPanelOd`
|
||||||
- `NotifyPanelOd`
|
- `NotifyPanelOd`
|
||||||
- Path `/org/asuslinux/Charge` changed to `/org/asuslinux/Power`
|
- Path `/org/asuslinux/Charge` changed to `/org/asuslinux/Power`
|
||||||
|
|||||||
Generated
+437
-366
File diff suppressed because it is too large
Load Diff
+40
-2
@@ -1,5 +1,43 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"]
|
members = ["asusctl", "daemon", "daemon-user", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "4.5.0"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
async-trait = "^0.1"
|
||||||
|
tokio = { version = "^1.21.2", features = ["macros", "rt-multi-thread", "time"]}
|
||||||
|
concat-idents = "^1.1"
|
||||||
|
dirs = "^4.0"
|
||||||
|
smol = "^1.2"
|
||||||
|
|
||||||
|
zbus = "^3.4"
|
||||||
|
zbus_macros = "^3.4"
|
||||||
|
zvariant = "^3.7"
|
||||||
|
zvariant_derive = "^3.7"
|
||||||
|
logind-zbus = { version = "^3.0" } #, default-features = false, features = ["non_blocking"] }
|
||||||
|
|
||||||
|
serde = "^1.0"
|
||||||
|
serde_derive = "^1.0"
|
||||||
|
serde_json = "^1.0"
|
||||||
|
toml = "^0.5.9"
|
||||||
|
|
||||||
|
log = "^0.4"
|
||||||
|
env_logger = "^0.9"
|
||||||
|
|
||||||
|
glam = { version = "^0.22", features = ["serde"] }
|
||||||
|
gumdrop = "^0.8"
|
||||||
|
udev = "^0.6"
|
||||||
|
rusb = "^0.9"
|
||||||
|
sysfs-class = "^0.1.2"
|
||||||
|
inotify = "^0.10.0"
|
||||||
|
|
||||||
|
png_pong = "^0.8"
|
||||||
|
pix = "^0.13"
|
||||||
|
tinybmp = "^0.3"
|
||||||
|
gif = "^0.11"
|
||||||
|
|
||||||
|
notify-rust = { git = "https://github.com/flukejones/notify-rust.git", default-features = false, features = ["z"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
# thin = 57s, asusd = 9.0M
|
# thin = 57s, asusd = 9.0M
|
||||||
@@ -10,7 +48,7 @@ opt-level = 3
|
|||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
debug = false
|
debug = true
|
||||||
opt-level = 1
|
opt-level = 1
|
||||||
|
|
||||||
[profile.bench]
|
[profile.bench]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ BIN_ROG := rog-control-center
|
|||||||
BIN_C := asusctl
|
BIN_C := asusctl
|
||||||
BIN_D := asusd
|
BIN_D := asusd
|
||||||
BIN_U := asusd-user
|
BIN_U := asusd-user
|
||||||
BIN_N := asus-notify
|
|
||||||
LEDCFG := asusd-ledmodes.toml
|
LEDCFG := asusd-ledmodes.toml
|
||||||
|
|
||||||
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
|
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
|
||||||
@@ -48,14 +47,12 @@ install:
|
|||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
|
|
||||||
|
|
||||||
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
||||||
$(INSTALL_DATA) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)"
|
$(INSTALL_DATA) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)"
|
||||||
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
|
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
|
||||||
|
|
||||||
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
||||||
$(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
|
|
||||||
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
|
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
|
||||||
|
|
||||||
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
|
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
|
||||||
@@ -78,12 +75,10 @@ uninstall:
|
|||||||
|
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN_D)"
|
rm -f "$(DESTDIR)$(bindir)/$(BIN_D)"
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN_N)"
|
|
||||||
rm -f "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
rm -f "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
||||||
rm -f "$(DESTDIR)/etc/asusd/$(LEDCFG)"
|
rm -f "$(DESTDIR)/etc/asusd/$(LEDCFG)"
|
||||||
rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
|
rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
|
||||||
rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
||||||
rm -r "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
|
|
||||||
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
|
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
|
||||||
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
||||||
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
||||||
@@ -114,5 +109,9 @@ ifeq ($(VENDORED),1)
|
|||||||
tar pxf vendor_asusctl_$(VERSION).tar.xz
|
tar pxf vendor_asusctl_$(VERSION).tar.xz
|
||||||
endif
|
endif
|
||||||
cargo build $(ARGS)
|
cargo build $(ARGS)
|
||||||
|
strip -s ./target/release/$(BIN_C)
|
||||||
|
strip -s ./target/release/$(BIN_D)
|
||||||
|
strip -s ./target/release/$(BIN_U)
|
||||||
|
strip -s ./target/release/$(BIN_ROG)
|
||||||
|
|
||||||
.PHONY: all clean distclean install uninstall update build
|
.PHONY: all clean distclean install uninstall update build
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "asus-notify"
|
|
||||||
version = "3.1.0"
|
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
zbus = "^2.2"
|
|
||||||
# serialisation
|
|
||||||
serde_json = "^1.0"
|
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
|
||||||
rog_aura = { path = "../rog-aura" }
|
|
||||||
rog_platform = { path = "../rog-platform" }
|
|
||||||
rog_profiles = { path = "../rog-profiles" }
|
|
||||||
smol = "^1.2"
|
|
||||||
|
|
||||||
[dependencies.notify-rust]
|
|
||||||
version = "^4.3"
|
|
||||||
default-features = false
|
|
||||||
features = ["z"]
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
|
||||||
use rog_aura::AuraEffect;
|
|
||||||
use rog_dbus::{
|
|
||||||
zbus_led::LedProxy, zbus_platform::RogBiosProxy, zbus_power::PowerProxy,
|
|
||||||
zbus_profile::ProfileProxy,
|
|
||||||
};
|
|
||||||
use rog_profiles::Profile;
|
|
||||||
use smol::{future, Executor};
|
|
||||||
use std::{
|
|
||||||
error::Error,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
use zbus::export::futures_util::StreamExt;
|
|
||||||
|
|
||||||
const NOTIF_HEADER: &str = "ROG Control";
|
|
||||||
|
|
||||||
macro_rules! notify {
|
|
||||||
($notifier:ident, $last_notif:ident, $data:expr) => {
|
|
||||||
if let Some(notif) = $last_notif.take() {
|
|
||||||
notif.close();
|
|
||||||
}
|
|
||||||
if let Ok(x) = $notifier($data) {
|
|
||||||
$last_notif.replace(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! base_notification {
|
|
||||||
($body:expr) => {
|
|
||||||
Notification::new()
|
|
||||||
.summary(NOTIF_HEADER)
|
|
||||||
.body($body)
|
|
||||||
.timeout(2000)
|
|
||||||
.show()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type SharedHandle = Arc<Mutex<Option<NotificationHandle>>>;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
println!("asus-notify version {}", env!("CARGO_PKG_VERSION"));
|
|
||||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
|
||||||
|
|
||||||
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
|
|
||||||
|
|
||||||
let executor = Executor::new();
|
|
||||||
// BIOS notif
|
|
||||||
let x = last_notification.clone();
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = RogBiosProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_notify_post_boot_sound().await {
|
|
||||||
p.for_each(|e| {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
if let Ok(ref mut lock) = x.try_lock() {
|
|
||||||
notify!(do_post_sound_notif, lock, &out.on());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
// Charge notif
|
|
||||||
let x = last_notification.clone();
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = PowerProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await {
|
|
||||||
p.for_each(|e| {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
if let Ok(ref mut lock) = x.try_lock() {
|
|
||||||
notify!(do_charge_notif, lock, &out.limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
// Profile notif
|
|
||||||
let x = last_notification.clone();
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = ProfileProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_notify_profile().await {
|
|
||||||
p.for_each(|e| {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
if let Ok(ref mut lock) = x.try_lock() {
|
|
||||||
notify!(do_thermal_notif, lock, &out.profile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
// LED notif
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = LedProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_notify_led().await {
|
|
||||||
p.for_each(|e| {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
if let Ok(ref mut lock) = last_notification.try_lock() {
|
|
||||||
notify!(do_led_notif, lock, &out.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
smol::block_on(executor.tick());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> {
|
|
||||||
let icon = match profile {
|
|
||||||
Profile::Balanced => "asus_notif_yellow",
|
|
||||||
Profile::Performance => "asus_notif_red",
|
|
||||||
Profile::Quiet => "asus_notif_green",
|
|
||||||
};
|
|
||||||
let profile: &str = (*profile).into();
|
|
||||||
let x = Notification::new()
|
|
||||||
.summary("ASUS ROG")
|
|
||||||
.body(&format!(
|
|
||||||
"Thermal profile changed to {}",
|
|
||||||
profile.to_uppercase(),
|
|
||||||
))
|
|
||||||
.hint(Hint::Resident(true))
|
|
||||||
.timeout(2000)
|
|
||||||
.hint(Hint::Category("device".into()))
|
|
||||||
//.hint(Hint::Transient(true))
|
|
||||||
.icon(icon)
|
|
||||||
.show()?;
|
|
||||||
Ok(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_led_notif(ledmode: &AuraEffect) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!(
|
|
||||||
"Keyboard LED mode changed to {}",
|
|
||||||
ledmode.mode_name()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!("Battery charge limit changed to {}", limit))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_post_sound_notif(on: &bool) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!("BIOS Post sound {}", on))
|
|
||||||
}
|
|
||||||
+8
-11
@@ -1,26 +1,23 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "4.3.3"
|
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
zbus = "^2.2"
|
|
||||||
rog_anime = { path = "../rog-anime" }
|
rog_anime = { path = "../rog-anime" }
|
||||||
rog_aura = { path = "../rog-aura" }
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rog_profiles = { path = "../rog-profiles" }
|
rog_profiles = { path = "../rog-profiles" }
|
||||||
rog_platform = { path = "../rog-platform" }
|
rog_platform = { path = "../rog-platform" }
|
||||||
daemon = { path = "../daemon" }
|
daemon = { path = "../daemon" }
|
||||||
gumdrop = "^0.8"
|
|
||||||
toml = "^0.5.8"
|
|
||||||
|
|
||||||
sysfs-class = "^0.1.2"
|
gumdrop.workspace = true
|
||||||
|
toml.workspace = true
|
||||||
|
sysfs-class.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tinybmp = "^0.3.3"
|
gif.workspace = true
|
||||||
glam = "^0.21.2"
|
tinybmp.workspace = true
|
||||||
|
glam.workspace = true
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
gif = "^0.11.2"
|
|
||||||
|
|||||||
+9
-14
@@ -29,23 +29,18 @@ mod profiles_cli;
|
|||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let args: Vec<String> = args().skip(1).collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
|
|
||||||
let parsed: CliStart;
|
|
||||||
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
||||||
match CliStart::parse_args_default(&args) {
|
let parsed = match CliStart::parse_args_default(&args) {
|
||||||
Ok(p) => {
|
Ok(p) => p,
|
||||||
parsed = p;
|
Err(err) if err.to_string() == missing_argument_k.to_string() => CliStart {
|
||||||
}
|
kbd_bright: Some(LedBrightness::new(None)),
|
||||||
Err(err) if err.to_string() == missing_argument_k.to_string() => {
|
..Default::default()
|
||||||
parsed = CliStart {
|
},
|
||||||
kbd_bright: Some(LedBrightness::new(None)),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("source {}", err);
|
eprintln!("source {}", err);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
let (dbus, _) = RogDbusClientBlocking::new()
|
let (dbus, _) = RogDbusClientBlocking::new()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -376,7 +371,7 @@ fn handle_anime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn verify_brightness(brightness: f32) {
|
fn verify_brightness(brightness: f32) {
|
||||||
if brightness < 0.0 || brightness > 1.0 {
|
if !(0.0..=1.0).contains(&brightness) {
|
||||||
println!(
|
println!(
|
||||||
"Image and global brightness must be between 0.0 and 1.0 (inclusive), was {}",
|
"Image and global brightness must be between 0.0 and 1.0 (inclusive), was {}",
|
||||||
brightness
|
brightness
|
||||||
@@ -474,7 +469,7 @@ fn handle_led_power1(
|
|||||||
}
|
}
|
||||||
|
|
||||||
println!("These options are for keyboards of product ID 0x1866 or TUF only");
|
println!("These options are for keyboards of product ID 0x1866 or TUF only");
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_led_power_1_do_1866(
|
fn handle_led_power_1_do_1866(
|
||||||
|
|||||||
+11
-12
@@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon-user"
|
name = "daemon-user"
|
||||||
version = "1.3.1"
|
version.workspace = true
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
description = "Usermode daemon for user settings, anime, per-key lighting"
|
description = "Usermode daemon for user settings, anime, per-key lighting"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
@@ -14,20 +14,19 @@ name = "asusd-user"
|
|||||||
path = "src/daemon.rs"
|
path = "src/daemon.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
dirs.workspace = true
|
||||||
|
smol.workspace = true
|
||||||
|
|
||||||
# serialisation
|
# serialisation
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_json = "^1.0"
|
serde_json.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
|
|
||||||
rog_anime = { path = "../rog-anime" }
|
rog_anime = { path = "../rog-anime" }
|
||||||
rog_aura = { path = "../rog-aura" }
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rog_platform = { path = "../rog-platform" }
|
rog_platform = { path = "../rog-platform" }
|
||||||
|
|
||||||
dirs = "^4.0"
|
zbus.workspace = true
|
||||||
|
zvariant.workspace = true
|
||||||
zbus = "^2.2"
|
zvariant_derive.workspace = true
|
||||||
zvariant = "^3.0"
|
|
||||||
zvariant_derive = "^3.0"
|
|
||||||
|
|
||||||
smol = "^1.2"
|
|
||||||
@@ -86,7 +86,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("{BOARD_NAME}, {e}");
|
println!("{BOARD_NAME}, {e}");
|
||||||
})
|
})
|
||||||
.unwrap_or(KeyLayout::ga401_layout());
|
.unwrap_or_else(|_| KeyLayout::ga401_layout());
|
||||||
|
|
||||||
executor
|
executor
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub trait ConfigLoadSave<T: DeserializeOwned + serde::Serialize> {
|
|||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
create_dir(path.clone())?;
|
create_dir(path.clone())?;
|
||||||
}
|
}
|
||||||
let name = self.name().clone();
|
let name = self.name();
|
||||||
path.push(name + ".cfg");
|
path.push(name + ".cfg");
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
@@ -230,7 +230,7 @@ impl Default for UserAuraConfig {
|
|||||||
80,
|
80,
|
||||||
40,
|
40,
|
||||||
));
|
));
|
||||||
seq.push(key.clone());
|
seq.push(key);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
name: "default".to_string(),
|
name: "default".to_string(),
|
||||||
|
|||||||
+15
-15
@@ -1,13 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "4.5.0-rc3"
|
version.workspace = true
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||||
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||||
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
|
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
@@ -24,24 +24,24 @@ rog_platform = { path = "../rog-platform" }
|
|||||||
rog_profiles = { path = "../rog-profiles" }
|
rog_profiles = { path = "../rog-profiles" }
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
|
||||||
async-trait = "^0.1"
|
async-trait.workspace = true
|
||||||
tokio = { version = "^1.21.1", features = ["macros", "rt-multi-thread", "time"]}
|
tokio.workspace = true
|
||||||
|
|
||||||
# cli and logging
|
# cli and logging
|
||||||
log = "^0.4"
|
log.workspace = true
|
||||||
env_logger = "^0.9"
|
env_logger.workspace = true
|
||||||
|
|
||||||
zbus = "^2.2"
|
zbus.workspace = true
|
||||||
zvariant = "^3.2"
|
zvariant.workspace = true
|
||||||
logind-zbus = { version = "^3.0" } #, default-features = false, features = ["non_blocking"] }
|
logind-zbus.workspace = true
|
||||||
|
|
||||||
# serialisation
|
# serialisation
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
serde_json = "^1.0"
|
serde_json.workspace = true
|
||||||
toml = "^0.5.8"
|
toml.workspace = true
|
||||||
|
|
||||||
# Device control
|
# Device control
|
||||||
sysfs-class = "^0.1.2" # used for backlight control and baord ID
|
sysfs-class.workspace = true # used for backlight control and baord ID
|
||||||
|
|
||||||
concat-idents = "1.1.3"
|
concat-idents.workspace = true
|
||||||
@@ -130,7 +130,7 @@ impl CtrlAnime {
|
|||||||
.ok();
|
.ok();
|
||||||
false // Don't exit yet
|
false // Don't exit yet
|
||||||
})
|
})
|
||||||
.map(|r| Ok(r))
|
.map(Ok)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
warn!("rog_anime::run_animation:callback failed");
|
warn!("rog_anime::run_animation:callback failed");
|
||||||
Err(AnimeError::NoFrames)
|
Err(AnimeError::NoFrames)
|
||||||
|
|||||||
@@ -123,14 +123,14 @@ impl CtrlAnimeZbus {
|
|||||||
#[dbus_interface(property)]
|
#[dbus_interface(property)]
|
||||||
async fn awake_enabled(&self) -> bool {
|
async fn awake_enabled(&self) -> bool {
|
||||||
let lock = self.0.lock().await;
|
let lock = self.0.lock().await;
|
||||||
return lock.config.awake_enabled;
|
lock.config.awake_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the status of if factory system-status animations are enabled
|
/// Get the status of if factory system-status animations are enabled
|
||||||
#[dbus_interface(property)]
|
#[dbus_interface(property)]
|
||||||
async fn boot_enabled(&self) -> bool {
|
async fn boot_enabled(&self) -> bool {
|
||||||
let lock = self.0.lock().await;
|
let lock = self.0.lock().await;
|
||||||
return lock.config.boot_anim_enabled;
|
lock.config.boot_anim_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
||||||
@@ -152,10 +152,10 @@ impl crate::CtrlTask for CtrlAnimeZbus {
|
|||||||
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
|
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
|
||||||
if start {
|
if start {
|
||||||
info!("CtrlAnimeTask running sleep animation");
|
info!("CtrlAnimeTask running sleep animation");
|
||||||
CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true);
|
CtrlAnime::run_thread(inner, lock.cache.shutdown.clone(), true);
|
||||||
} else {
|
} else {
|
||||||
info!("CtrlAnimeTask running wake animation");
|
info!("CtrlAnimeTask running wake animation");
|
||||||
CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true);
|
CtrlAnime::run_thread(inner, lock.cache.wake.clone(), true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ impl AuraPowerConfig {
|
|||||||
match control {
|
match control {
|
||||||
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0],
|
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0],
|
||||||
AuraPowerConfig::AuraDev1866(c) => {
|
AuraPowerConfig::AuraDev1866(c) => {
|
||||||
let c: Vec<AuraDev1866> = c.iter().map(|v| *v).collect();
|
let c: Vec<AuraDev1866> = c.iter().copied().collect();
|
||||||
AuraDev1866::to_bytes(&c)
|
AuraDev1866::to_bytes(&c)
|
||||||
}
|
}
|
||||||
AuraPowerConfig::AuraDev19b6(c) => {
|
AuraPowerConfig::AuraDev19b6(c) => {
|
||||||
let c: Vec<AuraDev19b6> = c.iter().map(|v| *v).collect();
|
let c: Vec<AuraDev19b6> = c.iter().copied().collect();
|
||||||
AuraDev19b6::to_bytes(&c)
|
AuraDev19b6::to_bytes(&c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,19 +95,19 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
|
|||||||
fn from(config: &AuraPowerConfig) -> Self {
|
fn from(config: &AuraPowerConfig) -> Self {
|
||||||
match config {
|
match config {
|
||||||
AuraPowerConfig::AuraDevTuf(d) => AuraPowerDev {
|
AuraPowerConfig::AuraDevTuf(d) => AuraPowerDev {
|
||||||
tuf: d.iter().map(|o| *o).collect(),
|
tuf: d.iter().copied().collect(),
|
||||||
x1866: vec![],
|
x1866: vec![],
|
||||||
x19b6: vec![],
|
x19b6: vec![],
|
||||||
},
|
},
|
||||||
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev {
|
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev {
|
||||||
tuf: vec![],
|
tuf: vec![],
|
||||||
x1866: d.iter().map(|o| *o).collect(),
|
x1866: d.iter().copied().collect(),
|
||||||
x19b6: vec![],
|
x19b6: vec![],
|
||||||
},
|
},
|
||||||
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev {
|
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev {
|
||||||
tuf: vec![],
|
tuf: vec![],
|
||||||
x1866: vec![],
|
x1866: vec![],
|
||||||
x19b6: d.iter().map(|o| *o).collect(),
|
x19b6: d.iter().copied().collect(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ impl Default for AuraConfig {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut prod_id = AuraDevice::Unknown;
|
let mut prod_id = AuraDevice::Unknown;
|
||||||
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||||
if let Ok(_) = HidRaw::new(prod) {
|
if HidRaw::new(prod).is_ok() {
|
||||||
prod_id = AuraDevice::from(*prod);
|
prod_id = AuraDevice::from(*prod);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -335,26 +335,34 @@ mod tests {
|
|||||||
fn set_multizone_4key_config() {
|
fn set_multizone_4key_config() {
|
||||||
let mut config = AuraConfig::default();
|
let mut config = AuraConfig::default();
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.colour1 = Colour(0xff, 0x00, 0xff);
|
colour1: Colour(0xff, 0x00, 0xff),
|
||||||
effect.zone = AuraZone::Key1;
|
zone: AuraZone::Key1,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
assert!(config.multizone.is_some());
|
assert!(config.multizone.is_some());
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.colour1 = Colour(0x00, 0xff, 0xff);
|
colour1: Colour(0x00, 0xff, 0xff),
|
||||||
effect.zone = AuraZone::Key2;
|
zone: AuraZone::Key2,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.colour1 = Colour(0xff, 0xff, 0x00);
|
colour1: Colour(0xff, 0xff, 0x00),
|
||||||
effect.zone = AuraZone::Key3;
|
zone: AuraZone::Key3,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.colour1 = Colour(0x00, 0xff, 0x00);
|
colour1: Colour(0x00, 0xff, 0x00),
|
||||||
effect.zone = AuraZone::Key4;
|
zone: AuraZone::Key4,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let effect_clone = effect.clone();
|
let effect_clone = effect.clone();
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
// This should replace existing
|
// This should replace existing
|
||||||
@@ -373,25 +381,33 @@ mod tests {
|
|||||||
fn set_multizone_multimode_config() {
|
fn set_multizone_multimode_config() {
|
||||||
let mut config = AuraConfig::default();
|
let mut config = AuraConfig::default();
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.zone = AuraZone::Key1;
|
zone: AuraZone::Key1,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
assert!(config.multizone.is_some());
|
assert!(config.multizone.is_some());
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.zone = AuraZone::Key2;
|
zone: AuraZone::Key2,
|
||||||
effect.mode = AuraModeNum::Breathe;
|
mode: AuraModeNum::Breathe,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.zone = AuraZone::Key3;
|
zone: AuraZone::Key3,
|
||||||
effect.mode = AuraModeNum::Comet;
|
mode: AuraModeNum::Comet,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let effect = AuraEffect {
|
||||||
effect.zone = AuraZone::Key4;
|
zone: AuraZone::Key4,
|
||||||
effect.mode = AuraModeNum::Pulse;
|
mode: AuraModeNum::Pulse,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
config.set_builtin(effect);
|
config.set_builtin(effect);
|
||||||
|
|
||||||
let res = config.multizone.unwrap();
|
let res = config.multizone.unwrap();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ impl GetSupported for CtrlKbdLed {
|
|||||||
|
|
||||||
let mut prod_id = AuraDevice::Unknown;
|
let mut prod_id = AuraDevice::Unknown;
|
||||||
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||||
if let Ok(_) = HidRaw::new(prod) {
|
if HidRaw::new(prod).is_ok() {
|
||||||
prod_id = AuraDevice::from(*prod);
|
prod_id = AuraDevice::from(*prod);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ impl GetSupported for CtrlKbdLed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd)]
|
||||||
pub enum LEDNode {
|
pub enum LEDNode {
|
||||||
KbdLed(KeyboardLed),
|
KbdLed(KeyboardLed),
|
||||||
Rog(HidRaw),
|
Rog(HidRaw),
|
||||||
@@ -121,13 +121,13 @@ impl CtrlKbdLed {
|
|||||||
pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
|
pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
|
||||||
self.kd_brightness
|
self.kd_brightness
|
||||||
.get_brightness()
|
.get_brightness()
|
||||||
.map_err(|e| RogError::Platform(e))
|
.map_err(RogError::Platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
||||||
self.kd_brightness
|
self.kd_brightness
|
||||||
.set_brightness(brightness as u8)
|
.set_brightness(brightness as u8)
|
||||||
.map_err(|e| RogError::Platform(e))
|
.map_err(RogError::Platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_brightness(&mut self) -> Result<(), RogError> {
|
pub fn next_brightness(&mut self) -> Result<(), RogError> {
|
||||||
@@ -176,10 +176,9 @@ impl CtrlKbdLed {
|
|||||||
/// On success the aura config file is read to refresh cached values, then the effect is
|
/// On success the aura config file is read to refresh cached values, then the effect is
|
||||||
/// stored and config written to disk.
|
/// stored and config written to disk.
|
||||||
pub(crate) fn set_effect(&mut self, effect: AuraEffect) -> Result<(), RogError> {
|
pub(crate) fn set_effect(&mut self, effect: AuraEffect) -> Result<(), RogError> {
|
||||||
if !self.supported_modes.standard.contains(&effect.mode) {
|
if !self.supported_modes.standard.contains(&effect.mode)
|
||||||
return Err(RogError::AuraEffectNotSupported);
|
|| effect.zone != AuraZone::None
|
||||||
} else if effect.zone != AuraZone::None
|
&& !self.supported_modes.multizone.contains(&effect.zone)
|
||||||
&& !self.supported_modes.multizone.contains(&effect.zone)
|
|
||||||
{
|
{
|
||||||
return Err(RogError::AuraEffectNotSupported);
|
return Err(RogError::AuraEffectNotSupported);
|
||||||
}
|
}
|
||||||
@@ -387,9 +386,11 @@ mod tests {
|
|||||||
config,
|
config,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut effect = AuraEffect::default();
|
let mut effect = AuraEffect {
|
||||||
effect.colour1 = Colour(0xff, 0x00, 0xff);
|
colour1: Colour(0xff, 0x00, 0xff),
|
||||||
effect.zone = AuraZone::None;
|
zone: AuraZone::None,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
// This error comes from write_bytes because we don't have a keyboard node stored
|
// This error comes from write_bytes because we don't have a keyboard node stored
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -421,10 +422,7 @@ mod tests {
|
|||||||
|
|
||||||
controller.supported_modes.multizone.push(AuraZone::Key2);
|
controller.supported_modes.multizone.push(AuraZone::Key2);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
controller
|
controller.set_effect(effect).unwrap_err().to_string(),
|
||||||
.set_effect(effect.clone())
|
|
||||||
.unwrap_err()
|
|
||||||
.to_string(),
|
|
||||||
"No supported Aura keyboard"
|
"No supported Aura keyboard"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl CtrlKbdLedZbus {
|
|||||||
lock.config.read();
|
lock.config.read();
|
||||||
lock.config.brightness = (bright as u32).into();
|
lock.config.brightness = (bright as u32).into();
|
||||||
lock.config.write();
|
lock.config.write();
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,19 +192,19 @@ impl CtrlKbdLedZbus {
|
|||||||
// #[dbus_interface(property)]
|
// #[dbus_interface(property)]
|
||||||
async fn leds_enabled(&self) -> AuraPowerDev {
|
async fn leds_enabled(&self) -> AuraPowerDev {
|
||||||
let ctrl = self.0.lock().await;
|
let ctrl = self.0.lock().await;
|
||||||
return AuraPowerDev::from(&ctrl.config.enabled);
|
AuraPowerDev::from(&ctrl.config.enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current mode data
|
/// Return the current mode data
|
||||||
async fn led_mode(&self) -> AuraModeNum {
|
async fn led_mode(&self) -> AuraModeNum {
|
||||||
let ctrl = self.0.lock().await;
|
let ctrl = self.0.lock().await;
|
||||||
return ctrl.config.current_mode;
|
ctrl.config.current_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a list of available modes
|
/// Return a list of available modes
|
||||||
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
||||||
let ctrl = self.0.lock().await;
|
let ctrl = self.0.lock().await;
|
||||||
return ctrl.config.builtins.clone();
|
ctrl.config.builtins.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> {
|
async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> {
|
||||||
|
|||||||
+24
-39
@@ -78,7 +78,7 @@ impl CtrlPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_gfx_mode(&self, mode: GpuMode) -> Result<(), RogError> {
|
fn set_gfx_mode(&self, mode: GpuMode) -> Result<(), RogError> {
|
||||||
self.platform.set_gpu_mux_mode(mode.to_mux())?;
|
self.platform.set_gpu_mux_mode(mode.to_mux_attr())?;
|
||||||
// self.update_initramfs(enable)?;
|
// self.update_initramfs(enable)?;
|
||||||
if mode == GpuMode::Discrete {
|
if mode == GpuMode::Discrete {
|
||||||
info!("Set system-level graphics mode: Dedicated Nvidia");
|
info!("Set system-level graphics mode: Dedicated Nvidia");
|
||||||
@@ -147,7 +147,7 @@ impl CtrlPlatform {
|
|||||||
) {
|
) {
|
||||||
self.set_gfx_mode(mode)
|
self.set_gfx_mode(mode)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err);
|
warn!("CtrlRogBios: set_gpu_mux_mode {}", err);
|
||||||
err
|
err
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
@@ -156,7 +156,7 @@ impl CtrlPlatform {
|
|||||||
|
|
||||||
fn gpu_mux_mode(&self) -> GpuMode {
|
fn gpu_mux_mode(&self) -> GpuMode {
|
||||||
match self.platform.get_gpu_mux_mode() {
|
match self.platform.get_gpu_mux_mode() {
|
||||||
Ok(m) => GpuMode::from_mux(m),
|
Ok(m) => GpuMode::from_mux(m as u8),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("CtrlRogBios: get_gfx_mode {}", e);
|
warn!("CtrlRogBios: get_gfx_mode {}", e);
|
||||||
GpuMode::Error
|
GpuMode::Error
|
||||||
@@ -202,21 +202,16 @@ impl CtrlPlatform {
|
|||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
overdrive: bool,
|
overdrive: bool,
|
||||||
) {
|
) {
|
||||||
if self
|
match self.platform.set_panel_od(overdrive) {
|
||||||
.platform
|
Ok(_) => {
|
||||||
.set_panel_od(overdrive)
|
if let Some(mut lock) = self.config.try_lock() {
|
||||||
.map_err(|err| {
|
lock.panel_od = overdrive;
|
||||||
warn!("CtrlRogBios: set_panel_overdrive {}", err);
|
lock.write();
|
||||||
err
|
}
|
||||||
})
|
Self::notify_panel_od(&ctxt, overdrive).await.ok();
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
if let Some(mut lock) = self.config.try_lock() {
|
|
||||||
lock.panel_od = overdrive;
|
|
||||||
lock.write();
|
|
||||||
}
|
}
|
||||||
Self::notify_panel_od(&ctxt, overdrive).await.ok();
|
Err(err) => warn!("CtrlRogBios: set_panel_overdrive {}", err),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `panel_od` value from platform. Updates the stored value in internal config also.
|
/// Get the `panel_od` value from platform. Updates the stored value in internal config also.
|
||||||
@@ -245,17 +240,12 @@ impl CtrlPlatform {
|
|||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
disable: bool,
|
disable: bool,
|
||||||
) {
|
) {
|
||||||
if self
|
match self.platform.set_dgpu_disable(disable) {
|
||||||
.platform
|
Ok(_) => {
|
||||||
.set_dgpu_disable(disable)
|
Self::notify_dgpu_disable(&ctxt, disable).await.ok();
|
||||||
.map_err(|err| {
|
}
|
||||||
warn!("CtrlRogBios: set_dgpu_disable {}", err);
|
Err(err) => warn!("CtrlRogBios: set_dgpu_disable {}", err),
|
||||||
err
|
};
|
||||||
})
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
Self::notify_dgpu_disable(&ctxt, disable).await.ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dgpu_disable(&self) -> bool {
|
fn dgpu_disable(&self) -> bool {
|
||||||
@@ -280,17 +270,12 @@ impl CtrlPlatform {
|
|||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
enable: bool,
|
enable: bool,
|
||||||
) {
|
) {
|
||||||
if self
|
match self.platform.set_egpu_enable(enable) {
|
||||||
.platform
|
Ok(_) => {
|
||||||
.set_egpu_enable(enable)
|
Self::notify_egpu_enable(&ctxt, enable).await.ok();
|
||||||
.map_err(|err| {
|
}
|
||||||
warn!("CtrlRogBios: set_egpu_enable {}", err);
|
Err(err) => warn!("CtrlRogBios: set_egpu_enable {}", err),
|
||||||
err
|
};
|
||||||
})
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
Self::notify_egpu_enable(&ctxt, enable).await.ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn egpu_enable(&self) -> bool {
|
fn egpu_enable(&self) -> bool {
|
||||||
|
|||||||
+56
-26
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::systemd::{do_systemd_unit_action, SystemdUnitAction};
|
||||||
use crate::{config::Config, error::RogError, GetSupported};
|
use crate::{config::Config, error::RogError, GetSupported};
|
||||||
use crate::{task_watch_item, CtrlTask};
|
use crate::{task_watch_item, CtrlTask};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -5,13 +6,15 @@ use log::{info, warn};
|
|||||||
use rog_platform::power::AsusPower;
|
use rog_platform::power::AsusPower;
|
||||||
use rog_platform::supported::ChargeSupportedFunctions;
|
use rog_platform::supported::ChargeSupportedFunctions;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time::sleep;
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
use zbus::export::futures_util::lock::Mutex;
|
use zbus::export::futures_util::lock::Mutex;
|
||||||
use zbus::export::futures_util::StreamExt;
|
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
use zbus::SignalContext;
|
use zbus::SignalContext;
|
||||||
|
|
||||||
const ZBUS_PATH: &str = "/org/asuslinux/Power";
|
const ZBUS_PATH: &str = "/org/asuslinux/Power";
|
||||||
|
const NVIDIA_POWERD: &str = "nvidia-powerd.service";
|
||||||
|
|
||||||
impl GetSupported for CtrlPower {
|
impl GetSupported for CtrlPower {
|
||||||
type A = ChargeSupportedFunctions;
|
type A = ChargeSupportedFunctions;
|
||||||
@@ -49,13 +52,15 @@ impl CtrlPower {
|
|||||||
err
|
err
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
Self::notify_charge_control_end_threshold(&ctxt, limit).await?;
|
Self::notify_charge_control_end_threshold(&ctxt, limit)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn charge_control_end_threshold(&self) -> u8 {
|
fn charge_control_end_threshold(&self) -> u8 {
|
||||||
loop {
|
loop {
|
||||||
if let Some(config) = self.config.try_lock() {
|
if let Some(mut config) = self.config.try_lock() {
|
||||||
let limit = self
|
let limit = self
|
||||||
.power
|
.power
|
||||||
.get_charge_control_end_threshold()
|
.get_charge_control_end_threshold()
|
||||||
@@ -64,11 +69,10 @@ impl CtrlPower {
|
|||||||
err
|
err
|
||||||
})
|
})
|
||||||
.unwrap_or(100);
|
.unwrap_or(100);
|
||||||
if let Some(mut config) = self.config.try_lock() {
|
|
||||||
config.read();
|
config.read();
|
||||||
config.bat_charge_limit = limit;
|
config.bat_charge_limit = limit;
|
||||||
config.write();
|
config.write();
|
||||||
}
|
|
||||||
|
|
||||||
return config.bat_charge_limit;
|
return config.bat_charge_limit;
|
||||||
}
|
}
|
||||||
@@ -163,6 +167,16 @@ impl CtrlTask for CtrlPower {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
if let Ok(value) = power1.power.get_online() {
|
||||||
|
let action = if value == 1 {
|
||||||
|
SystemdUnitAction::Restart
|
||||||
|
} else {
|
||||||
|
SystemdUnitAction::Stop
|
||||||
|
};
|
||||||
|
if do_systemd_unit_action(action, NVIDIA_POWERD).is_ok() {
|
||||||
|
info!("CtrlPower task: did {action:?} on {NVIDIA_POWERD}");
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
move || {},
|
move || {},
|
||||||
move || {
|
move || {
|
||||||
@@ -176,6 +190,16 @@ impl CtrlTask for CtrlPower {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
if let Ok(value) = power2.power.get_online() {
|
||||||
|
let action = if value == 1 {
|
||||||
|
SystemdUnitAction::Restart
|
||||||
|
} else {
|
||||||
|
SystemdUnitAction::Stop
|
||||||
|
};
|
||||||
|
if do_systemd_unit_action(action, NVIDIA_POWERD).is_ok() {
|
||||||
|
info!("CtrlPower task: did {action:?} on {NVIDIA_POWERD}");
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -184,25 +208,31 @@ impl CtrlTask for CtrlPower {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let ctrl = self.clone();
|
let ctrl = self.clone();
|
||||||
match ctrl.power.monitor_online() {
|
tokio::spawn(async move {
|
||||||
Ok(mut watch) => {
|
let mut online = 10;
|
||||||
tokio::spawn(async move {
|
loop {
|
||||||
let mut buffer = [0; 32];
|
if let Ok(value) = ctrl.power.get_online() {
|
||||||
watch
|
if online != value {
|
||||||
.event_stream(&mut buffer)
|
online = value;
|
||||||
.unwrap()
|
let action = if value == 1 {
|
||||||
.for_each(|_| async {
|
SystemdUnitAction::Restart
|
||||||
if let Ok(value) = ctrl.power.get_online() {
|
} else {
|
||||||
Self::notify_mains_online(&signal_ctxt, value == 1)
|
SystemdUnitAction::Stop
|
||||||
.await
|
};
|
||||||
.unwrap();
|
if do_systemd_unit_action(action, NVIDIA_POWERD).is_ok() {
|
||||||
}
|
info!("CtrlPower task: did {action:?} on {NVIDIA_POWERD}");
|
||||||
})
|
}
|
||||||
.await;
|
|
||||||
});
|
Self::notify_mains_online(&signal_ctxt, value == 1)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The inotify doesn't pick up events when the kernel changes internal value
|
||||||
|
// so we need to watch it with a thread and sleep unfortunately
|
||||||
|
sleep(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
Err(e) => info!("inotify watch failed: {}", e),
|
});
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ impl ProfileZbus {
|
|||||||
if let Some(curves) = &ctrl.config.fan_curves {
|
if let Some(curves) = &ctrl.config.fan_curves {
|
||||||
return Ok(curves.get_enabled_curve_profiles().to_vec());
|
return Ok(curves.get_enabled_curve_profiles().to_vec());
|
||||||
}
|
}
|
||||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
|
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
|
||||||
@@ -99,7 +99,7 @@ impl ProfileZbus {
|
|||||||
) -> zbus::fdo::Result<()> {
|
) -> zbus::fdo::Result<()> {
|
||||||
let mut ctrl = self.0.lock().await;
|
let mut ctrl = self.0.lock().await;
|
||||||
ctrl.config.read();
|
ctrl.config.read();
|
||||||
return if let Some(curves) = &mut ctrl.config.fan_curves {
|
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||||
curves.set_profile_curve_enabled(profile, enabled);
|
curves.set_profile_curve_enabled(profile, enabled);
|
||||||
|
|
||||||
ctrl.write_profile_curve_to_platform()
|
ctrl.write_profile_curve_to_platform()
|
||||||
@@ -110,7 +110,7 @@ impl ProfileZbus {
|
|||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the fan-curve data for the currently active Profile
|
/// Get the fan-curve data for the currently active Profile
|
||||||
@@ -121,7 +121,7 @@ impl ProfileZbus {
|
|||||||
let curve = curves.get_fan_curves_for(profile);
|
let curve = curves.get_fan_curves_for(profile);
|
||||||
return Ok(curve.clone());
|
return Ok(curve.clone());
|
||||||
}
|
}
|
||||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the fan curve for the specified profile.
|
/// Set the fan curve for the specified profile.
|
||||||
@@ -216,7 +216,6 @@ impl CtrlTask for ProfileZbus {
|
|||||||
lock.write_profile_curve_to_platform().unwrap();
|
lock.write_profile_curve_to_platform().unwrap();
|
||||||
lock.save_config();
|
lock.save_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::notify_profile(&signal_ctxt.clone(), lock.config.active_profile)
|
Self::notify_profile(&signal_ctxt.clone(), lock.config.active_profile)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|||||||
+17
-9
@@ -10,6 +10,7 @@ use daemon::ctrl_anime::CtrlAnime;
|
|||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
use zbus::SignalContext;
|
||||||
|
|
||||||
use daemon::ctrl_anime::{config::AnimeConfig, trait_impls::CtrlAnimeZbus};
|
use daemon::ctrl_anime::{config::AnimeConfig, trait_impls::CtrlAnimeZbus};
|
||||||
use daemon::ctrl_aura::{config::AuraConfig, controller::CtrlKbdLed, trait_impls::CtrlKbdLedZbus};
|
use daemon::ctrl_aura::{config::AuraConfig, controller::CtrlKbdLed, trait_impls::CtrlKbdLedZbus};
|
||||||
@@ -78,7 +79,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
match CtrlPlatform::new(config.clone()) {
|
match CtrlPlatform::new(config.clone()) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
start_tasks(ctrl, &mut connection).await?;
|
let sig_ctx = CtrlPlatform::signal_context(&connection)?;
|
||||||
|
start_tasks(ctrl, &mut connection, sig_ctx).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("CtrlPlatform: {}", err);
|
error!("CtrlPlatform: {}", err);
|
||||||
@@ -87,7 +89,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
match CtrlPower::new(config.clone()) {
|
match CtrlPower::new(config.clone()) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
start_tasks(ctrl, &mut connection).await?;
|
let sig_ctx = CtrlPower::signal_context(&connection)?;
|
||||||
|
start_tasks(ctrl, &mut connection, sig_ctx).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("CtrlPower: {}", err);
|
error!("CtrlPower: {}", err);
|
||||||
@@ -99,7 +102,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
match CtrlPlatformProfile::new(profile_config) {
|
match CtrlPlatformProfile::new(profile_config) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let zbus = ProfileZbus(Arc::new(Mutex::new(ctrl)));
|
let zbus = ProfileZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
start_tasks(zbus, &mut connection).await?;
|
let sig_ctx = ProfileZbus::signal_context(&connection)?;
|
||||||
|
start_tasks(zbus, &mut connection, sig_ctx).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Profile control: {}", err);
|
error!("Profile control: {}", err);
|
||||||
@@ -112,7 +116,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
match CtrlAnime::new(AnimeConfig::load()) {
|
match CtrlAnime::new(AnimeConfig::load()) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let zbus = CtrlAnimeZbus(Arc::new(Mutex::new(ctrl)));
|
let zbus = CtrlAnimeZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
start_tasks(zbus, &mut connection).await?;
|
let sig_ctx = CtrlAnimeZbus::signal_context(&connection)?;
|
||||||
|
start_tasks(zbus, &mut connection, sig_ctx).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
info!("AniMe control: {}", err);
|
info!("AniMe control: {}", err);
|
||||||
@@ -124,7 +129,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
match CtrlKbdLed::new(laptop, aura_config) {
|
match CtrlKbdLed::new(laptop, aura_config) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
|
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
start_tasks(zbus, &mut connection).await?;
|
let sig_ctx = CtrlKbdLedZbus::signal_context(&connection)?;
|
||||||
|
start_tasks(zbus, &mut connection, sig_ctx).await?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Keyboard control: {}", err);
|
error!("Keyboard control: {}", err);
|
||||||
@@ -140,7 +146,11 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_tasks<T>(mut zbus: T, connection: &mut Connection) -> Result<(), Box<dyn Error>>
|
async fn start_tasks<T>(
|
||||||
|
mut zbus: T,
|
||||||
|
connection: &mut Connection,
|
||||||
|
signal_ctx: SignalContext<'static>,
|
||||||
|
) -> Result<(), Box<dyn Error>>
|
||||||
where
|
where
|
||||||
T: ZbusRun + Reloadable + CtrlTask + Clone,
|
T: ZbusRun + Reloadable + CtrlTask + Clone,
|
||||||
{
|
{
|
||||||
@@ -151,8 +161,6 @@ where
|
|||||||
.unwrap_or_else(|err| warn!("Controller error: {}", err));
|
.unwrap_or_else(|err| warn!("Controller error: {}", err));
|
||||||
zbus.add_to_server(connection).await;
|
zbus.add_to_server(connection).await;
|
||||||
|
|
||||||
task.create_tasks(CtrlKbdLedZbus::signal_context(&connection)?)
|
task.create_tasks(signal_ctx).await.ok();
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ pub enum RogError {
|
|||||||
NoAuraNode,
|
NoAuraNode,
|
||||||
Anime(AnimeError),
|
Anime(AnimeError),
|
||||||
Platform(PlatformError),
|
Platform(PlatformError),
|
||||||
|
SystemdUnitAction(String),
|
||||||
|
SystemdUnitWaitTimeout(String),
|
||||||
|
Command(String, std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RogError {
|
impl fmt::Display for RogError {
|
||||||
@@ -60,6 +63,17 @@ impl fmt::Display for RogError {
|
|||||||
RogError::NoAuraNode => write!(f, "No Aura keyboard node found"),
|
RogError::NoAuraNode => write!(f, "No Aura keyboard node found"),
|
||||||
RogError::Anime(deets) => write!(f, "AniMe Matrix error: {}", deets),
|
RogError::Anime(deets) => write!(f, "AniMe Matrix error: {}", deets),
|
||||||
RogError::Platform(deets) => write!(f, "Asus Platform error: {}", deets),
|
RogError::Platform(deets) => write!(f, "Asus Platform error: {}", deets),
|
||||||
|
RogError::SystemdUnitAction(action) => {
|
||||||
|
write!(f, "systemd unit action {} failed", action)
|
||||||
|
}
|
||||||
|
RogError::SystemdUnitWaitTimeout(state) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Timed out waiting for systemd unit change {} state",
|
||||||
|
state
|
||||||
|
)
|
||||||
|
}
|
||||||
|
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -14,6 +14,8 @@ pub mod ctrl_profiles;
|
|||||||
/// Laptop matching to determine capabilities
|
/// Laptop matching to determine capabilities
|
||||||
pub mod laptops;
|
pub mod laptops;
|
||||||
|
|
||||||
|
pub mod systemd;
|
||||||
|
|
||||||
/// Fetch all supported functions for the laptop
|
/// Fetch all supported functions for the laptop
|
||||||
pub mod ctrl_supported;
|
pub mod ctrl_supported;
|
||||||
|
|
||||||
@@ -62,8 +64,9 @@ macro_rules! task_watch_item {
|
|||||||
let mut buffer = [0; 32];
|
let mut buffer = [0; 32];
|
||||||
watch.event_stream(&mut buffer).unwrap().for_each(|_| async {
|
watch.event_stream(&mut buffer).unwrap().for_each(|_| async {
|
||||||
let value = ctrl.$name();
|
let value = ctrl.$name();
|
||||||
|
dbg!(&value);
|
||||||
concat_idents::concat_idents!(notif_fn = notify_, $name {
|
concat_idents::concat_idents!(notif_fn = notify_, $name {
|
||||||
Self::notif_fn(&signal_ctxt, value).await.unwrap();
|
Self::notif_fn(&signal_ctxt, value).await.ok();
|
||||||
});
|
});
|
||||||
}).await;
|
}).await;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use crate::error::RogError;
|
||||||
|
|
||||||
|
/// An action for `systemctl`
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum SystemdUnitAction {
|
||||||
|
Stop,
|
||||||
|
Start,
|
||||||
|
Restart,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SystemdUnitAction> for &str {
|
||||||
|
fn from(s: SystemdUnitAction) -> Self {
|
||||||
|
match s {
|
||||||
|
SystemdUnitAction::Stop => "stop",
|
||||||
|
SystemdUnitAction::Start => "start",
|
||||||
|
SystemdUnitAction::Restart => "restart",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum SystemdUnitState {
|
||||||
|
Active,
|
||||||
|
Inactive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SystemdUnitState> for &str {
|
||||||
|
fn from(s: SystemdUnitState) -> Self {
|
||||||
|
match s {
|
||||||
|
SystemdUnitState::Active => "active",
|
||||||
|
SystemdUnitState::Inactive => "inactive",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Change the state of a systemd unit. Blocks while running command.
|
||||||
|
pub fn do_systemd_unit_action(action: SystemdUnitAction, unit: &str) -> Result<(), RogError> {
|
||||||
|
let mut cmd = Command::new("systemctl");
|
||||||
|
cmd.arg(<&str>::from(action));
|
||||||
|
cmd.arg(unit);
|
||||||
|
|
||||||
|
let status = cmd
|
||||||
|
.status()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if !status.success() {
|
||||||
|
let msg = format!("systemctl {action:?} {unit} failed: {status:?}",);
|
||||||
|
return Err(RogError::SystemdUnitAction(msg));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get systemd unit state. Blocks while command is run.
|
||||||
|
pub fn is_systemd_unit_state(state: SystemdUnitState, unit: &str) -> Result<bool, RogError> {
|
||||||
|
let mut cmd = Command::new("systemctl");
|
||||||
|
cmd.arg("is-active");
|
||||||
|
cmd.arg(unit);
|
||||||
|
|
||||||
|
let output = cmd
|
||||||
|
.output()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if output.stdout.starts_with(<&str>::from(state).as_bytes()) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wait for a systemd unit to change to `state`. Checks state every 250ms for 3 seconds. Blocks while running wait.
|
||||||
|
pub fn wait_systemd_unit_state(state: SystemdUnitState, unit: &str) -> Result<(), RogError> {
|
||||||
|
let mut cmd = Command::new("systemctl");
|
||||||
|
cmd.arg("is-active");
|
||||||
|
cmd.arg(unit);
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
while count <= (4 * 3) {
|
||||||
|
// 3 seconds max
|
||||||
|
let output = cmd
|
||||||
|
.output()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if output.stdout.starts_with(<&str>::from(state).as_bytes()) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// fine to block here, nobody doing shit now
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
Err(RogError::SystemdUnitWaitTimeout(<&str>::from(state).into()))
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=ASUS Notifications
|
|
||||||
StartLimitInterval=200
|
|
||||||
StartLimitBurst=2
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStartPre=/usr/bin/sleep 2
|
|
||||||
ExecStart=/usr/bin/asus-notify
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=1
|
|
||||||
Type=simple
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
+19
-19
@@ -21,21 +21,7 @@ per_key = true
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus M"
|
prod_family = "Zephyrus M"
|
||||||
board_names = ["GU502GV"]
|
board_names = ["GU502G"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
|
||||||
multizone = []
|
|
||||||
per_key = true
|
|
||||||
|
|
||||||
[[led_data]]
|
|
||||||
prod_family = "Zephyrus M"
|
|
||||||
board_names = ["GM501GS"]
|
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
|
||||||
multizone = ["Key1", "Key2", "Key3", "Key4"]
|
|
||||||
per_key = false
|
|
||||||
|
|
||||||
[[led_data]]
|
|
||||||
prod_family = "ROG Zephyrus M15"
|
|
||||||
board_names = ["GU502LW", "GU502LV"]
|
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = true
|
per_key = true
|
||||||
@@ -47,6 +33,13 @@ standard = ["Static", "Breathe", "Strobe", "Pulse"]
|
|||||||
multizone = []
|
multizone = []
|
||||||
per_key = false
|
per_key = false
|
||||||
|
|
||||||
|
[[led_data]]
|
||||||
|
prod_family = "ROG Zephyrus M15"
|
||||||
|
board_names = ["GU502L"]
|
||||||
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = []
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus M16"
|
prod_family = "ROG Zephyrus M16"
|
||||||
board_names = ["GU603Z", "GU603H"]
|
board_names = ["GU603Z", "GU603H"]
|
||||||
@@ -56,7 +49,7 @@ per_key = false
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus S17"
|
prod_family = "ROG Zephyrus S17"
|
||||||
board_names = ["GX703HS"]
|
board_names = ["GX703H"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = false
|
per_key = false
|
||||||
@@ -64,14 +57,14 @@ per_key = false
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus"
|
prod_family = "Zephyrus"
|
||||||
board_names = ["GM501GM", "GX531"]
|
board_names = ["GM501G", "GX531"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
multizone = ["Key1", "Key2", "Key3", "Key4"]
|
multizone = ["Key1", "Key2", "Key3", "Key4"]
|
||||||
per_key = false
|
per_key = false
|
||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G531GW", "G533QR", "G533QS", "G733QS", "G733QR", "G513QR", "G713QR", "G513QM", "G713IC", "G713RS"]
|
board_names = ["G531GW", "G533QR", "G533QS", "G733Q", "G513QR", "G713QR", "G513QM", "G713IC", "G713RS"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = true
|
per_key = true
|
||||||
@@ -177,7 +170,7 @@ per_key = true
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Flow X13"
|
prod_family = "ROG Flow X13"
|
||||||
board_names = ["GV301QH", "GV301QE"]
|
board_names = ["GV301Q"]
|
||||||
standard = ["Static", "Breathe", "Pulse"]
|
standard = ["Static", "Breathe", "Pulse"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = false
|
per_key = false
|
||||||
@@ -188,3 +181,10 @@ board_names = ["G513IC", "G513RC"]
|
|||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = false
|
per_key = false
|
||||||
|
|
||||||
|
[[led_data]]
|
||||||
|
prod_family = "ROG Flow X16"
|
||||||
|
board_names = ["GV601R"]
|
||||||
|
standard = ["Static", "Breathe", "Strobe", "Pulse"]
|
||||||
|
multizone = []
|
||||||
|
per_key = false
|
||||||
|
|||||||
+12
-12
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_anime"
|
name = "rog_anime"
|
||||||
version = "1.3.5"
|
version.workspace = true
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
@@ -9,7 +9,7 @@ homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
|||||||
documentation = "https://docs.rs/rog-anime"
|
documentation = "https://docs.rs/rog-anime"
|
||||||
description = "Types useful for translating images and other data for display on the ASUS AniMe Matrix display"
|
description = "Types useful for translating images and other data for display on the ASUS AniMe Matrix display"
|
||||||
keywords = ["ROG", "ASUS", "AniMe"]
|
keywords = ["ROG", "ASUS", "AniMe"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
exclude = ["data"]
|
exclude = ["data"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -18,17 +18,17 @@ dbus = ["zvariant", "zbus"]
|
|||||||
detect = ["sysfs-class"]
|
detect = ["sysfs-class"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
png_pong = "^0.8.0"
|
png_pong.workspace = true
|
||||||
pix = "0.13"
|
pix.workspace = true
|
||||||
gif = "^0.11.2"
|
gif.workspace = true
|
||||||
log = "*"
|
log.workspace = true
|
||||||
|
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
|
|
||||||
glam = { version = "^0.21.2", features = ["serde"] }
|
glam.workspace = true
|
||||||
|
|
||||||
zvariant = { version = "^3.0", optional = true }
|
zvariant = { workspace = true, optional = true }
|
||||||
zbus = { version = "^2.2", optional = true }
|
zbus = { workspace = true, optional = true }
|
||||||
|
|
||||||
sysfs-class = { version = "^0.1", optional = true }
|
sysfs-class = { workspace = true, optional = true }
|
||||||
@@ -29,7 +29,7 @@ const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
|||||||
const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
|
const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||||
pub struct AnimePowerStates {
|
pub struct AnimePowerStates {
|
||||||
pub brightness: u8,
|
pub brightness: u8,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ impl AnimeDiagonal {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_data_buffer(&self, anime_type: AnimeType) -> Result<AnimeDataBuffer> {
|
pub fn into_data_buffer(&self, anime_type: AnimeType) -> Result<AnimeDataBuffer> {
|
||||||
match anime_type {
|
match anime_type {
|
||||||
AnimeType::GA401 => self.into_ga401_packets(),
|
AnimeType::GA401 => self.to_ga401_packets(),
|
||||||
AnimeType::GA402 => self.into_ga402_packets(),
|
AnimeType::GA402 => self.to_ga402_packets(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do conversion from the nested Vec in AnimeMatrix to the two required
|
/// Do conversion from the nested Vec in AnimeMatrix to the two required
|
||||||
/// packets suitable for sending over USB
|
/// packets suitable for sending over USB
|
||||||
fn into_ga401_packets(&self) -> Result<AnimeDataBuffer> {
|
fn to_ga401_packets(&self) -> Result<AnimeDataBuffer> {
|
||||||
let mut buf = vec![0u8; AnimeType::GA401.data_length()];
|
let mut buf = vec![0u8; AnimeType::GA401.data_length()];
|
||||||
|
|
||||||
buf[1..=32].copy_from_slice(&self.get_row(0, 3, 32));
|
buf[1..=32].copy_from_slice(&self.get_row(0, 3, 32));
|
||||||
@@ -200,12 +200,12 @@ impl AnimeDiagonal {
|
|||||||
AnimeDataBuffer::from_vec(crate::AnimeType::GA401, buf)
|
AnimeDataBuffer::from_vec(crate::AnimeType::GA401, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_ga402_packets(&self) -> Result<AnimeDataBuffer> {
|
fn to_ga402_packets(&self) -> Result<AnimeDataBuffer> {
|
||||||
let mut buf = vec![0u8; AnimeType::GA402.data_length()];
|
let mut buf = vec![0u8; AnimeType::GA402.data_length()];
|
||||||
let mut start_index: usize = 0;
|
let mut start_index: usize = 0;
|
||||||
|
|
||||||
fn copy_slice(
|
fn copy_slice(
|
||||||
buf: &mut Vec<u8>,
|
buf: &mut [u8],
|
||||||
anime: &AnimeDiagonal,
|
anime: &AnimeDiagonal,
|
||||||
x: usize,
|
x: usize,
|
||||||
y: usize,
|
y: usize,
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ impl AnimeImage {
|
|||||||
width: u32,
|
width: u32,
|
||||||
anime_type: AnimeType,
|
anime_type: AnimeType,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
if bright < 0.0 || bright > 1.0 {
|
if !(0.0..=1.0).contains(&bright) {
|
||||||
return Err(AnimeError::InvalidBrightness(bright));
|
return Err(AnimeError::InvalidBrightness(bright));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
|
|||||||
let dmi = sysfs_class::DmiId::default();
|
let dmi = sysfs_class::DmiId::default();
|
||||||
let board_name = dmi.board_name()?;
|
let board_name = dmi.board_name()?;
|
||||||
|
|
||||||
if board_name.contains("GA401I") {
|
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
||||||
return Ok(AnimeType::GA401);
|
|
||||||
} else if board_name.contains("GA401Q") {
|
|
||||||
return Ok(AnimeType::GA401);
|
return Ok(AnimeType::GA401);
|
||||||
} else if board_name.contains("GA402R") {
|
} else if board_name.contains("GA402R") {
|
||||||
return Ok(AnimeType::GA402);
|
return Ok(AnimeType::GA402);
|
||||||
|
|||||||
+7
-7
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_aura"
|
name = "rog_aura"
|
||||||
version = "1.3.3"
|
version.workspace = true
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
@@ -9,7 +9,7 @@ homepage = "https://gitlab.com/asus-linux/asusctl"
|
|||||||
documentation = "https://docs.rs/rog-anime"
|
documentation = "https://docs.rs/rog-anime"
|
||||||
description = "Types useful for fancy keyboards on ASUS ROG laptops"
|
description = "Types useful for fancy keyboards on ASUS ROG laptops"
|
||||||
keywords = ["ROG", "ASUS", "Aura"]
|
keywords = ["ROG", "ASUS", "Aura"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
exclude = ["data"]
|
exclude = ["data"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -17,10 +17,10 @@ default = ["dbus", "toml"]
|
|||||||
dbus = ["zvariant"]
|
dbus = ["zvariant"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
toml = { version = "^0.5", optional = true }
|
toml = { workspace = true, optional = true }
|
||||||
zvariant = { version = "^3.0", optional = true }
|
zvariant = { workspace = true, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "^1.0"
|
serde_json.workspace = true
|
||||||
@@ -12,7 +12,7 @@ use zvariant::Type;
|
|||||||
use crate::{error::Error, LED_MSG_LEN};
|
use crate::{error::Error, LED_MSG_LEN};
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum LedBrightness {
|
pub enum LedBrightness {
|
||||||
Off,
|
Off,
|
||||||
Low,
|
Low,
|
||||||
@@ -33,7 +33,7 @@ impl From<u32> for LedBrightness {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Copy, Deserialize, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Copy, Deserialize, Serialize)]
|
||||||
pub struct Colour(pub u8, pub u8, pub u8);
|
pub struct Colour(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
impl Default for Colour {
|
impl Default for Colour {
|
||||||
@@ -85,7 +85,7 @@ impl From<Colour> for [u8; 3] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum Speed {
|
pub enum Speed {
|
||||||
Low = 0xe1,
|
Low = 0xe1,
|
||||||
Med = 0xeb,
|
Med = 0xeb,
|
||||||
@@ -123,7 +123,7 @@ impl From<Speed> for u8 {
|
|||||||
///
|
///
|
||||||
/// Enum corresponds to the required integer value
|
/// Enum corresponds to the required integer value
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Right,
|
Right,
|
||||||
Left,
|
Left,
|
||||||
@@ -251,7 +251,7 @@ impl From<u8> for AuraModeNum {
|
|||||||
|
|
||||||
/// Base effects have no zoning, while multizone is 1-4
|
/// Base effects have no zoning, while multizone is 1-4
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum AuraZone {
|
pub enum AuraZone {
|
||||||
/// Used if keyboard has no zones, or if setting all
|
/// Used if keyboard has no zones, or if setting all
|
||||||
#[default]
|
#[default]
|
||||||
@@ -325,8 +325,8 @@ impl AuraEffect {
|
|||||||
&self.mode
|
&self.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mode_name(&self) -> String {
|
pub fn mode_name(&self) -> &str {
|
||||||
(<&str>::from(&self.mode)).to_string()
|
<&str>::from(&self.mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mode_num(&self) -> u8 {
|
pub fn mode_num(&self) -> u8 {
|
||||||
|
|||||||
+21
-28
@@ -1,6 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum Key {
|
pub enum Key {
|
||||||
VolUp,
|
VolUp,
|
||||||
VolDown,
|
VolDown,
|
||||||
@@ -235,51 +235,44 @@ impl KeyShape {
|
|||||||
/// A blank is used to space keys out in GUI's and can be used or ignored
|
/// A blank is used to space keys out in GUI's and can be used or ignored
|
||||||
/// depednign on the per-key effect
|
/// depednign on the per-key effect
|
||||||
pub const fn is_blank(&self) -> bool {
|
pub const fn is_blank(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
|
self,
|
||||||
Self::NormalBlank
|
Self::NormalBlank
|
||||||
| Self::FuncBlank
|
| Self::FuncBlank
|
||||||
| Self::ArrowBlank
|
| Self::ArrowBlank
|
||||||
| Self::ArrowSplitBlank
|
| Self::ArrowSplitBlank
|
||||||
| Self::ArrowRegularBlank => true,
|
| Self::ArrowRegularBlank
|
||||||
_ => false,
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A spacer is used to space keys out in GUI's, but ignored in per-key effects
|
/// A spacer is used to space keys out in GUI's, but ignored in per-key effects
|
||||||
pub const fn is_spacer(&self) -> bool {
|
pub const fn is_spacer(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
|
self,
|
||||||
Self::FuncSpacer
|
Self::FuncSpacer
|
||||||
| Self::NormalSpacer
|
| Self::NormalSpacer
|
||||||
| Self::ArrowSpacer
|
| Self::ArrowSpacer
|
||||||
| Self::ArrowSplitSpacer
|
| Self::ArrowSplitSpacer
|
||||||
| Self::ArrowRegularSpacer => true,
|
| Self::ArrowRegularSpacer
|
||||||
_ => false,
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All keys with a postfix of some number
|
/// All keys with a postfix of some number
|
||||||
pub const fn is_group(&self) -> bool {
|
pub const fn is_group(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
Self::LShift3 | Self::RShift3 => true,
|
self,
|
||||||
Self::Return3 | Self::Space5 | Self::Backspace3 => true,
|
Self::LShift3 | Self::RShift3 | Self::Return3 | Self::Space5 | Self::Backspace3
|
||||||
_ => false,
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mostly intended as a helper for signalling when to draw a
|
/// Mostly intended as a helper for signalling when to draw a
|
||||||
/// split/compact arrow cluster
|
/// split/compact arrow cluster
|
||||||
pub const fn is_arrow_cluster(&self) -> bool {
|
pub const fn is_arrow_cluster(&self) -> bool {
|
||||||
match self {
|
matches!(self, Self::Arrow | Self::ArrowBlank | Self::ArrowSpacer)
|
||||||
Self::Arrow | Self::ArrowBlank | Self::ArrowSpacer => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn is_arrow_splits(&self) -> bool {
|
pub const fn is_arrow_splits(&self) -> bool {
|
||||||
match self {
|
matches!(self, Self::Arrow | Self::ArrowBlank | Self::ArrowSpacer)
|
||||||
Self::ArrowSplit | Self::ArrowSplitBlank | Self::ArrowSplitSpacer => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ impl KeyLayout {
|
|||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let read_len = file.read_to_string(&mut buf)?;
|
let read_len = file.read_to_string(&mut buf)?;
|
||||||
if read_len == 0 {
|
if read_len == 0 {
|
||||||
return Err(Error::Io(std::io::ErrorKind::InvalidData.into()));
|
Err(Error::Io(std::io::ErrorKind::InvalidData.into()))
|
||||||
} else {
|
} else {
|
||||||
return Ok(toml::from_str::<Self>(&buf)?);
|
Ok(toml::from_str::<Self>(&buf)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,16 +138,11 @@ impl EffectState for Breathe {
|
|||||||
|
|
||||||
let speed = 4 - <u8>::from(*speed);
|
let speed = 4 - <u8>::from(*speed);
|
||||||
|
|
||||||
let colour: &mut Colour;
|
|
||||||
if *colour_actual == Colour(0, 0, 0) {
|
if *colour_actual == Colour(0, 0, 0) {
|
||||||
*use_colour1 = !*use_colour1;
|
*use_colour1 = !*use_colour1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*use_colour1 {
|
let colour = if !*use_colour1 { colour2 } else { colour1 };
|
||||||
colour = colour2;
|
|
||||||
} else {
|
|
||||||
colour = colour1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let r1_scale = colour.0 / speed / 2;
|
let r1_scale = colour.0 / speed / 2;
|
||||||
let g1_scale = colour.1 / speed / 2;
|
let g1_scale = colour.1 / speed / 2;
|
||||||
|
|||||||
+13
-13
@@ -21,7 +21,7 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize, Default)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)]
|
||||||
pub enum AuraDevice {
|
pub enum AuraDevice {
|
||||||
Tuf,
|
Tuf,
|
||||||
X1854,
|
X1854,
|
||||||
@@ -127,7 +127,7 @@ impl BitOr<AuraDev1866> for AuraDev1866 {
|
|||||||
type Output = u32;
|
type Output = u32;
|
||||||
|
|
||||||
fn bitor(self, rhs: AuraDev1866) -> Self::Output {
|
fn bitor(self, rhs: AuraDev1866) -> Self::Output {
|
||||||
return self as u32 | rhs as u32;
|
self as u32 | rhs as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ impl BitAnd<AuraDev1866> for AuraDev1866 {
|
|||||||
type Output = u32;
|
type Output = u32;
|
||||||
|
|
||||||
fn bitand(self, rhs: AuraDev1866) -> Self::Output {
|
fn bitand(self, rhs: AuraDev1866) -> Self::Output {
|
||||||
return self as u32 & rhs as u32;
|
self as u32 & rhs as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,14 +178,14 @@ pub enum AuraDev19b6 {
|
|||||||
SleepKeyb = 1 << 5,
|
SleepKeyb = 1 << 5,
|
||||||
ShutdownLogo = 1 << 6,
|
ShutdownLogo = 1 << 6,
|
||||||
ShutdownKeyb = 1 << 7,
|
ShutdownKeyb = 1 << 7,
|
||||||
BootBar = 1 << 7 + 2,
|
BootBar = 1 << (7 + 2),
|
||||||
AwakeBar = 1 << 7 + 3,
|
AwakeBar = 1 << (7 + 3),
|
||||||
SleepBar = 1 << 7 + 4,
|
SleepBar = 1 << (7 + 4),
|
||||||
ShutdownBar = 1 << 7 + 5,
|
ShutdownBar = 1 << (7 + 5),
|
||||||
BootLid = 1 << 15 + 1,
|
BootLid = 1 << (15 + 1),
|
||||||
AwakeLid = 1 << 15 + 2,
|
AwakeLid = 1 << (15 + 2),
|
||||||
SleepLid = 1 << 15 + 3,
|
SleepLid = 1 << (15 + 3),
|
||||||
ShutdownLid = 1 << 15 + 4,
|
ShutdownLid = 1 << (15 + 4),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AuraDev19b6> for u32 {
|
impl From<AuraDev19b6> for u32 {
|
||||||
@@ -216,7 +216,7 @@ impl BitOr<AuraDev19b6> for AuraDev19b6 {
|
|||||||
type Output = u16;
|
type Output = u16;
|
||||||
|
|
||||||
fn bitor(self, rhs: AuraDev19b6) -> Self::Output {
|
fn bitor(self, rhs: AuraDev19b6) -> Self::Output {
|
||||||
return self as u16 | rhs as u16;
|
self as u16 | rhs as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ impl BitAnd<AuraDev19b6> for AuraDev19b6 {
|
|||||||
type Output = u16;
|
type Output = u16;
|
||||||
|
|
||||||
fn bitand(self, rhs: AuraDev19b6) -> Self::Output {
|
fn bitand(self, rhs: AuraDev19b6) -> Self::Output {
|
||||||
return self as u16 & rhs as u16;
|
self as u16 & rhs as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog-control-center"
|
name = "rog-control-center"
|
||||||
version = "1.1.1"
|
version.workspace = true
|
||||||
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -8,8 +8,8 @@ edition = "2021"
|
|||||||
mocking = []
|
mocking = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
egui = { git = "https://github.com/emilk/egui" }
|
egui = { git = "https://github.com/flukejones/egui" }
|
||||||
eframe= { git = "https://github.com/emilk/egui" }
|
eframe= { git = "https://github.com/flukejones/egui" }
|
||||||
#eframe= { git = "https://github.com/emilk/egui", default-features = false, features = ["dark-light", "default_fonts", "wgpu"] }
|
#eframe= { git = "https://github.com/emilk/egui", default-features = false, features = ["dark-light", "default_fonts", "wgpu"] }
|
||||||
|
|
||||||
daemon = { path = "../daemon" }
|
daemon = { path = "../daemon" }
|
||||||
@@ -18,20 +18,17 @@ rog_dbus = { path = "../rog-dbus" }
|
|||||||
rog_aura = { path = "../rog-aura" }
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_profiles = { path = "../rog-profiles" }
|
rog_profiles = { path = "../rog-profiles" }
|
||||||
rog_platform = { path = "../rog-platform" }
|
rog_platform = { path = "../rog-platform" }
|
||||||
# supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git" }
|
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", default-features = false }
|
||||||
|
#supergfxctl = { path = "../../supergfxctl", default-features = false }
|
||||||
|
|
||||||
smol = "^1.2"
|
tokio.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
toml.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
serde_derive.workspace = true
|
||||||
|
zbus.workspace = true
|
||||||
|
dirs.workspace = true
|
||||||
|
notify-rust.workspace = true
|
||||||
|
|
||||||
serde = "^1.0"
|
|
||||||
toml = "^0.5"
|
|
||||||
serde_json = "^1.0"
|
|
||||||
serde_derive = "^1.0"
|
|
||||||
zbus = "^2.3"
|
|
||||||
nix = "^0.20.0"
|
nix = "^0.20.0"
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
dirs = "3.0.1"
|
|
||||||
|
|
||||||
[dependencies.notify-rust]
|
|
||||||
version = "^4.3"
|
|
||||||
default-features = false
|
|
||||||
features = ["z"]
|
|
||||||
@@ -10,6 +10,7 @@ pub enum Error {
|
|||||||
ConfigLockFail,
|
ConfigLockFail,
|
||||||
XdgVars,
|
XdgVars,
|
||||||
Zbus(zbus::Error),
|
Zbus(zbus::Error),
|
||||||
|
Notification(notify_rust::error::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@@ -22,6 +23,7 @@ impl fmt::Display for Error {
|
|||||||
Error::ConfigLockFail => write!(f, "Failed to lock user config"),
|
Error::ConfigLockFail => write!(f, "Failed to lock user config"),
|
||||||
Error::XdgVars => write!(f, "XDG environment vars appear unset"),
|
Error::XdgVars => write!(f, "XDG environment vars appear unset"),
|
||||||
Error::Zbus(err) => write!(f, "Error: {}", err),
|
Error::Zbus(err) => write!(f, "Error: {}", err),
|
||||||
|
Error::Notification(err) => write!(f, "Notification Error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,3 +47,9 @@ impl From<zbus::Error> for Error {
|
|||||||
Error::Zbus(err)
|
Error::Zbus(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<notify_rust::error::Error> for Error {
|
||||||
|
fn from(err: notify_rust::error::Error) -> Self {
|
||||||
|
Error::Notification(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub fn print_versions() {
|
|||||||
pub const SHOWING_GUI: u8 = 1;
|
pub const SHOWING_GUI: u8 = 1;
|
||||||
pub const SHOW_GUI: u8 = 2;
|
pub const SHOW_GUI: u8 = 2;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum Page {
|
pub enum Page {
|
||||||
System,
|
System,
|
||||||
AuraEffects,
|
AuraEffects,
|
||||||
@@ -75,7 +75,7 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
|
|||||||
// If the app is running this ends up stacked on top of SHOWING_GUI
|
// If the app is running this ends up stacked on top of SHOWING_GUI
|
||||||
ipc_file.write_all(&[SHOW_GUI])?;
|
ipc_file.write_all(&[SHOW_GUI])?;
|
||||||
// tiny sleep to give the app a chance to respond
|
// tiny sleep to give the app a chance to respond
|
||||||
sleep(Duration::from_millis(10));
|
sleep(Duration::from_millis(100));
|
||||||
ipc_file.read(&mut buf).ok();
|
ipc_file.read(&mut buf).ok();
|
||||||
|
|
||||||
// First entry is the actual state
|
// First entry is the actual state
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
use eframe::NativeOptions;
|
||||||
use rog_aura::layouts::KeyLayout;
|
use rog_aura::layouts::KeyLayout;
|
||||||
use rog_control_center::{
|
use rog_control_center::{
|
||||||
config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
|
config::Config, error::Result, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
|
||||||
page_states::PageDataStates, print_versions, startup_error::AppErrorShow, RogApp,
|
page_states::PageDataStates, print_versions, startup_error::AppErrorShow, RogApp,
|
||||||
RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI,
|
RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI,
|
||||||
};
|
};
|
||||||
|
use rog_platform::supported::SupportedFunctions;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
@@ -18,11 +21,17 @@ const DATA_DIR: &str = "/usr/share/rog-gui/";
|
|||||||
const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
||||||
const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
|
const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<()> {
|
||||||
print_versions();
|
print_versions();
|
||||||
|
|
||||||
|
// start tokio
|
||||||
|
let rt = Runtime::new().expect("Unable to create Runtime");
|
||||||
|
// Enter the runtime so that `tokio::spawn` is available immediately.
|
||||||
|
let _enter = rt.enter();
|
||||||
|
|
||||||
let native_options = eframe::NativeOptions {
|
let native_options = eframe::NativeOptions {
|
||||||
decorated: false,
|
vsync: true,
|
||||||
|
decorated: true,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
min_window_size: Some(egui::vec2(840.0, 600.0)),
|
min_window_size: Some(egui::vec2(840.0, 600.0)),
|
||||||
max_window_size: Some(egui::vec2(840.0, 600.0)),
|
max_window_size: Some(egui::vec2(840.0, 600.0)),
|
||||||
@@ -72,8 +81,56 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("{BOARD_NAME}, {e}");
|
println!("{BOARD_NAME}, {e}");
|
||||||
})
|
})
|
||||||
.unwrap_or(KeyLayout::ga401_layout());
|
.unwrap_or_else(|_| KeyLayout::ga401_layout());
|
||||||
|
|
||||||
|
// tmp-dir must live to the end of program life
|
||||||
|
let _tmp_dir = match tempfile::Builder::new()
|
||||||
|
.prefix("rog-gui")
|
||||||
|
.rand_bytes(0)
|
||||||
|
.tempdir()
|
||||||
|
{
|
||||||
|
Ok(tmp) => tmp,
|
||||||
|
Err(_) => on_tmp_dir_exists().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let states =
|
||||||
|
setup_page_state_and_notifs(layout.clone(), &config, native_options.clone(), &dbus)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if !start_closed {
|
||||||
|
start_app(states.clone(), native_options.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = Config::load().unwrap();
|
||||||
|
if !config.run_in_background {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.run_in_background {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
// blocks until it is read, typically the read will happen after a second
|
||||||
|
// process writes to the IPC (so there is data to actually read)
|
||||||
|
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
|
||||||
|
start_closed = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
// // This is just a blocker to idle and ensure the reator reacts
|
||||||
|
// sleep(Duration::from_millis(1000)).await;
|
||||||
|
// }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_page_state_and_notifs(
|
||||||
|
keyboard_layout: KeyLayout,
|
||||||
|
config: &Config,
|
||||||
|
native_options: NativeOptions,
|
||||||
|
dbus: &RogDbusClientBlocking,
|
||||||
|
) -> Result<PageDataStates> {
|
||||||
// Cheap method to alert to notifications rather than spinning a thread for each
|
// Cheap method to alert to notifications rather than spinning a thread for each
|
||||||
// This is quite different when done in a retained mode app
|
// This is quite different when done in a retained mode app
|
||||||
let charge_notified = Arc::new(AtomicBool::new(false));
|
let charge_notified = Arc::new(AtomicBool::new(false));
|
||||||
@@ -94,68 +151,39 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
notifs_enabled.clone(),
|
notifs_enabled.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// tmp-dir must live to the end of program life
|
let supported = match dbus.proxies().supported().supported_functions() {
|
||||||
let _tmp_dir = match tempfile::Builder::new()
|
Ok(s) => s,
|
||||||
.prefix("rog-gui")
|
Err(e) => {
|
||||||
.rand_bytes(0)
|
|
||||||
.tempdir()
|
|
||||||
{
|
|
||||||
Ok(tmp) => tmp,
|
|
||||||
Err(_) => on_tmp_dir_exists().unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let states = {
|
|
||||||
let supported = match dbus.proxies().supported().supported_functions() {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
eframe::run_native(
|
|
||||||
"ROG Control Center",
|
|
||||||
native_options.clone(),
|
|
||||||
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PageDataStates::new(
|
|
||||||
layout.clone(),
|
|
||||||
notifs_enabled.clone(),
|
|
||||||
charge_notified.clone(),
|
|
||||||
bios_notified.clone(),
|
|
||||||
aura_notified.clone(),
|
|
||||||
anime_notified.clone(),
|
|
||||||
profiles_notified.clone(),
|
|
||||||
fans_notified.clone(),
|
|
||||||
&supported,
|
|
||||||
&dbus,
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
if !start_closed {
|
|
||||||
let mut ipc_file = get_ipc_file().unwrap();
|
|
||||||
ipc_file.write_all(&[SHOWING_GUI]).unwrap();
|
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"ROG Control Center",
|
"ROG Control Center",
|
||||||
native_options.clone(),
|
native_options,
|
||||||
Box::new(move |cc| {
|
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
|
||||||
Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
SupportedFunctions::default()
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let config = Config::load().unwrap();
|
PageDataStates::new(
|
||||||
if !config.run_in_background {
|
keyboard_layout,
|
||||||
break;
|
notifs_enabled.clone(),
|
||||||
}
|
charge_notified.clone(),
|
||||||
|
bios_notified.clone(),
|
||||||
|
aura_notified.clone(),
|
||||||
|
anime_notified.clone(),
|
||||||
|
profiles_notified.clone(),
|
||||||
|
fans_notified.clone(),
|
||||||
|
&supported,
|
||||||
|
&dbus,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf = [0u8; 4];
|
fn start_app(states: PageDataStates, native_options: NativeOptions) -> Result<()> {
|
||||||
// blocks until it is read, typically the read will happen after a second
|
let mut ipc_file = get_ipc_file().unwrap();
|
||||||
// process writes to the IPC (so there is data to actually read)
|
ipc_file.write_all(&[SHOWING_GUI]).unwrap();
|
||||||
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
|
eframe::run_native(
|
||||||
start_closed = false;
|
"ROG Control Center",
|
||||||
continue;
|
native_options,
|
||||||
}
|
Box::new(move |cc| Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())),
|
||||||
}
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+227
-193
@@ -1,44 +1,65 @@
|
|||||||
//TODO: a lot of app state refresh depends on this so there needs
|
use crate::error::Result;
|
||||||
// to be an extra AtomicBool for checking if notifications are enabled
|
|
||||||
|
|
||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
use notify_rust::{Hint, Notification, NotificationHandle};
|
||||||
use rog_aura::AuraEffect;
|
|
||||||
use rog_dbus::{
|
use rog_dbus::{
|
||||||
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
||||||
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
||||||
};
|
};
|
||||||
|
use rog_platform::platform::GpuMode;
|
||||||
use rog_profiles::Profile;
|
use rog_profiles::Profile;
|
||||||
use smol::{future, Executor};
|
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
fmt::Display,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
thread::spawn,
|
|
||||||
};
|
};
|
||||||
use zbus::export::futures_util::StreamExt;
|
use supergfxctl::pci_device::GfxPower;
|
||||||
|
use zbus::export::futures_util::{future, StreamExt};
|
||||||
|
|
||||||
const NOTIF_HEADER: &str = "ROG Control";
|
const NOTIF_HEADER: &str = "ROG Control";
|
||||||
|
|
||||||
macro_rules! notify {
|
macro_rules! notify {
|
||||||
($notifier:ident, $last_notif:ident, $data:expr) => {
|
($notifier:expr, $last_notif:ident) => {
|
||||||
if let Some(notif) = $last_notif.take() {
|
if let Some(notif) = $last_notif.take() {
|
||||||
notif.close();
|
notif.close();
|
||||||
}
|
}
|
||||||
if let Ok(x) = $notifier($data) {
|
if let Ok(x) = $notifier {
|
||||||
$last_notif.replace(x);
|
$last_notif.replace(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! base_notification {
|
macro_rules! recv_notif {
|
||||||
($body:expr) => {
|
($proxy:ident,
|
||||||
Notification::new()
|
$signal:ident,
|
||||||
.summary(NOTIF_HEADER)
|
$was_notified:ident,
|
||||||
.body($body)
|
$last_notif:ident,
|
||||||
.timeout(2000)
|
$notif_enabled:ident,
|
||||||
.show()
|
[$($out_arg:ident)+],
|
||||||
|
$msg:literal,
|
||||||
|
$notifier:ident) => {
|
||||||
|
let last_notif = $last_notif.clone();
|
||||||
|
let notifs_enabled1 = $notif_enabled.clone();
|
||||||
|
let notified = $was_notified.clone();
|
||||||
|
// TODO: make a macro or generic function or something...
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
|
let proxy = $proxy::new(&conn).await.unwrap();
|
||||||
|
if let Ok(p) = proxy.$signal().await {
|
||||||
|
p.for_each(|e| {
|
||||||
|
if let Ok(out) = e.args() {
|
||||||
|
if notifs_enabled1.load(Ordering::SeqCst) {
|
||||||
|
if let Ok(ref mut lock) = last_notif.try_lock() {
|
||||||
|
notify!($notifier($msg, &out$(.$out_arg)+()), lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notified.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
future::ready(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,205 +73,218 @@ pub fn start_notifications(
|
|||||||
profiles_notified: Arc<AtomicBool>,
|
profiles_notified: Arc<AtomicBool>,
|
||||||
_fans_notified: Arc<AtomicBool>,
|
_fans_notified: Arc<AtomicBool>,
|
||||||
notifs_enabled: Arc<AtomicBool>,
|
notifs_enabled: Arc<AtomicBool>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<()> {
|
||||||
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
|
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
let executor = Executor::new();
|
|
||||||
// BIOS notif
|
// BIOS notif
|
||||||
let last_notif = last_notification.clone();
|
recv_notif!(
|
||||||
let notifs_enabled1 = notifs_enabled.clone();
|
RogBiosProxy,
|
||||||
let bios_notified1 = bios_notified.clone();
|
receive_notify_post_boot_sound,
|
||||||
// TODO: make a macro or generic function or something...
|
bios_notified,
|
||||||
executor
|
last_notification,
|
||||||
.spawn(async move {
|
notifs_enabled,
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
[on],
|
||||||
let proxy = RogBiosProxy::new(&conn).await.unwrap();
|
"BIOS Post sound",
|
||||||
if let Ok(p) = proxy.receive_notify_post_boot_sound().await {
|
do_notification
|
||||||
p.for_each(|e| {
|
);
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
|
||||||
notify!(do_post_sound_notif, lock, &out.on());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bios_notified1.store(true, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
executor
|
recv_notif!(
|
||||||
.spawn(async move {
|
RogBiosProxy,
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
receive_notify_panel_od,
|
||||||
let proxy = RogBiosProxy::new(&conn).await.unwrap();
|
bios_notified,
|
||||||
if let Ok(p) = proxy.receive_notify_panel_od().await {
|
last_notification,
|
||||||
p.for_each(|_| {
|
notifs_enabled,
|
||||||
bios_notified.store(true, Ordering::SeqCst);
|
[overdrive],
|
||||||
future::ready(())
|
"Panel Overdrive enabled:",
|
||||||
})
|
do_notification
|
||||||
.await;
|
);
|
||||||
};
|
|
||||||
})
|
recv_notif!(
|
||||||
.detach();
|
RogBiosProxy,
|
||||||
|
receive_notify_dgpu_disable,
|
||||||
|
bios_notified,
|
||||||
|
last_notification,
|
||||||
|
notifs_enabled,
|
||||||
|
[disable],
|
||||||
|
"BIOS dGPU disabled",
|
||||||
|
do_notification
|
||||||
|
);
|
||||||
|
|
||||||
|
recv_notif!(
|
||||||
|
RogBiosProxy,
|
||||||
|
receive_notify_egpu_enable,
|
||||||
|
bios_notified,
|
||||||
|
last_notification,
|
||||||
|
notifs_enabled,
|
||||||
|
[enable],
|
||||||
|
"BIOS eGPU enabled",
|
||||||
|
do_notification
|
||||||
|
);
|
||||||
|
|
||||||
|
recv_notif!(
|
||||||
|
RogBiosProxy,
|
||||||
|
receive_notify_gpu_mux_mode,
|
||||||
|
bios_notified,
|
||||||
|
last_notification,
|
||||||
|
notifs_enabled,
|
||||||
|
[mode],
|
||||||
|
"BIOS GPU MUX mode (reboot required)",
|
||||||
|
mux_notification
|
||||||
|
);
|
||||||
|
|
||||||
// Charge notif
|
// Charge notif
|
||||||
let last_notif = last_notification.clone();
|
recv_notif!(
|
||||||
let notifs_enabled1 = notifs_enabled.clone();
|
PowerProxy,
|
||||||
executor
|
receive_notify_charge_control_end_threshold,
|
||||||
.spawn(async move {
|
charge_notified,
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
last_notification,
|
||||||
let proxy = PowerProxy::new(&conn).await.unwrap();
|
notifs_enabled,
|
||||||
if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await {
|
[limit],
|
||||||
p.for_each(|e| {
|
"Battery charge limit changed to",
|
||||||
if let Ok(out) = e.args() {
|
do_notification
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
);
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
|
||||||
notify!(do_charge_notif, lock, &out.limit);
|
recv_notif!(
|
||||||
}
|
PowerProxy,
|
||||||
}
|
receive_notify_mains_online,
|
||||||
charge_notified.store(true, Ordering::SeqCst);
|
bios_notified,
|
||||||
}
|
last_notification,
|
||||||
future::ready(())
|
notifs_enabled,
|
||||||
})
|
[on],
|
||||||
.await;
|
"AC Power power is",
|
||||||
};
|
ac_power_notification
|
||||||
})
|
);
|
||||||
.detach();
|
|
||||||
|
|
||||||
// Profile notif
|
// Profile notif
|
||||||
let last_notif = last_notification.clone();
|
recv_notif!(
|
||||||
let notifs_enabled1 = notifs_enabled.clone();
|
ProfileProxy,
|
||||||
executor
|
receive_notify_profile,
|
||||||
.spawn(async move {
|
profiles_notified,
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
last_notification,
|
||||||
let proxy = ProfileProxy::new(&conn).await.unwrap();
|
notifs_enabled,
|
||||||
if let Ok(p) = proxy.receive_notify_profile().await {
|
[profile],
|
||||||
p.for_each(|e| {
|
"Profile changed to",
|
||||||
if let Ok(out) = e.args() {
|
do_thermal_notif
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
);
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
// notify!(do_thermal_notif(&out.profile), lock);
|
||||||
notify!(do_thermal_notif, lock, &out.profile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
profiles_notified.store(true, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
// LED notif
|
// LED notif
|
||||||
let last_notif = last_notification.clone();
|
recv_notif!(
|
||||||
let aura_notif = aura_notified.clone();
|
LedProxy,
|
||||||
|
receive_notify_led,
|
||||||
|
aura_notified,
|
||||||
|
last_notification,
|
||||||
|
notifs_enabled,
|
||||||
|
[data mode_name],
|
||||||
|
"Keyboard LED mode changed to",
|
||||||
|
do_notification
|
||||||
|
);
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
|
let proxy = LedProxy::new(&conn).await.unwrap();
|
||||||
|
if let Ok(p) = proxy.receive_all_signals().await {
|
||||||
|
p.for_each(|_| {
|
||||||
|
aura_notified.store(true, Ordering::SeqCst);
|
||||||
|
future::ready(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
|
let proxy = AnimeProxy::new(&conn).await.unwrap();
|
||||||
|
if let Ok(p) = proxy.receive_power_states().await {
|
||||||
|
p.for_each(|_| {
|
||||||
|
anime_notified.store(true, Ordering::SeqCst);
|
||||||
|
future::ready(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
let notifs_enabled1 = notifs_enabled.clone();
|
let notifs_enabled1 = notifs_enabled.clone();
|
||||||
executor
|
let last_notif = last_notification.clone();
|
||||||
.spawn(async move {
|
let bios_notified1 = bios_notified.clone();
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
tokio::spawn(async move {
|
||||||
let proxy = LedProxy::new(&conn).await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
if let Ok(p) = proxy.receive_notify_led().await {
|
let proxy = supergfxctl::zbus_proxy::DaemonProxy::new(&conn)
|
||||||
p.for_each(|e| {
|
.await
|
||||||
if let Ok(out) = e.args() {
|
.unwrap();
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
if let Ok(p) = proxy.receive_notify_gfx_status().await {
|
||||||
|
p.for_each(|e| {
|
||||||
|
if let Ok(out) = e.args() {
|
||||||
|
if notifs_enabled1.load(Ordering::SeqCst) {
|
||||||
|
let status = out.status();
|
||||||
|
if *status != GfxPower::Unknown {
|
||||||
|
// Required check because status cycles through active/unknown/suspended
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
if let Ok(ref mut lock) = last_notif.try_lock() {
|
||||||
notify!(do_led_notif, lock, &out.data);
|
notify!(
|
||||||
|
do_notification(
|
||||||
|
"dGPU status changed:",
|
||||||
|
&format!("{status:?}",)
|
||||||
|
),
|
||||||
|
lock
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aura_notif.store(true, Ordering::SeqCst);
|
|
||||||
}
|
}
|
||||||
future::ready(())
|
}
|
||||||
})
|
bios_notified1.store(true, Ordering::SeqCst);
|
||||||
.await;
|
future::ready(())
|
||||||
};
|
})
|
||||||
})
|
.await;
|
||||||
.detach();
|
};
|
||||||
|
|
||||||
let aura_notif = aura_notified.clone();
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = LedProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_notify_led().await {
|
|
||||||
p.for_each(|_| {
|
|
||||||
aura_notif.store(true, Ordering::SeqCst);
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = LedProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_all_signals().await {
|
|
||||||
p.for_each(|_| {
|
|
||||||
aura_notified.store(true, Ordering::SeqCst);
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
|
||||||
let proxy = AnimeProxy::new(&conn).await.unwrap();
|
|
||||||
if let Ok(p) = proxy.receive_power_states().await {
|
|
||||||
p.for_each(|_| {
|
|
||||||
anime_notified.store(true, Ordering::SeqCst);
|
|
||||||
future::ready(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
spawn(move || loop {
|
|
||||||
smol::block_on(executor.tick());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> {
|
fn base_notification<T>(message: &str, data: &T) -> Notification
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
let mut notif = Notification::new();
|
||||||
|
|
||||||
|
notif
|
||||||
|
.summary(NOTIF_HEADER)
|
||||||
|
.body(&format!("{message} {data}"))
|
||||||
|
.timeout(2000)
|
||||||
|
//.hint(Hint::Resident(true))
|
||||||
|
.hint(Hint::Category("device".into()));
|
||||||
|
|
||||||
|
notif
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_notification<T>(message: &str, data: &T) -> Result<NotificationHandle>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
Ok(base_notification(message, data).show()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ac_power_notification(message: &str, on: &bool) -> Result<NotificationHandle> {
|
||||||
|
let data = if *on {
|
||||||
|
"plugged".to_string()
|
||||||
|
} else {
|
||||||
|
"unplugged".to_string()
|
||||||
|
};
|
||||||
|
Ok(base_notification(message, &data).show()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actual GpuMode unused as data is never correct until switched by reboot
|
||||||
|
fn mux_notification(message: &str, _: &GpuMode) -> Result<NotificationHandle> {
|
||||||
|
Ok(base_notification(message, &"").show()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_thermal_notif(message: &str, profile: &Profile) -> Result<NotificationHandle> {
|
||||||
let icon = match profile {
|
let icon = match profile {
|
||||||
Profile::Balanced => "asus_notif_yellow",
|
Profile::Balanced => "asus_notif_yellow",
|
||||||
Profile::Performance => "asus_notif_red",
|
Profile::Performance => "asus_notif_red",
|
||||||
Profile::Quiet => "asus_notif_green",
|
Profile::Quiet => "asus_notif_green",
|
||||||
};
|
};
|
||||||
let profile: &str = (*profile).into();
|
let profile: &str = (*profile).into();
|
||||||
let x = Notification::new()
|
let mut notif = base_notification(message, &profile.to_uppercase());
|
||||||
.summary("ASUS ROG")
|
Ok(notif.icon(icon).show()?)
|
||||||
.body(&format!(
|
|
||||||
"Thermal profile changed to {}",
|
|
||||||
profile.to_uppercase(),
|
|
||||||
))
|
|
||||||
.hint(Hint::Resident(true))
|
|
||||||
.timeout(2000)
|
|
||||||
.hint(Hint::Category("device".into()))
|
|
||||||
//.hint(Hint::Transient(true))
|
|
||||||
.icon(icon)
|
|
||||||
.show()?;
|
|
||||||
Ok(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_led_notif(ledmode: &AuraEffect) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!(
|
|
||||||
"Keyboard LED mode changed to {}",
|
|
||||||
ledmode.mode_name()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!("Battery charge limit changed to {}", limit))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_post_sound_notif(on: &bool) -> Result<NotificationHandle, notify_rust::error::Error> {
|
|
||||||
base_notification!(&format!("BIOS Post sound {}", on))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ impl AnimeState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PageDataStates {
|
pub struct PageDataStates {
|
||||||
pub keyboard_layout: KeyLayout,
|
pub keyboard_layout: KeyLayout,
|
||||||
pub notifs_enabled: Arc<AtomicBool>,
|
pub notifs_enabled: Arc<AtomicBool>,
|
||||||
@@ -262,6 +262,7 @@ pub struct PageDataStates {
|
|||||||
pub error: Option<String>,
|
pub error: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
impl PageDataStates {
|
impl PageDataStates {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
keyboard_layout: KeyLayout,
|
keyboard_layout: KeyLayout,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ impl<'a> RogApp<'a> {
|
|||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.heading("Experimental application for asusd");
|
ui.heading("Base settings");
|
||||||
|
|
||||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||||
ui.spacing_mut().item_spacing = egui::vec2(8.0, 10.0);
|
ui.spacing_mut().item_spacing = egui::vec2(8.0, 10.0);
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ fn aura_power1(
|
|||||||
if ui.toggle_value(&mut keyboard, "Keyboard").changed() {
|
if ui.toggle_value(&mut keyboard, "Keyboard").changed() {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if !supported.keyboard_led.multizone_led_mode.is_empty() {
|
if !supported.keyboard_led.multizone_led_mode.is_empty()
|
||||||
if ui.toggle_value(&mut lightbar, "Lightbar").changed() {
|
&& ui.toggle_value(&mut lightbar, "Lightbar").changed()
|
||||||
changed = true;
|
{
|
||||||
}
|
changed = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
|||||||
@@ -54,47 +54,46 @@ pub fn rog_bios_group(
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
if supported.rog_bios_ctrl.post_sound {
|
if supported.rog_bios_ctrl.post_sound
|
||||||
if ui
|
&& ui
|
||||||
.add(egui::Checkbox::new(
|
.add(egui::Checkbox::new(
|
||||||
&mut states.bios.post_sound,
|
&mut states.bios.post_sound,
|
||||||
"POST sound",
|
"POST sound",
|
||||||
))
|
))
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.rog_bios()
|
.rog_bios()
|
||||||
.set_post_boot_sound(states.bios.post_sound)
|
.set_post_boot_sound(states.bios.post_sound)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
states.error = Some(err.to_string());
|
states.error = Some(err.to_string());
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if supported.rog_bios_ctrl.post_sound {
|
if supported.rog_bios_ctrl.post_sound
|
||||||
if ui
|
&& ui
|
||||||
.add(egui::Checkbox::new(
|
.add(egui::Checkbox::new(
|
||||||
&mut states.bios.panel_overdrive,
|
&mut states.bios.panel_overdrive,
|
||||||
"Panel overdrive",
|
"Panel overdrive",
|
||||||
))
|
))
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.rog_bios()
|
.rog_bios()
|
||||||
.set_panel_od(states.bios.panel_overdrive)
|
.set_panel_od(states.bios.panel_overdrive)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
states.error = Some(err.to_string());
|
states.error = Some(err.to_string());
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if supported.rog_bios_ctrl.gpu_mux {
|
if supported.rog_bios_ctrl.gpu_mux {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.horizontal_wrapped(|ui| ui.label("GPU MUX mode (reboot required)"));
|
ui.horizontal_wrapped(|ui| ui.label("GPU MUX mode"));
|
||||||
|
ui.horizontal_wrapped(|ui| ui.label("NOTE: Value does not change until rebooted"));
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
changed = ui
|
changed = ui
|
||||||
.selectable_value(
|
.selectable_value(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use egui::{vec2, Align2, Button, FontId, Id, Rect, RichText, Sense, Vec2};
|
use egui::{vec2, Align2, FontId, Id, Sense};
|
||||||
|
|
||||||
use crate::{RogApp, VERSION};
|
use crate::{RogApp, VERSION};
|
||||||
|
|
||||||
@@ -27,20 +27,20 @@ impl<'a> RogApp<'a> {
|
|||||||
let height = titlebar_rect.height();
|
let height = titlebar_rect.height();
|
||||||
// Paint the title:
|
// Paint the title:
|
||||||
ui.painter().text(
|
ui.painter().text(
|
||||||
titlebar_rect.center_top() + vec2(0.0, height / 2.0),
|
titlebar_rect.right_top() + vec2(0.0, height / 2.0),
|
||||||
Align2::CENTER_CENTER,
|
Align2::RIGHT_CENTER,
|
||||||
format!("ROG Control Center v{}", VERSION),
|
format!("v{}", VERSION),
|
||||||
FontId::proportional(height - 2.0),
|
FontId::proportional(height - 2.0),
|
||||||
text_color,
|
text_color,
|
||||||
);
|
);
|
||||||
// Add the close button:
|
// // Add the close button:
|
||||||
let close_response = ui.put(
|
// let close_response = ui.put(
|
||||||
Rect::from_min_size(titlebar_rect.right_top(), Vec2::splat(height)),
|
// Rect::from_min_size(titlebar_rect.right_top(), Vec2::splat(height)),
|
||||||
Button::new(RichText::new("❌").size(height - 4.0)).frame(false),
|
// Button::new(RichText::new("❌").size(height - 4.0)).frame(false),
|
||||||
);
|
// );
|
||||||
if close_response.clicked() {
|
// if close_response.clicked() {
|
||||||
frame.close();
|
// frame.close();
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -1,19 +1,19 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_dbus"
|
name = "rog_dbus"
|
||||||
version = "4.4.0"
|
version.workspace = true
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||||
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||||
description = "dbus interface methods for asusctl"
|
description = "dbus interface methods for asusctl"
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rog_anime = { path = "../rog-anime" }
|
rog_anime = { path = "../rog-anime" }
|
||||||
rog_aura = { path = "../rog-aura" }
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_profiles = { path = "../rog-profiles" }
|
rog_profiles = { path = "../rog-profiles" }
|
||||||
rog_platform = { path = "../rog-platform" }
|
rog_platform = { path = "../rog-platform" }
|
||||||
zbus = "^2.2"
|
zbus.workspace = true
|
||||||
zbus_macros = "^2.0"
|
zbus_macros.workspace = true
|
||||||
zvariant = "^3.0"
|
zvariant.workspace = true
|
||||||
|
|||||||
@@ -7,26 +7,33 @@ use zbus_macros::dbus_proxy;
|
|||||||
)]
|
)]
|
||||||
trait Anime {
|
trait Anime {
|
||||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||||
|
#[inline]
|
||||||
fn set_boot_on_off(&self, status: bool) -> zbus::Result<()>;
|
fn set_boot_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Set the global AniMe brightness
|
/// Set the global AniMe brightness
|
||||||
|
#[inline]
|
||||||
fn set_brightness(&self, bright: f32) -> zbus::Result<()>;
|
fn set_brightness(&self, bright: f32) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Set whether the AniMe is displaying images/data
|
/// Set whether the AniMe is displaying images/data
|
||||||
|
#[inline]
|
||||||
fn set_on_off(&self, status: bool) -> zbus::Result<()>;
|
fn set_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
||||||
|
#[inline]
|
||||||
fn write(&self, input: AnimeDataBuffer) -> zbus::Result<()>;
|
fn write(&self, input: AnimeDataBuffer) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Get status of if the AniMe LEDs are on
|
/// Get status of if the AniMe LEDs are on
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(property)]
|
#[dbus_proxy(property)]
|
||||||
fn awake_enabled(&self) -> zbus::Result<bool>;
|
fn awake_enabled(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// Get the status of if factory system-status animations are enabled
|
/// Get the status of if factory system-status animations are enabled
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(property)]
|
#[dbus_proxy(property)]
|
||||||
fn boot_enabled(&self) -> zbus::Result<bool>;
|
fn boot_enabled(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn power_states(&self, data: AnimePowerStates) -> zbus::Result<()>;
|
fn power_states(&self, data: AnimePowerStates) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,46 +34,60 @@ const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 F
|
|||||||
)]
|
)]
|
||||||
trait Led {
|
trait Led {
|
||||||
/// NextLedMode method
|
/// NextLedMode method
|
||||||
|
#[inline]
|
||||||
fn next_led_mode(&self) -> zbus::Result<()>;
|
fn next_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// PrevLedMode method
|
/// PrevLedMode method
|
||||||
|
#[inline]
|
||||||
fn prev_led_mode(&self) -> zbus::Result<()>;
|
fn prev_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Toggle to next led brightness
|
/// Toggle to next led brightness
|
||||||
|
#[inline]
|
||||||
fn next_led_brightness(&self) -> zbus::Result<()>;
|
fn next_led_brightness(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Toggle to previous led brightness
|
/// Toggle to previous led brightness
|
||||||
|
#[inline]
|
||||||
fn prev_led_brightness(&self) -> zbus::Result<()>;
|
fn prev_led_brightness(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetBrightness method
|
/// SetBrightness method
|
||||||
|
#[inline]
|
||||||
fn set_brightness(&self, brightness: LedBrightness) -> zbus::Result<()>;
|
fn set_brightness(&self, brightness: LedBrightness) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetLedMode method
|
/// SetLedMode method
|
||||||
|
#[inline]
|
||||||
fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>;
|
fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_leds_power(&self, options: AuraPowerDev, enabled: bool) -> zbus::Result<()>;
|
fn set_leds_power(&self, options: AuraPowerDev, enabled: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()>;
|
fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()>;
|
||||||
|
|
||||||
/// NotifyLed signal
|
/// NotifyLed signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>;
|
fn notify_led(&self, data: AuraEffect) -> zbus::Result<()>;
|
||||||
|
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
|
#[inline]
|
||||||
fn notify_power_states(&self, data: AuraPowerDev) -> zbus::Result<()>;
|
fn notify_power_states(&self, data: AuraPowerDev) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// LedBrightness property
|
/// LedBrightness property
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(property)]
|
#[dbus_proxy(property)]
|
||||||
fn led_brightness(&self) -> zbus::Result<i16>;
|
fn led_brightness(&self) -> zbus::Result<i16>;
|
||||||
|
|
||||||
/// LedMode property
|
/// LedMode property
|
||||||
|
#[inline]
|
||||||
fn led_mode(&self) -> zbus::Result<AuraModeNum>;
|
fn led_mode(&self) -> zbus::Result<AuraModeNum>;
|
||||||
|
|
||||||
/// LedModes property
|
/// LedModes property
|
||||||
|
#[inline]
|
||||||
fn led_modes(&self) -> zbus::Result<BTreeMap<AuraModeNum, AuraEffect>>;
|
fn led_modes(&self) -> zbus::Result<BTreeMap<AuraModeNum, AuraEffect>>;
|
||||||
|
|
||||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||||
// #[dbus_proxy(property)]
|
// #[dbus_proxy(property)]
|
||||||
|
#[inline]
|
||||||
fn leds_enabled(&self) -> zbus::Result<AuraPowerDev>;
|
fn leds_enabled(&self) -> zbus::Result<AuraPowerDev>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,52 +28,67 @@ use zbus_macros::dbus_proxy;
|
|||||||
)]
|
)]
|
||||||
trait RogBios {
|
trait RogBios {
|
||||||
/// DgpuDisable method
|
/// DgpuDisable method
|
||||||
|
#[inline]
|
||||||
fn dgpu_disable(&self) -> zbus::Result<bool>;
|
fn dgpu_disable(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// EgpuEnable method
|
/// EgpuEnable method
|
||||||
|
#[inline]
|
||||||
fn egpu_enable(&self) -> zbus::Result<bool>;
|
fn egpu_enable(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// GpuMuxMode method
|
/// GpuMuxMode method
|
||||||
|
#[inline]
|
||||||
fn gpu_mux_mode(&self) -> zbus::Result<GpuMode>;
|
fn gpu_mux_mode(&self) -> zbus::Result<GpuMode>;
|
||||||
|
|
||||||
/// PanelOd method
|
/// PanelOd method
|
||||||
|
#[inline]
|
||||||
fn panel_od(&self) -> zbus::Result<bool>;
|
fn panel_od(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// PostBootSound method
|
/// PostBootSound method
|
||||||
|
#[inline]
|
||||||
fn post_boot_sound(&self) -> zbus::Result<i16>;
|
fn post_boot_sound(&self) -> zbus::Result<i16>;
|
||||||
|
|
||||||
/// SetDgpuDisable method
|
/// SetDgpuDisable method
|
||||||
|
#[inline]
|
||||||
fn set_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
fn set_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetEgpuEnable method
|
/// SetEgpuEnable method
|
||||||
|
#[inline]
|
||||||
fn set_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
fn set_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetGpuMuxMode method
|
/// SetGpuMuxMode method
|
||||||
|
#[inline]
|
||||||
fn set_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
fn set_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetPanelOd method
|
/// SetPanelOd method
|
||||||
|
#[inline]
|
||||||
fn set_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
fn set_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetPostBootSound method
|
/// SetPostBootSound method
|
||||||
|
#[inline]
|
||||||
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyDgpuDisable signal
|
/// NotifyDgpuDisable signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
fn notify_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyEgpuEnable signal
|
/// NotifyEgpuEnable signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
fn notify_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyGpuMuxMode signal
|
/// NotifyGpuMuxMode signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
fn notify_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyPanelOd signal
|
/// NotifyPanelOd signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
fn notify_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyPostBootSound signal
|
/// NotifyPostBootSound signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
fn notify_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,19 +27,24 @@ use zbus_macros::dbus_proxy;
|
|||||||
)]
|
)]
|
||||||
trait Power {
|
trait Power {
|
||||||
/// charge_control_end_threshold method
|
/// charge_control_end_threshold method
|
||||||
|
#[inline]
|
||||||
fn charge_control_end_threshold(&self) -> zbus::Result<u8>;
|
fn charge_control_end_threshold(&self) -> zbus::Result<u8>;
|
||||||
|
|
||||||
/// MainsOnline method
|
/// MainsOnline method
|
||||||
|
#[inline]
|
||||||
fn mains_online(&self) -> zbus::Result<bool>;
|
fn mains_online(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// set_charge_control_end_threshold method
|
/// set_charge_control_end_threshold method
|
||||||
|
#[inline]
|
||||||
fn set_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<()>;
|
fn set_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyCharge signal
|
/// NotifyCharge signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<u8>;
|
fn notify_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<u8>;
|
||||||
|
|
||||||
/// NotifyMainsOnline signal
|
/// NotifyMainsOnline signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_mains_online(&self, on: bool) -> zbus::Result<()>;
|
fn notify_mains_online(&self, on: bool) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,44 +31,55 @@ use zbus_macros::dbus_proxy;
|
|||||||
)]
|
)]
|
||||||
trait Profile {
|
trait Profile {
|
||||||
/// Get the fan-curve data for the currently active Profile
|
/// Get the fan-curve data for the currently active Profile
|
||||||
|
#[inline]
|
||||||
fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet>;
|
fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet>;
|
||||||
|
|
||||||
/// Fetch the active profile name
|
/// Fetch the active profile name
|
||||||
|
#[inline]
|
||||||
fn active_profile(&self) -> zbus::Result<Profile>;
|
fn active_profile(&self) -> zbus::Result<Profile>;
|
||||||
|
|
||||||
/// Get a list of profiles that have fan-curves enabled.
|
/// Get a list of profiles that have fan-curves enabled.
|
||||||
|
#[inline]
|
||||||
fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>>;
|
fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>>;
|
||||||
|
|
||||||
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
||||||
/// If fan-curves are supported will also activate a fan curve for profile.
|
/// If fan-curves are supported will also activate a fan curve for profile.
|
||||||
|
#[inline]
|
||||||
fn next_profile(&self) -> zbus::Result<()>;
|
fn next_profile(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Fetch profile names
|
/// Fetch profile names
|
||||||
|
#[inline]
|
||||||
fn profiles(&self) -> zbus::Result<Vec<Profile>>;
|
fn profiles(&self) -> zbus::Result<Vec<Profile>>;
|
||||||
|
|
||||||
/// Set this platform_profile name as active
|
/// Set this platform_profile name as active
|
||||||
|
#[inline]
|
||||||
fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>;
|
fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Set a profile fan curve enabled status. Will also activate a fan curve.
|
/// Set a profile fan curve enabled status. Will also activate a fan curve.
|
||||||
|
#[inline]
|
||||||
fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()>;
|
fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Set the fan curve for the specified profile, or the profile the user is
|
/// Set the fan curve for the specified profile, or the profile the user is
|
||||||
/// currently in if profile == None. Will also activate the fan curve.
|
/// currently in if profile == None. Will also activate the fan curve.
|
||||||
|
#[inline]
|
||||||
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::Result<()>;
|
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Reset the stored (self) and device curve to the defaults of the platform.
|
/// Reset the stored (self) and device curve to the defaults of the platform.
|
||||||
///
|
///
|
||||||
/// Each platform_profile has a different default and the defualt can be read
|
/// Each platform_profile has a different default and the defualt can be read
|
||||||
/// only for the currently active profile.
|
/// only for the currently active profile.
|
||||||
|
#[inline]
|
||||||
fn set_active_curve_to_defaults(&self) -> zbus::Result<()>;
|
fn set_active_curve_to_defaults(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// Reset the stored (self) and device curve to the defaults of the platform.
|
/// Reset the stored (self) and device curve to the defaults of the platform.
|
||||||
///
|
///
|
||||||
/// Each platform_profile has a different default and the defualt can be read
|
/// Each platform_profile has a different default and the defualt can be read
|
||||||
/// only for the currently active profile.
|
/// only for the currently active profile.
|
||||||
|
#[inline]
|
||||||
fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()>;
|
fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()>;
|
||||||
|
|
||||||
/// NotifyProfile signal
|
/// NotifyProfile signal
|
||||||
|
#[inline]
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_profile(&self, profile: Profile) -> zbus::Result<Profile>;
|
async fn notify_profile(&self, profile: Profile) -> zbus::Result<Profile>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,6 @@ use zbus_macros::dbus_proxy;
|
|||||||
)]
|
)]
|
||||||
trait Supported {
|
trait Supported {
|
||||||
/// SupportedFunctions method
|
/// SupportedFunctions method
|
||||||
|
#[inline]
|
||||||
fn supported_functions(&self) -> zbus::Result<SupportedFunctions>;
|
fn supported_functions(&self) -> zbus::Result<SupportedFunctions>;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-16
@@ -1,23 +1,18 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_platform"
|
name = "rog_platform"
|
||||||
version = "0.1.1"
|
version.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "*"
|
log.workspace = true
|
||||||
|
|
||||||
rog_aura = { path = "../rog-aura" }
|
rog_aura = { path = "../rog-aura" }
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
zvariant = "^3.0"
|
zvariant.workspace = true
|
||||||
zvariant_derive = "^3.0"
|
zvariant_derive.workspace = true
|
||||||
|
sysfs-class.workspace = true
|
||||||
|
concat-idents.workspace = true
|
||||||
|
udev.workspace = true
|
||||||
|
inotify.workspace = true
|
||||||
|
|
||||||
udev = "^0.6"
|
rusb.workspace = true
|
||||||
rusb = "^0.9"
|
|
||||||
sysfs-class = "^0.1"
|
|
||||||
inotify = "^0.10.0"
|
|
||||||
# inotify = { version = "0.10.0", default-features = false }
|
|
||||||
|
|
||||||
concat-idents = "1.1.3"
|
|
||||||
@@ -4,7 +4,7 @@ use log::{info, warn};
|
|||||||
|
|
||||||
use crate::error::{PlatformError, Result};
|
use crate::error::{PlatformError, Result};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
|
||||||
pub struct HidRaw(PathBuf);
|
pub struct HidRaw(PathBuf);
|
||||||
|
|
||||||
impl HidRaw {
|
impl HidRaw {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
has_attr, set_attr_u8_array, to_device,
|
has_attr, set_attr_u8_array, to_device,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Clone)]
|
||||||
pub struct KeyboardLed {
|
pub struct KeyboardLed {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
@@ -32,10 +32,12 @@ impl KeyboardLed {
|
|||||||
PlatformError::Udev("match_subsystem failed".into(), err)
|
PlatformError::Udev("match_subsystem failed".into(), err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for device in enumerator.scan_devices().map_err(|err| {
|
if let Some(device) = (enumerator.scan_devices().map_err(|err| {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
PlatformError::Udev("scan_devices failed".into(), err)
|
PlatformError::Udev("scan_devices failed".into(), err)
|
||||||
})? {
|
})?)
|
||||||
|
.next()
|
||||||
|
{
|
||||||
info!("Found keyboard LED controls at {:?}", device.sysname());
|
info!("Found keyboard LED controls at {:?}", device.sysname());
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
path: device.syspath().to_owned(),
|
path: device.syspath().to_owned(),
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<(
|
|||||||
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
|
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
|
||||||
if let Some(value) = device.attribute_value(attr_name) {
|
if let Some(value) = device.attribute_value(attr_name) {
|
||||||
let tmp = value.to_string_lossy();
|
let tmp = value.to_string_lossy();
|
||||||
return Ok(tmp.parse::<u8>().map_err(|_| PlatformError::ParseNum)?);
|
return tmp.parse::<u8>().map_err(|_| PlatformError::ParseNum);
|
||||||
}
|
}
|
||||||
Err(PlatformError::AttrNotFound(attr_name.to_string()))
|
Err(PlatformError::AttrNotFound(attr_name.to_string()))
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ pub fn read_attr_u8_array(device: &Device, attr_name: &str) -> Result<Vec<u8>> {
|
|||||||
let tmp = value.to_string_lossy();
|
let tmp = value.to_string_lossy();
|
||||||
let tmp = tmp
|
let tmp = tmp
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map(|v| u8::from_str_radix(v, 10).unwrap_or(0))
|
.map(|v| v.parse::<u8>().unwrap_or(0))
|
||||||
.collect();
|
.collect();
|
||||||
return Ok(tmp);
|
return Ok(tmp);
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ mod tests {
|
|||||||
|
|
||||||
let tmp: Vec<u8> = tmp
|
let tmp: Vec<u8> = tmp
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map(|v| u8::from_str_radix(v, 10).unwrap_or(0))
|
.map(|v| v.parse::<u8>().unwrap_or(0))
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(tmp, &[1, 2, 3, 4, 5]);
|
assert_eq!(tmp, &[1, 2, 3, 4, 5]);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-20
@@ -5,7 +5,7 @@ macro_rules! has_attr {
|
|||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self) -> bool {
|
pub fn fn_name(&self) -> bool {
|
||||||
match to_device(&self.$item) {
|
match to_device(&self.$item) {
|
||||||
Ok(p) => crate::has_attr(&p, $attr_name),
|
Ok(p) => $crate::has_attr(&p, $attr_name),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ macro_rules! watch_attr {
|
|||||||
path.push($attr_name);
|
path.push($attr_name);
|
||||||
if let Some(path) = path.to_str() {
|
if let Some(path) = path.to_str() {
|
||||||
let mut inotify = inotify::Inotify::init()?;
|
let mut inotify = inotify::Inotify::init()?;
|
||||||
inotify.add_watch(path, inotify::WatchMask::MODIFY)
|
inotify.add_watch(path, inotify::WatchMask::CLOSE_WRITE)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
if e.kind() == std::io::ErrorKind::NotFound {
|
if e.kind() == std::io::ErrorKind::NotFound {
|
||||||
PlatformError::AttrNotFound(format!("{}", $attr_name))
|
PlatformError::AttrNotFound(format!("{}", $attr_name))
|
||||||
@@ -45,7 +45,7 @@ macro_rules! get_attr_bool {
|
|||||||
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self) -> Result<bool> {
|
pub fn fn_name(&self) -> Result<bool> {
|
||||||
crate::read_attr_bool(&to_device(&self.$item)?, $attr_name)
|
$crate::read_attr_bool(&to_device(&self.$item)?, $attr_name)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -57,7 +57,7 @@ macro_rules! set_attr_bool {
|
|||||||
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self, value: bool) -> Result<()> {
|
pub fn fn_name(&self, value: bool) -> Result<()> {
|
||||||
crate::write_attr_bool(&mut to_device(&self.$item)?, $attr_name, value)
|
$crate::write_attr_bool(&mut to_device(&self.$item)?, $attr_name, value)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -66,10 +66,10 @@ macro_rules! set_attr_bool {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! attr_bool {
|
macro_rules! attr_bool {
|
||||||
($attr_name:literal, $item:ident) => {
|
($attr_name:literal, $item:ident) => {
|
||||||
crate::has_attr!($attr_name $item);
|
$crate::has_attr!($attr_name $item);
|
||||||
crate::get_attr_bool!( $attr_name $item);
|
$crate::get_attr_bool!( $attr_name $item);
|
||||||
crate::set_attr_bool!($attr_name $item);
|
$crate::set_attr_bool!($attr_name $item);
|
||||||
crate::watch_attr!($attr_name $item);
|
$crate::watch_attr!($attr_name $item);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,19 +79,20 @@ macro_rules! get_attr_u8 {
|
|||||||
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self) -> Result<u8> {
|
pub fn fn_name(&self) -> Result<u8> {
|
||||||
crate::read_attr_u8(&to_device(&self.$item)?, $attr_name)
|
$crate::read_attr_u8(&to_device(&self.$item)?, $attr_name)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Most attributes expect `u8` as a char, so `1` should be written as `b'1'`.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! set_attr_u8 {
|
macro_rules! set_attr_u8 {
|
||||||
($(#[$doc_comment:meta])? $attr_name:literal $item:ident) => {
|
($(#[$doc_comment:meta])? $attr_name:literal $item:ident) => {
|
||||||
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self, value: u8) -> Result<()> {
|
pub fn fn_name(&self, value: u8) -> Result<()> {
|
||||||
crate::write_attr_u8(&mut to_device(&self.$item)?, $attr_name, value)
|
$crate::write_attr_u8(&mut to_device(&self.$item)?, $attr_name, value)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -100,10 +101,10 @@ macro_rules! set_attr_u8 {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! attr_u8 {
|
macro_rules! attr_u8 {
|
||||||
($attr_name:literal, $item:ident) => {
|
($attr_name:literal, $item:ident) => {
|
||||||
crate::has_attr!($attr_name $item);
|
$crate::has_attr!($attr_name $item);
|
||||||
crate::get_attr_u8!($attr_name $item);
|
$crate::get_attr_u8!($attr_name $item);
|
||||||
crate::set_attr_u8!($attr_name $item);
|
$crate::set_attr_u8!($attr_name $item);
|
||||||
crate::watch_attr!($attr_name $item);
|
$crate::watch_attr!($attr_name $item);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ macro_rules! get_attr_u8_array {
|
|||||||
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
concat_idents::concat_idents!(fn_name = get_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self) -> Result<Vec<u8>> {
|
pub fn fn_name(&self) -> Result<Vec<u8>> {
|
||||||
crate::read_attr_u8_array(&to_device(&self.$item)?, $attr_name)
|
$crate::read_attr_u8_array(&to_device(&self.$item)?, $attr_name)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -125,7 +126,7 @@ macro_rules! set_attr_u8_array {
|
|||||||
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
concat_idents::concat_idents!(fn_name = set_, $attr_name {
|
||||||
$(#[$doc_comment])*
|
$(#[$doc_comment])*
|
||||||
pub fn fn_name(&self, values: &[u8]) -> Result<()> {
|
pub fn fn_name(&self, values: &[u8]) -> Result<()> {
|
||||||
crate::write_attr_u8_array(&mut to_device(&self.$item)?, $attr_name, values)
|
$crate::write_attr_u8_array(&mut to_device(&self.$item)?, $attr_name, values)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -134,9 +135,9 @@ macro_rules! set_attr_u8_array {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! attr_u8_array {
|
macro_rules! attr_u8_array {
|
||||||
($attr_name:literal, $item:ident) => {
|
($attr_name:literal, $item:ident) => {
|
||||||
crate::has_attr!($attr_name $item);
|
$crate::has_attr!($attr_name $item);
|
||||||
crate::get_attr_u8_array!($attr_name $item);
|
$crate::get_attr_u8_array!($attr_name $item);
|
||||||
crate::set_attr_u8_array!($attr_name $item);
|
$crate::set_attr_u8_array!($attr_name $item);
|
||||||
crate::watch_attr!($attr_name $item);
|
$crate::watch_attr!($attr_name $item);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{path::PathBuf, str::FromStr};
|
use std::{fmt::Display, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -17,7 +17,7 @@ use crate::{
|
|||||||
/// - gpu_mux
|
/// - gpu_mux
|
||||||
/// - keyboard_mode, set keyboard RGB mode and speed
|
/// - keyboard_mode, set keyboard RGB mode and speed
|
||||||
/// - keyboard_state, set keyboard power states
|
/// - keyboard_state, set keyboard power states
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
|
||||||
pub struct AsusPlatform {
|
pub struct AsusPlatform {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
pp_path: PathBuf,
|
pp_path: PathBuf,
|
||||||
@@ -38,10 +38,12 @@ impl AsusPlatform {
|
|||||||
PlatformError::Udev("match_subsystem failed".into(), err)
|
PlatformError::Udev("match_subsystem failed".into(), err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for device in enumerator.scan_devices().map_err(|err| {
|
if let Some(device) = (enumerator.scan_devices().map_err(|err| {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
PlatformError::Udev("scan_devices failed".into(), err)
|
PlatformError::Udev("scan_devices failed".into(), err)
|
||||||
})? {
|
})?)
|
||||||
|
.next()
|
||||||
|
{
|
||||||
info!("Found platform support at {:?}", device.sysname());
|
info!("Found platform support at {:?}", device.sysname());
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
path: device.syspath().to_owned(),
|
path: device.syspath().to_owned(),
|
||||||
@@ -56,14 +58,14 @@ impl AsusPlatform {
|
|||||||
attr_bool!("dgpu_disable", path);
|
attr_bool!("dgpu_disable", path);
|
||||||
attr_bool!("egpu_enable", path);
|
attr_bool!("egpu_enable", path);
|
||||||
attr_bool!("panel_od", path);
|
attr_bool!("panel_od", path);
|
||||||
attr_u8!("gpu_mux_mode", path);
|
attr_bool!("gpu_mux_mode", path);
|
||||||
// This is technically the same as `platform_profile` since both are tied in-kernel
|
// This is technically the same as `platform_profile` since both are tied in-kernel
|
||||||
attr_u8!("throttle_thermal_policy", path);
|
attr_u8!("throttle_thermal_policy", path);
|
||||||
// The acpi platform_profile support
|
// The acpi platform_profile support
|
||||||
attr_u8!("platform_profile", pp_path);
|
attr_u8!("platform_profile", pp_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Type, Debug, PartialEq, Clone, Copy)]
|
#[derive(Serialize, Deserialize, Type, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum GpuMode {
|
pub enum GpuMode {
|
||||||
Discrete,
|
Discrete,
|
||||||
Optimus,
|
Optimus,
|
||||||
@@ -74,21 +76,22 @@ pub enum GpuMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GpuMode {
|
impl GpuMode {
|
||||||
pub fn to_mux(&self) -> u8 {
|
/// For writing to `gpu_mux_mode` attribute
|
||||||
|
pub fn to_mux_attr(&self) -> bool {
|
||||||
if *self == Self::Discrete {
|
if *self == Self::Discrete {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
1
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_dgpu(&self) -> u8 {
|
pub fn to_dgpu_attr(&self) -> u8 {
|
||||||
if *self == Self::Integrated {
|
if *self == Self::Integrated {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_egpu(&self) -> u8 {
|
pub fn to_egpu_attr(&self) -> u8 {
|
||||||
if *self == Self::Egpu {
|
if *self == Self::Egpu {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -118,3 +121,16 @@ impl GpuMode {
|
|||||||
Self::Optimus
|
Self::Optimus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for GpuMode {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
GpuMode::Discrete => write!(f, "Discrete"),
|
||||||
|
GpuMode::Optimus => write!(f, "Optimus"),
|
||||||
|
GpuMode::Integrated => write!(f, "Integrated"),
|
||||||
|
GpuMode::Egpu => write!(f, "eGPU"),
|
||||||
|
GpuMode::Error => write!(f, "Error"),
|
||||||
|
GpuMode::NotSupported => write!(f, "Not Supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::{
|
|||||||
/// - gpu_mux
|
/// - gpu_mux
|
||||||
/// - keyboard_mode, set keyboard RGB mode and speed
|
/// - keyboard_mode, set keyboard RGB mode and speed
|
||||||
/// - keyboard_state, set keyboard power states
|
/// - keyboard_state, set keyboard power states
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
|
||||||
pub struct AsusPower {
|
pub struct AsusPower {
|
||||||
mains: PathBuf,
|
mains: PathBuf,
|
||||||
battery: PathBuf,
|
battery: PathBuf,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use crate::error::{PlatformError, Result};
|
use crate::error::{PlatformError, Result};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct USBRaw(DeviceHandle<rusb::GlobalContext>);
|
pub struct USBRaw(DeviceHandle<rusb::GlobalContext>);
|
||||||
|
|
||||||
impl USBRaw {
|
impl USBRaw {
|
||||||
@@ -43,6 +43,6 @@ impl USBRaw {
|
|||||||
message,
|
message,
|
||||||
Duration::from_millis(200),
|
Duration::from_millis(200),
|
||||||
)
|
)
|
||||||
.map_err(|e| PlatformError::USB(e))
|
.map_err(PlatformError::USB)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_profiles"
|
name = "rog_profiles"
|
||||||
version = "1.1.3"
|
version.workspace = true
|
||||||
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["dbus"]
|
default = ["dbus"]
|
||||||
dbus = ["zvariant", "zvariant_derive"]
|
dbus = ["zvariant", "zvariant_derive"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
udev = "^0.6"
|
udev.workspace = true
|
||||||
serde = "^1.0"
|
serde.workspace = true
|
||||||
serde_derive = "^1.0"
|
serde_derive.workspace = true
|
||||||
|
|
||||||
zvariant = { version = "^3.0", optional = true }
|
zvariant = { workspace = true, optional = true }
|
||||||
zvariant_derive = { version = "^3.0", optional = true }
|
zvariant_derive = { workspace = true, optional = true }
|
||||||
@@ -2,6 +2,7 @@ pub mod error;
|
|||||||
pub mod fan_curve_set;
|
pub mod fan_curve_set;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
@@ -113,8 +114,14 @@ impl std::str::FromStr for Profile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Profile {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
|
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum FanCurvePU {
|
pub enum FanCurvePU {
|
||||||
CPU,
|
CPU,
|
||||||
GPU,
|
GPU,
|
||||||
|
|||||||
Reference in New Issue
Block a user