mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user