mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Update config & dbus parts, cleanup deps, device power states
- Add extra config options and dbus methods - Add power state signals for anime and led - Refactor to use channels for dbus signal handler send/recv - Split out profiles independant parts to a rog-profiles crate - Cleanup dependencies - Fix some dbus Supported issues
This commit is contained in:
18
rog-profiles/Cargo.toml
Normal file
18
rog-profiles/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "rog_profiles"
|
||||
version = "0.1.0"
|
||||
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["dbus"]
|
||||
dbus = ["zvariant", "zvariant_derive"]
|
||||
|
||||
[dependencies]
|
||||
rog_fan_curve = { version = "^0.1", features = ["serde"] }
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
intel-pstate = "^0.2"
|
||||
|
||||
zvariant = { version = "^2.6", optional = true }
|
||||
zvariant_derive = { version = "^2.6", optional = true }
|
||||
54
rog-profiles/src/error.rs
Normal file
54
rog-profiles/src/error.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::fmt;
|
||||
|
||||
use intel_pstate::PStateError;
|
||||
use rog_fan_curve::CurveError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProfileError {
|
||||
ParseFanLevel,
|
||||
MissingProfile(String),
|
||||
Path(String, std::io::Error),
|
||||
Read(String, std::io::Error),
|
||||
Write(String, std::io::Error),
|
||||
NotSupported,
|
||||
NotFound(String),
|
||||
IntelPstate(PStateError),
|
||||
FanCurve(CurveError),
|
||||
Io(std::io::Error),
|
||||
//Zbus(zbus::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for ProfileError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ProfileError::ParseFanLevel => write!(f, "Parse profile error"),
|
||||
ProfileError::MissingProfile(profile) => {
|
||||
write!(f, "Profile does not exist {}", profile)
|
||||
}
|
||||
ProfileError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
||||
ProfileError::Read(path, error) => write!(f, "Read {}: {}", path, error),
|
||||
ProfileError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
||||
ProfileError::NotSupported => write!(f, "Not supported"),
|
||||
ProfileError::NotFound(deets) => write!(f, "Not found: {}", deets),
|
||||
ProfileError::IntelPstate(err) => write!(f, "Intel pstate error: {}", err),
|
||||
ProfileError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err),
|
||||
ProfileError::Io(detail) => write!(f, "std::io error: {}", detail),
|
||||
//Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ProfileError {}
|
||||
|
||||
impl From<PStateError> for ProfileError {
|
||||
fn from(err: PStateError) -> Self {
|
||||
ProfileError::IntelPstate(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CurveError> for ProfileError {
|
||||
fn from(err: CurveError) -> Self {
|
||||
ProfileError::FanCurve(err)
|
||||
}
|
||||
}
|
||||
8
rog-profiles/src/lib.rs
Normal file
8
rog-profiles/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
pub mod error;
|
||||
pub mod profiles;
|
||||
|
||||
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
|
||||
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
|
||||
static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost";
|
||||
|
||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
185
rog-profiles/src/profiles.rs
Normal file
185
rog-profiles/src/profiles.rs
Normal file
@@ -0,0 +1,185 @@
|
||||
use rog_fan_curve::{Curve, Fan};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::io::Write;
|
||||
use std::{fs::OpenOptions, path::Path, str::FromStr};
|
||||
#[cfg(feature = "dbus")]
|
||||
use zvariant_derive::Type;
|
||||
|
||||
use crate::{error::ProfileError, AMD_BOOST_PATH, FAN_TYPE_1_PATH, FAN_TYPE_2_PATH};
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Profile {
|
||||
pub name: String,
|
||||
pub min_percentage: u8,
|
||||
pub max_percentage: u8,
|
||||
pub turbo: bool,
|
||||
pub fan_preset: FanLevel,
|
||||
pub fan_curve: String,
|
||||
}
|
||||
|
||||
impl Default for Profile {
|
||||
fn default() -> Self {
|
||||
Profile {
|
||||
name: "new".into(),
|
||||
min_percentage: 0,
|
||||
max_percentage: 100,
|
||||
turbo: false,
|
||||
fan_preset: FanLevel::Normal,
|
||||
fan_curve: "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn new(
|
||||
name: String,
|
||||
min_percentage: u8,
|
||||
max_percentage: u8,
|
||||
turbo: bool,
|
||||
fan_preset: FanLevel,
|
||||
fan_curve: String,
|
||||
) -> Self {
|
||||
Profile {
|
||||
name,
|
||||
min_percentage,
|
||||
max_percentage,
|
||||
turbo,
|
||||
fan_preset,
|
||||
fan_curve,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_intel_supported() -> bool {
|
||||
intel_pstate::PState::new().is_ok()
|
||||
}
|
||||
|
||||
pub fn get_fan_path() -> Result<&'static str, ProfileError> {
|
||||
if Path::new(FAN_TYPE_1_PATH).exists() {
|
||||
Ok(FAN_TYPE_1_PATH)
|
||||
} else if Path::new(FAN_TYPE_2_PATH).exists() {
|
||||
Ok(FAN_TYPE_2_PATH)
|
||||
} else {
|
||||
Err(ProfileError::NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_system_pstate(&self) -> Result<(), ProfileError> {
|
||||
// Set CPU pstate
|
||||
if let Ok(pstate) = intel_pstate::PState::new() {
|
||||
pstate.set_min_perf_pct(self.min_percentage)?;
|
||||
pstate.set_max_perf_pct(self.max_percentage)?;
|
||||
pstate.set_no_turbo(!self.turbo)?;
|
||||
} else {
|
||||
// must be AMD CPU
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(AMD_BOOST_PATH)
|
||||
.map_err(|err| ProfileError::Path(AMD_BOOST_PATH.into(), err))?;
|
||||
|
||||
let boost = if self.turbo { "1" } else { "0" }; // opposite of Intel
|
||||
file.write_all(boost.as_bytes())
|
||||
.map_err(|err| ProfileError::Write(AMD_BOOST_PATH.into(), err))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_system_fan_mode(&self) -> Result<(), ProfileError> {
|
||||
let path = Profile::get_fan_path()?;
|
||||
let mut fan_ctrl = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(path)
|
||||
.map_err(|err| ProfileError::Path(path.into(), err))?;
|
||||
fan_ctrl
|
||||
.write_all(format!("{}\n", <u8>::from(self.fan_preset)).as_bytes())
|
||||
.map_err(|err| ProfileError::Write(path.into(), err))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_system_fan_curve(&self) -> Result<(), ProfileError> {
|
||||
if !self.fan_curve.is_empty() {
|
||||
if let Ok(curve) = Profile::parse_fan_curve(&self.fan_curve) {
|
||||
use rog_fan_curve::Board;
|
||||
if let Some(board) = Board::from_board_name() {
|
||||
curve.apply(board, Fan::Cpu)?;
|
||||
curve.apply(board, Fan::Gpu)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_system_all(&self) -> Result<(), ProfileError> {
|
||||
self.set_system_pstate()?;
|
||||
if !self.fan_curve.is_empty() {
|
||||
self.set_system_fan_mode()?;
|
||||
} else {
|
||||
self.set_system_fan_curve()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_fan_curve(data: &str) -> Result<Curve, String> {
|
||||
let curve = Curve::from_config_str(data)?;
|
||||
if let Err(err) = curve.check_safety(Fan::Cpu) {
|
||||
return Err(format!("Unsafe curve {:?}", err));
|
||||
}
|
||||
if let Err(err) = curve.check_safety(Fan::Gpu) {
|
||||
return Err(format!("Unsafe curve {:?}", err));
|
||||
}
|
||||
Ok(curve)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum FanLevel {
|
||||
Normal,
|
||||
Boost,
|
||||
Silent,
|
||||
}
|
||||
|
||||
impl FromStr for FanLevel {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"normal" => Ok(FanLevel::Normal),
|
||||
"boost" => Ok(FanLevel::Boost),
|
||||
"silent" => Ok(FanLevel::Silent),
|
||||
_ => Err("Invalid fan level"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for FanLevel {
|
||||
fn from(n: u8) -> Self {
|
||||
match n {
|
||||
0 => FanLevel::Normal,
|
||||
1 => FanLevel::Boost,
|
||||
2 => FanLevel::Silent,
|
||||
_ => FanLevel::Normal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FanLevel> for u8 {
|
||||
fn from(n: FanLevel) -> Self {
|
||||
match n {
|
||||
FanLevel::Normal => 0,
|
||||
FanLevel::Boost => 1,
|
||||
FanLevel::Silent => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&FanLevel> for u8 {
|
||||
fn from(n: &FanLevel) -> Self {
|
||||
match n {
|
||||
FanLevel::Normal => 0,
|
||||
FanLevel::Boost => 1,
|
||||
FanLevel::Silent => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user