mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
376 lines
8.8 KiB
Rust
376 lines
8.8 KiB
Rust
use std::fmt::Display;
|
|
use std::path::PathBuf;
|
|
use std::str::FromStr;
|
|
|
|
use log::{info, warn};
|
|
use serde::{Deserialize, Serialize};
|
|
use typeshare::typeshare;
|
|
use zbus::zvariant::{OwnedValue, Type, Value};
|
|
|
|
use crate::error::{PlatformError, Result};
|
|
use crate::{attr_bool, attr_string, attr_u8, to_device};
|
|
|
|
/// The "platform" device provides access to things like:
|
|
/// - `dgpu_disable`
|
|
/// - `egpu_enable`
|
|
/// - `panel_od`
|
|
/// - `gpu_mux`
|
|
/// - various CPU an GPU tunings
|
|
/// - `keyboard_mode`, set keyboard RGB mode and speed
|
|
/// - `keyboard_state`, set keyboard power states
|
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
|
|
pub struct RogPlatform {
|
|
path: PathBuf,
|
|
pp_path: PathBuf,
|
|
}
|
|
|
|
impl RogPlatform {
|
|
attr_bool!("dgpu_disable", path);
|
|
|
|
attr_bool!("egpu_enable", path);
|
|
|
|
attr_u8!("gpu_mux_mode", path);
|
|
|
|
attr_bool!("panel_od", path);
|
|
|
|
attr_bool!("mini_led_mode", path);
|
|
|
|
attr_u8!(
|
|
/// This is technically the same as `platform_profile` since both are
|
|
/// tied in-kernel
|
|
"throttle_thermal_policy",
|
|
path
|
|
);
|
|
|
|
attr_string!(
|
|
/// The acpi platform_profile support
|
|
"platform_profile",
|
|
pp_path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Package Power Target total of CPU: PL1 on Intel, SPL on AMD.
|
|
/// Shown on Intel+Nvidia or AMD+Nvidia based systems:
|
|
/// * min=5, max=250
|
|
"ppt_pl1_spl",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT,
|
|
/// on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems:
|
|
/// * min=5, max=250
|
|
"ppt_pl2_sppt",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Fast Package Power Tracking Limit of CPU. AMD+Nvidia only:
|
|
/// * min=5, max=250
|
|
"ppt_fppt",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// APU SPPT limit. Shown on full AMD systems only:
|
|
/// * min=5, max=130
|
|
"ppt_apu_sppt",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Platform SPPT limit. Shown on full AMD systems only:
|
|
/// * min=5, max=130
|
|
"ppt_platform_sppt",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Dynamic boost limit of the Nvidia dGPU:
|
|
/// * min=5, max=25
|
|
"nv_dynamic_boost",
|
|
path
|
|
);
|
|
|
|
attr_u8!(
|
|
/// Target temperature limit of the Nvidia dGPU:
|
|
/// * min=75, max=87
|
|
"nv_temp_target",
|
|
path
|
|
);
|
|
|
|
attr_bool!(
|
|
/// Control the POST animation "FWOOoosh" sound
|
|
"boot_sound",
|
|
path
|
|
);
|
|
|
|
pub fn new() -> Result<Self> {
|
|
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
|
warn!("{}", err);
|
|
PlatformError::Udev("enumerator failed".into(), err)
|
|
})?;
|
|
enumerator.match_subsystem("platform").map_err(|err| {
|
|
warn!("{}", err);
|
|
PlatformError::Udev("match_subsystem failed".into(), err)
|
|
})?;
|
|
enumerator.match_sysname("asus-nb-wmi").map_err(|err| {
|
|
warn!("{}", err);
|
|
PlatformError::Udev("match_subsystem failed".into(), err)
|
|
})?;
|
|
|
|
if let Some(device) = (enumerator.scan_devices().map_err(|err| {
|
|
warn!("{}", err);
|
|
PlatformError::Udev("scan_devices failed".into(), err)
|
|
})?)
|
|
.next()
|
|
{
|
|
info!("Found platform support at {:?}", device.sysname());
|
|
return Ok(Self {
|
|
path: device.syspath().to_owned(),
|
|
pp_path: PathBuf::from_str("/sys/firmware/acpi").unwrap(),
|
|
});
|
|
}
|
|
Err(PlatformError::MissingFunction(
|
|
"asus-nb-wmi not found".into(),
|
|
))
|
|
}
|
|
}
|
|
|
|
impl Default for RogPlatform {
|
|
fn default() -> Self {
|
|
unsafe {
|
|
Self {
|
|
path: PathBuf::from_str("/this_shouldNeVErr_exisid").unwrap_unchecked(),
|
|
pp_path: PathBuf::from_str("/this_shouldNeVErr_exisid").unwrap_unchecked(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[typeshare]
|
|
#[repr(u8)]
|
|
#[derive(
|
|
Serialize, Deserialize, Default, Type, Value, OwnedValue, Debug, PartialEq, Eq, Clone, Copy,
|
|
)]
|
|
pub enum GpuMode {
|
|
Optimus = 0,
|
|
Integrated = 1,
|
|
Egpu = 2,
|
|
Vfio = 3,
|
|
Ultimate = 4,
|
|
#[default]
|
|
Error = 254,
|
|
NotSupported = 255,
|
|
}
|
|
|
|
impl From<u8> for GpuMode {
|
|
fn from(v: u8) -> Self {
|
|
match v {
|
|
0 => GpuMode::Optimus,
|
|
1 => GpuMode::Integrated,
|
|
2 => GpuMode::Egpu,
|
|
3 => GpuMode::Vfio,
|
|
4 => GpuMode::Ultimate,
|
|
5 => GpuMode::Error,
|
|
_ => GpuMode::NotSupported,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<GpuMode> for u8 {
|
|
fn from(v: GpuMode) -> Self {
|
|
v as u8
|
|
}
|
|
}
|
|
|
|
impl GpuMode {
|
|
/// For writing to `gpu_mux_mode` attribute
|
|
pub fn to_mux_attr(&self) -> u8 {
|
|
if *self == Self::Ultimate {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
pub fn to_dgpu_attr(&self) -> u8 {
|
|
if *self == Self::Integrated {
|
|
return 1;
|
|
}
|
|
0
|
|
}
|
|
|
|
pub fn to_egpu_attr(&self) -> u8 {
|
|
if *self == Self::Egpu {
|
|
return 1;
|
|
}
|
|
0
|
|
}
|
|
|
|
pub fn from_mux(num: u8) -> Self {
|
|
if num == 0 {
|
|
return Self::Ultimate;
|
|
}
|
|
Self::Optimus
|
|
}
|
|
|
|
pub fn from_dgpu(num: u8) -> Self {
|
|
if num == 1 {
|
|
return Self::Integrated;
|
|
}
|
|
Self::Optimus
|
|
}
|
|
|
|
// `from_dgpu()` should be called also, and should take precedence if result
|
|
// are not equal.
|
|
pub fn from_egpu(num: u8) -> Self {
|
|
if num == 1 {
|
|
return Self::Egpu;
|
|
}
|
|
Self::Optimus
|
|
}
|
|
}
|
|
|
|
impl Display for GpuMode {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
GpuMode::Optimus => write!(f, "Optimus"),
|
|
GpuMode::Integrated => write!(f, "Integrated"),
|
|
GpuMode::Egpu => write!(f, "eGPU"),
|
|
GpuMode::Vfio => write!(f, "VFIO"),
|
|
GpuMode::Ultimate => write!(f, "Ultimate"),
|
|
GpuMode::Error => write!(f, "Error"),
|
|
GpuMode::NotSupported => write!(f, "Not Supported"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[typeshare]
|
|
#[repr(u32)]
|
|
#[derive(
|
|
Deserialize,
|
|
Serialize,
|
|
Default,
|
|
Type,
|
|
Value,
|
|
OwnedValue,
|
|
Debug,
|
|
PartialEq,
|
|
Eq,
|
|
PartialOrd,
|
|
Ord,
|
|
Hash,
|
|
Clone,
|
|
Copy,
|
|
)]
|
|
#[zvariant(signature = "u")]
|
|
/// `throttle_thermal_policy` in asus_wmi
|
|
pub enum ThrottlePolicy {
|
|
#[default]
|
|
Balanced = 0,
|
|
Performance = 1,
|
|
Quiet = 2,
|
|
}
|
|
|
|
impl ThrottlePolicy {
|
|
pub const fn next(self) -> Self {
|
|
match self {
|
|
Self::Balanced => Self::Performance,
|
|
Self::Performance => Self::Quiet,
|
|
Self::Quiet => Self::Balanced,
|
|
}
|
|
}
|
|
|
|
pub const fn list() -> [Self; 3] {
|
|
[Self::Balanced, Self::Performance, Self::Quiet]
|
|
}
|
|
}
|
|
|
|
impl From<u8> for ThrottlePolicy {
|
|
fn from(num: u8) -> Self {
|
|
match num {
|
|
0 => Self::Balanced,
|
|
1 => Self::Performance,
|
|
2 => Self::Quiet,
|
|
_ => {
|
|
warn!("Unknown number for PlatformProfile: {}", num);
|
|
Self::Balanced
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<i32> for ThrottlePolicy {
|
|
fn from(num: i32) -> Self {
|
|
(num as u8).into()
|
|
}
|
|
}
|
|
|
|
impl From<ThrottlePolicy> for u8 {
|
|
fn from(p: ThrottlePolicy) -> Self {
|
|
match p {
|
|
ThrottlePolicy::Balanced => 0,
|
|
ThrottlePolicy::Performance => 1,
|
|
ThrottlePolicy::Quiet => 2,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ThrottlePolicy> for i32 {
|
|
fn from(p: ThrottlePolicy) -> Self {
|
|
<u8>::from(p) as i32
|
|
}
|
|
}
|
|
|
|
impl From<ThrottlePolicy> for &str {
|
|
fn from(profile: ThrottlePolicy) -> &'static str {
|
|
match profile {
|
|
ThrottlePolicy::Balanced => "balanced",
|
|
ThrottlePolicy::Performance => "performance",
|
|
ThrottlePolicy::Quiet => "quiet",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for ThrottlePolicy {
|
|
type Err = PlatformError;
|
|
|
|
fn from_str(profile: &str) -> Result<Self> {
|
|
match profile.to_ascii_lowercase().trim() {
|
|
"balanced" => Ok(ThrottlePolicy::Balanced),
|
|
"performance" => Ok(ThrottlePolicy::Performance),
|
|
"quiet" => Ok(ThrottlePolicy::Quiet),
|
|
_ => Err(PlatformError::NotSupported),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for ThrottlePolicy {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", self)
|
|
}
|
|
}
|
|
|
|
/// CamelCase names of the properties. Intended for use with DBUS
|
|
#[typeshare]
|
|
#[repr(u8)]
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type, PartialEq, PartialOrd)]
|
|
#[zvariant(signature = "s")]
|
|
pub enum Properties {
|
|
ChargeControlEndThreshold,
|
|
DgpuDisable,
|
|
GpuMuxMode,
|
|
PostAnimationSound,
|
|
PanelOd,
|
|
MiniLedMode,
|
|
EgpuEnable,
|
|
ThrottlePolicy,
|
|
PptPl1Spl,
|
|
PptPl2Sppt,
|
|
PptFppt,
|
|
PptApuSppt,
|
|
PptPlatformSppt,
|
|
NvDynamicBoost,
|
|
NvTempTarget,
|
|
}
|