Compare commits

...

9 Commits

Author SHA1 Message Date
Luke Jones 0aac0ce495 Merge branch 'fluke/refactor-patterns' into 'main'
bugfix: don't deadlock on change compute/vfio/compute

Closes #88 and #86

See merge request asus-linux/asusctl!58
2021-05-15 10:25:03 +00:00
Luke D. Jones e24b4858a4 bugfix: don't deadlock on change compute/vfio/compute
Closes: #86 #88
2021-05-15 22:22:36 +12:00
Luke D. Jones cf2b459e48 Add legal statement for trademarks 2021-05-06 12:29:12 +12:00
Luke D. Jones 895179fdad Add legal statement for trademarks 2021-05-06 12:27:59 +12:00
Luke Jones fe3e8792eb Merge branch 'readmefix' into 'main'
corrected auto-builds url

See merge request asus-linux/asusctl!56
2021-05-03 18:53:15 +00:00
Aaron Johnson 1916641e2e corrected auto-builds url 2021-05-03 12:58:33 -05:00
Luke Jones 3ea0737be9 Merge branch 'fluke/refactor-patterns' into 'main'
Fluke/refactor patterns

See merge request asus-linux/asusctl!55
2021-04-26 03:53:21 +00:00
Luke D. Jones c67373a830 bugfix: add version to user daemon. Fix multiple anime config 2021-04-26 15:49:35 +12:00
Luke D. Jones 41cbf4d353 Refactor dameon gfx 2021-04-25 22:53:38 +12:00
22 changed files with 356 additions and 328 deletions
+10 -1
View File
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
# [3.5.2] - 2021-05-15
### Changed
- Bugfix: prevent the hang on compute/integrated mode change
# [3.5.1] - 2021-04-25
### Changed
+ Anime:
- Fix using multiple configs
# [3.5.0] - 2021-04-25
### Changed
+ Keyboard:
@@ -23,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Enable basic multiple user anime configs (asusd-user must still be restarted)
+ Profiles:
- Enable dbus methods for freq min/max, fan curve, fan preset, CPU turbo enable.
These options will apply to the active profile if no profile name is specified.
These options will apply to the active profile if no profile name is specified.
# [3.4.1] - 2021-04-11
### Changed
Generated
+3 -3
View File
@@ -206,7 +206,7 @@ dependencies = [
[[package]]
name = "daemon"
version = "3.5.0"
version = "3.5.2"
dependencies = [
"env_logger",
"intel-pstate",
@@ -230,7 +230,7 @@ dependencies = [
[[package]]
name = "daemon-user"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"dirs 3.0.1",
"rog_anime",
@@ -899,7 +899,7 @@ checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "rog_anime"
version = "1.0.3"
version = "1.0.4"
dependencies = [
"gif",
"glam",
+1 -1
View File
@@ -13,4 +13,4 @@ opt-level = 1
[profile.bench]
debug = false
opt-level = 3
opt-level = 3
+12 -2
View File
@@ -160,7 +160,7 @@ Requirements are rust >= 1.40 installed from rustup.io if the distro provided ve
## Installing
Packaging and auto-builds are available [here](https://build.opensuse.org/package/show/home:luke_nukem:asus/asus-nb-ctrl)
Packaging and auto-builds are available [here](https://build.opensuse.org/package/show/home:luke_nukem:asus/asusctl)
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/)
@@ -243,6 +243,16 @@ Please file a support request.
omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm "
```
# License
# License & Trademarks
Mozilla Public License 2 (MPL-2.0)
---
ASUS and ROG Trademark is either a US registered trademark or trademark of ASUSTeK Computer Inc. in the United States and/or other countries.
Reference to any ASUS products, services, processes, or other information and/or use of ASUS Trademarks does not constitute or imply endorsement, sponsorship, or recommendation thereof by ASUS.
The use of ROG and ASUS trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with ASUS ROG laptops.
---
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "daemon-user"
version = "1.1.0"
version = "1.1.1"
authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2018"
description = "Usermode daemon for user settings, anime, per-key lighting"
@@ -27,4 +27,4 @@ dirs = "3.0.1"
zbus = "^1.9.1"
zvariant = "^2.6"
zvariant_derive = "^2.6"
zvariant_derive = "^2.6"
+3 -1
View File
@@ -16,7 +16,9 @@ use std::sync::atomic::AtomicBool;
static ANIME_INNER_EARLY_RETURN: AtomicBool = AtomicBool::new(false);
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" rog-dbus version {}", rog_dbus::VERSION);
println!("user daemon v{}", rog_user::VERSION);
println!(" rog-anime v{}", rog_anime::VERSION);
println!(" rog-dbus v{}", rog_dbus::VERSION);
let (client, _) = AuraDbusClient::new().unwrap();
let supported = client.proxies().supported().get_supported_functions()?;
+2
View File
@@ -7,3 +7,5 @@ pub mod ctrl_anime;
pub mod zbus_anime;
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
+4 -6
View File
@@ -63,7 +63,7 @@ impl UserAnimeConfig {
create_dir(path.clone())?;
}
path.push(name + ".cfg");
path.push(name.clone() + ".cfg");
let mut file = OpenOptions::new()
.read(true)
@@ -75,7 +75,7 @@ impl UserAnimeConfig {
if let Ok(read_len) = file.read_to_string(&mut buf) {
if read_len == 0 {
let default = UserAnimeConfig::default();
let default = UserAnimeConfig { name, ..Default::default() };
let json = serde_json::to_string_pretty(&default).unwrap();
file.write_all(json.as_bytes())?;
return Ok(default);
@@ -89,7 +89,7 @@ impl UserAnimeConfig {
impl Default for UserAnimeConfig {
fn default() -> Self {
let x = Self {
Self {
name: "default".to_string(),
anime: vec![
AnimeAction::AsusAnimation {
@@ -122,9 +122,7 @@ impl Default for UserAnimeConfig {
time: AnimTime::Cycles(2),
},
],
};
println!("{}", serde_json::to_string_pretty(&x).unwrap());
x
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "daemon"
version = "3.5.0"
version = "3.5.2"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
@@ -1,3 +1,4 @@
use ::zbus::Connection;
use ctrl_gfx::error::GfxError;
use ctrl_gfx::*;
use ctrl_rog_bios::CtrlRogBios;
@@ -14,8 +15,6 @@ use std::{str::FromStr, sync::mpsc};
use std::{sync::Arc, sync::Mutex};
use sysfs_class::{PciDevice, SysClass};
use system::{GraphicsDevice, PciBus};
use zbus::{dbus_interface, Connection};
use zvariant::ObjectPath;
use crate::*;
@@ -32,62 +31,6 @@ pub struct CtrlGraphics {
thread_kill: Arc<Mutex<Option<mpsc::Sender<bool>>>>,
}
trait Dbus {
fn vendor(&self) -> zbus::fdo::Result<GfxVendors>;
fn power(&self) -> zbus::fdo::Result<GfxPower>;
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction>;
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>;
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>;
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlGraphics {
fn vendor(&self) -> zbus::fdo::Result<GfxVendors> {
self.get_gfx_mode().map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})
}
fn power(&self) -> zbus::fdo::Result<GfxPower> {
Self::get_runtime_status().map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})
}
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
info!("GFX: Switching gfx mode to {}", <&str>::from(vendor));
let msg = self.set_gfx_config(vendor).map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})?;
self.notify_gfx(&vendor)
.unwrap_or_else(|err| warn!("GFX: {}", err));
self.notify_action(&msg)
.unwrap_or_else(|err| warn!("GFX: {}", err));
Ok(msg)
}
#[dbus_interface(signal)]
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()> {}
#[dbus_interface(signal)]
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()> {}
}
impl ZbusAdd for CtrlGraphics {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&ObjectPath::from_str_unchecked("/org/asuslinux/Gfx"), self)
.map_err(|err| {
warn!("GFX: CtrlGraphics: add_to_server {}", err);
err
})
.ok();
}
}
impl Reloadable for CtrlGraphics {
fn reload(&mut self) -> Result<(), RogError> {
self.auto_power()?;
@@ -183,7 +126,7 @@ impl CtrlGraphics {
Ok(GfxVendors::Hybrid)
}
fn get_runtime_status() -> Result<GfxPower, RogError> {
pub(super) fn get_runtime_status() -> Result<GfxPower, RogError> {
let path = Path::new("/sys/bus/pci/devices/0000:01:00.0/power/runtime_status");
if path.exists() {
let buf = std::fs::read_to_string(path).map_err(|err| {
@@ -664,11 +607,14 @@ impl CtrlGraphics {
let bus = self.bus.clone();
Self::do_vendor_tasks(vendor, vfio_enable, &devices, &bus)?;
info!("GFX: Graphics mode changed to {}", <&str>::from(vendor));
if let Ok(config) = self.config.lock() {
if matches!(vendor, GfxVendors::Compute | GfxVendors::Vfio)
&& config.gfx_save_compute_vfio
{
Self::save_gfx_mode(vendor, self.config.clone());
if matches!(vendor, GfxVendors::Compute | GfxVendors::Vfio) {
loop {
if let Ok(config) = self.config.try_lock() {
if config.gfx_save_compute_vfio {
Self::save_gfx_mode(vendor, self.config.clone());
}
return Ok(action_required);
}
}
}
}
@@ -682,7 +628,7 @@ impl CtrlGraphics {
let devices = self.nvidia.clone();
let bus = self.bus.clone();
let vfio_enable = if let Ok(config) = self.config.lock() {
let vfio_enable = if let Ok(config) = self.config.try_lock() {
config.gfx_vfio_enable
} else {
false
+3 -1
View File
@@ -1,9 +1,11 @@
pub mod error;
pub mod gfx;
pub mod controller;
pub mod system;
pub mod zbus_gfx;
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];
const VFIO_DRIVERS: [&str; 5] = [
+56
View File
@@ -0,0 +1,56 @@
use rog_types::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors};
use ::zbus::{dbus_interface};
use zvariant::ObjectPath;
use log::{error, warn, info};
use crate::ZbusAdd;
use super::controller::CtrlGraphics;
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlGraphics {
fn vendor(&self) -> zbus::fdo::Result<GfxVendors> {
self.get_gfx_mode().map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})
}
fn power(&self) -> zbus::fdo::Result<GfxPower> {
Self::get_runtime_status().map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})
}
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
info!("GFX: Switching gfx mode to {}", <&str>::from(vendor));
let msg = self.set_gfx_config(vendor).map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})?;
self.notify_gfx(&vendor)
.unwrap_or_else(|err| warn!("GFX: {}", err));
self.notify_action(&msg)
.unwrap_or_else(|err| warn!("GFX: {}", err));
Ok(msg)
}
#[dbus_interface(signal)]
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()> {}
#[dbus_interface(signal)]
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()> {}
}
impl ZbusAdd for CtrlGraphics {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&ObjectPath::from_str_unchecked("/org/asuslinux/Gfx"), self)
.map_err(|err| {
warn!("GFX: CtrlGraphics: add_to_server {}", err);
err
})
.ok();
}
}
+240
View File
@@ -0,0 +1,240 @@
use crate::error::RogError;
use crate::{config::Config, GetSupported};
use log::{info, warn};
use rog_types::{
profile::{FanLevel, Profile, ProfileEvent},
supported::FanCpuSupportedFunctions,
};
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use super::*;
pub struct CtrlFanAndCpu {
pub path: &'static str,
pub config: Arc<Mutex<Config>>,
}
impl GetSupported for CtrlFanAndCpu {
type A = FanCpuSupportedFunctions;
fn get_supported() -> Self::A {
FanCpuSupportedFunctions {
stock_fan_modes: CtrlFanAndCpu::get_fan_path().is_ok(),
min_max_freq: intel_pstate::PState::new().is_ok(),
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
}
}
}
impl crate::Reloadable for CtrlFanAndCpu {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
let profile = config.active_profile.clone();
self.set(&profile, &mut config)?;
// info!(
// "Reloaded fan mode: {:?}",
// FanLevel::from(config.power_profile)
// );
}
Ok(())
}
}
impl CtrlFanAndCpu {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlFanAndCpu::get_fan_path()?;
info!("Device has thermal throttle control");
Ok(CtrlFanAndCpu { path, config })
}
fn get_fan_path() -> Result<&'static str, RogError> {
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(RogError::MissingFunction(
"Fan mode not available, you may require a v5.8.10 series kernel or newer".into(),
))
}
}
/// Toggle to next profile in list
pub(super) fn do_next_profile(&mut self, config: &mut Config) -> Result<(), RogError> {
config.read();
let mut i = config
.toggle_profiles
.iter()
.position(|x| x == &config.active_profile)
.map(|i| i + 1)
.unwrap_or(0);
if i >= config.toggle_profiles.len() {
i = 0;
}
let new_profile = config
.toggle_profiles
.get(i)
.unwrap_or(&config.active_profile)
.clone();
self.set(&new_profile, config)?;
info!("Profile was changed: {}", &new_profile);
Ok(())
}
fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> {
let mode = config.active_profile.clone();
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
config.read();
let mut mode_config = config
.power_profiles
.get_mut(&mode)
.ok_or_else(|| RogError::MissingProfile(mode.clone()))?;
config.curr_fan_mode = preset;
mode_config.fan_preset = preset;
config.write();
fan_ctrl
.write_all(format!("{}\n", preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
info!("Fan mode set to: {:?}", FanLevel::from(preset));
Ok(())
}
pub(super) fn handle_profile_event(
&mut self,
event: &ProfileEvent,
config: &mut Config,
) -> Result<(), RogError> {
match event {
ProfileEvent::Toggle => self.do_next_profile(config)?,
ProfileEvent::ChangeMode(mode) => {
self.set_fan_mode(*mode, config)?;
let mode = config.active_profile.clone();
self.set_pstate_for_fan_mode(&mode, config)?;
self.set_fan_curve_for_fan_mode(&mode, config)?;
}
ProfileEvent::Cli(command) => {
let profile_key = match command.profile.as_ref() {
Some(k) => k.clone(),
None => config.active_profile.clone(),
};
let mut profile = if command.create {
config
.power_profiles
.entry(profile_key.clone())
.or_insert_with(Profile::default)
} else {
config
.power_profiles
.get_mut(&profile_key)
.ok_or_else(|| RogError::MissingProfile(profile_key.clone()))?
};
if command.turbo.is_some() {
profile.turbo = command.turbo.unwrap();
}
if let Some(min_perc) = command.min_percentage {
profile.min_percentage = min_perc;
}
if let Some(max_perc) = command.max_percentage {
profile.max_percentage = max_perc;
}
if let Some(ref preset) = command.fan_preset {
profile.fan_preset = preset.into();
}
if let Some(ref curve) = command.curve {
profile.fan_curve = Some(curve.clone());
}
self.set(&profile_key, config)?;
}
}
Ok(())
}
pub(super) fn set(&mut self, profile: &str, config: &mut Config) -> Result<(), RogError> {
let mode_config = config
.power_profiles
.get(profile)
.ok_or_else(|| RogError::MissingProfile(profile.into()))?;
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
config.curr_fan_mode = mode_config.fan_preset;
fan_ctrl
.write_all(format!("{}\n", mode_config.fan_preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
self.set_pstate_for_fan_mode(profile, config)?;
self.set_fan_curve_for_fan_mode(profile, config)?;
config.active_profile = profile.into();
config.write();
Ok(())
}
fn set_pstate_for_fan_mode(&self, mode: &str, config: &mut Config) -> Result<(), RogError> {
info!("Setting pstate");
let mode_config = config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
// Set CPU pstate
if let Ok(pstate) = intel_pstate::PState::new() {
pstate.set_min_perf_pct(mode_config.min_percentage)?;
pstate.set_max_perf_pct(mode_config.max_percentage)?;
pstate.set_no_turbo(!mode_config.turbo)?;
info!(
"Intel CPU Power: min: {}%, max: {}%, turbo: {}",
mode_config.min_percentage, mode_config.max_percentage, mode_config.turbo
);
} else {
info!("Setting pstate for AMD CPU");
// must be AMD CPU
let mut file = OpenOptions::new()
.write(true)
.open(AMD_BOOST_PATH)
.map_err(|err| RogError::Path(self.path.into(), err))?;
let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel
file.write_all(boost.as_bytes())
.map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?;
info!("AMD CPU Turbo: {}", boost);
}
Ok(())
}
fn set_fan_curve_for_fan_mode(&self, mode: &str, config: &Config) -> Result<(), RogError> {
let mode_config = &config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
if let Some(ref curve) = mode_config.fan_curve {
use rog_fan_curve::{Board, Fan};
if let Some(board) = Board::from_board_name() {
curve.apply(board, Fan::Cpu)?;
curve.apply(board, Fan::Gpu)?;
} else {
warn!("Fan curve unsupported on this board.")
}
}
Ok(())
}
}
+1 -237
View File
@@ -1,243 +1,7 @@
pub mod zbus;
use crate::error::RogError;
use crate::{config::Config, GetSupported};
use log::{info, warn};
use rog_types::{
profile::{FanLevel, Profile, ProfileEvent},
supported::FanCpuSupportedFunctions,
};
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
pub mod controller;
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 struct CtrlFanAndCpu {
pub path: &'static str,
config: Arc<Mutex<Config>>,
}
impl GetSupported for CtrlFanAndCpu {
type A = FanCpuSupportedFunctions;
fn get_supported() -> Self::A {
FanCpuSupportedFunctions {
stock_fan_modes: CtrlFanAndCpu::get_fan_path().is_ok(),
min_max_freq: intel_pstate::PState::new().is_ok(),
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
}
}
}
impl crate::Reloadable for CtrlFanAndCpu {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
let profile = config.active_profile.clone();
self.set(&profile, &mut config)?;
// info!(
// "Reloaded fan mode: {:?}",
// FanLevel::from(config.power_profile)
// );
}
Ok(())
}
}
impl CtrlFanAndCpu {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlFanAndCpu::get_fan_path()?;
info!("Device has thermal throttle control");
Ok(CtrlFanAndCpu { path, config })
}
fn get_fan_path() -> Result<&'static str, RogError> {
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(RogError::MissingFunction(
"Fan mode not available, you may require a v5.8.10 series kernel or newer".into(),
))
}
}
/// Toggle to next profile in list
pub(super) fn do_next_profile(&mut self, config: &mut Config) -> Result<(), RogError> {
config.read();
let mut i = config
.toggle_profiles
.iter()
.position(|x| x == &config.active_profile)
.map(|i| i + 1)
.unwrap_or(0);
if i >= config.toggle_profiles.len() {
i = 0;
}
let new_profile = config
.toggle_profiles
.get(i)
.unwrap_or(&config.active_profile)
.clone();
self.set(&new_profile, config)?;
info!("Profile was changed: {}", &new_profile);
Ok(())
}
fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> {
let mode = config.active_profile.clone();
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
config.read();
let mut mode_config = config
.power_profiles
.get_mut(&mode)
.ok_or_else(|| RogError::MissingProfile(mode.clone()))?;
config.curr_fan_mode = preset;
mode_config.fan_preset = preset;
config.write();
fan_ctrl
.write_all(format!("{}\n", preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
info!("Fan mode set to: {:?}", FanLevel::from(preset));
Ok(())
}
fn handle_profile_event(
&mut self,
event: &ProfileEvent,
config: &mut Config,
) -> Result<(), RogError> {
match event {
ProfileEvent::Toggle => self.do_next_profile(config)?,
ProfileEvent::ChangeMode(mode) => {
self.set_fan_mode(*mode, config)?;
let mode = config.active_profile.clone();
self.set_pstate_for_fan_mode(&mode, config)?;
self.set_fan_curve_for_fan_mode(&mode, config)?;
}
ProfileEvent::Cli(command) => {
let profile_key = match command.profile.as_ref() {
Some(k) => k.clone(),
None => config.active_profile.clone(),
};
let mut profile = if command.create {
config
.power_profiles
.entry(profile_key.clone())
.or_insert_with(Profile::default)
} else {
config
.power_profiles
.get_mut(&profile_key)
.ok_or_else(|| RogError::MissingProfile(profile_key.clone()))?
};
if command.turbo.is_some() {
profile.turbo = command.turbo.unwrap();
}
if let Some(min_perc) = command.min_percentage {
profile.min_percentage = min_perc;
}
if let Some(max_perc) = command.max_percentage {
profile.max_percentage = max_perc;
}
if let Some(ref preset) = command.fan_preset {
profile.fan_preset = preset.into();
}
if let Some(ref curve) = command.curve {
profile.fan_curve = Some(curve.clone());
}
self.set(&profile_key, config)?;
}
}
Ok(())
}
fn set(&mut self, profile: &str, config: &mut Config) -> Result<(), RogError> {
let mode_config = config
.power_profiles
.get(profile)
.ok_or_else(|| RogError::MissingProfile(profile.into()))?;
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
config.curr_fan_mode = mode_config.fan_preset;
fan_ctrl
.write_all(format!("{}\n", mode_config.fan_preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
self.set_pstate_for_fan_mode(profile, config)?;
self.set_fan_curve_for_fan_mode(profile, config)?;
config.active_profile = profile.into();
config.write();
Ok(())
}
fn set_pstate_for_fan_mode(&self, mode: &str, config: &mut Config) -> Result<(), RogError> {
info!("Setting pstate");
let mode_config = config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
// Set CPU pstate
if let Ok(pstate) = intel_pstate::PState::new() {
pstate.set_min_perf_pct(mode_config.min_percentage)?;
pstate.set_max_perf_pct(mode_config.max_percentage)?;
pstate.set_no_turbo(!mode_config.turbo)?;
info!(
"Intel CPU Power: min: {}%, max: {}%, turbo: {}",
mode_config.min_percentage, mode_config.max_percentage, mode_config.turbo
);
} else {
info!("Setting pstate for AMD CPU");
// must be AMD CPU
let mut file = OpenOptions::new()
.write(true)
.open(AMD_BOOST_PATH)
.map_err(|err| RogError::Path(self.path.into(), err))?;
let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel
file.write_all(boost.as_bytes())
.map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?;
info!("AMD CPU Turbo: {}", boost);
}
Ok(())
}
fn set_fan_curve_for_fan_mode(&self, mode: &str, config: &Config) -> Result<(), RogError> {
let mode_config = &config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
if let Some(ref curve) = mode_config.fan_curve {
use rog_fan_curve::{Board, Fan};
if let Some(board) = Board::from_board_name() {
curve.apply(board, Fan::Cpu)?;
curve.apply(board, Fan::Gpu)?;
} else {
warn!("Fan curve unsupported on this board.")
}
}
Ok(())
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ use std::sync::Mutex;
use zbus::{dbus_interface, fdo::Error};
use zvariant::ObjectPath;
use super::CtrlFanAndCpu;
use super::controller::CtrlFanAndCpu;
pub struct FanAndCpuZbus {
inner: Arc<Mutex<CtrlFanAndCpu>>,
+1 -4
View File
@@ -3,10 +3,7 @@ use serde_derive::{Deserialize, Serialize};
use zbus::dbus_interface;
use zvariant::ObjectPath;
use crate::{
ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::CtrlKbdLed,
ctrl_profiles::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios, GetSupported,
};
use crate::{GetSupported, ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::CtrlKbdLed, ctrl_profiles::controller::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios};
use rog_types::supported::{
AnimeSupportedFunctions, ChargeSupportedFunctions, FanCpuSupportedFunctions,
+2 -2
View File
@@ -3,9 +3,9 @@ use daemon::{
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
};
use daemon::{config_anime::AnimeConfig, config_aura::AuraConfig, ctrl_charge::CtrlCharge};
use daemon::{ctrl_anime::*, ctrl_gfx::gfx::CtrlGraphics};
use daemon::{ctrl_anime::*, ctrl_gfx::controller::CtrlGraphics};
use daemon::{
ctrl_profiles::{zbus::FanAndCpuZbus, CtrlFanAndCpu},
ctrl_profiles::{zbus::FanAndCpuZbus, controller::CtrlFanAndCpu},
laptops::LaptopLedData,
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "rog_anime"
version = "1.0.3"
version = "1.0.4"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
+2
View File
@@ -31,3 +31,5 @@ pub mod error;
/// Provides const methods to create the USB HID control packets
pub mod usb;
pub static VERSION: &str = env!("CARGO_PKG_VERSION");