mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Merge branch 'fluke/inotify' into 'main'
Fluke/inotify See merge request asus-linux/asusctl!133
This commit is contained in:
31
CHANGELOG.md
31
CHANGELOG.md
@@ -4,7 +4,36 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased ]
|
## [Unreleased - 4.5.0]
|
||||||
|
### Added
|
||||||
|
- intofy watches on:
|
||||||
|
- `charge_control_end_threshold`
|
||||||
|
- `panel_od`
|
||||||
|
- `gpu_mux_mode`
|
||||||
|
- `platform_profile`
|
||||||
|
- keyboard brightness
|
||||||
|
- These allow for updating any associated config and sending dbus notifications.
|
||||||
|
- New dbus methods
|
||||||
|
- `DgpuDisable`
|
||||||
|
- `SetDgpuDisable`
|
||||||
|
- `NotifyDgpuDisable`
|
||||||
|
- `EgpuEnable`
|
||||||
|
- `SetEgpuEnable`
|
||||||
|
- `NotifyEgpuEnable`
|
||||||
|
- `MainsOnline` (This is AC, check if plugged in or not)
|
||||||
|
- `NotifyMainsOnline`
|
||||||
|
### Changed
|
||||||
|
- Use loops to ensure that mutex is gained for LED changes.
|
||||||
|
- asusctl now uses tokio for async runtime. This helps simplify some code.
|
||||||
|
### Breaking
|
||||||
|
- DBUS: all charge control methods renamed to:
|
||||||
|
- `ChargeControlEndThreshold`
|
||||||
|
- `SetChargeControlEndThreshold`
|
||||||
|
- `NotifyChargeControlEndThreshold`
|
||||||
|
- `PanelOd` (form PanelOverdrive)
|
||||||
|
- `SetPanelOd`
|
||||||
|
- `NotifyPanelOd`
|
||||||
|
- Path `/org/asuslinux/Charge` changed to `/org/asuslinux/Power`
|
||||||
|
|
||||||
## [v4.4.0] - 2022-08-29
|
## [v4.4.0] - 2022-08-29
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -572,9 +572,10 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "4.4.0"
|
version = "4.5.0-rc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"concat-idents",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
"logind-zbus",
|
"logind-zbus",
|
||||||
@@ -586,8 +587,8 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"smol",
|
|
||||||
"sysfs-class",
|
"sysfs-class",
|
||||||
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"zbus",
|
"zbus",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
@@ -1703,6 +1704,16 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.5.7"
|
version = "0.5.7"
|
||||||
@@ -2528,18 +2539,32 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.20.1"
|
version = "1.21.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
|
checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
"num_cpus",
|
||||||
|
"once_cell",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.9"
|
version = "0.5.9"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
use notify_rust::{Hint, Notification, NotificationHandle};
|
||||||
use rog_aura::AuraEffect;
|
use rog_aura::AuraEffect;
|
||||||
use rog_dbus::{
|
use rog_dbus::{
|
||||||
zbus_charge::ChargeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
zbus_led::LedProxy, zbus_platform::RogBiosProxy, zbus_power::PowerProxy,
|
||||||
zbus_profile::ProfileProxy,
|
zbus_profile::ProfileProxy,
|
||||||
};
|
};
|
||||||
use rog_profiles::Profile;
|
use rog_profiles::Profile;
|
||||||
@@ -54,7 +54,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
p.for_each(|e| {
|
p.for_each(|e| {
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if let Ok(ref mut lock) = x.try_lock() {
|
if let Ok(ref mut lock) = x.try_lock() {
|
||||||
notify!(do_post_sound_notif, lock, &out.sound());
|
notify!(do_post_sound_notif, lock, &out.on());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
future::ready(())
|
future::ready(())
|
||||||
@@ -69,8 +69,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
executor
|
executor
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
let proxy = ChargeProxy::new(&conn).await.unwrap();
|
let proxy = PowerProxy::new(&conn).await.unwrap();
|
||||||
if let Ok(p) = proxy.receive_notify_charge().await {
|
if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await {
|
||||||
p.for_each(|e| {
|
p.for_each(|e| {
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if let Ok(ref mut lock) = x.try_lock() {
|
if let Ok(ref mut lock) = x.try_lock() {
|
||||||
|
|||||||
@@ -211,7 +211,9 @@ fn do_parsed(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(chg_limit) = parsed.chg_limit {
|
if let Some(chg_limit) = parsed.chg_limit {
|
||||||
dbus.proxies().charge().set_limit(chg_limit)?;
|
dbus.proxies()
|
||||||
|
.charge()
|
||||||
|
.set_charge_control_end_threshold(chg_limit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -803,10 +805,10 @@ fn handle_bios_option(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(opt) = cmd.panel_overdrive_set {
|
if let Some(opt) = cmd.panel_overdrive_set {
|
||||||
dbus.proxies().rog_bios().set_panel_overdrive(opt)?;
|
dbus.proxies().rog_bios().set_panel_od(opt)?;
|
||||||
}
|
}
|
||||||
if cmd.panel_overdrive_get {
|
if cmd.panel_overdrive_get {
|
||||||
let res = dbus.proxies().rog_bios().panel_overdrive()?;
|
let res = dbus.proxies().rog_bios().panel_od()?;
|
||||||
println!("Panel overdrive on: {}", res);
|
println!("Panel overdrive on: {}", res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "4.4.0"
|
version = "4.5.0-rc3"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
@@ -25,7 +25,7 @@ rog_profiles = { path = "../rog-profiles" }
|
|||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
|
||||||
async-trait = "^0.1"
|
async-trait = "^0.1"
|
||||||
smol = "^1.2"
|
tokio = { version = "^1.21.1", features = ["macros", "rt-multi-thread", "time"]}
|
||||||
|
|
||||||
# cli and logging
|
# cli and logging
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
@@ -43,3 +43,5 @@ toml = "^0.5.8"
|
|||||||
|
|
||||||
# Device control
|
# Device control
|
||||||
sysfs-class = "^0.1.2" # used for backlight control and baord ID
|
sysfs-class = "^0.1.2" # used for backlight control and baord ID
|
||||||
|
|
||||||
|
concat-idents = "1.1.3"
|
||||||
@@ -1,29 +1,19 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod zbus;
|
/// Implements CtrlTask, Reloadable, ZbusRun
|
||||||
|
pub mod trait_impls;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use self::config::{AnimeConfig, AnimeConfigCached};
|
||||||
|
use crate::{error::RogError, GetSupported};
|
||||||
|
use ::zbus::export::futures_util::lock::Mutex;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_anime::{
|
use rog_anime::{
|
||||||
error::AnimeError,
|
error::AnimeError,
|
||||||
usb::{
|
usb::{get_anime_type, pkt_for_flush, pkts_for_init},
|
||||||
get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on,
|
|
||||||
pkts_for_init,
|
|
||||||
},
|
|
||||||
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
|
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
|
||||||
};
|
};
|
||||||
use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw};
|
use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw};
|
||||||
use smol::Executor;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::{
|
use std::{convert::TryFrom, error::Error, sync::Arc, thread::sleep};
|
||||||
convert::TryFrom,
|
|
||||||
error::Error,
|
|
||||||
sync::{Arc, Mutex, MutexGuard},
|
|
||||||
thread::sleep,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{error::RogError, GetSupported};
|
|
||||||
|
|
||||||
use self::config::{AnimeConfig, AnimeConfigCached};
|
|
||||||
|
|
||||||
impl GetSupported for CtrlAnime {
|
impl GetSupported for CtrlAnime {
|
||||||
type A = AnimeSupportedFunctions;
|
type A = AnimeSupportedFunctions;
|
||||||
@@ -85,6 +75,7 @@ impl CtrlAnime {
|
|||||||
|
|
||||||
// The only reason for this outer thread is to prevent blocking while waiting for the
|
// The only reason for this outer thread is to prevent blocking while waiting for the
|
||||||
// next spawned thread to exit
|
// next spawned thread to exit
|
||||||
|
// TODO: turn this in to async task (maybe? COuld still risk blocking main thread)
|
||||||
std::thread::Builder::new()
|
std::thread::Builder::new()
|
||||||
.name("AniMe system thread start".into())
|
.name("AniMe system thread start".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
@@ -95,7 +86,7 @@ impl CtrlAnime {
|
|||||||
let thread_running;
|
let thread_running;
|
||||||
let anime_type;
|
let anime_type;
|
||||||
loop {
|
loop {
|
||||||
if let Ok(lock) = inner.try_lock() {
|
if let Some(lock) = inner.try_lock() {
|
||||||
thread_exit = lock.thread_exit.clone();
|
thread_exit = lock.thread_exit.clone();
|
||||||
thread_running = lock.thread_running.clone();
|
thread_running = lock.thread_running.clone();
|
||||||
anime_type = lock.anime_type;
|
anime_type = lock.anime_type;
|
||||||
@@ -139,9 +130,10 @@ impl CtrlAnime {
|
|||||||
.ok();
|
.ok();
|
||||||
false // Don't exit yet
|
false // Don't exit yet
|
||||||
})
|
})
|
||||||
.map_err(|err| {
|
.map(|r| Ok(r))
|
||||||
warn!("rog_anime::run_animation:callback {}", err);
|
.unwrap_or_else(|| {
|
||||||
AnimeError::NoFrames
|
warn!("rog_anime::run_animation:callback failed");
|
||||||
|
Err(AnimeError::NoFrames)
|
||||||
})
|
})
|
||||||
}) {
|
}) {
|
||||||
warn!("rog_anime::run_animation:Animation {}", err);
|
warn!("rog_anime::run_animation:Animation {}", err);
|
||||||
@@ -150,7 +142,7 @@ impl CtrlAnime {
|
|||||||
}
|
}
|
||||||
ActionData::Image(image) => {
|
ActionData::Image(image) => {
|
||||||
once = false;
|
once = false;
|
||||||
if let Ok(lock) = inner.try_lock() {
|
if let Some(lock) = inner.try_lock() {
|
||||||
lock.write_data_buffer(image.as_ref().clone())
|
lock.write_data_buffer(image.as_ref().clone())
|
||||||
.map_err(|e| error!("{}", e))
|
.map_err(|e| error!("{}", e))
|
||||||
.ok();
|
.ok();
|
||||||
@@ -171,7 +163,7 @@ impl CtrlAnime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear the display on exit
|
// Clear the display on exit
|
||||||
if let Ok(lock) = inner.try_lock() {
|
if let Some(lock) = inner.try_lock() {
|
||||||
if let Ok(data) =
|
if let Ok(data) =
|
||||||
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()])
|
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()])
|
||||||
.map_err(|e| error!("{}", e))
|
.map_err(|e| error!("{}", e))
|
||||||
@@ -216,85 +208,3 @@ impl CtrlAnime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlAnimeTask {
|
|
||||||
inner: Arc<Mutex<CtrlAnime>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlAnimeTask {
|
|
||||||
pub async fn new(inner: Arc<Mutex<CtrlAnime>>) -> CtrlAnimeTask {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl crate::CtrlTask for CtrlAnimeTask {
|
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
|
||||||
let run_action =
|
|
||||||
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
|
|
||||||
if start {
|
|
||||||
info!("CtrlAnimeTask running sleep animation");
|
|
||||||
CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true);
|
|
||||||
} else {
|
|
||||||
info!("CtrlAnimeTask running wake animation");
|
|
||||||
CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let inner1 = self.inner.clone();
|
|
||||||
let inner2 = self.inner.clone();
|
|
||||||
let inner3 = self.inner.clone();
|
|
||||||
let inner4 = self.inner.clone();
|
|
||||||
self.create_sys_event_tasks(
|
|
||||||
executor,
|
|
||||||
// Loop is required to try an attempt to get the mutex *without* blocking
|
|
||||||
// other threads - it is possible to end up with deadlocks otherwise.
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner1.clone().try_lock() {
|
|
||||||
run_action(true, lock, inner1.clone());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner2.clone().try_lock() {
|
|
||||||
run_action(false, lock, inner2.clone());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner3.clone().try_lock() {
|
|
||||||
run_action(true, lock, inner3.clone());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner4.clone().try_lock() {
|
|
||||||
run_action(false, lock, inner4.clone());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CtrlAnimeReloader(pub Arc<Mutex<CtrlAnime>>);
|
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlAnimeReloader {
|
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
|
||||||
if let Ok(lock) = self.0.try_lock() {
|
|
||||||
lock.node
|
|
||||||
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
|
|
||||||
lock.node.write_bytes(&pkt_for_apply())?;
|
|
||||||
lock.node
|
|
||||||
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
|
|
||||||
lock.node.write_bytes(&pkt_for_apply())?;
|
|
||||||
|
|
||||||
let action = lock.cache.boot.clone();
|
|
||||||
CtrlAnime::run_thread(self.0.clone(), action, true);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
216
daemon/src/ctrl_anime/trait_impls.rs
Normal file
216
daemon/src/ctrl_anime/trait_impls.rs
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
use super::CtrlAnime;
|
||||||
|
use crate::error::RogError;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use log::{info, warn};
|
||||||
|
use rog_anime::{
|
||||||
|
usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on},
|
||||||
|
AnimeDataBuffer, AnimePowerStates,
|
||||||
|
};
|
||||||
|
use std::sync::{atomic::Ordering, Arc};
|
||||||
|
use zbus::{
|
||||||
|
dbus_interface,
|
||||||
|
export::futures_util::lock::{Mutex, MutexGuard},
|
||||||
|
Connection, SignalContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime";
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
|
/// The struct with the main dbus methods requires this trait
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::ZbusRun for CtrlAnimeZbus {
|
||||||
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
|
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of these calls can be guarnateed to succeed unless we loop until okay
|
||||||
|
// If the try_lock *does* succeed then any other thread trying to lock will not grab it
|
||||||
|
// until we finish.
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl CtrlAnimeZbus {
|
||||||
|
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
||||||
|
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
|
||||||
|
let lock = self.0.lock().await;
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
lock.write_data_buffer(input).map_err(|err| {
|
||||||
|
warn!("rog_anime::run_animation:callback {}", err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the global AniMe brightness
|
||||||
|
async fn set_brightness(&self, bright: f32) {
|
||||||
|
let mut lock = self.0.lock().await;
|
||||||
|
let mut bright = bright;
|
||||||
|
if bright < 0.0 {
|
||||||
|
bright = 0.0
|
||||||
|
} else if bright > 1.0 {
|
||||||
|
bright = 1.0;
|
||||||
|
}
|
||||||
|
lock.config.brightness = bright;
|
||||||
|
lock.config.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set whether the AniMe is displaying images/data
|
||||||
|
async fn set_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
|
||||||
|
let mut lock = self.0.lock().await;
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_for_set_on(status))
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("rog_anime::run_animation:callback {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
lock.config.awake_enabled = status;
|
||||||
|
lock.config.write();
|
||||||
|
|
||||||
|
Self::notify_power_states(
|
||||||
|
&ctxt,
|
||||||
|
AnimePowerStates {
|
||||||
|
brightness: lock.config.brightness.floor() as u8,
|
||||||
|
enabled: lock.config.awake_enabled,
|
||||||
|
boot_anim_enabled: lock.config.boot_anim_enabled,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||||
|
async fn set_boot_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, on: bool) {
|
||||||
|
let mut lock = self.0.lock().await;
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_for_set_boot(on))
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("rog_anime::run_animation:callback {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_for_apply())
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("rog_anime::run_animation:callback {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
lock.config.boot_anim_enabled = on;
|
||||||
|
lock.config.write();
|
||||||
|
|
||||||
|
Self::notify_power_states(
|
||||||
|
&ctxt,
|
||||||
|
AnimePowerStates {
|
||||||
|
brightness: lock.config.brightness.floor() as u8,
|
||||||
|
enabled: lock.config.awake_enabled,
|
||||||
|
boot_anim_enabled: lock.config.boot_anim_enabled,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main loop is the base system set action if the user isn't running
|
||||||
|
/// the user daemon
|
||||||
|
async fn run_main_loop(&self, start: bool) {
|
||||||
|
if start {
|
||||||
|
let lock = self.0.lock().await;
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get status of if the AniMe LEDs are on/displaying while system is awake
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn awake_enabled(&self) -> bool {
|
||||||
|
let lock = self.0.lock().await;
|
||||||
|
return lock.config.awake_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the status of if factory system-status animations are enabled
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn boot_enabled(&self) -> bool {
|
||||||
|
let lock = self.0.lock().await;
|
||||||
|
return lock.config.boot_anim_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_power_states(
|
||||||
|
ctxt: &SignalContext<'_>,
|
||||||
|
data: AnimePowerStates,
|
||||||
|
) -> zbus::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::CtrlTask for CtrlAnimeZbus {
|
||||||
|
fn zbus_path() -> &'static str {
|
||||||
|
ZBUS_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
|
let run_action =
|
||||||
|
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
|
||||||
|
if start {
|
||||||
|
info!("CtrlAnimeTask running sleep animation");
|
||||||
|
CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true);
|
||||||
|
} else {
|
||||||
|
info!("CtrlAnimeTask running wake animation");
|
||||||
|
CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let inner1 = self.0.clone();
|
||||||
|
let inner2 = self.0.clone();
|
||||||
|
let inner3 = self.0.clone();
|
||||||
|
let inner4 = self.0.clone();
|
||||||
|
self.create_sys_event_tasks(
|
||||||
|
// Loop is required to try an attempt to get the mutex *without* blocking
|
||||||
|
// other threads - it is possible to end up with deadlocks otherwise.
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner1.try_lock() {
|
||||||
|
run_action(true, lock, inner1.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner2.try_lock() {
|
||||||
|
run_action(false, lock, inner2.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner3.try_lock() {
|
||||||
|
run_action(true, lock, inner3.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner4.try_lock() {
|
||||||
|
run_action(false, lock, inner4.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::Reloadable for CtrlAnimeZbus {
|
||||||
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
if let Some(lock) = self.0.try_lock() {
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
|
||||||
|
lock.node.write_bytes(&pkt_for_apply())?;
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
|
||||||
|
lock.node.write_bytes(&pkt_for_apply())?;
|
||||||
|
|
||||||
|
let action = lock.cache.boot.clone();
|
||||||
|
CtrlAnime::run_thread(self.0.clone(), action, true);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use log::warn;
|
|
||||||
use rog_anime::{
|
|
||||||
usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on},
|
|
||||||
AnimeDataBuffer, AnimePowerStates,
|
|
||||||
};
|
|
||||||
use zbus::{dbus_interface, Connection, SignalContext};
|
|
||||||
|
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
|
|
||||||
use super::CtrlAnime;
|
|
||||||
|
|
||||||
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
|
|
||||||
|
|
||||||
/// The struct with the main dbus methods requires this trait
|
|
||||||
#[async_trait]
|
|
||||||
impl crate::ZbusAdd for CtrlAnimeZbus {
|
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Anime", server).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// None of these calls can be guarnateed to succeed unless we loop until okay
|
|
||||||
// If the try_lock *does* succeed then any other thread trying to lock will not grab it
|
|
||||||
// until we finish.
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl CtrlAnimeZbus {
|
|
||||||
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
|
||||||
fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
|
|
||||||
'outer: loop {
|
|
||||||
if let Ok(lock) = self.0.try_lock() {
|
|
||||||
lock.thread_exit.store(true, Ordering::SeqCst);
|
|
||||||
lock.write_data_buffer(input).map_err(|err| {
|
|
||||||
warn!("rog_anime::run_animation:callback {}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the global AniMe brightness
|
|
||||||
fn set_brightness(&self, bright: f32) {
|
|
||||||
'outer: loop {
|
|
||||||
if let Ok(mut lock) = self.0.try_lock() {
|
|
||||||
let mut bright = bright;
|
|
||||||
if bright < 0.0 {
|
|
||||||
bright = 0.0
|
|
||||||
} else if bright > 1.0 {
|
|
||||||
bright = 1.0;
|
|
||||||
}
|
|
||||||
lock.config.brightness = bright;
|
|
||||||
lock.config.write();
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether the AniMe is displaying images/data
|
|
||||||
async fn set_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
|
|
||||||
let states;
|
|
||||||
'outer: loop {
|
|
||||||
if let Ok(mut lock) = self.0.try_lock() {
|
|
||||||
lock.node
|
|
||||||
.write_bytes(&pkt_for_set_on(status))
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("rog_anime::run_animation:callback {}", err);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
lock.config.awake_enabled = status;
|
|
||||||
lock.config.write();
|
|
||||||
|
|
||||||
states = Some(AnimePowerStates {
|
|
||||||
brightness: lock.config.brightness.floor() as u8,
|
|
||||||
enabled: lock.config.awake_enabled,
|
|
||||||
boot_anim_enabled: lock.config.boot_anim_enabled,
|
|
||||||
});
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(state) = states {
|
|
||||||
Self::notify_power_states(&ctxt, state).await.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
|
||||||
async fn set_boot_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, on: bool) {
|
|
||||||
let states;
|
|
||||||
'outer: loop {
|
|
||||||
if let Ok(mut lock) = self.0.try_lock() {
|
|
||||||
lock.node
|
|
||||||
.write_bytes(&pkt_for_set_boot(on))
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("rog_anime::run_animation:callback {}", err);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
lock.node
|
|
||||||
.write_bytes(&pkt_for_apply())
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("rog_anime::run_animation:callback {}", err);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
lock.config.boot_anim_enabled = on;
|
|
||||||
lock.config.write();
|
|
||||||
|
|
||||||
states = Some(AnimePowerStates {
|
|
||||||
brightness: lock.config.brightness.floor() as u8,
|
|
||||||
enabled: lock.config.awake_enabled,
|
|
||||||
boot_anim_enabled: lock.config.boot_anim_enabled,
|
|
||||||
});
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(state) = states {
|
|
||||||
Self::notify_power_states(&ctxt, state).await.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The main loop is the base system set action if the user isn't running
|
|
||||||
/// the user daemon
|
|
||||||
fn run_main_loop(&self, start: bool) {
|
|
||||||
if start {
|
|
||||||
'outer: loop {
|
|
||||||
if let Ok(lock) = self.0.try_lock() {
|
|
||||||
lock.thread_exit.store(true, Ordering::SeqCst);
|
|
||||||
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get status of if the AniMe LEDs are on/displaying while system is awake
|
|
||||||
#[dbus_interface(property)]
|
|
||||||
fn awake_enabled(&self) -> bool {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return ctrl.config.awake_enabled;
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the status of if factory system-status animations are enabled
|
|
||||||
#[dbus_interface(property)]
|
|
||||||
fn boot_enabled(&self) -> bool {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return ctrl.config.boot_anim_enabled;
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify listeners of the status of AniMe LED power and factory system-status animations
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
async fn notify_power_states(
|
|
||||||
ctxt: &SignalContext<'_>,
|
|
||||||
data: AnimePowerStates,
|
|
||||||
) -> zbus::Result<()>;
|
|
||||||
}
|
|
||||||
@@ -114,7 +114,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
#[serde(default)]
|
// #[serde(default)]
|
||||||
pub struct AuraConfig {
|
pub struct AuraConfig {
|
||||||
pub brightness: LedBrightness,
|
pub brightness: LedBrightness,
|
||||||
pub current_mode: AuraModeNum,
|
pub current_mode: AuraModeNum,
|
||||||
@@ -271,7 +271,7 @@ impl AuraConfig {
|
|||||||
if l == 0 {
|
if l == 0 {
|
||||||
warn!("File is empty {}", AURA_CONFIG_PATH);
|
warn!("File is empty {}", AURA_CONFIG_PATH);
|
||||||
} else {
|
} else {
|
||||||
let x: AuraConfig = serde_json::from_str(&buf)
|
let x = serde_json::from_str(&buf)
|
||||||
.unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH));
|
.unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH));
|
||||||
*self = x;
|
*self = x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::RogError,
|
error::RogError,
|
||||||
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
||||||
CtrlTask,
|
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use log::{info, warn};
|
||||||
use log::{error, info, warn};
|
|
||||||
use rog_aura::{
|
use rog_aura::{
|
||||||
usb::{AuraDevice, LED_APPLY, LED_SET},
|
usb::{AuraDevice, LED_APPLY, LED_SET},
|
||||||
AuraEffect, KeyColourArray, LedBrightness, PerKeyRaw, LED_MSG_LEN,
|
AuraEffect, KeyColourArray, LedBrightness, PerKeyRaw, LED_MSG_LEN,
|
||||||
};
|
};
|
||||||
use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
|
use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
|
||||||
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions};
|
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions};
|
||||||
use smol::Executor;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::sync::MutexGuard;
|
|
||||||
|
|
||||||
use crate::GetSupported;
|
use crate::GetSupported;
|
||||||
|
|
||||||
@@ -74,104 +68,6 @@ pub struct CtrlKbdLed {
|
|||||||
pub config: AuraConfig,
|
pub config: AuraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlKbdLedTask {
|
|
||||||
inner: Arc<Mutex<CtrlKbdLed>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlKbdLedTask {
|
|
||||||
pub fn new(inner: Arc<Mutex<CtrlKbdLed>>) -> Self {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
|
|
||||||
let bright = lock.kd_brightness.get_brightness()?;
|
|
||||||
lock.config.read();
|
|
||||||
lock.config.brightness = (bright as u32).into();
|
|
||||||
lock.config.write();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl CtrlTask for CtrlKbdLedTask {
|
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
|
||||||
let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| {
|
|
||||||
// If waking up
|
|
||||||
if !start {
|
|
||||||
info!("CtrlKbdLedTask reloading brightness and modes");
|
|
||||||
lock.set_brightness(lock.config.brightness)
|
|
||||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
|
||||||
.ok();
|
|
||||||
lock.write_current_config_mode()
|
|
||||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
|
||||||
.ok();
|
|
||||||
} else if start {
|
|
||||||
info!("CtrlKbdLedTask saving last brightness");
|
|
||||||
Self::update_config(&mut lock)
|
|
||||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let inner1 = self.inner.clone();
|
|
||||||
let inner2 = self.inner.clone();
|
|
||||||
let inner3 = self.inner.clone();
|
|
||||||
let inner4 = self.inner.clone();
|
|
||||||
self.create_sys_event_tasks(
|
|
||||||
executor,
|
|
||||||
// Loop so that we do aquire the lock but also don't block other
|
|
||||||
// threads (prevents potential deadlocks)
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner1.clone().try_lock() {
|
|
||||||
load_save(true, lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner2.clone().try_lock() {
|
|
||||||
load_save(false, lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner3.clone().try_lock() {
|
|
||||||
load_save(false, lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || loop {
|
|
||||||
if let Ok(lock) = inner4.clone().try_lock() {
|
|
||||||
load_save(false, lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CtrlKbdLedReloader(pub Arc<Mutex<CtrlKbdLed>>);
|
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlKbdLedReloader {
|
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.write_current_config_mode()?;
|
|
||||||
ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CtrlKbdLedZbus(pub Arc<Mutex<CtrlKbdLed>>);
|
|
||||||
|
|
||||||
impl CtrlKbdLedZbus {
|
|
||||||
pub fn new(inner: Arc<Mutex<CtrlKbdLed>>) -> Self {
|
|
||||||
Self(inner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlKbdLed {
|
impl CtrlKbdLed {
|
||||||
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
||||||
let mut led_prod = None;
|
let mut led_prod = None;
|
||||||
@@ -393,7 +289,7 @@ impl CtrlKbdLed {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_current_config_mode(&mut self) -> Result<(), RogError> {
|
pub(super) fn write_current_config_mode(&mut self) -> Result<(), RogError> {
|
||||||
if self.config.multizone_on {
|
if self.config.multizone_on {
|
||||||
let mode = self.config.current_mode;
|
let mode = self.config.current_mode;
|
||||||
let mut create = false;
|
let mut create = false;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod controller;
|
pub mod controller;
|
||||||
pub mod zbus;
|
/// Implements CtrlTask, Reloadable, ZbusRun
|
||||||
|
pub mod trait_impls;
|
||||||
|
|||||||
320
daemon/src/ctrl_aura/trait_impls.rs
Normal file
320
daemon/src/ctrl_aura/trait_impls.rs
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use log::{error, info, warn};
|
||||||
|
use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum, LedBrightness, PerKeyRaw};
|
||||||
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
use zbus::{
|
||||||
|
dbus_interface,
|
||||||
|
export::futures_util::{
|
||||||
|
lock::{Mutex, MutexGuard},
|
||||||
|
StreamExt,
|
||||||
|
},
|
||||||
|
Connection, SignalContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{error::RogError, CtrlTask};
|
||||||
|
|
||||||
|
use super::controller::CtrlKbdLed;
|
||||||
|
|
||||||
|
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Aura";
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CtrlKbdLedZbus(pub Arc<Mutex<CtrlKbdLed>>);
|
||||||
|
|
||||||
|
impl CtrlKbdLedZbus {
|
||||||
|
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
|
||||||
|
let bright = lock.kd_brightness.get_brightness()?;
|
||||||
|
lock.config.read();
|
||||||
|
lock.config.brightness = (bright as u32).into();
|
||||||
|
lock.config.write();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::ZbusRun for CtrlKbdLedZbus {
|
||||||
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
|
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main interface for changing, reading, or notfying signals
|
||||||
|
///
|
||||||
|
/// LED commands are split between Brightness, Modes, Per-Key
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl CtrlKbdLedZbus {
|
||||||
|
/// Set the keyboard brightness level (0-3)
|
||||||
|
async fn set_brightness(&mut self, brightness: LedBrightness) {
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
ctrl.set_brightness(brightness)
|
||||||
|
.map_err(|err| warn!("{}", err))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a variety of states, input is array of enum.
|
||||||
|
/// `enabled` sets if the sent array should be disabled or enabled
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// pub struct AuraPowerDev {
|
||||||
|
/// pub x1866: Vec<AuraDev1866>,
|
||||||
|
/// pub x19b6: Vec<AuraDev19b6>,
|
||||||
|
/// }
|
||||||
|
/// pub enum AuraDev1866 {
|
||||||
|
/// Awake,
|
||||||
|
/// Keyboard,
|
||||||
|
/// Lightbar,
|
||||||
|
/// Boot,
|
||||||
|
/// Sleep,
|
||||||
|
/// }
|
||||||
|
/// enum AuraDev19b6 {
|
||||||
|
/// BootLogo,
|
||||||
|
/// BootKeyb,
|
||||||
|
/// AwakeLogo,
|
||||||
|
/// AwakeKeyb,
|
||||||
|
/// SleepLogo,
|
||||||
|
/// SleepKeyb,
|
||||||
|
/// ShutdownLogo,
|
||||||
|
/// ShutdownKeyb,
|
||||||
|
/// AwakeBar,
|
||||||
|
/// BootBar,
|
||||||
|
/// SleepBar,
|
||||||
|
/// ShutdownBar,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
async fn set_leds_power(
|
||||||
|
&mut self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
options: AuraPowerDev,
|
||||||
|
enabled: bool,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
for p in options.tuf {
|
||||||
|
ctrl.config.enabled.set_tuf(p, enabled);
|
||||||
|
}
|
||||||
|
for p in options.x1866 {
|
||||||
|
ctrl.config.enabled.set_0x1866(p, enabled);
|
||||||
|
}
|
||||||
|
for p in options.x19b6 {
|
||||||
|
ctrl.config.enabled.set_0x19b6(p, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl.config.write();
|
||||||
|
|
||||||
|
ctrl.set_power_states().map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Self::notify_power_states(&ctxt, &AuraPowerDev::from(&ctrl.config.enabled))
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_led_mode(
|
||||||
|
&mut self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
effect: AuraEffect,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
|
||||||
|
ctrl.set_effect(effect).map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
|
Self::notify_led(&ctxt, mode.clone())
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn next_led_mode(
|
||||||
|
&self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
|
||||||
|
ctrl.toggle_mode(false).map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
|
Self::notify_led(&ctxt, mode.clone())
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn prev_led_mode(
|
||||||
|
&self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
|
||||||
|
ctrl.toggle_mode(true).map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
|
Self::notify_led(&ctxt, mode.clone())
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn next_led_brightness(&self) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.next_brightness().map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn prev_led_brightness(&self) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.prev_brightness().map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||||
|
// #[dbus_interface(property)]
|
||||||
|
async fn leds_enabled(&self) -> AuraPowerDev {
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
return AuraPowerDev::from(&ctrl.config.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the current mode data
|
||||||
|
async fn led_mode(&self) -> AuraModeNum {
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
return ctrl.config.current_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a list of available modes
|
||||||
|
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
return ctrl.config.builtins.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.write_effect_block(&data)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the current LED brightness
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn led_brightness(&self) -> i8 {
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_led(signal_ctxt: &SignalContext<'_>, data: AuraEffect) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_power_states(
|
||||||
|
signal_ctxt: &SignalContext<'_>,
|
||||||
|
data: &AuraPowerDev,
|
||||||
|
) -> zbus::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl CtrlTask for CtrlKbdLedZbus {
|
||||||
|
fn zbus_path() -> &'static str {
|
||||||
|
ZBUS_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
|
let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| {
|
||||||
|
// If waking up
|
||||||
|
if !start {
|
||||||
|
info!("CtrlKbdLedTask reloading brightness and modes");
|
||||||
|
lock.set_brightness(lock.config.brightness)
|
||||||
|
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||||
|
.ok();
|
||||||
|
lock.write_current_config_mode()
|
||||||
|
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||||
|
.ok();
|
||||||
|
} else if start {
|
||||||
|
info!("CtrlKbdLedTask saving last brightness");
|
||||||
|
Self::update_config(&mut lock)
|
||||||
|
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let inner1 = self.0.clone();
|
||||||
|
let inner2 = self.0.clone();
|
||||||
|
let inner3 = self.0.clone();
|
||||||
|
let inner4 = self.0.clone();
|
||||||
|
self.create_sys_event_tasks(
|
||||||
|
// Loop so that we do aquire the lock but also don't block other
|
||||||
|
// threads (prevents potential deadlocks)
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner1.try_lock() {
|
||||||
|
load_save(true, lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner2.try_lock() {
|
||||||
|
load_save(false, lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner3.try_lock() {
|
||||||
|
load_save(true, lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner4.try_lock() {
|
||||||
|
load_save(false, lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let ctrl2 = self.0.clone();
|
||||||
|
let ctrl = self.0.lock().await;
|
||||||
|
let mut watch = ctrl.kd_brightness.monitor_brightness()?;
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buffer = [0; 32];
|
||||||
|
watch
|
||||||
|
.event_stream(&mut buffer)
|
||||||
|
.unwrap()
|
||||||
|
.for_each(|_| async {
|
||||||
|
if let Some(lock) = ctrl2.try_lock() {
|
||||||
|
load_save(true, lock);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::Reloadable for CtrlKbdLedZbus {
|
||||||
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.write_current_config_mode()?;
|
||||||
|
ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use log::warn;
|
|
||||||
use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum, LedBrightness, PerKeyRaw};
|
|
||||||
use zbus::{dbus_interface, Connection, SignalContext};
|
|
||||||
|
|
||||||
use super::controller::CtrlKbdLedZbus;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl crate::ZbusAdd for CtrlKbdLedZbus {
|
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Aura", server).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The main interface for changing, reading, or notfying signals
|
|
||||||
///
|
|
||||||
/// LED commands are split between Brightness, Modes, Per-Key
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl CtrlKbdLedZbus {
|
|
||||||
/// Set the keyboard brightness level (0-3)
|
|
||||||
async fn set_brightness(&mut self, brightness: LedBrightness) {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.set_brightness(brightness)
|
|
||||||
.map_err(|err| warn!("{}", err))
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a variety of states, input is array of enum.
|
|
||||||
/// `enabled` sets if the sent array should be disabled or enabled
|
|
||||||
///
|
|
||||||
/// ```text
|
|
||||||
/// pub struct AuraPowerDev {
|
|
||||||
/// pub x1866: Vec<AuraDev1866>,
|
|
||||||
/// pub x19b6: Vec<AuraDev19b6>,
|
|
||||||
/// }
|
|
||||||
/// pub enum AuraDev1866 {
|
|
||||||
/// Awake,
|
|
||||||
/// Keyboard,
|
|
||||||
/// Lightbar,
|
|
||||||
/// Boot,
|
|
||||||
/// Sleep,
|
|
||||||
/// }
|
|
||||||
/// enum AuraDev19b6 {
|
|
||||||
/// BootLogo,
|
|
||||||
/// BootKeyb,
|
|
||||||
/// AwakeLogo,
|
|
||||||
/// AwakeKeyb,
|
|
||||||
/// SleepLogo,
|
|
||||||
/// SleepKeyb,
|
|
||||||
/// ShutdownLogo,
|
|
||||||
/// ShutdownKeyb,
|
|
||||||
/// AwakeBar,
|
|
||||||
/// BootBar,
|
|
||||||
/// SleepBar,
|
|
||||||
/// ShutdownBar,
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
async fn set_leds_power(
|
|
||||||
&mut self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
options: AuraPowerDev,
|
|
||||||
enabled: bool,
|
|
||||||
) -> zbus::fdo::Result<()> {
|
|
||||||
let mut states = None;
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
for p in options.tuf {
|
|
||||||
ctrl.config.enabled.set_tuf(p, enabled);
|
|
||||||
}
|
|
||||||
for p in options.x1866 {
|
|
||||||
ctrl.config.enabled.set_0x1866(p, enabled);
|
|
||||||
}
|
|
||||||
for p in options.x19b6 {
|
|
||||||
ctrl.config.enabled.set_0x19b6(p, enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl.config.write();
|
|
||||||
|
|
||||||
ctrl.set_power_states().map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
states = Some(AuraPowerDev::from(&ctrl.config.enabled));
|
|
||||||
}
|
|
||||||
// Need to pull state out like this due to MutexGuard
|
|
||||||
if let Some(states) = states {
|
|
||||||
Self::notify_power_states(&ctxt, &states)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_led_mode(
|
|
||||||
&mut self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
effect: AuraEffect,
|
|
||||||
) -> zbus::fdo::Result<()> {
|
|
||||||
let mut led = None;
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.set_effect(effect).map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
|
||||||
led = Some(mode.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(led) = led {
|
|
||||||
Self::notify_led(&ctxt, led)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn next_led_mode(
|
|
||||||
&self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
) -> zbus::fdo::Result<()> {
|
|
||||||
let mut led = None;
|
|
||||||
if let Ok(mut ctrl) = self.0.lock() {
|
|
||||||
ctrl.toggle_mode(false).map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
|
||||||
led = Some(mode.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(led) = led {
|
|
||||||
Self::notify_led(&ctxt, led)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn prev_led_mode(
|
|
||||||
&self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
) -> zbus::fdo::Result<()> {
|
|
||||||
let mut led = None;
|
|
||||||
if let Ok(mut ctrl) = self.0.lock() {
|
|
||||||
ctrl.toggle_mode(true).map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
|
||||||
led = Some(mode.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(led) = led {
|
|
||||||
Self::notify_led(&ctxt, led)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn next_led_brightness(&self) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.next_brightness().map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn prev_led_brightness(&self) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.prev_brightness().map_err(|e| {
|
|
||||||
warn!("{}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
|
||||||
// #[dbus_interface(property)]
|
|
||||||
async fn leds_enabled(&self) -> AuraPowerDev {
|
|
||||||
loop {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return AuraPowerDev::from(&ctrl.config.enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the current mode data
|
|
||||||
async fn led_mode(&self) -> AuraModeNum {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return ctrl.config.current_mode;
|
|
||||||
}
|
|
||||||
AuraModeNum::Static
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a list of available modes
|
|
||||||
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
|
||||||
loop {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return ctrl.config.builtins.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.0.try_lock() {
|
|
||||||
ctrl.write_effect_block(&data)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the current LED brightness
|
|
||||||
#[dbus_interface(property)]
|
|
||||||
async fn led_brightness(&self) -> i8 {
|
|
||||||
if let Ok(ctrl) = self.0.try_lock() {
|
|
||||||
return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1);
|
|
||||||
}
|
|
||||||
warn!("SetKeyBacklight could not serialise");
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
async fn notify_led(signal_ctxt: &SignalContext<'_>, data: AuraEffect) -> zbus::Result<()>;
|
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
async fn notify_power_states(
|
|
||||||
signal_ctxt: &SignalContext<'_>,
|
|
||||||
data: &AuraPowerDev,
|
|
||||||
) -> zbus::Result<()>;
|
|
||||||
}
|
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
use crate::CtrlTask;
|
|
||||||
use crate::{config::Config, error::RogError, GetSupported};
|
use crate::{config::Config, error::RogError, GetSupported};
|
||||||
|
use crate::{task_watch_item, CtrlTask};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_platform::platform::{AsusPlatform, GpuMode};
|
use rog_platform::platform::{AsusPlatform, GpuMode};
|
||||||
use rog_platform::supported::RogBiosSupportedFunctions;
|
use rog_platform::supported::RogBiosSupportedFunctions;
|
||||||
use smol::Executor;
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use zbus::export::futures_util::lock::Mutex;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
use zbus::{dbus_interface, SignalContext};
|
use zbus::{dbus_interface, SignalContext};
|
||||||
|
|
||||||
static ASUS_POST_LOGO_SOUND: &str =
|
const ZBUS_PATH: &str = "/org/asuslinux/Platform";
|
||||||
|
const ASUS_POST_LOGO_SOUND: &str =
|
||||||
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CtrlRogBios {
|
pub struct CtrlPlatform {
|
||||||
platform: AsusPlatform,
|
platform: AsusPlatform,
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetSupported for CtrlRogBios {
|
impl GetSupported for CtrlPlatform {
|
||||||
type A = RogBiosSupportedFunctions;
|
type A = RogBiosSupportedFunctions;
|
||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
@@ -49,7 +49,7 @@ impl GetSupported for CtrlRogBios {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtrlRogBios {
|
impl CtrlPlatform {
|
||||||
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
||||||
let platform = AsusPlatform::new()?;
|
let platform = AsusPlatform::new()?;
|
||||||
|
|
||||||
@@ -59,12 +59,12 @@ impl CtrlRogBios {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Path::new(ASUS_POST_LOGO_SOUND).exists() {
|
if Path::new(ASUS_POST_LOGO_SOUND).exists() {
|
||||||
CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?;
|
CtrlPlatform::set_path_mutable(ASUS_POST_LOGO_SOUND)?;
|
||||||
} else {
|
} else {
|
||||||
info!("Switch for POST boot sound not detected");
|
info!("Switch for POST boot sound not detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CtrlRogBios { platform, config })
|
Ok(CtrlPlatform { platform, config })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_path_mutable(path: &str) -> Result<(), RogError> {
|
fn set_path_mutable(path: &str) -> Result<(), RogError> {
|
||||||
@@ -129,7 +129,7 @@ impl CtrlRogBios {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_panel_od(&self, enable: bool) -> Result<(), RogError> {
|
fn set_panel_overdrive(&self, enable: bool) -> Result<(), RogError> {
|
||||||
self.platform.set_panel_od(enable).map_err(|err| {
|
self.platform.set_panel_od(enable).map_err(|err| {
|
||||||
warn!("CtrlRogBios: set_panel_overdrive {}", err);
|
warn!("CtrlRogBios: set_panel_overdrive {}", err);
|
||||||
err
|
err
|
||||||
@@ -139,7 +139,7 @@ impl CtrlRogBios {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl CtrlRogBios {
|
impl CtrlPlatform {
|
||||||
async fn set_gpu_mux_mode(
|
async fn set_gpu_mux_mode(
|
||||||
&mut self,
|
&mut self,
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
@@ -197,12 +197,13 @@ impl CtrlRogBios {
|
|||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn notify_post_boot_sound(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
|
async fn notify_post_boot_sound(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
|
||||||
|
|
||||||
async fn set_panel_overdrive(
|
async fn set_panel_od(
|
||||||
&mut self,
|
&mut self,
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
overdrive: bool,
|
overdrive: bool,
|
||||||
) {
|
) {
|
||||||
if self
|
if self
|
||||||
|
.platform
|
||||||
.set_panel_od(overdrive)
|
.set_panel_od(overdrive)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: set_panel_overdrive {}", err);
|
warn!("CtrlRogBios: set_panel_overdrive {}", err);
|
||||||
@@ -210,67 +211,149 @@ impl CtrlRogBios {
|
|||||||
})
|
})
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
if let Ok(mut lock) = self.config.try_lock() {
|
if let Some(mut lock) = self.config.try_lock() {
|
||||||
lock.panel_od = overdrive;
|
lock.panel_od = overdrive;
|
||||||
lock.write();
|
lock.write();
|
||||||
}
|
}
|
||||||
Self::notify_panel_overdrive(&ctxt, overdrive).await.ok();
|
Self::notify_panel_od(&ctxt, overdrive).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn panel_overdrive(&self) -> bool {
|
/// Get the `panel_od` value from platform. Updates the stored value in internal config also.
|
||||||
self.platform
|
fn panel_od(&self) -> bool {
|
||||||
|
let od = self
|
||||||
|
.platform
|
||||||
.get_panel_od()
|
.get_panel_od()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: get panel overdrive {}", err);
|
warn!("CtrlRogBios: get_panel_od {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if let Some(mut lock) = self.config.try_lock() {
|
||||||
|
lock.panel_od = od;
|
||||||
|
lock.write();
|
||||||
|
}
|
||||||
|
od
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_panel_od(signal_ctxt: &SignalContext<'_>, overdrive: bool) -> zbus::Result<()> {
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_dgpu_disable(
|
||||||
|
&mut self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
disable: bool,
|
||||||
|
) {
|
||||||
|
if self
|
||||||
|
.platform
|
||||||
|
.set_dgpu_disable(disable)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: set_dgpu_disable {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Self::notify_dgpu_disable(&ctxt, disable).await.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dgpu_disable(&self) -> bool {
|
||||||
|
self.platform
|
||||||
|
.get_dgpu_disable()
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: get_dgpu_disable {}", err);
|
||||||
err
|
err
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn notify_panel_overdrive(
|
async fn notify_dgpu_disable(
|
||||||
signal_ctxt: &SignalContext<'_>,
|
signal_ctxt: &SignalContext<'_>,
|
||||||
overdrive: bool,
|
disable: bool,
|
||||||
) -> zbus::Result<()> {
|
) -> zbus::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_egpu_enable(
|
||||||
|
&mut self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
enable: bool,
|
||||||
|
) {
|
||||||
|
if self
|
||||||
|
.platform
|
||||||
|
.set_egpu_enable(enable)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: set_egpu_enable {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Self::notify_egpu_enable(&ctxt, enable).await.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn egpu_enable(&self) -> bool {
|
||||||
|
self.platform
|
||||||
|
.get_egpu_enable()
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: get_egpu_enable {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_egpu_enable(signal_ctxt: &SignalContext<'_>, enable: bool) -> zbus::Result<()> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl crate::ZbusAdd for CtrlRogBios {
|
impl crate::ZbusRun for CtrlPlatform {
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Platform", server).await;
|
Self::add_to_server_helper(self, "/org/asuslinux/Platform", server).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlRogBios {
|
#[async_trait]
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
impl crate::Reloadable for CtrlPlatform {
|
||||||
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
if self.platform.has_panel_od() {
|
if self.platform.has_panel_od() {
|
||||||
let p = if let Ok(lock) = self.config.try_lock() {
|
let p = if let Some(lock) = self.config.try_lock() {
|
||||||
lock.panel_od
|
lock.panel_od
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
self.set_panel_od(p)?;
|
self.set_panel_overdrive(p)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CtrlPlatform {
|
||||||
|
task_watch_item!(panel_od platform);
|
||||||
|
task_watch_item!(dgpu_disable platform);
|
||||||
|
task_watch_item!(egpu_enable platform);
|
||||||
|
task_watch_item!(gpu_mux_mode platform);
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl CtrlTask for CtrlRogBios {
|
impl CtrlTask for CtrlPlatform {
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
fn zbus_path() -> &'static str {
|
||||||
|
ZBUS_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
let platform1 = self.clone();
|
let platform1 = self.clone();
|
||||||
let platform2 = self.clone();
|
let platform2 = self.clone();
|
||||||
self.create_sys_event_tasks(
|
self.create_sys_event_tasks(
|
||||||
executor,
|
|
||||||
move || {},
|
move || {},
|
||||||
move || {
|
move || {
|
||||||
info!("CtrlRogBios reloading panel_od");
|
info!("CtrlRogBios reloading panel_od");
|
||||||
if let Ok(lock) = platform1.config.try_lock() {
|
if let Some(lock) = platform1.config.try_lock() {
|
||||||
if platform1.platform.has_panel_od() {
|
if platform1.platform.has_panel_od() {
|
||||||
platform1
|
platform1
|
||||||
.set_panel_od(lock.panel_od)
|
.set_panel_overdrive(lock.panel_od)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlCharge: set_limit {}", err);
|
warn!("CtrlCharge: set_limit {}", err);
|
||||||
err
|
err
|
||||||
@@ -282,10 +365,10 @@ impl CtrlTask for CtrlRogBios {
|
|||||||
move || {},
|
move || {},
|
||||||
move || {
|
move || {
|
||||||
info!("CtrlRogBios reloading panel_od");
|
info!("CtrlRogBios reloading panel_od");
|
||||||
if let Ok(lock) = platform2.config.try_lock() {
|
if let Some(lock) = platform2.config.try_lock() {
|
||||||
if platform2.platform.has_panel_od() {
|
if platform2.platform.has_panel_od() {
|
||||||
platform2
|
platform2
|
||||||
.set_panel_od(lock.panel_od)
|
.set_panel_overdrive(lock.panel_od)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlCharge: set_limit {}", err);
|
warn!("CtrlCharge: set_limit {}", err);
|
||||||
err
|
err
|
||||||
@@ -297,6 +380,11 @@ impl CtrlTask for CtrlRogBios {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
self.watch_panel_od(signal_ctxt.clone()).await?;
|
||||||
|
self.watch_dgpu_disable(signal_ctxt.clone()).await?;
|
||||||
|
self.watch_egpu_enable(signal_ctxt.clone()).await?;
|
||||||
|
self.watch_gpu_mux_mode(signal_ctxt.clone()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
use crate::CtrlTask;
|
|
||||||
use crate::{config::Config, error::RogError, GetSupported};
|
use crate::{config::Config, error::RogError, GetSupported};
|
||||||
|
use crate::{task_watch_item, CtrlTask};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{info, warn};
|
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 smol::Executor;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
|
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";
|
||||||
|
|
||||||
impl GetSupported for CtrlPower {
|
impl GetSupported for CtrlPower {
|
||||||
type A = ChargeSupportedFunctions;
|
type A = ChargeSupportedFunctions;
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ pub struct CtrlPower {
|
|||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl CtrlPower {
|
impl CtrlPower {
|
||||||
async fn set_limit(
|
async fn set_charge_control_end_threshold(
|
||||||
&mut self,
|
&mut self,
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
limit: u8,
|
limit: u8,
|
||||||
@@ -47,31 +49,62 @@ impl CtrlPower {
|
|||||||
err
|
err
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
Self::notify_charge(&ctxt, limit).await?;
|
Self::notify_charge_control_end_threshold(&ctxt, limit).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn limit(&self) -> i8 {
|
fn charge_control_end_threshold(&self) -> u8 {
|
||||||
if let Ok(config) = self.config.try_lock() {
|
loop {
|
||||||
return config.bat_charge_limit as i8;
|
if let Some(config) = self.config.try_lock() {
|
||||||
|
let limit = self
|
||||||
|
.power
|
||||||
|
.get_charge_control_end_threshold()
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlCharge: get_charge_control_end_threshold {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.unwrap_or(100);
|
||||||
|
if let Some(mut config) = self.config.try_lock() {
|
||||||
|
config.read();
|
||||||
|
config.bat_charge_limit = limit;
|
||||||
|
config.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.bat_charge_limit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-1
|
}
|
||||||
|
|
||||||
|
fn mains_online(&self) -> bool {
|
||||||
|
if self.power.has_online() {
|
||||||
|
if let Ok(v) = self.power.get_online() {
|
||||||
|
return v == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn notify_charge(ctxt: &SignalContext<'_>, limit: u8) -> zbus::Result<()>;
|
async fn notify_charge_control_end_threshold(
|
||||||
|
ctxt: &SignalContext<'_>,
|
||||||
|
limit: u8,
|
||||||
|
) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_mains_online(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl crate::ZbusAdd for CtrlPower {
|
impl crate::ZbusRun for CtrlPower {
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Charge", server).await;
|
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl crate::Reloadable for CtrlPower {
|
impl crate::Reloadable for CtrlPower {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
if let Ok(mut config) = self.config.try_lock() {
|
if let Some(mut config) = self.config.try_lock() {
|
||||||
config.read();
|
config.read();
|
||||||
self.set(config.bat_charge_limit)?;
|
self.set(config.bat_charge_limit)?;
|
||||||
}
|
}
|
||||||
@@ -96,7 +129,7 @@ impl CtrlPower {
|
|||||||
|
|
||||||
info!("Battery charge limit: {}", limit);
|
info!("Battery charge limit: {}", limit);
|
||||||
|
|
||||||
if let Ok(mut config) = self.config.try_lock() {
|
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();
|
||||||
@@ -104,19 +137,24 @@ impl CtrlPower {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task_watch_item!(charge_control_end_threshold power);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl CtrlTask for CtrlPower {
|
impl CtrlTask for CtrlPower {
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
fn zbus_path() -> &'static str {
|
||||||
|
ZBUS_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
let power1 = self.clone();
|
let power1 = self.clone();
|
||||||
let power2 = self.clone();
|
let power2 = self.clone();
|
||||||
self.create_sys_event_tasks(
|
self.create_sys_event_tasks(
|
||||||
executor,
|
|
||||||
move || {},
|
move || {},
|
||||||
move || {
|
move || {
|
||||||
info!("CtrlCharge reloading charge limit");
|
info!("CtrlCharge reloading charge limit");
|
||||||
if let Ok(lock) = power1.config.try_lock() {
|
if let Some(lock) = power1.config.try_lock() {
|
||||||
power1
|
power1
|
||||||
.set(lock.bat_charge_limit)
|
.set(lock.bat_charge_limit)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
@@ -129,7 +167,7 @@ impl CtrlTask for CtrlPower {
|
|||||||
move || {},
|
move || {},
|
||||||
move || {
|
move || {
|
||||||
info!("CtrlCharge reloading charge limit");
|
info!("CtrlCharge reloading charge limit");
|
||||||
if let Ok(lock) = power2.config.try_lock() {
|
if let Some(lock) = power2.config.try_lock() {
|
||||||
power2
|
power2
|
||||||
.set(lock.bat_charge_limit)
|
.set(lock.bat_charge_limit)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
@@ -142,6 +180,30 @@ impl CtrlTask for CtrlPower {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
self.watch_charge_control_end_threshold(signal_ctxt.clone())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let ctrl = self.clone();
|
||||||
|
match ctrl.power.monitor_online() {
|
||||||
|
Ok(mut watch) => {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buffer = [0; 32];
|
||||||
|
watch
|
||||||
|
.event_stream(&mut buffer)
|
||||||
|
.unwrap()
|
||||||
|
.for_each(|_| async {
|
||||||
|
if let Ok(value) = ctrl.power.get_online() {
|
||||||
|
Self::notify_mains_online(&signal_ctxt, value == 1)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => info!("inotify watch failed: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
use crate::{CtrlTask, GetSupported};
|
use crate::GetSupported;
|
||||||
use async_trait::async_trait;
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use rog_platform::platform::AsusPlatform;
|
||||||
use rog_platform::supported::PlatformProfileFunctions;
|
use rog_platform::supported::PlatformProfileFunctions;
|
||||||
use rog_profiles::error::ProfileError;
|
use rog_profiles::error::ProfileError;
|
||||||
use rog_profiles::{FanCurveProfiles, Profile};
|
use rog_profiles::{FanCurveProfiles, Profile};
|
||||||
use smol::Executor;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use super::config::ProfileConfig;
|
use super::config::ProfileConfig;
|
||||||
|
|
||||||
pub struct CtrlPlatformProfile {
|
pub struct CtrlPlatformProfile {
|
||||||
pub config: ProfileConfig,
|
pub config: ProfileConfig,
|
||||||
|
pub platform: AsusPlatform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetSupported for CtrlPlatformProfile {
|
impl GetSupported for CtrlPlatformProfile {
|
||||||
@@ -39,27 +38,13 @@ impl GetSupported for CtrlPlatformProfile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlPlatformProfile {
|
|
||||||
/// Fetch the active profile and use that to set all related components up
|
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
|
||||||
if let Some(curves) = &mut self.config.fan_curves {
|
|
||||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
|
||||||
// There is a possibility that the curve was default zeroed, so this call initialises
|
|
||||||
// the data from system read and we need to save it after
|
|
||||||
curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?;
|
|
||||||
self.config.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlPlatformProfile {
|
impl CtrlPlatformProfile {
|
||||||
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
|
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
|
||||||
if Profile::is_platform_profile_supported() {
|
let platform = AsusPlatform::new()?;
|
||||||
|
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
|
||||||
info!("Device has profile control available");
|
info!("Device has profile control available");
|
||||||
|
|
||||||
let mut controller = CtrlPlatformProfile { config };
|
let mut controller = CtrlPlatformProfile { config, platform };
|
||||||
if FanCurveProfiles::get_device().is_ok() {
|
if FanCurveProfiles::get_device().is_ok() {
|
||||||
info!("Device has fan curves available");
|
info!("Device has fan curves available");
|
||||||
if controller.config.fan_curves.is_none() {
|
if controller.config.fan_curves.is_none() {
|
||||||
@@ -129,32 +114,3 @@ impl CtrlPlatformProfile {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlProfileTask {
|
|
||||||
ctrl: Arc<Mutex<CtrlPlatformProfile>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlProfileTask {
|
|
||||||
pub fn new(ctrl: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
|
|
||||||
Self { ctrl }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl CtrlTask for CtrlProfileTask {
|
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
|
||||||
let ctrl = self.ctrl.clone();
|
|
||||||
self.repeating_task(666, executor, move || {
|
|
||||||
if let Ok(ref mut lock) = ctrl.try_lock() {
|
|
||||||
let new_profile = Profile::get_active_profile().unwrap();
|
|
||||||
if new_profile != lock.config.active_profile {
|
|
||||||
lock.config.active_profile = new_profile;
|
|
||||||
lock.write_profile_curve_to_platform().unwrap();
|
|
||||||
lock.save_config();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod controller;
|
pub mod controller;
|
||||||
pub mod zbus;
|
/// Implements CtrlTask, Reloadable, ZbusRun
|
||||||
|
pub mod trait_impls;
|
||||||
|
|||||||
247
daemon/src/ctrl_profiles/trait_impls.rs
Normal file
247
daemon/src/ctrl_profiles/trait_impls.rs
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use log::warn;
|
||||||
|
use rog_profiles::fan_curve_set::CurveData;
|
||||||
|
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||||
|
use rog_profiles::FanCurveProfiles;
|
||||||
|
use rog_profiles::Profile;
|
||||||
|
use zbus::export::futures_util::lock::Mutex;
|
||||||
|
use zbus::export::futures_util::StreamExt;
|
||||||
|
use zbus::Connection;
|
||||||
|
use zbus::SignalContext;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use zbus::{dbus_interface, fdo::Error};
|
||||||
|
|
||||||
|
use crate::error::RogError;
|
||||||
|
use crate::CtrlTask;
|
||||||
|
|
||||||
|
use super::controller::CtrlPlatformProfile;
|
||||||
|
|
||||||
|
const ZBUS_PATH: &str = "/org/asuslinux/Profile";
|
||||||
|
const UNSUPPORTED_MSG: &str =
|
||||||
|
"Fan curves are not supported on this laptop or you require a patched kernel";
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ProfileZbus(pub Arc<Mutex<CtrlPlatformProfile>>);
|
||||||
|
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl ProfileZbus {
|
||||||
|
/// Fetch profile names
|
||||||
|
fn profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
||||||
|
if let Ok(profiles) = Profile::get_profile_names() {
|
||||||
|
return Ok(profiles);
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get all profile details".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
||||||
|
/// If fan-curves are supported will also activate a fan curve for profile.
|
||||||
|
async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.set_next_profile()
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
ctrl.save_config();
|
||||||
|
|
||||||
|
Self::notify_profile(&ctxt, ctrl.config.active_profile)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the active profile name
|
||||||
|
async fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
Ok(ctrl.config.active_profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set this platform_profile name as active
|
||||||
|
async fn set_active_profile(
|
||||||
|
&self,
|
||||||
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
|
profile: Profile,
|
||||||
|
) {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
// Read first just incase the user has modified the config before calling this
|
||||||
|
ctrl.config.read();
|
||||||
|
Profile::set_profile(profile)
|
||||||
|
.map_err(|e| warn!("set_profile, {}", e))
|
||||||
|
.ok();
|
||||||
|
ctrl.config.active_profile = profile;
|
||||||
|
ctrl.write_profile_curve_to_platform()
|
||||||
|
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
ctrl.save_config();
|
||||||
|
|
||||||
|
Self::notify_profile(&ctxt, ctrl.config.active_profile)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of profiles that have fan-curves enabled.
|
||||||
|
async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
if let Some(curves) = &ctrl.config.fan_curves {
|
||||||
|
return Ok(curves.get_enabled_curve_profiles().to_vec());
|
||||||
|
}
|
||||||
|
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
|
||||||
|
/// same profile mode
|
||||||
|
async fn set_fan_curve_enabled(
|
||||||
|
&mut self,
|
||||||
|
profile: Profile,
|
||||||
|
enabled: bool,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
return if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||||
|
curves.set_profile_curve_enabled(profile, enabled);
|
||||||
|
|
||||||
|
ctrl.write_profile_curve_to_platform()
|
||||||
|
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
ctrl.save_config();
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the fan-curve data for the currently active Profile
|
||||||
|
async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
if let Some(curves) = &ctrl.config.fan_curves {
|
||||||
|
let curve = curves.get_fan_curves_for(profile);
|
||||||
|
return Ok(curve.clone());
|
||||||
|
}
|
||||||
|
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the fan curve for the specified profile.
|
||||||
|
/// Will also activate the fan curve if the user is in the same mode.
|
||||||
|
async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||||
|
curves
|
||||||
|
.save_fan_curve(curve, profile)
|
||||||
|
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||||
|
} else {
|
||||||
|
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||||
|
}
|
||||||
|
ctrl.write_profile_curve_to_platform()
|
||||||
|
.map_err(|e| warn!("Profile::set_profile, {}", e))
|
||||||
|
.ok();
|
||||||
|
ctrl.save_config();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// only for the currently active profile.
|
||||||
|
async fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
ctrl.set_active_curve_to_defaults()
|
||||||
|
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
|
||||||
|
.ok();
|
||||||
|
ctrl.save_config();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// only for the currently active profile.
|
||||||
|
async fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
ctrl.config.read();
|
||||||
|
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
|
||||||
|
|
||||||
|
Profile::set_profile(profile)
|
||||||
|
.map_err(|e| warn!("set_profile, {}", e))
|
||||||
|
.ok();
|
||||||
|
ctrl.set_active_curve_to_defaults()
|
||||||
|
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
Profile::set_profile(active)
|
||||||
|
.map_err(|e| warn!("set_profile, {}", e))
|
||||||
|
.ok();
|
||||||
|
ctrl.save_config();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
async fn notify_profile(signal_ctxt: &SignalContext<'_>, profile: Profile) -> zbus::Result<()> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::ZbusRun for ProfileZbus {
|
||||||
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
|
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl CtrlTask for ProfileZbus {
|
||||||
|
fn zbus_path() -> &'static str {
|
||||||
|
ZBUS_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
|
let ctrl = self.0.clone();
|
||||||
|
let mut watch = self.0.lock().await.platform.monitor_platform_profile()?;
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buffer = [0; 32];
|
||||||
|
watch
|
||||||
|
.event_stream(&mut buffer)
|
||||||
|
.unwrap()
|
||||||
|
.for_each(|_| async {
|
||||||
|
let mut lock = ctrl.lock().await;
|
||||||
|
let new_profile = Profile::get_active_profile().unwrap();
|
||||||
|
if new_profile != lock.config.active_profile {
|
||||||
|
lock.config.active_profile = new_profile;
|
||||||
|
lock.write_profile_curve_to_platform().unwrap();
|
||||||
|
lock.save_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::notify_profile(&signal_ctxt.clone(), lock.config.active_profile)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl crate::Reloadable for ProfileZbus {
|
||||||
|
/// Fetch the active profile and use that to set all related components up
|
||||||
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
let mut ctrl = self.0.lock().await;
|
||||||
|
let active = ctrl.config.active_profile;
|
||||||
|
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||||
|
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||||
|
// There is a possibility that the curve was default zeroed, so this call initialises
|
||||||
|
// the data from system read and we need to save it after
|
||||||
|
curves.write_profile_curve_to_platform(active, &mut device)?;
|
||||||
|
ctrl.config.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
use log::warn;
|
|
||||||
use rog_profiles::fan_curve_set::CurveData;
|
|
||||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
|
||||||
use rog_profiles::Profile;
|
|
||||||
use zbus::Connection;
|
|
||||||
use zbus::SignalContext;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use zbus::{dbus_interface, fdo::Error};
|
|
||||||
|
|
||||||
use super::controller::CtrlPlatformProfile;
|
|
||||||
|
|
||||||
static UNSUPPORTED_MSG: &str =
|
|
||||||
"Fan curves are not supported on this laptop or you require a patched kernel";
|
|
||||||
|
|
||||||
pub struct ProfileZbus {
|
|
||||||
inner: Arc<Mutex<CtrlPlatformProfile>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProfileZbus {
|
|
||||||
pub fn new(inner: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl ProfileZbus {
|
|
||||||
/// Fetch profile names
|
|
||||||
fn profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
|
||||||
if let Ok(profiles) = Profile::get_profile_names() {
|
|
||||||
return Ok(profiles);
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get all profile details".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
|
||||||
/// If fan-curves are supported will also activate a fan curve for profile.
|
|
||||||
async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) {
|
|
||||||
let mut profile = None;
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.set_next_profile()
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
ctrl.save_config();
|
|
||||||
profile = Some(ctrl.config.active_profile);
|
|
||||||
}
|
|
||||||
if let Some(profile) = profile {
|
|
||||||
Self::notify_profile(&ctxt, profile).await.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile name
|
|
||||||
fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
return Ok(ctrl.config.active_profile);
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get active profile name".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set this platform_profile name as active
|
|
||||||
async fn set_active_profile(
|
|
||||||
&self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
profile: Profile,
|
|
||||||
) {
|
|
||||||
let mut tmp = None;
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
// Read first just incase the user has modified the config before calling this
|
|
||||||
ctrl.config.read();
|
|
||||||
Profile::set_profile(profile)
|
|
||||||
.map_err(|e| warn!("set_profile, {}", e))
|
|
||||||
.ok();
|
|
||||||
ctrl.config.active_profile = profile;
|
|
||||||
ctrl.write_profile_curve_to_platform()
|
|
||||||
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
ctrl.save_config();
|
|
||||||
tmp = Some(ctrl.config.active_profile);
|
|
||||||
}
|
|
||||||
if let Some(profile) = tmp {
|
|
||||||
Self::notify_profile(&ctxt, profile).await.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a list of profiles that have fan-curves enabled.
|
|
||||||
fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
if let Some(curves) = &ctrl.config.fan_curves {
|
|
||||||
return Ok(curves.get_enabled_curve_profiles().to_vec());
|
|
||||||
}
|
|
||||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get enabled fan curve names".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
|
|
||||||
/// same profile mode
|
|
||||||
fn set_fan_curve_enabled(&mut self, profile: Profile, enabled: bool) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
return if let Some(curves) = &mut ctrl.config.fan_curves {
|
|
||||||
curves.set_profile_curve_enabled(profile, enabled);
|
|
||||||
|
|
||||||
ctrl.write_profile_curve_to_platform()
|
|
||||||
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
ctrl.save_config();
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get enabled fan curve names".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the fan-curve data for the currently active Profile
|
|
||||||
fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
if let Some(curves) = &ctrl.config.fan_curves {
|
|
||||||
let curve = curves.get_fan_curves_for(profile);
|
|
||||||
return Ok(curve.clone());
|
|
||||||
}
|
|
||||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
|
||||||
}
|
|
||||||
Err(Error::Failed("Failed to get fan curve data".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the fan curve for the specified profile.
|
|
||||||
/// Will also activate the fan curve if the user is in the same mode.
|
|
||||||
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
if let Some(curves) = &mut ctrl.config.fan_curves {
|
|
||||||
curves
|
|
||||||
.save_fan_curve(curve, profile)
|
|
||||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
|
||||||
} else {
|
|
||||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
|
||||||
}
|
|
||||||
ctrl.write_profile_curve_to_platform()
|
|
||||||
.map_err(|e| warn!("Profile::set_profile, {}", e))
|
|
||||||
.ok();
|
|
||||||
ctrl.save_config();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
/// only for the currently active profile.
|
|
||||||
fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
ctrl.set_active_curve_to_defaults()
|
|
||||||
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
|
|
||||||
.ok();
|
|
||||||
ctrl.save_config();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
/// only for the currently active profile.
|
|
||||||
fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
ctrl.config.read();
|
|
||||||
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
|
|
||||||
|
|
||||||
Profile::set_profile(profile)
|
|
||||||
.map_err(|e| warn!("set_profile, {}", e))
|
|
||||||
.ok();
|
|
||||||
ctrl.set_active_curve_to_defaults()
|
|
||||||
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
Profile::set_profile(active)
|
|
||||||
.map_err(|e| warn!("set_profile, {}", e))
|
|
||||||
.ok();
|
|
||||||
ctrl.save_config();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
async fn notify_profile(signal_ctxt: &SignalContext<'_>, profile: Profile) -> zbus::Result<()> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl crate::ZbusAdd for ProfileZbus {
|
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Profile", server).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ use zbus::Connection;
|
|||||||
use zvariant::Type;
|
use zvariant::Type;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ctrl_anime::CtrlAnime, ctrl_aura::controller::CtrlKbdLed, ctrl_platform::CtrlRogBios,
|
ctrl_anime::CtrlAnime, ctrl_aura::controller::CtrlKbdLed, ctrl_platform::CtrlPlatform,
|
||||||
ctrl_power::CtrlPower, ctrl_profiles::controller::CtrlPlatformProfile, GetSupported,
|
ctrl_power::CtrlPower, ctrl_profiles::controller::CtrlPlatformProfile, GetSupported,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ impl SupportedFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl crate::ZbusAdd for SupportedFunctions {
|
impl crate::ZbusRun for SupportedFunctions {
|
||||||
async fn add_to_server(self, server: &mut Connection) {
|
async fn add_to_server(self, server: &mut Connection) {
|
||||||
Self::add_to_server_helper(self, "/org/asuslinux/Supported", server).await;
|
Self::add_to_server_helper(self, "/org/asuslinux/Supported", server).await;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ impl GetSupported for SupportedFunctions {
|
|||||||
keyboard_led: CtrlKbdLed::get_supported(),
|
keyboard_led: CtrlKbdLed::get_supported(),
|
||||||
charge_ctrl: CtrlPower::get_supported(),
|
charge_ctrl: CtrlPower::get_supported(),
|
||||||
platform_profile: CtrlPlatformProfile::get_supported(),
|
platform_profile: CtrlPlatformProfile::get_supported(),
|
||||||
rog_bios_ctrl: CtrlRogBios::get_supported(),
|
rog_bios_ctrl: CtrlPlatform::get_supported(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,35 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use ::zbus::export::futures_util::lock::Mutex;
|
||||||
use ::zbus::Connection;
|
use ::zbus::Connection;
|
||||||
use daemon::ctrl_profiles::controller::CtrlProfileTask;
|
use daemon::ctrl_anime::CtrlAnime;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use smol::Executor;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
use daemon::ctrl_anime::config::AnimeConfig;
|
use daemon::ctrl_anime::{config::AnimeConfig, trait_impls::CtrlAnimeZbus};
|
||||||
use daemon::ctrl_anime::zbus::CtrlAnimeZbus;
|
use daemon::ctrl_aura::{config::AuraConfig, controller::CtrlKbdLed, trait_impls::CtrlKbdLedZbus};
|
||||||
use daemon::ctrl_anime::*;
|
use daemon::ctrl_platform::CtrlPlatform;
|
||||||
use daemon::ctrl_aura::config::AuraConfig;
|
|
||||||
use daemon::ctrl_aura::controller::{
|
|
||||||
CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus,
|
|
||||||
};
|
|
||||||
use daemon::ctrl_platform::CtrlRogBios;
|
|
||||||
use daemon::ctrl_power::CtrlPower;
|
use daemon::ctrl_power::CtrlPower;
|
||||||
use daemon::ctrl_profiles::config::ProfileConfig;
|
use daemon::ctrl_profiles::{
|
||||||
|
config::ProfileConfig, controller::CtrlPlatformProfile, trait_impls::ProfileZbus,
|
||||||
|
};
|
||||||
|
use daemon::laptops::LaptopLedData;
|
||||||
use daemon::{
|
use daemon::{
|
||||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||||
};
|
};
|
||||||
use daemon::{
|
use daemon::{CtrlTask, Reloadable, ZbusRun};
|
||||||
ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus},
|
|
||||||
laptops::LaptopLedData,
|
|
||||||
};
|
|
||||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
|
||||||
use rog_dbus::DBUS_NAME;
|
use rog_dbus::DBUS_NAME;
|
||||||
use rog_profiles::Profile;
|
use rog_profiles::Profile;
|
||||||
|
|
||||||
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
|
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
|
||||||
|
|
||||||
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
logger
|
logger
|
||||||
.target(env_logger::Target::Stdout)
|
.target(env_logger::Target::Stdout)
|
||||||
@@ -61,14 +58,12 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
info!(" rog-profiles v{}", rog_profiles::VERSION);
|
info!(" rog-profiles v{}", rog_profiles::VERSION);
|
||||||
info!("rog-platform v{}", rog_platform::VERSION);
|
info!("rog-platform v{}", rog_platform::VERSION);
|
||||||
|
|
||||||
let mut executor = Executor::new();
|
start_daemon().await?;
|
||||||
|
|
||||||
smol::block_on(start_daemon(&mut executor))?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The actual main loop for the daemon
|
/// The actual main loop for the daemon
|
||||||
async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>> {
|
async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||||
let supported = SupportedFunctions::get_supported();
|
let supported = SupportedFunctions::get_supported();
|
||||||
print_board_info();
|
print_board_info();
|
||||||
println!("{}", serde_json::to_string_pretty(&supported)?);
|
println!("{}", serde_json::to_string_pretty(&supported)?);
|
||||||
@@ -81,77 +76,46 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
|
|||||||
|
|
||||||
supported.add_to_server(&mut connection).await;
|
supported.add_to_server(&mut connection).await;
|
||||||
|
|
||||||
match CtrlRogBios::new(config.clone()) {
|
match CtrlPlatform::new(config.clone()) {
|
||||||
Ok(mut ctrl) => {
|
Ok(ctrl) => {
|
||||||
// Do a reload of any settings
|
start_tasks(ctrl, &mut connection).await?;
|
||||||
ctrl.reload()
|
|
||||||
.unwrap_or_else(|err| warn!("CtrlRogBios: {}", err));
|
|
||||||
// Then register to dbus server
|
|
||||||
ctrl.add_to_server(&mut connection).await;
|
|
||||||
|
|
||||||
let task = CtrlRogBios::new(config.clone())?;
|
|
||||||
task.create_tasks(executor).await.ok();
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("rog_bios_control: {}", err);
|
error!("CtrlPlatform: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match CtrlPower::new(config.clone()) {
|
match CtrlPower::new(config.clone()) {
|
||||||
Ok(mut ctrl) => {
|
Ok(ctrl) => {
|
||||||
// Do a reload of any settings
|
start_tasks(ctrl, &mut connection).await?;
|
||||||
ctrl.reload()
|
|
||||||
.unwrap_or_else(|err| warn!("CtrlPower: {}", err));
|
|
||||||
// Then register to dbus server
|
|
||||||
ctrl.add_to_server(&mut connection).await;
|
|
||||||
|
|
||||||
let task = CtrlPower::new(config)?;
|
|
||||||
task.create_tasks(executor).await.ok();
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("charge_control: {}", err);
|
error!("CtrlPower: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Profile::is_platform_profile_supported() {
|
if Profile::is_platform_profile_supported() {
|
||||||
let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into());
|
let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into());
|
||||||
match CtrlPlatformProfile::new(profile_config) {
|
match CtrlPlatformProfile::new(profile_config) {
|
||||||
Ok(mut ctrl) => {
|
Ok(ctrl) => {
|
||||||
ctrl.reload()
|
let zbus = ProfileZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
start_tasks(zbus, &mut connection).await?;
|
||||||
|
|
||||||
let tmp = Arc::new(Mutex::new(ctrl));
|
|
||||||
let task = CtrlProfileTask::new(tmp.clone());
|
|
||||||
task.create_tasks(executor).await.ok();
|
|
||||||
|
|
||||||
let task = ProfileZbus::new(tmp.clone());
|
|
||||||
task.add_to_server(&mut connection).await;
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Profile control: {}", err);
|
error!("Profile control: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!("platform_profile support not found. This requires kernel 5.15.x or the patch applied: https://lkml.org/lkml/2021/8/18/1022");
|
warn!("platform_profile support not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
match CtrlAnime::new(AnimeConfig::load()) {
|
match CtrlAnime::new(AnimeConfig::load()) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let inner = Arc::new(Mutex::new(ctrl));
|
let zbus = CtrlAnimeZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
|
start_tasks(zbus, &mut connection).await?;
|
||||||
let mut reload = CtrlAnimeReloader(inner.clone());
|
|
||||||
reload
|
|
||||||
.reload()
|
|
||||||
.unwrap_or_else(|err| warn!("AniMe: {}", err));
|
|
||||||
|
|
||||||
let zbus = CtrlAnimeZbus(inner.clone());
|
|
||||||
zbus.add_to_server(&mut connection).await;
|
|
||||||
|
|
||||||
let task = CtrlAnimeTask::new(inner).await;
|
|
||||||
task.create_tasks(executor).await.ok();
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("AniMe control: {}", err);
|
info!("AniMe control: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,19 +123,8 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
|
|||||||
let aura_config = AuraConfig::load(&laptop);
|
let aura_config = AuraConfig::load(&laptop);
|
||||||
match CtrlKbdLed::new(laptop, aura_config) {
|
match CtrlKbdLed::new(laptop, aura_config) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let inner = Arc::new(Mutex::new(ctrl));
|
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
|
||||||
|
start_tasks(zbus, &mut connection).await?;
|
||||||
let mut reload = CtrlKbdLedReloader(inner.clone());
|
|
||||||
reload
|
|
||||||
.reload()
|
|
||||||
.unwrap_or_else(|err| warn!("Keyboard LED control: {}", err));
|
|
||||||
|
|
||||||
CtrlKbdLedZbus::new(inner.clone())
|
|
||||||
.add_to_server(&mut connection)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let task = CtrlKbdLedTask::new(inner);
|
|
||||||
task.create_tasks(executor).await.ok();
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Keyboard control: {}", err);
|
error!("Keyboard control: {}", err);
|
||||||
@@ -180,7 +133,26 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
|
|||||||
|
|
||||||
// Request dbus name after finishing initalizing all functions
|
// Request dbus name after finishing initalizing all functions
|
||||||
connection.request_name(DBUS_NAME).await?;
|
connection.request_name(DBUS_NAME).await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
smol::block_on(executor.tick());
|
// This is just a blocker to idle and ensure the reator reacts
|
||||||
|
sleep(Duration::from_millis(1000)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn start_tasks<T>(mut zbus: T, connection: &mut Connection) -> Result<(), Box<dyn Error>>
|
||||||
|
where
|
||||||
|
T: ZbusRun + Reloadable + CtrlTask + Clone,
|
||||||
|
{
|
||||||
|
let task = zbus.clone();
|
||||||
|
|
||||||
|
zbus.reload()
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| warn!("Controller error: {}", err));
|
||||||
|
zbus.add_to_server(connection).await;
|
||||||
|
|
||||||
|
task.create_tasks(CtrlKbdLedZbus::signal_context(&connection)?)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,25 +19,73 @@ pub mod ctrl_supported;
|
|||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use config::Config;
|
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use logind_zbus::manager::ManagerProxy;
|
use logind_zbus::manager::ManagerProxy;
|
||||||
use smol::{stream::StreamExt, Executor, Timer};
|
use zbus::{export::futures_util::StreamExt, Connection, SignalContext};
|
||||||
use zbus::Connection;
|
|
||||||
use zvariant::ObjectPath;
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
|
/// This macro adds a function which spawns an `inotify` task on the passed in `Executor`.
|
||||||
|
///
|
||||||
|
/// The generated function is `watch_<name>()`. Self requires the following methods to be available:
|
||||||
|
/// - `<name>() -> SomeValue`, functionally is a getter, but is allowed to have side effects.
|
||||||
|
/// - `notify_<name>(SignalContext, SomeValue)`
|
||||||
|
///
|
||||||
|
/// In most cases if `SomeValue` is stored in a config then `<name>()` getter is expected to update it.
|
||||||
|
/// The getter should *never* write back to the path or attribute that is being watched or an
|
||||||
|
/// infinite loop will occur.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// impl CtrlRogBios {
|
||||||
|
/// task_watch_item!(panel_od platform);
|
||||||
|
/// task_watch_item!(gpu_mux_mode platform);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! task_watch_item {
|
||||||
|
($name:ident $self_inner:ident) => {
|
||||||
|
concat_idents::concat_idents!(fn_name = watch_, $name {
|
||||||
|
async fn fn_name(
|
||||||
|
&self,
|
||||||
|
signal_ctxt: SignalContext<'static>,
|
||||||
|
) -> Result<(), RogError> {
|
||||||
|
use zbus::export::futures_util::StreamExt;
|
||||||
|
|
||||||
|
let ctrl = self.clone();
|
||||||
|
concat_idents::concat_idents!(watch_fn = monitor_, $name {
|
||||||
|
match self.$self_inner.watch_fn() {
|
||||||
|
Ok(mut watch) => {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buffer = [0; 32];
|
||||||
|
watch.event_stream(&mut buffer).unwrap().for_each(|_| async {
|
||||||
|
let value = ctrl.$name();
|
||||||
|
concat_idents::concat_idents!(notif_fn = notify_, $name {
|
||||||
|
Self::notif_fn(&signal_ctxt, value).await.unwrap();
|
||||||
|
});
|
||||||
|
}).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => info!("inotify watch failed: {}. You can ignore this if your device does not support the feature", e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
pub trait Reloadable {
|
pub trait Reloadable {
|
||||||
fn reload(&mut self) -> Result<(), RogError>;
|
async fn reload(&mut self) -> Result<(), RogError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ZbusAdd {
|
pub trait ZbusRun {
|
||||||
async fn add_to_server(self, server: &mut Connection);
|
async fn add_to_server(self, server: &mut Connection);
|
||||||
|
|
||||||
async fn add_to_server_helper(
|
async fn add_to_server_helper(
|
||||||
@@ -60,29 +108,33 @@ pub trait ZbusAdd {
|
|||||||
/// Set up a task to run on the async executor
|
/// Set up a task to run on the async executor
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait CtrlTask {
|
pub trait CtrlTask {
|
||||||
/// Implement to set up various tasks that may be required, using the `Executor`.
|
fn zbus_path() -> &'static str;
|
||||||
/// No blocking loops are allowed, or they must be run on a separate thread.
|
|
||||||
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError>;
|
|
||||||
|
|
||||||
/// Create a timed repeating task
|
fn signal_context(connection: &Connection) -> Result<SignalContext<'static>, zbus::Error> {
|
||||||
async fn repeating_task(
|
SignalContext::new(connection, Self::zbus_path())
|
||||||
&self,
|
|
||||||
millis: u64,
|
|
||||||
executor: &mut Executor,
|
|
||||||
mut task: impl FnMut() + Send + 'static,
|
|
||||||
) {
|
|
||||||
let timer = Timer::interval(Duration::from_millis(millis));
|
|
||||||
executor
|
|
||||||
.spawn(async move {
|
|
||||||
timer.for_each(|_| task()).await;
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implement to set up various tasks that may be required, using the `Executor`.
|
||||||
|
/// No blocking loops are allowed, or they must be run on a separate thread.
|
||||||
|
async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>;
|
||||||
|
|
||||||
|
// /// Create a timed repeating task
|
||||||
|
// async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + 'static) {
|
||||||
|
// use std::time::Duration;
|
||||||
|
// use tokio::time;
|
||||||
|
// let mut timer = time::interval(Duration::from_millis(millis));
|
||||||
|
// tokio::spawn(async move {
|
||||||
|
// timer.tick().await;
|
||||||
|
// task();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
/// Free helper method to create tasks to run on: sleep, wake, shutdown, boot
|
/// Free helper method to create tasks to run on: sleep, wake, shutdown, boot
|
||||||
|
///
|
||||||
|
/// The closures can potentially block, so execution time should be the minimal possible
|
||||||
|
/// such as save a variable.
|
||||||
async fn create_sys_event_tasks(
|
async fn create_sys_event_tasks(
|
||||||
&self,
|
&self,
|
||||||
executor: &mut Executor,
|
|
||||||
mut on_sleep: impl FnMut() + Send + 'static,
|
mut on_sleep: impl FnMut() + Send + 'static,
|
||||||
mut on_wake: impl FnMut() + Send + 'static,
|
mut on_wake: impl FnMut() + Send + 'static,
|
||||||
mut on_shutdown: impl FnMut() + Send + 'static,
|
mut on_shutdown: impl FnMut() + Send + 'static,
|
||||||
@@ -96,54 +148,40 @@ pub trait CtrlTask {
|
|||||||
.await
|
.await
|
||||||
.expect("Controller could not create ManagerProxy");
|
.expect("Controller could not create ManagerProxy");
|
||||||
|
|
||||||
executor
|
tokio::spawn(async move {
|
||||||
.spawn(async move {
|
if let Ok(mut notif) = manager.receive_prepare_for_sleep().await {
|
||||||
if let Ok(notif) = manager.receive_prepare_for_sleep().await {
|
while let Some(event) = notif.next().await {
|
||||||
notif
|
if let Ok(args) = event.args() {
|
||||||
.for_each(|event| {
|
if args.start {
|
||||||
if let Ok(args) = event.args() {
|
on_sleep();
|
||||||
if args.start {
|
} else if !args.start() {
|
||||||
on_sleep();
|
on_wake();
|
||||||
} else if !args.start() {
|
}
|
||||||
on_wake();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.detach();
|
});
|
||||||
|
|
||||||
let manager = ManagerProxy::new(&connection)
|
let manager = ManagerProxy::new(&connection)
|
||||||
.await
|
.await
|
||||||
.expect("Controller could not create ManagerProxy");
|
.expect("Controller could not create ManagerProxy");
|
||||||
|
|
||||||
executor
|
tokio::spawn(async move {
|
||||||
.spawn(async move {
|
if let Ok(mut notif) = manager.receive_prepare_for_shutdown().await {
|
||||||
if let Ok(notif) = manager.receive_prepare_for_shutdown().await {
|
while let Some(event) = notif.next().await {
|
||||||
notif
|
if let Ok(args) = event.args() {
|
||||||
.for_each(|event| {
|
if args.start {
|
||||||
if let Ok(args) = event.args() {
|
on_shutdown();
|
||||||
if args.start {
|
} else if !args.start() {
|
||||||
on_shutdown();
|
on_boot();
|
||||||
} else if !args.start() {
|
}
|
||||||
on_boot();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CtrlTaskComplex {
|
|
||||||
type A;
|
|
||||||
|
|
||||||
fn do_task(&mut self, config: &mut Config, event: Self::A);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait GetSupported {
|
pub trait GetSupported {
|
||||||
type A;
|
type A;
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ per_key = false
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus M16"
|
prod_family = "ROG Zephyrus M16"
|
||||||
board_names = ["GU603HR", "GU603HE", "GU603HM"]
|
board_names = ["GU603Z", "GU603H"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
multizone = []
|
multizone = []
|
||||||
per_key = false
|
per_key = false
|
||||||
|
|||||||
@@ -18,81 +18,112 @@ Then for each trait that is required a new struct is required that can have the
|
|||||||
|
|
||||||
Main controller:
|
Main controller:
|
||||||
|
|
||||||
|
For a very simple controller that doesn't need exclusive access you can clone across threads
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CtrlAnime {
|
||||||
|
<things the controller requires>
|
||||||
|
config: Arc<Mutex<Config>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the task trait used for such things as file watches, or logind
|
||||||
|
// notifications (boot/suspend/shutdown etc)
|
||||||
|
impl crate::CtrlTask for CtrlAnime {}
|
||||||
|
|
||||||
|
// The trait to easily add the controller to Zbus to enable the zbus derived functions
|
||||||
|
// to be polled, run, react etc.
|
||||||
|
impl crate::ZbusAdd for CtrlAnime {}
|
||||||
|
|
||||||
|
impl CtrlAnime {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise, you will need to share the controller via mutex
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub struct CtrlAnime {
|
pub struct CtrlAnime {
|
||||||
<things the controller requires>
|
<things the controller requires>
|
||||||
}
|
}
|
||||||
|
// Like this
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CtrlAnimeTask(Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
impl CtrlAnime {
|
#[derive(Clone)]
|
||||||
<functions the controller exposes>
|
pub struct CtrlAnimeZbus(Arc<Mutex<CtrlAnime>>);
|
||||||
}
|
|
||||||
|
impl CtrlAnime {}
|
||||||
```
|
```
|
||||||
|
|
||||||
The task trait. There are three ways to implement this:
|
The task trait:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
// Mutex should always be async mutex
|
||||||
pub struct CtrlAnimeTask(Arc<Mutex<CtrlAnime>>);
|
pub struct CtrlAnimeTask(Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
impl crate::CtrlTask for CtrlAnimeTask {
|
impl crate::CtrlTask for CtrlAnimeTask {
|
||||||
// This will run once only
|
// This will run once only
|
||||||
fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
if let Ok(lock) = self.inner.try_lock() {
|
let lock self.inner.lock().await;
|
||||||
<some action>
|
<some action>
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will run until the notification stream closes (which in most cases will be never)
|
// This will run until the notification stream closes (which in most cases will be never)
|
||||||
fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||||
let connection = Connection::system().await.unwrap();
|
let inner1 = self.inner.clone();
|
||||||
let manager = ManagerProxy::new(&connection).await.unwrap();
|
let inner2 = self.inner.clone();
|
||||||
|
let inner3 = self.inner.clone();
|
||||||
let inner = self.inner.clone();
|
let inner4 = self.inner.clone();
|
||||||
executor
|
// This is a free method on CtrlTask trait
|
||||||
.spawn(async move {
|
self.create_sys_event_tasks(
|
||||||
// A notification from logind dbus interface
|
// Loop is required to try an attempt to get the mutex *without* blocking
|
||||||
if let Ok(p) = manager.receive_prepare_for_sleep().await {
|
// other threads - it is possible to end up with deadlocks otherwise.
|
||||||
// A stream that will continuously output events
|
move || loop {
|
||||||
p.for_each(|_| {
|
if let Some(lock) = inner1.try_lock() {
|
||||||
if let Ok(lock) = inner.try_lock() {
|
run_action(true, lock, inner1.clone());
|
||||||
// Do stuff here
|
break;
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.detach();
|
move || loop {
|
||||||
}
|
if let Some(lock) = inner2.try_lock() {
|
||||||
|
run_action(false, lock, inner2.clone());
|
||||||
// This task will run every 500 milliseconds
|
break;
|
||||||
fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
|
}
|
||||||
let inner = self.inner.clone();
|
},
|
||||||
// This is a provided free trait to help set up a repeating task
|
move || loop {
|
||||||
self.repeating_task(500, executor, move || {
|
if let Some(lock) = inner3.try_lock() {
|
||||||
if let Ok(lock) = inner.try_lock() {
|
run_action(true, lock, inner3.clone());
|
||||||
// Do stuff here
|
break;
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
move || loop {
|
||||||
|
if let Some(lock) = inner4.try_lock() {
|
||||||
|
run_action(false, lock, inner4.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The reloader trait
|
The reloader trait
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub struct CtrlAnimeReloader(Arc<Mutex<CtrlAnime>>);
|
pub struct CtrlAnimeReloader(Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlAnimeReloader {
|
impl crate::Reloadable for CtrlAnimeReloader {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
if let Ok(lock) = self.inner.try_lock() {
|
let lock = self.inner.lock().await;
|
||||||
<some action>
|
<some action>
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The Zbus requirements:
|
The Zbus requirements:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub struct CtrlAnimeZbus(Arc<Mutex<CtrlAnime>>);
|
pub struct CtrlAnimeZbus(Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
@@ -106,10 +137,9 @@ impl crate::ZbusAdd for CtrlAnimeZbus {
|
|||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl CtrlAnimeZbus {
|
impl CtrlAnimeZbus {
|
||||||
fn <zbus method>() {
|
async fn <zbus method>() {
|
||||||
if let Ok(lock) = self.inner.try_lock() {
|
let lock = self.inner.lock().await;
|
||||||
<some action>
|
<some action>
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
start_closed = false;
|
start_closed = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dbg!("asda");
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ impl Bios {
|
|||||||
pub fn gpu_mux_mode(&self) -> Result<i16> {
|
pub fn gpu_mux_mode(&self) -> Result<i16> {
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
pub fn panel_overdrive(&self) -> Result<i16> {
|
pub fn panel_od(&self) -> Result<i16> {
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
pub fn set_post_boot_sound(&self, _b: bool) -> Result<()> {
|
pub fn set_post_boot_sound(&self, _b: bool) -> Result<()> {
|
||||||
@@ -74,7 +74,7 @@ impl Bios {
|
|||||||
pub fn set_gpu_mux_mode(&self, _b: bool) -> Result<()> {
|
pub fn set_gpu_mux_mode(&self, _b: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn set_panel_overdrive(&self, _b: bool) -> Result<()> {
|
pub fn set_panel_od(&self, _b: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ impl Supported {
|
|||||||
rog_bios_ctrl: RogBiosSupportedFunctions {
|
rog_bios_ctrl: RogBiosSupportedFunctions {
|
||||||
post_sound: true,
|
post_sound: true,
|
||||||
dedicated_gfx: true,
|
dedicated_gfx: true,
|
||||||
panel_overdrive: true,
|
panel_od: true,
|
||||||
dgpu_disable: true,
|
dgpu_disable: true,
|
||||||
egpu_enable: true,
|
egpu_enable: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
use notify_rust::{Hint, Notification, NotificationHandle};
|
||||||
use rog_aura::AuraEffect;
|
use rog_aura::AuraEffect;
|
||||||
use rog_dbus::{
|
use rog_dbus::{
|
||||||
zbus_anime::AnimeProxy, zbus_charge::ChargeProxy, zbus_led::LedProxy,
|
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
||||||
zbus_platform::RogBiosProxy, zbus_profile::ProfileProxy,
|
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
||||||
};
|
};
|
||||||
use rog_profiles::Profile;
|
use rog_profiles::Profile;
|
||||||
use smol::{future, Executor};
|
use smol::{future, Executor};
|
||||||
@@ -70,7 +70,7 @@ pub fn start_notifications(
|
|||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
if notifs_enabled1.load(Ordering::SeqCst) {
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
if let Ok(ref mut lock) = last_notif.try_lock() {
|
||||||
notify!(do_post_sound_notif, lock, &out.sound());
|
notify!(do_post_sound_notif, lock, &out.on());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bios_notified1.store(true, Ordering::SeqCst);
|
bios_notified1.store(true, Ordering::SeqCst);
|
||||||
@@ -86,7 +86,7 @@ pub fn start_notifications(
|
|||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
let proxy = RogBiosProxy::new(&conn).await.unwrap();
|
let proxy = RogBiosProxy::new(&conn).await.unwrap();
|
||||||
if let Ok(p) = proxy.receive_notify_panel_overdrive().await {
|
if let Ok(p) = proxy.receive_notify_panel_od().await {
|
||||||
p.for_each(|_| {
|
p.for_each(|_| {
|
||||||
bios_notified.store(true, Ordering::SeqCst);
|
bios_notified.store(true, Ordering::SeqCst);
|
||||||
future::ready(())
|
future::ready(())
|
||||||
@@ -102,8 +102,8 @@ pub fn start_notifications(
|
|||||||
executor
|
executor
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
let proxy = ChargeProxy::new(&conn).await.unwrap();
|
let proxy = PowerProxy::new(&conn).await.unwrap();
|
||||||
if let Ok(p) = proxy.receive_notify_charge().await {
|
if let Ok(p) = proxy.receive_notify_charge_control_end_threshold().await {
|
||||||
p.for_each(|e| {
|
p.for_each(|e| {
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
if notifs_enabled1.load(Ordering::SeqCst) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ impl BiosState {
|
|||||||
GpuMode::NotSupported
|
GpuMode::NotSupported
|
||||||
},
|
},
|
||||||
panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive {
|
panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive {
|
||||||
dbus.proxies().rog_bios().panel_overdrive()?
|
dbus.proxies().rog_bios().panel_od()?
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
@@ -258,7 +258,7 @@ pub struct PageDataStates {
|
|||||||
pub anime: AnimeState,
|
pub anime: AnimeState,
|
||||||
pub profiles: ProfilesState,
|
pub profiles: ProfilesState,
|
||||||
pub fan_curves: FanCurvesState,
|
pub fan_curves: FanCurvesState,
|
||||||
pub charge_limit: i16,
|
pub charge_limit: u8,
|
||||||
pub error: Option<String>,
|
pub error: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ impl PageDataStates {
|
|||||||
keyboard_layout,
|
keyboard_layout,
|
||||||
notifs_enabled,
|
notifs_enabled,
|
||||||
was_notified: charge_notified,
|
was_notified: charge_notified,
|
||||||
charge_limit: dbus.proxies().charge().limit()?,
|
charge_limit: dbus.proxies().charge().charge_control_end_threshold()?,
|
||||||
bios: BiosState::new(bios_notified, supported, dbus)?,
|
bios: BiosState::new(bios_notified, supported, dbus)?,
|
||||||
aura: AuraState::new(aura_notified, supported, dbus)?,
|
aura: AuraState::new(aura_notified, supported, dbus)?,
|
||||||
anime: AnimeState::new(anime_notified, supported, dbus)?,
|
anime: AnimeState::new(anime_notified, supported, dbus)?,
|
||||||
@@ -296,7 +296,7 @@ impl PageDataStates {
|
|||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let mut notified = false;
|
let mut notified = false;
|
||||||
if self.was_notified.load(Ordering::SeqCst) {
|
if self.was_notified.load(Ordering::SeqCst) {
|
||||||
self.charge_limit = dbus.proxies().charge().limit()?;
|
self.charge_limit = dbus.proxies().charge().charge_control_end_threshold()?;
|
||||||
self.was_notified.store(false, Ordering::SeqCst);
|
self.was_notified.store(false, Ordering::SeqCst);
|
||||||
notified = true;
|
notified = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ impl eframe::App for AppErrorShow {
|
|||||||
.add(Button::new(RichText::new("Okay").size(20.0)))
|
.add(Button::new(RichText::new("Okay").size(20.0)))
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
frame.quit();
|
frame.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub fn rog_bios_group(
|
|||||||
if ui.add(slider).drag_released() {
|
if ui.add(slider).drag_released() {
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.charge()
|
.charge()
|
||||||
.set_limit(states.charge_limit as u8)
|
.set_charge_control_end_threshold(states.charge_limit as u8)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
states.error = Some(err.to_string());
|
states.error = Some(err.to_string());
|
||||||
})
|
})
|
||||||
@@ -82,7 +82,7 @@ pub fn rog_bios_group(
|
|||||||
{
|
{
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.rog_bios()
|
.rog_bios()
|
||||||
.set_panel_overdrive(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());
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl<'a> RogApp<'a> {
|
|||||||
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.quit();
|
frame.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
|||||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||||
|
|
||||||
pub mod zbus_anime;
|
pub mod zbus_anime;
|
||||||
pub mod zbus_charge;
|
|
||||||
pub mod zbus_led;
|
pub mod zbus_led;
|
||||||
pub mod zbus_platform;
|
pub mod zbus_platform;
|
||||||
|
pub mod zbus_power;
|
||||||
pub mod zbus_profile;
|
pub mod zbus_profile;
|
||||||
pub mod zbus_supported;
|
pub mod zbus_supported;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|||||||
|
|
||||||
pub struct DbusProxiesBlocking<'a> {
|
pub struct DbusProxiesBlocking<'a> {
|
||||||
anime: zbus_anime::AnimeProxyBlocking<'a>,
|
anime: zbus_anime::AnimeProxyBlocking<'a>,
|
||||||
charge: zbus_charge::ChargeProxyBlocking<'a>,
|
charge: zbus_power::PowerProxyBlocking<'a>,
|
||||||
led: zbus_led::LedProxyBlocking<'a>,
|
led: zbus_led::LedProxyBlocking<'a>,
|
||||||
profile: zbus_profile::ProfileProxyBlocking<'a>,
|
profile: zbus_profile::ProfileProxyBlocking<'a>,
|
||||||
rog_bios: zbus_platform::RogBiosProxyBlocking<'a>,
|
rog_bios: zbus_platform::RogBiosProxyBlocking<'a>,
|
||||||
@@ -35,7 +35,7 @@ impl<'a> DbusProxiesBlocking<'a> {
|
|||||||
DbusProxiesBlocking {
|
DbusProxiesBlocking {
|
||||||
anime: zbus_anime::AnimeProxyBlocking::new(&conn)?,
|
anime: zbus_anime::AnimeProxyBlocking::new(&conn)?,
|
||||||
led: zbus_led::LedProxyBlocking::new(&conn)?,
|
led: zbus_led::LedProxyBlocking::new(&conn)?,
|
||||||
charge: zbus_charge::ChargeProxyBlocking::new(&conn)?,
|
charge: zbus_power::PowerProxyBlocking::new(&conn)?,
|
||||||
profile: zbus_profile::ProfileProxyBlocking::new(&conn)?,
|
profile: zbus_profile::ProfileProxyBlocking::new(&conn)?,
|
||||||
rog_bios: zbus_platform::RogBiosProxyBlocking::new(&conn)?,
|
rog_bios: zbus_platform::RogBiosProxyBlocking::new(&conn)?,
|
||||||
supported: zbus_supported::SupportedProxyBlocking::new(&conn)?,
|
supported: zbus_supported::SupportedProxyBlocking::new(&conn)?,
|
||||||
@@ -48,7 +48,7 @@ impl<'a> DbusProxiesBlocking<'a> {
|
|||||||
&self.anime
|
&self.anime
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn charge(&self) -> &zbus_charge::ChargeProxyBlocking<'a> {
|
pub fn charge(&self) -> &zbus_power::PowerProxyBlocking<'a> {
|
||||||
&self.charge
|
&self.charge
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ impl<'a> RogDbusClientBlocking<'a> {
|
|||||||
|
|
||||||
pub struct DbusProxies<'a> {
|
pub struct DbusProxies<'a> {
|
||||||
anime: zbus_anime::AnimeProxy<'a>,
|
anime: zbus_anime::AnimeProxy<'a>,
|
||||||
charge: zbus_charge::ChargeProxy<'a>,
|
charge: zbus_power::PowerProxy<'a>,
|
||||||
led: zbus_led::LedProxy<'a>,
|
led: zbus_led::LedProxy<'a>,
|
||||||
profile: zbus_profile::ProfileProxy<'a>,
|
profile: zbus_profile::ProfileProxy<'a>,
|
||||||
rog_bios: zbus_platform::RogBiosProxy<'a>,
|
rog_bios: zbus_platform::RogBiosProxy<'a>,
|
||||||
@@ -104,7 +104,7 @@ impl<'a> DbusProxies<'a> {
|
|||||||
DbusProxies {
|
DbusProxies {
|
||||||
anime: zbus_anime::AnimeProxy::new(&conn).await?,
|
anime: zbus_anime::AnimeProxy::new(&conn).await?,
|
||||||
led: zbus_led::LedProxy::new(&conn).await?,
|
led: zbus_led::LedProxy::new(&conn).await?,
|
||||||
charge: zbus_charge::ChargeProxy::new(&conn).await?,
|
charge: zbus_power::PowerProxy::new(&conn).await?,
|
||||||
profile: zbus_profile::ProfileProxy::new(&conn).await?,
|
profile: zbus_profile::ProfileProxy::new(&conn).await?,
|
||||||
rog_bios: zbus_platform::RogBiosProxy::new(&conn).await?,
|
rog_bios: zbus_platform::RogBiosProxy::new(&conn).await?,
|
||||||
supported: zbus_supported::SupportedProxy::new(&conn).await?,
|
supported: zbus_supported::SupportedProxy::new(&conn).await?,
|
||||||
@@ -117,7 +117,7 @@ impl<'a> DbusProxies<'a> {
|
|||||||
&self.anime
|
&self.anime
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn charge(&self) -> &zbus_charge::ChargeProxy<'a> {
|
pub fn charge(&self) -> &zbus_power::PowerProxy<'a> {
|
||||||
&self.charge
|
&self.charge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,33 +27,53 @@ use zbus_macros::dbus_proxy;
|
|||||||
default_path = "/org/asuslinux/Platform"
|
default_path = "/org/asuslinux/Platform"
|
||||||
)]
|
)]
|
||||||
trait RogBios {
|
trait RogBios {
|
||||||
/// DedicatedGraphicMode method
|
/// DgpuDisable method
|
||||||
|
fn dgpu_disable(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
/// EgpuEnable method
|
||||||
|
fn egpu_enable(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
/// GpuMuxMode method
|
||||||
fn gpu_mux_mode(&self) -> zbus::Result<GpuMode>;
|
fn gpu_mux_mode(&self) -> zbus::Result<GpuMode>;
|
||||||
|
|
||||||
|
/// PanelOd method
|
||||||
|
fn panel_od(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
/// PostBootSound method
|
/// PostBootSound method
|
||||||
fn post_boot_sound(&self) -> zbus::Result<i16>;
|
fn post_boot_sound(&self) -> zbus::Result<i16>;
|
||||||
|
|
||||||
/// SetDedicatedGraphicMode method
|
/// SetDgpuDisable method
|
||||||
|
fn set_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetEgpuEnable method
|
||||||
|
fn set_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetGpuMuxMode method
|
||||||
fn set_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
fn set_gpu_mux_mode(&self, mode: GpuMode) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetPanelOd method
|
||||||
|
fn set_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetPostBootSound method
|
/// SetPostBootSound method
|
||||||
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// PanelOverdrive method
|
/// NotifyDgpuDisable signal
|
||||||
fn panel_overdrive(&self) -> zbus::Result<bool>;
|
#[dbus_proxy(signal)]
|
||||||
|
fn notify_dgpu_disable(&self, disable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetPanelOverdrive method
|
/// NotifyEgpuEnable signal
|
||||||
fn set_panel_overdrive(&self, overdrive: bool) -> zbus::Result<()>;
|
#[dbus_proxy(signal)]
|
||||||
|
fn notify_egpu_enable(&self, enable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyDedicatedGraphicMode signal
|
/// NotifyGpuMuxMode signal
|
||||||
#[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
|
||||||
|
#[dbus_proxy(signal)]
|
||||||
|
fn notify_panel_od(&self, overdrive: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyPostBootSound signal
|
/// NotifyPostBootSound signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_post_boot_sound(&self, sound: bool) -> zbus::Result<()>;
|
fn notify_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyPanelOverdrive signal
|
|
||||||
#[dbus_proxy(signal)]
|
|
||||||
fn notify_panel_overdrive(&self, overdrive: bool) -> zbus::Result<()>;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,16 +23,23 @@ use zbus_macros::dbus_proxy;
|
|||||||
|
|
||||||
#[dbus_proxy(
|
#[dbus_proxy(
|
||||||
interface = "org.asuslinux.Daemon",
|
interface = "org.asuslinux.Daemon",
|
||||||
default_path = "/org/asuslinux/Charge"
|
default_path = "/org/asuslinux/Power"
|
||||||
)]
|
)]
|
||||||
trait Charge {
|
trait Power {
|
||||||
/// Limit method
|
/// charge_control_end_threshold method
|
||||||
fn limit(&self) -> zbus::Result<i16>;
|
fn charge_control_end_threshold(&self) -> zbus::Result<u8>;
|
||||||
|
|
||||||
/// SetLimit method
|
/// MainsOnline method
|
||||||
fn set_limit(&self, limit: u8) -> zbus::Result<()>;
|
fn mains_online(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
/// set_charge_control_end_threshold method
|
||||||
|
fn set_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyCharge signal
|
/// NotifyCharge signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_charge(&self, limit: u8) -> zbus::Result<u8>;
|
fn notify_charge_control_end_threshold(&self, limit: u8) -> zbus::Result<u8>;
|
||||||
|
|
||||||
|
/// NotifyMainsOnline signal
|
||||||
|
#[dbus_proxy(signal)]
|
||||||
|
fn notify_mains_online(&self, on: bool) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
@@ -18,5 +18,6 @@ udev = "^0.6"
|
|||||||
rusb = "^0.9"
|
rusb = "^0.9"
|
||||||
sysfs-class = "^0.1"
|
sysfs-class = "^0.1"
|
||||||
inotify = "^0.10.0"
|
inotify = "^0.10.0"
|
||||||
|
# inotify = { version = "0.10.0", default-features = false }
|
||||||
|
|
||||||
concat-idents = "1.1.3"
|
concat-idents = "1.1.3"
|
||||||
@@ -15,7 +15,8 @@ pub enum PlatformError {
|
|||||||
AttrNotFound(String),
|
AttrNotFound(String),
|
||||||
MissingFunction(String),
|
MissingFunction(String),
|
||||||
MissingLedBrightNode(String, std::io::Error),
|
MissingLedBrightNode(String, std::io::Error),
|
||||||
Io(String, std::io::Error),
|
IoPath(String, std::io::Error),
|
||||||
|
Io(std::io::Error),
|
||||||
NoAuraKeyboard,
|
NoAuraKeyboard,
|
||||||
NoAuraNode,
|
NoAuraNode,
|
||||||
}
|
}
|
||||||
@@ -33,9 +34,10 @@ impl fmt::Display for PlatformError {
|
|||||||
PlatformError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
PlatformError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
||||||
PlatformError::NotSupported => write!(f, "Not supported"),
|
PlatformError::NotSupported => write!(f, "Not supported"),
|
||||||
PlatformError::AttrNotFound(deets) => write!(f, "Attribute not found: {}", deets),
|
PlatformError::AttrNotFound(deets) => write!(f, "Attribute not found: {}", deets),
|
||||||
|
PlatformError::Io(deets) => write!(f, "std::io error: {}", deets),
|
||||||
PlatformError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
|
PlatformError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
|
||||||
PlatformError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
|
PlatformError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
|
||||||
PlatformError::Io(path, detail) => write!(f, "std::io error: {} {}", path, detail),
|
PlatformError::IoPath(path, detail) => write!(f, "{} {}", path, detail),
|
||||||
PlatformError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
|
PlatformError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
|
||||||
PlatformError::NoAuraNode => write!(f, "No Aura keyboard node found"),
|
PlatformError::NoAuraNode => write!(f, "No Aura keyboard node found"),
|
||||||
}
|
}
|
||||||
@@ -49,3 +51,9 @@ impl From<rusb::Error> for PlatformError {
|
|||||||
PlatformError::USB(err)
|
PlatformError::USB(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for PlatformError {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
PlatformError::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ impl HidRaw {
|
|||||||
|
|
||||||
for device in enumerator
|
for device in enumerator
|
||||||
.scan_devices()
|
.scan_devices()
|
||||||
.map_err(|e| PlatformError::Io("enumerator".to_owned(), e))?
|
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
|
||||||
{
|
{
|
||||||
if let Some(parent) = device
|
if let Some(parent) = device
|
||||||
.parent_with_subsystem_devtype("usb", "usb_device")
|
.parent_with_subsystem_devtype("usb", "usb_device")
|
||||||
.map_err(|e| PlatformError::Io(device.devpath().to_string_lossy().to_string(), e))?
|
.map_err(|e| {
|
||||||
|
PlatformError::IoPath(device.devpath().to_string_lossy().to_string(), e)
|
||||||
|
})?
|
||||||
{
|
{
|
||||||
if let Some(parent) = parent.attribute_value("idProduct") {
|
if let Some(parent) = parent.attribute_value("idProduct") {
|
||||||
if parent == id_product {
|
if parent == id_product {
|
||||||
@@ -47,9 +49,9 @@ impl HidRaw {
|
|||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&self.0)
|
.open(&self.0)
|
||||||
.map_err(|e| PlatformError::Io(self.0.to_string_lossy().to_string(), e))?;
|
.map_err(|e| PlatformError::IoPath(self.0.to_string_lossy().to_string(), e))?;
|
||||||
// println!("write: {:02x?}", &message);
|
// println!("write: {:02x?}", &message);
|
||||||
file.write_all(message)
|
file.write_all(message)
|
||||||
.map_err(|e| PlatformError::Io(self.0.to_string_lossy().to_string(), e))
|
.map_err(|e| PlatformError::IoPath(self.0.to_string_lossy().to_string(), e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub fn read_attr_bool(device: &Device, attr_name: &str) -> Result<bool> {
|
|||||||
pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<()> {
|
pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<()> {
|
||||||
device
|
device
|
||||||
.set_attribute_value(attr, &(value as u8).to_string())
|
.set_attribute_value(attr, &(value as u8).to_string())
|
||||||
.map_err(|e| PlatformError::Io(attr.into(), e))
|
.map_err(|e| PlatformError::IoPath(attr.into(), e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
|
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
|
||||||
@@ -59,7 +59,7 @@ pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
|
|||||||
pub fn write_attr_u8(device: &mut Device, attr: &str, value: u8) -> Result<()> {
|
pub fn write_attr_u8(device: &mut Device, attr: &str, value: u8) -> Result<()> {
|
||||||
device
|
device
|
||||||
.set_attribute_value(attr, &(value).to_string())
|
.set_attribute_value(attr, &(value).to_string())
|
||||||
.map_err(|e| PlatformError::Io(attr.into(), e))
|
.map_err(|e| PlatformError::IoPath(attr.into(), e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_attr_u8_array(device: &Device, attr_name: &str) -> Result<Vec<u8>> {
|
pub fn read_attr_u8_array(device: &Device, attr_name: &str) -> Result<Vec<u8>> {
|
||||||
@@ -79,7 +79,7 @@ pub fn write_attr_u8_array(device: &mut Device, attr: &str, values: &[u8]) -> Re
|
|||||||
let tmp = tmp.trim();
|
let tmp = tmp.trim();
|
||||||
device
|
device
|
||||||
.set_attribute_value(attr, &tmp)
|
.set_attribute_value(attr, &tmp)
|
||||||
.map_err(|e| PlatformError::Io(attr.into(), e))
|
.map_err(|e| PlatformError::IoPath(attr.into(), e))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -21,9 +21,19 @@ macro_rules! watch_attr {
|
|||||||
pub fn fn_name(&self) -> Result<inotify::Inotify> {
|
pub fn fn_name(&self) -> Result<inotify::Inotify> {
|
||||||
let mut path = self.$item.clone();
|
let mut path = self.$item.clone();
|
||||||
path.push($attr_name);
|
path.push($attr_name);
|
||||||
let mut inotify = inotify::Inotify::init().unwrap();
|
if let Some(path) = path.to_str() {
|
||||||
inotify.add_watch(path.to_str().unwrap(), inotify::WatchMask::MODIFY).unwrap();
|
let mut inotify = inotify::Inotify::init()?;
|
||||||
Ok(inotify)
|
inotify.add_watch(path, inotify::WatchMask::MODIFY)
|
||||||
|
.map_err(|e| {
|
||||||
|
if e.kind() == std::io::ErrorKind::NotFound {
|
||||||
|
PlatformError::AttrNotFound(format!("{}", $attr_name))
|
||||||
|
} else {
|
||||||
|
PlatformError::IoPath(format!("{}", path), e)
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
return Ok(inotify);
|
||||||
|
}
|
||||||
|
Err(PlatformError::AttrNotFound(format!("{}", $attr_name)))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -127,5 +137,6 @@ macro_rules! attr_u8_array {
|
|||||||
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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -20,6 +20,7 @@ use crate::{
|
|||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub struct AsusPlatform {
|
pub struct AsusPlatform {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
pp_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsusPlatform {
|
impl AsusPlatform {
|
||||||
@@ -44,6 +45,7 @@ impl AsusPlatform {
|
|||||||
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(),
|
||||||
|
pp_path: PathBuf::from_str("/sys/firmware/acpi").unwrap(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(PlatformError::MissingFunction(
|
Err(PlatformError::MissingFunction(
|
||||||
@@ -55,6 +57,10 @@ impl AsusPlatform {
|
|||||||
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_u8!("gpu_mux_mode", path);
|
||||||
|
// This is technically the same as `platform_profile` since both are tied in-kernel
|
||||||
|
attr_u8!("throttle_thermal_policy", path);
|
||||||
|
// The acpi platform_profile support
|
||||||
|
attr_u8!("platform_profile", pp_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Type, Debug, PartialEq, Clone, Copy)]
|
#[derive(Serialize, Deserialize, Type, Debug, PartialEq, Clone, Copy)]
|
||||||
|
|||||||
@@ -102,4 +102,5 @@ impl AsusPower {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attr_u8!("charge_control_end_threshold", battery);
|
attr_u8!("charge_control_end_threshold", battery);
|
||||||
|
attr_u8!("online", mains);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user