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> {
Ok(()) let p = if let Ok(lock) = self.config.try_lock() {
} lock.panel_od
}
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 { } else {
info!("Switch for POST boot sound not detected"); false
} };
self.set_panel_od(p)?;
Ok(CtrlRogBios {
platform,
_config: 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(()) 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> { #[async_trait]
let path = ASUS_POST_LOGO_SOUND; impl CtrlTask for CtrlRogBios {
let mut file = OpenOptions::new() async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
.read(true) let connection = Connection::system()
.open(path) .await
.map_err(|err| RogError::Path(path.into(), err))?; .expect("CtrlRogBios could not create dbus connection");
let mut data = Vec::new(); let manager = ManagerProxy::new(&connection)
file.read_to_end(&mut data) .await
.map_err(|err| RogError::Read(path.into(), err))?; .expect("CtrlRogBios could not create ManagerProxy");
let idx = data.len() - 1; let platform = self.clone();
Ok(data[idx] as i8) executor
} .spawn(async move {
if let Ok(notif) = manager.receive_prepare_for_sleep().await {
pub(super) fn set_boot_sound(on: bool) -> Result<(), RogError> { notif
let path = ASUS_POST_LOGO_SOUND; .for_each(|event| {
let mut file = OpenOptions::new() if let Ok(args) = event.args() {
.read(true) // If waking up
.write(true) if !args.start {
.open(path) info!("CtrlRogBios reloading panel_od");
.map_err(|err| RogError::Path(path.into(), err))?; if let Ok(lock) = platform.config.try_lock() {
platform
let mut data = Vec::new(); .set_panel_od(lock.panel_od)
file.read_to_end(&mut data) .map_err(|err| {
.map_err(|err| RogError::Read(path.into(), err))?; warn!("CtrlCharge: set_limit {}", 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 {