daemon: fix keyboard brightness setting

Closes #241
This commit is contained in:
Luke D. Jones
2022-08-20 21:42:18 +12:00
parent f8cdde2adf
commit 3fe5896596
5 changed files with 176 additions and 93 deletions

View File

@@ -7,15 +7,18 @@ use std::path::PathBuf;
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
#[derive(Deserialize, Serialize, Default)] #[derive(Deserialize, Serialize, Default)]
#[serde(default)]
pub struct Config { pub struct Config {
/// Save charge limit for restoring on boot /// Save charge limit for restoring on boot
pub bat_charge_limit: u8, pub bat_charge_limit: u8,
pub panel_od: bool,
} }
impl Config { impl Config {
fn new() -> Self { fn new() -> Self {
Config { Config {
bat_charge_limit: 100, bat_charge_limit: 100,
panel_od: false,
} }
} }

View File

@@ -238,7 +238,7 @@ impl CtrlKbdLed {
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> { pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
self.kd_brightness self.kd_brightness
.set_brightness(brightness.as_char_code()) .set_brightness(brightness as u8)
.map_err(|e| RogError::Platform(e)) .map_err(|e| RogError::Platform(e))
} }

View File

@@ -1,8 +1,12 @@
use crate::CtrlTask;
use crate::{config::Config, error::RogError, GetSupported}; use crate::{config::Config, error::RogError, GetSupported};
use async_trait::async_trait; use async_trait::async_trait;
use log::{info, warn}; use log::{info, warn};
use logind_zbus::manager::ManagerProxy;
use rog_platform::platform::{AsusPlatform, GpuMode}; use rog_platform::platform::{AsusPlatform, GpuMode};
use rog_platform::supported::RogBiosSupportedFunctions; use rog_platform::supported::RogBiosSupportedFunctions;
use smol::stream::StreamExt;
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;
@@ -15,9 +19,10 @@ use zbus::{dbus_interface, SignalContext};
static ASUS_POST_LOGO_SOUND: &str = static 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)]
pub struct CtrlRogBios { pub struct CtrlRogBios {
platform: AsusPlatform, platform: AsusPlatform,
_config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
} }
impl GetSupported for CtrlRogBios { impl GetSupported for CtrlRogBios {
@@ -46,6 +51,95 @@ impl GetSupported for CtrlRogBios {
} }
} }
impl CtrlRogBios {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
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<i8, RogError> {
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")] #[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlRogBios { impl CtrlRogBios {
async fn set_gpu_mux_mode( async fn set_gpu_mux_mode(
@@ -118,6 +212,10 @@ impl CtrlRogBios {
}) })
.is_ok() .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(); Self::notify_panel_overdrive(&ctxt, overdrive).await.ok();
} }
} }
@@ -149,98 +247,84 @@ impl crate::ZbusAdd for CtrlRogBios {
impl crate::Reloadable for CtrlRogBios { impl crate::Reloadable for CtrlRogBios {
fn reload(&mut self) -> Result<(), RogError> { 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(()) Ok(())
} }
} }
impl CtrlRogBios { #[async_trait]
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> { impl CtrlTask for CtrlRogBios {
let platform = AsusPlatform::new()?; 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() { let manager = ManagerProxy::new(&connection)
info!("G-Sync Switchable Graphics not detected"); .await
info!("If your laptop is not a G-Sync enabled laptop then you can ignore this. Standard graphics switching will still work."); .expect("CtrlRogBios could not create ManagerProxy");
}
if Path::new(ASUS_POST_LOGO_SOUND).exists() { let platform = self.clone();
CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?; executor
} else { .spawn(async move {
info!("Switch for POST boot sound not detected"); if let Ok(notif) = manager.receive_prepare_for_sleep().await {
} notif
.for_each(|event| {
Ok(CtrlRogBios { if let Ok(args) = event.args() {
platform, // If waking up
_config: config, if !args.start {
}) info!("CtrlRogBios reloading panel_od");
} if let Ok(lock) = platform.config.try_lock() {
platform
fn set_path_mutable(path: &str) -> Result<(), RogError> { .set_panel_od(lock.panel_od)
let output = Command::new("/usr/bin/chattr") .map_err(|err| {
.arg("-i") warn!("CtrlCharge: set_limit {}", err);
.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<i8, RogError> {
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 err
})?; })
.ok();
}
}
}
})
.await;
}
})
.detach();
let manager = ManagerProxy::new(&connection)
.await
.expect("CtrlCharge could not create ManagerProxy");
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(()) Ok(())
} }
} }

View File

@@ -88,6 +88,9 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
.unwrap_or_else(|err| warn!("Battery charge limit: {}", err)); .unwrap_or_else(|err| warn!("Battery charge limit: {}", err));
// Then register to dbus server // Then register to dbus server
ctrl.add_to_server(&mut connection).await; 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!("rog_bios_control: {}", err);

View File

@@ -20,13 +20,6 @@ pub enum LedBrightness {
High, 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<u32> for LedBrightness { impl From<u32> for LedBrightness {
fn from(bright: u32) -> Self { fn from(bright: u32) -> Self {
match bright { match bright {