diff --git a/daemon/src/config.rs b/daemon/src/config.rs index 847326ae..a95d22f9 100644 --- a/daemon/src/config.rs +++ b/daemon/src/config.rs @@ -7,15 +7,18 @@ use std::path::PathBuf; pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; #[derive(Deserialize, Serialize, Default)] +#[serde(default)] pub struct Config { /// Save charge limit for restoring on boot pub bat_charge_limit: u8, + pub panel_od: bool, } impl Config { fn new() -> Self { Config { bat_charge_limit: 100, + panel_od: false, } } diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index 5ce525d3..0c19444f 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -238,7 +238,7 @@ impl CtrlKbdLed { pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> { self.kd_brightness - .set_brightness(brightness.as_char_code()) + .set_brightness(brightness as u8) .map_err(|e| RogError::Platform(e)) } diff --git a/daemon/src/ctrl_platform.rs b/daemon/src/ctrl_platform.rs index 2691e4cb..10c76611 100644 --- a/daemon/src/ctrl_platform.rs +++ b/daemon/src/ctrl_platform.rs @@ -1,8 +1,12 @@ +use crate::CtrlTask; use crate::{config::Config, error::RogError, GetSupported}; use async_trait::async_trait; use log::{info, warn}; +use logind_zbus::manager::ManagerProxy; use rog_platform::platform::{AsusPlatform, GpuMode}; use rog_platform::supported::RogBiosSupportedFunctions; +use smol::stream::StreamExt; +use smol::Executor; use std::fs::OpenOptions; use std::io::{Read, Write}; use std::path::Path; @@ -15,9 +19,10 @@ use zbus::{dbus_interface, SignalContext}; static ASUS_POST_LOGO_SOUND: &str = "/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e"; +#[derive(Clone)] pub struct CtrlRogBios { platform: AsusPlatform, - _config: Arc>, + config: Arc>, } impl GetSupported for CtrlRogBios { @@ -46,6 +51,95 @@ impl GetSupported for CtrlRogBios { } } +impl CtrlRogBios { + pub fn new(config: Arc>) -> Result { + let platform = AsusPlatform::new()?; + + if !platform.has_gpu_mux_mode() { + info!("G-Sync Switchable Graphics not detected"); + info!("If your laptop is not a G-Sync enabled laptop then you can ignore this. Standard graphics switching will still work."); + } + + if Path::new(ASUS_POST_LOGO_SOUND).exists() { + CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?; + } else { + info!("Switch for POST boot sound not detected"); + } + + Ok(CtrlRogBios { platform, config }) + } + + fn set_path_mutable(path: &str) -> Result<(), RogError> { + let output = Command::new("/usr/bin/chattr") + .arg("-i") + .arg(path) + .output() + .map_err(|err| RogError::Path(path.into(), err))?; + info!("Set {} writeable: status: {}", path, output.status); + Ok(()) + } + + fn set_gfx_mode(&self, mode: GpuMode) -> Result<(), RogError> { + self.platform.set_gpu_mux_mode(mode.to_mux())?; + // self.update_initramfs(enable)?; + if mode == GpuMode::Discrete { + info!("Set system-level graphics mode: Dedicated Nvidia"); + } else { + info!("Set system-level graphics mode: Optimus"); + } + Ok(()) + } + + pub fn get_boot_sound() -> Result { + let path = ASUS_POST_LOGO_SOUND; + let mut file = OpenOptions::new() + .read(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data) + .map_err(|err| RogError::Read(path.into(), err))?; + + let idx = data.len() - 1; + Ok(data[idx] as i8) + } + + pub(super) fn set_boot_sound(on: bool) -> Result<(), RogError> { + let path = ASUS_POST_LOGO_SOUND; + let mut file = OpenOptions::new() + .read(true) + .write(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data) + .map_err(|err| RogError::Read(path.into(), err))?; + + let idx = data.len() - 1; + if on { + data[idx] = 1; + info!("Set boot POST sound on"); + } else { + data[idx] = 0; + info!("Set boot POST sound off"); + } + file.write_all(&data) + .map_err(|err| RogError::Path(path.into(), err))?; + + Ok(()) + } + + fn set_panel_od(&self, enable: bool) -> Result<(), RogError> { + self.platform.set_panel_od(enable).map_err(|err| { + warn!("CtrlRogBios: set_panel_overdrive {}", err); + err + })?; + Ok(()) + } +} + #[dbus_interface(name = "org.asuslinux.Daemon")] impl CtrlRogBios { async fn set_gpu_mux_mode( @@ -118,6 +212,10 @@ impl CtrlRogBios { }) .is_ok() { + if let Ok(mut lock) = self.config.try_lock() { + lock.panel_od = overdrive; + lock.write(); + } Self::notify_panel_overdrive(&ctxt, overdrive).await.ok(); } } @@ -149,98 +247,84 @@ impl crate::ZbusAdd for CtrlRogBios { impl crate::Reloadable for CtrlRogBios { fn reload(&mut self) -> Result<(), RogError> { + let p = if let Ok(lock) = self.config.try_lock() { + lock.panel_od + } else { + false + }; + self.set_panel_od(p)?; Ok(()) } } -impl CtrlRogBios { - pub fn new(config: Arc>) -> Result { - let platform = AsusPlatform::new()?; +#[async_trait] +impl CtrlTask for CtrlRogBios { + async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { + let connection = Connection::system() + .await + .expect("CtrlRogBios could not create dbus connection"); - if !platform.has_gpu_mux_mode() { - info!("G-Sync Switchable Graphics not detected"); - info!("If your laptop is not a G-Sync enabled laptop then you can ignore this. Standard graphics switching will still work."); - } + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlRogBios could not create ManagerProxy"); - if Path::new(ASUS_POST_LOGO_SOUND).exists() { - CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?; - } else { - info!("Switch for POST boot sound not detected"); - } + let platform = self.clone(); + executor + .spawn(async move { + if let Ok(notif) = manager.receive_prepare_for_sleep().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + // If waking up + if !args.start { + info!("CtrlRogBios reloading panel_od"); + if let Ok(lock) = platform.config.try_lock() { + platform + .set_panel_od(lock.panel_od) + .map_err(|err| { + warn!("CtrlCharge: set_limit {}", err); + err + }) + .ok(); + } + } + } + }) + .await; + } + }) + .detach(); - Ok(CtrlRogBios { - platform, - _config: config, - }) - } + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlCharge could not create ManagerProxy"); - fn set_path_mutable(path: &str) -> Result<(), RogError> { - let output = Command::new("/usr/bin/chattr") - .arg("-i") - .arg(path) - .output() - .map_err(|err| RogError::Path(path.into(), err))?; - info!("Set {} writeable: status: {}", path, output.status); - Ok(()) - } - - fn set_gfx_mode(&self, mode: GpuMode) -> Result<(), RogError> { - self.platform.set_gpu_mux_mode(mode.to_mux())?; - // self.update_initramfs(enable)?; - if mode == GpuMode::Discrete { - info!("Set system-level graphics mode: Dedicated Nvidia"); - } else { - info!("Set system-level graphics mode: Optimus"); - } - Ok(()) - } - - pub fn get_boot_sound() -> Result { - let path = ASUS_POST_LOGO_SOUND; - let mut file = OpenOptions::new() - .read(true) - .open(path) - .map_err(|err| RogError::Path(path.into(), err))?; - - let mut data = Vec::new(); - file.read_to_end(&mut data) - .map_err(|err| RogError::Read(path.into(), err))?; - - let idx = data.len() - 1; - Ok(data[idx] as i8) - } - - pub(super) fn set_boot_sound(on: bool) -> Result<(), RogError> { - let path = ASUS_POST_LOGO_SOUND; - let mut file = OpenOptions::new() - .read(true) - .write(true) - .open(path) - .map_err(|err| RogError::Path(path.into(), err))?; - - let mut data = Vec::new(); - file.read_to_end(&mut data) - .map_err(|err| RogError::Read(path.into(), err))?; - - let idx = data.len() - 1; - if on { - data[idx] = 1; - info!("Set boot POST sound on"); - } else { - data[idx] = 0; - info!("Set boot POST sound off"); - } - file.write_all(&data) - .map_err(|err| RogError::Path(path.into(), err))?; - - Ok(()) - } - - fn set_panel_od(&mut self, enable: bool) -> Result<(), RogError> { - self.platform.set_panel_od(enable).map_err(|err| { - warn!("CtrlRogBios: set_panel_overdrive {}", err); - err - })?; + let platform = self.clone(); + executor + .spawn(async move { + if let Ok(notif) = manager.receive_prepare_for_shutdown().await { + notif + .for_each(|event| { + if let Ok(args) = event.args() { + // If waking up - intention is to catch hibernation event + if !args.start { + info!("CtrlRogBios reloading panel_od"); + if let Ok(lock) = platform.config.try_lock() { + platform + .set_panel_od(lock.panel_od) + .map_err(|err| { + warn!("CtrlCharge: set_limit {}", err); + err + }) + .ok(); + } + } + } + }) + .await; + } + }) + .detach(); Ok(()) } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 01169425..f70c698d 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -88,6 +88,9 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> .unwrap_or_else(|err| warn!("Battery charge limit: {}", 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) => { error!("rog_bios_control: {}", err); diff --git a/rog-aura/src/builtin_modes.rs b/rog-aura/src/builtin_modes.rs index bd296f41..0727a496 100644 --- a/rog-aura/src/builtin_modes.rs +++ b/rog-aura/src/builtin_modes.rs @@ -20,13 +20,6 @@ pub enum LedBrightness { High, } -impl LedBrightness { - pub fn as_char_code(&self) -> u8 { - std::char::from_digit(*self as u32, 10) - .expect("LedBrightness.as_char_code failed to convert") as u8 - } -} - impl From for LedBrightness { fn from(bright: u32) -> Self { match bright {