Temporary checkpoint

This commit is contained in:
Luke D. Jones
2021-08-22 14:01:05 +12:00
parent 8fcd05c2bb
commit 0ed97db4c1
32 changed files with 553 additions and 2341 deletions

View File

@@ -1,116 +1,114 @@
use crate::error::RogError;
use crate::{config::Config, GetSupported};
use crate::GetSupported;
use log::{info, warn};
use rog_profiles::profiles::Profile;
use rog_types::supported::FanCpuSupportedFunctions;
use rog_profiles::error::ProfileError;
use rog_profiles::{FanCurves, Profile};
use rog_types::supported::PlatformProfileFunctions;
use std::sync::Arc;
use std::sync::Mutex;
pub struct CtrlFanAndCpu {
pub config: Arc<Mutex<Config>>,
use super::config::ProfileConfig;
pub struct CtrlPlatformTask {
config: Arc<Mutex<ProfileConfig>>,
}
impl GetSupported for CtrlFanAndCpu {
type A = FanCpuSupportedFunctions;
impl CtrlPlatformTask {
pub fn new(config: Arc<Mutex<ProfileConfig>>) -> Self {
Self { config }
}
}
impl crate::CtrlTask for CtrlPlatformTask {
fn do_task(&self) -> Result<(), RogError> {
if let Ok(mut lock) = self.config.try_lock() {
// Refresh the config in-case the user has edited it
if let Some(curves) = &mut lock.fan_curves {
curves.update_from_platform();
}
}
Ok(())
}
}
pub struct CtrlPlatformProfile {
pub config: Arc<Mutex<ProfileConfig>>,
}
impl GetSupported for CtrlPlatformProfile {
type A = PlatformProfileFunctions;
fn get_supported() -> Self::A {
FanCpuSupportedFunctions {
stock_fan_modes: Profile::get_fan_path().is_ok(),
min_max_freq: Profile::get_intel_supported(),
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
if !Profile::is_platform_profile_supported() {
warn!(r#"
platform_profile kernel interface not found, your laptop does not support this, or the iterface is missing.
To enable profile support you require a kernel with the following patch applied:
https://lkml.org/lkml/2021/8/18/1022
"#);
}
if !FanCurves::is_fan_curves_supported() {
info!(r#"
fan curves kernel interface not found, your laptop does not support this, or the iterface is missing.
To enable fan-curve support you require a kernel with the following patch applied:
https://lkml.org/lkml/2021/8/20/232
Please note that as of 24/08/2021 this is not final.
"#);
}
PlatformProfileFunctions {
platform_profile: Profile::is_platform_profile_supported(),
fan_curves: FanCurves::is_fan_curves_supported(),
}
}
}
impl crate::Reloadable for CtrlFanAndCpu {
/// Fetcht he active profile and use that to set all related components up
impl crate::Reloadable for CtrlPlatformProfile {
/// Fetch the active profile and use that to set all related components up
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut cfg) = self.config.clone().try_lock() {
let active = cfg.active_profile.clone();
if let Some(existing) = cfg.power_profiles.get_mut(&active) {
existing.set_system_all()?;
if let Ok(cfg) = self.config.clone().try_lock() {
if let Some(curves) = &cfg.fan_curves {
curves.update_platform();
}
}
Ok(())
}
}
impl CtrlFanAndCpu {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
Profile::get_fan_path()?;
info!("Device has fan control available");
Ok(CtrlFanAndCpu { config })
impl CtrlPlatformProfile {
pub fn new(config: Arc<Mutex<ProfileConfig>>) -> Result<Self, RogError> {
if Profile::is_platform_profile_supported() {
info!("Device has profile control available");
return Ok(CtrlPlatformProfile { config });
}
Err(ProfileError::NotSupported.into())
}
/// Toggle to next profile in list
pub(super) fn do_next_profile(&mut self) -> Result<(), RogError> {
pub fn save_config(&self) {
if let Ok(lock) = self.config.lock() {
lock.write();
}
}
/// Toggle to next profile in list. This will first read the config, switch, then write out
pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
// Read first just incase the user has modified the config before calling this
config.read();
let mut toggle_index = config
.toggle_profiles
.binary_search(&config.active_profile)
.unwrap_or(0)
+ 1;
if toggle_index >= config.toggle_profiles.len() {
toggle_index = 0;
match config.active {
Profile::Balanced => {
Profile::set_profile(Profile::Performance);
config.active = Profile::Performance;
}
Profile::Performance => {
Profile::set_profile(Profile::Quiet);
config.active = Profile::Quiet;
}
Profile::Quiet => {
Profile::set_profile(Profile::Balanced);
config.active = Profile::Balanced;
}
}
let profile = config.toggle_profiles[toggle_index].clone();
if let Some(existing) = config.power_profiles.get(&profile) {
existing.set_system_all()?;
config.active_profile = existing.name.clone();
config.write();
info!("Profile was changed to: {}", &profile);
} else {
warn!(
"toggle_profile {} does not exist in power_profiles",
&profile
);
return Err(RogError::MissingProfile(profile.to_string()));
}
}
Ok(())
}
pub(super) fn set_active(&mut self, profile: &str) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
// Read first just incase the user has modified the config before calling this
config.read();
if let Some(existing) = config.power_profiles.get(profile) {
existing.set_system_all()?;
config.active_profile = existing.name.clone();
config.write();
info!("Profile was changed to: {}", profile);
} else {
warn!(
"toggle_profile {} does not exist in power_profiles",
profile
);
return Err(RogError::MissingProfile(profile.to_string()));
}
}
Ok(())
}
/// Create a new profile if the requested name doesn't exist, or modify existing
pub(super) fn new_or_modify(&mut self, profile: &Profile) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
config.read();
if let Some(existing) = config.power_profiles.get_mut(&profile.name) {
*existing = profile.clone();
existing.set_system_all()?;
} else {
config
.power_profiles
.insert(profile.name.clone(), profile.clone());
profile.set_system_all()?;
}
config.active_profile = profile.name.clone();
config.write();
}
Ok(())

View File

@@ -1,3 +1,3 @@
pub mod zbus;
pub mod config;
pub mod controller;
pub mod zbus;

View File

@@ -1,58 +1,54 @@
use log::warn;
use rog_profiles::profiles::Profile;
use rog_profiles::FanCurve;
use rog_profiles::Profile;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::{dbus_interface, fdo::Error};
use zvariant::ObjectPath;
use super::controller::CtrlFanAndCpu;
use super::controller::CtrlPlatformProfile;
pub struct FanAndCpuZbus {
inner: Arc<Mutex<CtrlFanAndCpu>>,
static UNSUPPORTED_MSG: &str =
"Fan curves are not supported on this laptop or you require a patched kernel";
pub struct ProfileZbus {
inner: Arc<Mutex<CtrlPlatformProfile>>,
}
impl FanAndCpuZbus {
pub fn new(inner: Arc<Mutex<CtrlFanAndCpu>>) -> Self {
impl ProfileZbus {
pub fn new(inner: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
Self { inner }
}
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl FanAndCpuZbus {
/// Create new profile and make active
fn set_profile(&self, profile: String) {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.set_active(&profile)
.unwrap_or_else(|err| warn!("{}", err));
impl ProfileZbus {
/// Fetch profile names
fn profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
if let Ok(profiles) = Profile::get_profile_names() {
return Ok(profiles);
}
self.do_notification();
Err(Error::Failed(
"Failed to get all profile details".to_string(),
))
}
/// New or modify profile details and make active, will create if it does not exist
fn new_or_modify(&self, profile: Profile) {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.new_or_modify(&profile)
.unwrap_or_else(|err| warn!("{}", err));
}
self.do_notification();
}
/// Fetch the active profile name
/// Toggle to next platform_profile. Names provided by `Profiles`
fn next_profile(&mut self) {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.do_next_profile()
ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err));
}
self.do_notification();
}
/// Fetch the active profile name
fn active_name(&mut self) -> zbus::fdo::Result<String> {
fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
return Ok(cfg.active_profile.clone());
return Ok(cfg.active);
}
}
Err(Error::Failed(
@@ -60,94 +56,96 @@ impl FanAndCpuZbus {
))
}
// TODO: Profile can't implement Type because of Curve
/// Fetch the active profile details
fn active_data(&mut self) -> zbus::fdo::Result<Profile> {
/// Set this platform_profile name as active
fn set_active_profile(&self, profile: Profile) {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
// Read first just incase the user has modified the config before calling this
cfg.read();
Profile::set_profile(profile);
cfg.active = profile;
}
ctrl.save_config();
}
self.do_notification();
}
/// Get a list of profiles that have fan-curves enabled.
fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
return Ok(profile.clone());
if let Some(curves) = &cfg.fan_curves {
return Ok(curves.get_enabled_curve_names().to_vec());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
}
Err(Error::Failed(
"Failed to get active profile details".to_string(),
"Failed to get enabled fan curve names".to_string(),
))
}
/// Fetch all profile data
fn profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
/// Get the fan-curve data for the currently active Profile
fn active_fan_curve_data(&mut self) -> zbus::fdo::Result<FanCurve> {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
return Ok(cfg.power_profiles.values().cloned().collect());
if let Some(curves) = &cfg.fan_curves {
return Ok((*curves.get_active_fan_curves()).clone());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
}
Err(Error::Failed(
"Failed to get all profile details".to_string(),
))
Err(Error::Failed("Failed to get fan curve data".to_string()))
}
fn profile_names(&self) -> zbus::fdo::Result<Vec<String>> {
/// Get fan-curve data for each Profile as an array of objects
fn fan_curves(&self) -> zbus::fdo::Result<Vec<FanCurve>> {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
let profile_names = cfg.power_profiles.keys().cloned().collect::<Vec<String>>();
return Ok(profile_names);
if let Some(curves) = &cfg.fan_curves {
return Ok(curves.get_all_fan_curves());
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
}
Err(Error::Failed("Failed to get all profile names".to_string()))
Err(Error::Failed("Failed to get all fan curves".to_string()))
}
fn remove(&self, profile: &str) -> zbus::fdo::Result<()> {
/// Set this fan-curve data
fn set_fan_curve(&self, curve: FanCurve) -> zbus::fdo::Result<()> {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
if !cfg.power_profiles.contains_key(profile) {
return Err(Error::Failed("Invalid profile specified".to_string()));
if let Some(curves) = &mut cfg.fan_curves {
curves.set_fan_curve(curve);
}
if cfg.power_profiles.keys().len() == 1 {
return Err(Error::Failed("Cannot delete the last profile".to_string()));
}
if cfg.active_profile == *profile {
return Err(Error::Failed(
"Cannot delete the active profile".to_string(),
));
}
cfg.power_profiles.remove(profile);
cfg.write();
return Ok(());
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
}
ctrl.save_config();
}
Err(Error::Failed("Failed to lock configuration".to_string()))
Err(Error::Failed("Failed to set fan curves".to_string()))
}
#[dbus_interface(signal)]
fn notify_profile(&self, profile: &Profile) -> zbus::Result<()> {}
}
impl FanAndCpuZbus {
impl ProfileZbus {
fn do_notification(&self) {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() {
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
self.notify_profile(profile)
.unwrap_or_else(|err| warn!("{}", err));
}
self.notify_profile(&cfg.active)
.unwrap_or_else(|err| warn!("{}", err));
}
}
}
}
impl crate::ZbusAdd for FanAndCpuZbus {
impl crate::ZbusAdd for ProfileZbus {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(