mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
rog-platform: refactor all related parts
This commit is contained in:
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- SetOffWhenSuspended, also add asusctl CLI option
|
- SetOffWhenSuspended, also add asusctl CLI option
|
||||||
- SetOffWhenLidClosed, also add asusctl CLI option
|
- SetOffWhenLidClosed, also add asusctl CLI option
|
||||||
- Anime: add brightness_on_battery config option
|
- Anime: add brightness_on_battery config option
|
||||||
|
- Platform: add `post_animation_sound`, kernel 6.7+ requires patch
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- asusd: remove set_image_brightness for anime
|
- asusd: remove set_image_brightness for anime
|
||||||
@@ -29,6 +30,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Ensure display is off when on battery and option is set
|
- Ensure display is off when on battery and option is set
|
||||||
- Ensure builtin animations run instead of custom animations if option is set
|
- Ensure builtin animations run instead of custom animations if option is set
|
||||||
|
|
||||||
|
### Breaking
|
||||||
|
- DBUS stuff. Again.
|
||||||
|
- Platform dbus refactored to Properties as it makes more sense than a pile of functions
|
||||||
|
|
||||||
## [v4.7.2]
|
## [v4.7.2]
|
||||||
### Added
|
### Added
|
||||||
- Support for G733PZ LED modes
|
- Support for G733PZ LED modes
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ version = "4.7.2"
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
async-trait = "^0.1"
|
async-trait = "^0.1"
|
||||||
tokio = { version = "^1.23.0", features = ["macros", "rt-multi-thread", "time", "sync"]}
|
tokio = { version = "^1.23.0", features = ["macros", "rt-multi-thread"]}
|
||||||
concat-idents = "^1.1"
|
concat-idents = "^1.1"
|
||||||
dirs = "^4.0"
|
dirs = "^4.0"
|
||||||
smol = "^1.3"
|
smol = "^1.3"
|
||||||
@@ -44,11 +44,11 @@ notify-rust = { git = "https://github.com/flukejones/notify-rust.git", default-f
|
|||||||
[profile.release]
|
[profile.release]
|
||||||
# thin = 57s, asusd = 9.0M
|
# thin = 57s, asusd = 9.0M
|
||||||
# fat = 72s, asusd = 6.4M
|
# fat = 72s, asusd = 6.4M
|
||||||
#lto = "fat"
|
lto = "fat"
|
||||||
debug = false
|
debug = false
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
#codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
debug = true
|
debug = true
|
||||||
|
|||||||
@@ -763,7 +763,7 @@ fn handle_bios_option(
|
|||||||
let usage: Vec<String> = BiosCommand::usage().lines().map(|s| s.to_owned()).collect();
|
let usage: Vec<String> = BiosCommand::usage().lines().map(|s| s.to_owned()).collect();
|
||||||
|
|
||||||
for line in usage.iter().filter(|line| {
|
for line in usage.iter().filter(|line| {
|
||||||
line.contains("sound") && supported.post_sound
|
line.contains("sound") && supported.post_animation_sound
|
||||||
|| line.contains("GPU") && supported.gpu_mux
|
|| line.contains("GPU") && supported.gpu_mux
|
||||||
|| line.contains("panel") && supported.panel_overdrive
|
|| line.contains("panel") && supported.panel_overdrive
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -12,17 +12,24 @@ pub struct Config {
|
|||||||
pub disable_nvidia_powerd_on_battery: bool,
|
pub disable_nvidia_powerd_on_battery: bool,
|
||||||
pub ac_command: String,
|
pub ac_command: String,
|
||||||
pub bat_command: String,
|
pub bat_command: String,
|
||||||
|
pub post_animation_sound: bool,
|
||||||
|
pub ppt_pl1_spl: Option<u8>,
|
||||||
|
pub ppt_pl2_sppt: Option<u8>,
|
||||||
|
pub ppt_fppt: Option<u8>,
|
||||||
|
pub ppt_apu_sppt: Option<u8>,
|
||||||
|
pub ppt_platform_sppt: Option<u8>,
|
||||||
|
pub nv_dynamic_boost: Option<u8>,
|
||||||
|
pub nv_temp_target: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdConfig for Config {
|
impl StdConfig for Config {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Config {
|
Config {
|
||||||
bat_charge_limit: 100,
|
bat_charge_limit: 100,
|
||||||
panel_od: false,
|
|
||||||
mini_led_mode: false,
|
|
||||||
disable_nvidia_powerd_on_battery: true,
|
disable_nvidia_powerd_on_battery: true,
|
||||||
ac_command: String::new(),
|
ac_command: String::new(),
|
||||||
bat_command: String::new(),
|
bat_command: String::new(),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +42,32 @@ impl StdConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdConfigLoad2<Config458, Config462> for Config {}
|
impl StdConfigLoad2<Config462, Config472> for Config {}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Default, Debug)]
|
||||||
|
pub struct Config472 {
|
||||||
|
/// Save charge limit for restoring on boot
|
||||||
|
pub bat_charge_limit: u8,
|
||||||
|
pub panel_od: bool,
|
||||||
|
pub mini_led_mode: bool,
|
||||||
|
pub disable_nvidia_powerd_on_battery: bool,
|
||||||
|
pub ac_command: String,
|
||||||
|
pub bat_command: String,
|
||||||
|
pub post_animation_sound: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Config472> for Config {
|
||||||
|
fn from(c: Config472) -> Self {
|
||||||
|
Self {
|
||||||
|
bat_charge_limit: c.bat_charge_limit,
|
||||||
|
panel_od: c.panel_od,
|
||||||
|
disable_nvidia_powerd_on_battery: true,
|
||||||
|
ac_command: c.ac_command,
|
||||||
|
bat_command: c.bat_command,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Config462 {
|
pub struct Config462 {
|
||||||
@@ -52,32 +84,10 @@ impl From<Config462> for Config {
|
|||||||
Self {
|
Self {
|
||||||
bat_charge_limit: c.bat_charge_limit,
|
bat_charge_limit: c.bat_charge_limit,
|
||||||
panel_od: c.panel_od,
|
panel_od: c.panel_od,
|
||||||
mini_led_mode: false,
|
|
||||||
disable_nvidia_powerd_on_battery: true,
|
disable_nvidia_powerd_on_battery: true,
|
||||||
ac_command: String::new(),
|
ac_command: String::new(),
|
||||||
bat_command: String::new(),
|
bat_command: String::new(),
|
||||||
}
|
..Default::default()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct Config458 {
|
|
||||||
/// Save charge limit for restoring on boot
|
|
||||||
pub bat_charge_limit: u8,
|
|
||||||
pub panel_od: bool,
|
|
||||||
pub ac_command: String,
|
|
||||||
pub bat_command: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Config458> for Config {
|
|
||||||
fn from(c: Config458) -> Self {
|
|
||||||
Self {
|
|
||||||
bat_charge_limit: c.bat_charge_limit,
|
|
||||||
panel_od: c.panel_od,
|
|
||||||
mini_led_mode: false,
|
|
||||||
disable_nvidia_powerd_on_battery: true,
|
|
||||||
ac_command: c.ac_command,
|
|
||||||
bat_command: c.bat_command,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,6 +382,23 @@ impl crate::Reloadable for CtrlAnimeZbus {
|
|||||||
lock.config.display_brightness,
|
lock.config.display_brightness,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let manager = get_logind_manager().await;
|
||||||
|
let lid_closed = manager.lid_closed().await.unwrap_or_default();
|
||||||
|
let power_plugged = manager.on_external_power().await.unwrap_or_default();
|
||||||
|
|
||||||
|
let on = (lid_closed && lock.config.off_when_lid_closed)
|
||||||
|
|| (power_plugged && lock.config.off_when_unplugged);
|
||||||
|
lock.node
|
||||||
|
.write_bytes(&pkt_set_enable_display(on))
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("create_sys_event_tasks::reload {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
if !on {
|
||||||
|
// early return so we don't run animation thread
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if !lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
|
if !lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
|
||||||
lock.node
|
lock.node
|
||||||
.write_bytes(&pkt_set_enable_powersave_anim(false))
|
.write_bytes(&pkt_set_enable_powersave_anim(false))
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::{Read, Write};
|
|
||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use config_traits::StdConfig;
|
use config_traits::StdConfig;
|
||||||
use log::{info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_platform::platform::{AsusPlatform, GpuMode};
|
use rog_platform::platform::{AsusPlatform, GpuMode};
|
||||||
use rog_platform::supported::PlatformSupportedFunctions;
|
use rog_platform::supported::PlatformSupportedFunctions;
|
||||||
use zbus::export::futures_util::lock::Mutex;
|
use zbus::export::futures_util::lock::Mutex;
|
||||||
|
use zbus::fdo::Error as FdoErr;
|
||||||
use zbus::{dbus_interface, Connection, SignalContext};
|
use zbus::{dbus_interface, Connection, SignalContext};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@@ -17,8 +14,92 @@ use crate::error::RogError;
|
|||||||
use crate::{task_watch_item, CtrlTask, GetSupported};
|
use crate::{task_watch_item, CtrlTask, GetSupported};
|
||||||
|
|
||||||
const ZBUS_PATH: &str = "/org/asuslinux/Platform";
|
const ZBUS_PATH: &str = "/org/asuslinux/Platform";
|
||||||
const ASUS_POST_LOGO_SOUND: &str =
|
|
||||||
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
macro_rules! platform_get_value {
|
||||||
|
($self:ident, $property:tt, $prop_name:literal) => {
|
||||||
|
concat_idents::concat_idents!(has = has_, $property {
|
||||||
|
if $self.platform.has() {
|
||||||
|
concat_idents::concat_idents!(get = get_, $property {
|
||||||
|
$self.platform
|
||||||
|
.get()
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: {}: {}", $prop_name, err);
|
||||||
|
FdoErr::Failed(format!("CtrlRogBios: {}: {}", $prop_name, err))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
error!("CtrlRogBios: {} not supported", $prop_name);
|
||||||
|
return Err(FdoErr::NotSupported(format!("CtrlRogBios: {} not supported", $prop_name)));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! platform_get_value_if_some {
|
||||||
|
($self:ident, $property:tt, $prop_name:literal, $default:expr) => {
|
||||||
|
concat_idents::concat_idents!(has = has_, $property {
|
||||||
|
if $self.platform.has() {
|
||||||
|
let lock = $self.config.lock().await;
|
||||||
|
Ok(lock.ppt_pl1_spl.unwrap_or($default))
|
||||||
|
} else {
|
||||||
|
error!("CtrlRogBios: {} not supported", $prop_name);
|
||||||
|
return Err(FdoErr::NotSupported(format!("CtrlRogBios: {} not supported", $prop_name)));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! platform_set_bool {
|
||||||
|
($self:ident, $property:tt, $prop_name:literal, $new_value:expr) => {
|
||||||
|
concat_idents::concat_idents!(has = has_, $property {
|
||||||
|
if $self.platform.has() {
|
||||||
|
concat_idents::concat_idents!(set = set_, $property {
|
||||||
|
$self.platform.set($new_value).map_err(|err| {
|
||||||
|
error!("CtrlRogBios: {} {err}", $prop_name);
|
||||||
|
FdoErr::NotSupported(format!("CtrlRogBios: {} {err}", $prop_name))
|
||||||
|
})?;
|
||||||
|
});
|
||||||
|
let mut lock = $self.config.lock().await;
|
||||||
|
lock.$property = $new_value;
|
||||||
|
lock.write();
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
error!("CtrlRogBios: {} not supported", $prop_name);
|
||||||
|
Err(FdoErr::NotSupported(format!("CtrlRogBios: {} not supported", $prop_name)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Intended only for setting platform object values where the value isn't
|
||||||
|
/// retained across boots
|
||||||
|
macro_rules! platform_set_with_min_max {
|
||||||
|
($self:ident, $property:tt, $prop_name:literal, $new_value:expr, $min_value:expr, $max_value:expr) => {
|
||||||
|
if !($min_value..=$max_value).contains(&$new_value) {
|
||||||
|
Err(FdoErr::Failed(
|
||||||
|
format!("CtrlRogBios: {} value not in range {}=..={}", $prop_name, $min_value, $max_value)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
concat_idents::concat_idents!(has = has_, $property {
|
||||||
|
if $self.platform.has() {
|
||||||
|
concat_idents::concat_idents!(set = set_, $property {
|
||||||
|
$self.platform.set($new_value).map_err(|err| {
|
||||||
|
error!("CtrlRogBios: {} {err}", $prop_name);
|
||||||
|
FdoErr::NotSupported(format!("CtrlRogBios: {} {err}", $prop_name))
|
||||||
|
})?;
|
||||||
|
});
|
||||||
|
let mut lock = $self.config.lock().await;
|
||||||
|
lock.$property = Some($new_value);
|
||||||
|
lock.write();
|
||||||
|
} else {
|
||||||
|
error!("CtrlRogBios: {} not supported", $prop_name);
|
||||||
|
return Err(FdoErr::NotSupported(format!("CtrlRogBios: {} not supported", $prop_name)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CtrlPlatform {
|
pub struct CtrlPlatform {
|
||||||
@@ -44,25 +125,9 @@ impl CtrlPlatform {
|
|||||||
info!("Standard graphics switching will still work.");
|
info!("Standard graphics switching will still work.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if Path::new(ASUS_POST_LOGO_SOUND).exists() {
|
|
||||||
CtrlPlatform::set_path_mutable(ASUS_POST_LOGO_SOUND)?;
|
|
||||||
} else {
|
|
||||||
info!("Switch for POST boot sound not detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CtrlPlatform { platform, config })
|
Ok(CtrlPlatform { 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> {
|
fn set_gfx_mode(&self, mode: GpuMode) -> Result<(), RogError> {
|
||||||
self.platform.set_gpu_mux_mode(mode.to_mux_attr())?;
|
self.platform.set_gpu_mux_mode(mode.to_mux_attr())?;
|
||||||
// self.update_initramfs(enable)?;
|
// self.update_initramfs(enable)?;
|
||||||
@@ -73,226 +138,177 @@ impl CtrlPlatform {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_boot_sound() -> Result<i8, RogError> {
|
|
||||||
let data = std::fs::read(ASUS_POST_LOGO_SOUND)
|
|
||||||
.map_err(|err| RogError::Read(ASUS_POST_LOGO_SOUND.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();
|
|
||||||
#[allow(clippy::verbose_file_reads)]
|
|
||||||
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_overdrive(&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 CtrlPlatform {
|
impl CtrlPlatform {
|
||||||
async fn set_gpu_mux_mode(
|
/// Returns a list of property names that this system supports
|
||||||
&mut self,
|
fn supported_properties(&self) -> Vec<String> {
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
let mut supported = Vec::new();
|
||||||
mode: GpuMode,
|
|
||||||
) {
|
macro_rules! push_name {
|
||||||
self.set_gfx_mode(mode)
|
($property:tt, $prop_name:literal) => {
|
||||||
.map_err(|err| {
|
concat_idents::concat_idents!(has = has_, $property {
|
||||||
warn!("CtrlRogBios: set_gpu_mux_mode {}", err);
|
if self.platform.has() {
|
||||||
err
|
supported.push($prop_name.to_owned());
|
||||||
})
|
}
|
||||||
.ok();
|
})
|
||||||
Self::notify_gpu_mux_mode(&ctxt, mode).await.ok();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_name!(dgpu_disable, "dgpu_disable");
|
||||||
|
push_name!(gpu_mux_mode, "gpu_mux_mode");
|
||||||
|
push_name!(post_animation_sound, "post_animation_sound");
|
||||||
|
push_name!(panel_od, "panel_od");
|
||||||
|
push_name!(mini_led_mode, "mini_led_mode");
|
||||||
|
push_name!(egpu_enable, "egpu_enable");
|
||||||
|
|
||||||
|
push_name!(ppt_pl1_spl, "ppt_pl1_spl");
|
||||||
|
push_name!(ppt_pl2_sppt, "ppt_pl2_sppt");
|
||||||
|
push_name!(ppt_fppt, "ppt_fppt");
|
||||||
|
push_name!(ppt_apu_sppt, "ppt_apu_sppt");
|
||||||
|
push_name!(ppt_platform_sppt, "ppt_platform_sppt");
|
||||||
|
push_name!(nv_dynamic_boost, "nv_dynamic_boost");
|
||||||
|
push_name!(nv_temp_target, "nv_temp_target");
|
||||||
|
|
||||||
|
supported
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gpu_mux_mode(&self) -> GpuMode {
|
#[dbus_interface(property)]
|
||||||
match self.platform.get_gpu_mux_mode() {
|
fn gpu_mux_mode(&self) -> Result<u8, FdoErr> {
|
||||||
Ok(m) => GpuMode::from_mux(m as u8),
|
self.platform.get_gpu_mux_mode().map_err(|err| {
|
||||||
Err(e) => {
|
warn!("CtrlRogBios: set_gpu_mux_mode {err}");
|
||||||
warn!("CtrlRogBios: get_gfx_mode {}", e);
|
FdoErr::NotSupported("CtrlRogBios: set_gpu_mux_mode not supported".to_owned())
|
||||||
GpuMode::Error
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_gpu_mux_mode(&mut self, mode: u8) -> Result<(), FdoErr> {
|
||||||
|
if self.platform.has_gpu_mux_mode() {
|
||||||
|
self.set_gfx_mode(mode.into()).map_err(|err| {
|
||||||
|
warn!("CtrlRogBios: set_gpu_mux_mode {}", err);
|
||||||
|
FdoErr::Failed(format!("CtrlRogBios: set_gpu_mux_mode: {err}"))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(FdoErr::NotSupported(
|
||||||
|
"CtrlRogBios: set_gpu_mux_mode not supported".to_owned(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(property)]
|
||||||
async fn notify_gpu_mux_mode(
|
fn post_animation_sound(&self) -> Result<bool, FdoErr> {
|
||||||
signal_ctxt: &SignalContext<'_>,
|
platform_get_value!(self, post_animation_sound, "post_animation_sound")
|
||||||
mode: GpuMode,
|
|
||||||
) -> zbus::Result<()> {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_post_boot_sound(
|
#[dbus_interface(property)]
|
||||||
&mut self,
|
async fn set_post_animation_sound(&mut self, on: bool) -> Result<(), FdoErr> {
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
platform_set_bool!(self, post_animation_sound, "post_animation_sound", on)
|
||||||
on: bool,
|
|
||||||
) {
|
|
||||||
Self::set_boot_sound(on)
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: set_post_boot_sound {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
Self::notify_post_boot_sound(&ctxt, on)
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: set_post_boot_sound {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_boot_sound(&self) -> i8 {
|
|
||||||
Self::get_boot_sound()
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: get_boot_sound {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.unwrap_or(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
async fn notify_post_boot_sound(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
|
|
||||||
|
|
||||||
async fn set_panel_od(&mut self, overdrive: bool) {
|
|
||||||
match self.platform.set_panel_od(overdrive) {
|
|
||||||
Ok(_) => {
|
|
||||||
if let Some(mut lock) = self.config.try_lock() {
|
|
||||||
lock.panel_od = overdrive;
|
|
||||||
lock.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => warn!("CtrlRogBios: set_panel_overdrive {}", err),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `panel_od` value from platform. Updates the stored value in
|
/// Get the `panel_od` value from platform. Updates the stored value in
|
||||||
/// internal config also.
|
/// internal config also.
|
||||||
fn panel_od(&self) -> bool {
|
#[dbus_interface(property)]
|
||||||
self.platform
|
fn panel_od(&self) -> Result<bool, FdoErr> {
|
||||||
.get_panel_od()
|
platform_get_value!(self, panel_od, "panel_od")
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: get_panel_od {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(property)]
|
||||||
async fn notify_panel_od(signal_ctxt: &SignalContext<'_>, overdrive: bool) -> zbus::Result<()> {
|
async fn set_panel_od(&mut self, overdrive: bool) -> Result<(), FdoErr> {
|
||||||
}
|
platform_set_bool!(self, panel_od, "panel_od", overdrive)
|
||||||
|
|
||||||
async fn set_mini_led_mode(&mut self, on: bool) {
|
|
||||||
match self.platform.set_mini_led_mode(on) {
|
|
||||||
Ok(_) => {
|
|
||||||
if let Some(mut lock) = self.config.try_lock() {
|
|
||||||
lock.mini_led_mode = on;
|
|
||||||
lock.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => warn!("CtrlRogBios: set_mini_led_mode {}", err),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `panel_od` value from platform. Updates the stored value in
|
/// Get the `panel_od` value from platform. Updates the stored value in
|
||||||
/// internal config also.
|
/// internal config also.
|
||||||
fn mini_led_mode(&self) -> bool {
|
#[dbus_interface(property)]
|
||||||
self.platform
|
fn mini_led_mode(&self) -> Result<bool, FdoErr> {
|
||||||
.get_mini_led_mode()
|
platform_get_value!(self, mini_led_mode, "mini_led_mode")
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: get_mini_led_mode {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(property)]
|
||||||
async fn notify_mini_led_mode(signal_ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
|
async fn set_mini_led_mode(&mut self, on: bool) -> Result<(), FdoErr> {
|
||||||
|
platform_set_bool!(self, mini_led_mode, "mini_led_mode", on)
|
||||||
async fn set_dgpu_disable(
|
|
||||||
&mut self,
|
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
|
||||||
disable: bool,
|
|
||||||
) {
|
|
||||||
match self.platform.set_dgpu_disable(disable) {
|
|
||||||
Ok(_) => {
|
|
||||||
Self::notify_dgpu_disable(&ctxt, disable).await.ok();
|
|
||||||
}
|
|
||||||
Err(err) => warn!("CtrlRogBios: set_dgpu_disable {}", err),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dgpu_disable(&self) -> bool {
|
#[dbus_interface(property)]
|
||||||
self.platform
|
fn dgpu_disable(&self) -> Result<bool, FdoErr> {
|
||||||
.get_dgpu_disable()
|
platform_get_value!(self, dgpu_disable, "dgpu_disable")
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: get_dgpu_disable {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(property)]
|
||||||
async fn notify_dgpu_disable(
|
fn egpu_enable(&self) -> Result<bool, FdoErr> {
|
||||||
signal_ctxt: &SignalContext<'_>,
|
platform_get_value!(self, egpu_enable, "egpu_enable")
|
||||||
disable: bool,
|
|
||||||
) -> zbus::Result<()> {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_egpu_enable(
|
/// ***************************************************************************
|
||||||
&mut self,
|
#[dbus_interface(property)]
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
async fn ppt_pl1_spl(&self) -> Result<u8, FdoErr> {
|
||||||
enable: bool,
|
platform_get_value_if_some!(self, ppt_pl1_spl, "ppt_pl1_spl", 5)
|
||||||
) {
|
|
||||||
match self.platform.set_egpu_enable(enable) {
|
|
||||||
Ok(_) => {
|
|
||||||
Self::notify_egpu_enable(&ctxt, enable).await.ok();
|
|
||||||
}
|
|
||||||
Err(err) => warn!("CtrlRogBios: set_egpu_enable {}", err),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn egpu_enable(&self) -> bool {
|
#[dbus_interface(property)]
|
||||||
self.platform
|
async fn set_ppt_pl1_spl(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
.get_egpu_enable()
|
platform_set_with_min_max!(self, ppt_pl1_spl, "ppt_pl1_spl", value, 5, 250)
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlRogBios: get_egpu_enable {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(property)]
|
||||||
async fn notify_egpu_enable(signal_ctxt: &SignalContext<'_>, enable: bool) -> zbus::Result<()> {
|
async fn ppt_pl2_sppt(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, ppt_pl2_sppt, "ppt_pl2_sppt", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_ppt_pl2_sppt(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, ppt_pl2_sppt, "ppt_pl2_sppt", value, 5, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn ppt_fppt(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, ppt_fppt, "ppt_fppt", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_ppt_fppt(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, ppt_fppt, "ppt_fppt", value, 5, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn ppt_apu_sppt(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, ppt_apu_sppt, "ppt_apu_sppt", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_ppt_apu_sppt(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, ppt_apu_sppt, "ppt_apu_sppt", value, 5, 130)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn ppt_platform_sppt(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, ppt_platform_sppt, "ppt_platform_sppt", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_ppt_platform_sppt(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, ppt_platform_sppt, "ppt_platform_sppt", value, 5, 130)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn nv_dynamic_boost(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, nv_dynamic_boost, "nv_dynamic_boost", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_nv_dynamic_boost(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, nv_dynamic_boost, "nv_dynamic_boost", value, 5, 25)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn nv_temp_target(&self) -> Result<u8, FdoErr> {
|
||||||
|
platform_get_value_if_some!(self, nv_temp_target, "nv_temp_target", 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
async fn set_nv_temp_target(&mut self, value: u8) -> Result<(), FdoErr> {
|
||||||
|
platform_set_with_min_max!(self, nv_temp_target, "nv_temp_target", value, 5, 87)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +328,7 @@ impl crate::Reloadable for CtrlPlatform {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
self.set_panel_overdrive(p)?;
|
self.platform.set_panel_od(p)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -320,12 +336,9 @@ impl crate::Reloadable for CtrlPlatform {
|
|||||||
|
|
||||||
impl CtrlPlatform {
|
impl CtrlPlatform {
|
||||||
task_watch_item!(panel_od platform);
|
task_watch_item!(panel_od platform);
|
||||||
|
// task_watch_item!(dgpu_disable platform);
|
||||||
task_watch_item!(dgpu_disable platform);
|
// task_watch_item!(egpu_enable platform);
|
||||||
|
// task_watch_item!(mini_led_mode platform);
|
||||||
task_watch_item!(egpu_enable platform);
|
|
||||||
|
|
||||||
task_watch_item!(mini_led_mode platform);
|
|
||||||
// NOTE: see note further below
|
// NOTE: see note further below
|
||||||
// task_watch_item!(gpu_mux_mode platform);
|
// task_watch_item!(gpu_mux_mode platform);
|
||||||
}
|
}
|
||||||
@@ -347,7 +360,8 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
let lock = platform1.config.lock().await;
|
let lock = platform1.config.lock().await;
|
||||||
if !sleeping && platform1.platform.has_panel_od() {
|
if !sleeping && platform1.platform.has_panel_od() {
|
||||||
platform1
|
platform1
|
||||||
.set_panel_overdrive(lock.panel_od)
|
.platform
|
||||||
|
.set_panel_od(lock.panel_od)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlCharge: panel_od {}", err);
|
warn!("CtrlCharge: panel_od {}", err);
|
||||||
err
|
err
|
||||||
@@ -363,7 +377,8 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
let lock = platform2.config.lock().await;
|
let lock = platform2.config.lock().await;
|
||||||
if !shutting_down && platform2.platform.has_panel_od() {
|
if !shutting_down && platform2.platform.has_panel_od() {
|
||||||
platform2
|
platform2
|
||||||
.set_panel_overdrive(lock.panel_od)
|
.platform
|
||||||
|
.set_panel_od(lock.panel_od)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlCharge: panel_od {}", err);
|
warn!("CtrlCharge: panel_od {}", err);
|
||||||
err
|
err
|
||||||
@@ -384,9 +399,9 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
self.watch_panel_od(signal_ctxt.clone()).await?;
|
self.watch_panel_od(signal_ctxt.clone()).await?;
|
||||||
self.watch_dgpu_disable(signal_ctxt.clone()).await?;
|
// self.watch_dgpu_disable(signal_ctxt.clone()).await?;
|
||||||
self.watch_egpu_enable(signal_ctxt.clone()).await?;
|
// self.watch_egpu_enable(signal_ctxt.clone()).await?;
|
||||||
self.watch_mini_led_mode(signal_ctxt.clone()).await?;
|
// self.watch_mini_led_mode(signal_ctxt.clone()).await?;
|
||||||
// NOTE: Can't have this as a watch because on a write to it, it reverts back to
|
// NOTE: Can't have this as a watch because on a write to it, it reverts back to
|
||||||
// booted-with value as it does not actually change until reboot.
|
// booted-with value as it does not actually change until reboot.
|
||||||
// self.watch_gpu_mux_mode(signal_ctxt.clone()).await?;
|
// self.watch_gpu_mux_mode(signal_ctxt.clone()).await?;
|
||||||
|
|||||||
@@ -72,10 +72,15 @@ macro_rules! task_watch_item {
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut buffer = [0; 32];
|
let mut buffer = [0; 32];
|
||||||
watch.into_event_stream(&mut buffer).unwrap().for_each(|_| async {
|
watch.into_event_stream(&mut buffer).unwrap().for_each(|_| async {
|
||||||
let value = ctrl.$name();
|
if let Ok(value) = ctrl.$name(){
|
||||||
concat_idents::concat_idents!(notif_fn = notify_, $name {
|
concat_idents::concat_idents!(notif_fn = $name, _changed {
|
||||||
Self::notif_fn(&signal_ctxt, value).await.ok();
|
Self::notif_fn(&ctrl, &signal_ctxt).await.ok();
|
||||||
});
|
});
|
||||||
|
if let Some(mut lock) = ctrl.config.try_lock() {
|
||||||
|
lock.$name = value;
|
||||||
|
lock.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
}).await;
|
}).await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ impl AsusPlatform {
|
|||||||
|
|
||||||
attr_bool!("mini_led_mode", path);
|
attr_bool!("mini_led_mode", path);
|
||||||
|
|
||||||
attr_bool!("gpu_mux_mode", path);
|
attr_u8!("gpu_mux_mode", path);
|
||||||
|
|
||||||
attr_u8!(
|
attr_u8!(
|
||||||
/// This is technically the same as `platform_profile` since both are
|
/// This is technically the same as `platform_profile` since both are
|
||||||
@@ -100,6 +100,12 @@ impl AsusPlatform {
|
|||||||
path
|
path
|
||||||
);
|
);
|
||||||
|
|
||||||
|
attr_bool!(
|
||||||
|
/// Control the POST animation "FWOOoosh" sound
|
||||||
|
"post_animation_sound",
|
||||||
|
path
|
||||||
|
);
|
||||||
|
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
@@ -146,7 +152,7 @@ impl Default for AsusPlatform {
|
|||||||
impl From<AsusPlatform> for PlatformSupportedFunctions {
|
impl From<AsusPlatform> for PlatformSupportedFunctions {
|
||||||
fn from(a: AsusPlatform) -> Self {
|
fn from(a: AsusPlatform) -> Self {
|
||||||
PlatformSupportedFunctions {
|
PlatformSupportedFunctions {
|
||||||
post_sound: false,
|
post_animation_sound: a.has_post_animation_sound(),
|
||||||
gpu_mux: a.has_gpu_mux_mode(),
|
gpu_mux: a.has_gpu_mux_mode(),
|
||||||
panel_overdrive: a.has_panel_od(),
|
panel_overdrive: a.has_panel_od(),
|
||||||
dgpu_disable: a.has_dgpu_disable(),
|
dgpu_disable: a.has_dgpu_disable(),
|
||||||
@@ -164,6 +170,7 @@ impl From<AsusPlatform> for PlatformSupportedFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
|
#[repr(u8)]
|
||||||
#[derive(Serialize, Deserialize, Default, Type, Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Serialize, Deserialize, Default, Type, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum GpuMode {
|
pub enum GpuMode {
|
||||||
Discrete,
|
Discrete,
|
||||||
@@ -177,13 +184,34 @@ pub enum GpuMode {
|
|||||||
NotSupported,
|
NotSupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u8> for GpuMode {
|
||||||
|
fn from(v: u8) -> Self {
|
||||||
|
match v {
|
||||||
|
0 => GpuMode::Discrete,
|
||||||
|
1 => GpuMode::Optimus,
|
||||||
|
2 => GpuMode::Integrated,
|
||||||
|
3 => GpuMode::Egpu,
|
||||||
|
4 => GpuMode::Vfio,
|
||||||
|
5 => GpuMode::Ultimate,
|
||||||
|
6 => GpuMode::Error,
|
||||||
|
_ => GpuMode::NotSupported,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GpuMode> for u8 {
|
||||||
|
fn from(v: GpuMode) -> Self {
|
||||||
|
v as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GpuMode {
|
impl GpuMode {
|
||||||
/// For writing to `gpu_mux_mode` attribute
|
/// For writing to `gpu_mux_mode` attribute
|
||||||
pub fn to_mux_attr(&self) -> bool {
|
pub fn to_mux_attr(&self) -> u8 {
|
||||||
if *self == Self::Discrete {
|
if *self == Self::Discrete {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
true
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_dgpu_attr(&self) -> u8 {
|
pub fn to_dgpu_attr(&self) -> u8 {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ pub struct LedSupportedFunctions {
|
|||||||
#[typeshare]
|
#[typeshare]
|
||||||
#[derive(Serialize, Deserialize, Type, Debug, Default, Clone)]
|
#[derive(Serialize, Deserialize, Type, Debug, Default, Clone)]
|
||||||
pub struct PlatformSupportedFunctions {
|
pub struct PlatformSupportedFunctions {
|
||||||
pub post_sound: bool,
|
pub post_animation_sound: bool,
|
||||||
pub gpu_mux: bool,
|
pub gpu_mux: bool,
|
||||||
pub panel_overdrive: bool,
|
pub panel_overdrive: bool,
|
||||||
pub dgpu_disable: bool,
|
pub dgpu_disable: bool,
|
||||||
@@ -132,7 +132,7 @@ impl fmt::Display for LedSupportedFunctions {
|
|||||||
impl fmt::Display for PlatformSupportedFunctions {
|
impl fmt::Display for PlatformSupportedFunctions {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
writeln!(f, "ROG BIOS:")?;
|
writeln!(f, "ROG BIOS:")?;
|
||||||
writeln!(f, "\tPOST sound switch: {}", self.post_sound)?;
|
writeln!(f, "\tPOST sound switch: {}", self.post_animation_sound)?;
|
||||||
writeln!(f, "\tPanel Overdrive: {}", self.panel_overdrive)?;
|
writeln!(f, "\tPanel Overdrive: {}", self.panel_overdrive)?;
|
||||||
writeln!(f, "\tMiniLED backlight: {}", self.mini_led_mode)?;
|
writeln!(f, "\tMiniLED backlight: {}", self.mini_led_mode)?;
|
||||||
writeln!(f, "\tdGPU disable switch: {}", self.dgpu_disable)?;
|
writeln!(f, "\tdGPU disable switch: {}", self.dgpu_disable)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user