mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
profiles: add dbus methods to change active profile
Closes #81, #73, #68
This commit is contained in:
25
CHANGELOG.md
25
CHANGELOG.md
@@ -6,15 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Changed
|
### Changed
|
||||||
- Split out all aura functionality that isn't dependent on the daemon in to a
|
+ Keyboard:
|
||||||
new crate `rog-aura`
|
- Split out all aura functionality that isn't dependent on the daemon in to a
|
||||||
- Correctly enable compute mode for nvidia plus no-reboot or logout if switching
|
new crate `rog-aura`
|
||||||
from vfio/integrated/compute.
|
- Keyboard LED control now includes:
|
||||||
- Add asusd config option to not save compute/vfio mode switch.
|
+ Enable/disable LED's while laptop is awake
|
||||||
- Enable basic multiple user anime configs (asusd-user must still be restarted)
|
+ Enable/disable LED animation while laptop is suspended and AC plugged in
|
||||||
- Keyboard LED control now includes:
|
- Properly reload the last used keyboard mode on boot
|
||||||
+ Enable/disable LED's while laptop is awake
|
+ Graphics:
|
||||||
+ Enable/disable LED animation while laptop is suspended and AC plugged in
|
- Correctly enable compute mode for nvidia plus no-reboot or logout if switching
|
||||||
|
from vfio/integrated/compute.
|
||||||
|
- Add asusd config option to not save compute/vfio mode switch.
|
||||||
|
+ Anime:
|
||||||
|
- 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.
|
||||||
|
|
||||||
# [3.4.1] - 2021-04-11
|
# [3.4.1] - 2021-04-11
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -426,18 +426,19 @@ fn handle_profile(
|
|||||||
cmd: &ProfileCommand,
|
cmd: &ProfileCommand,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if !cmd.next
|
if !cmd.next
|
||||||
&& !cmd.create
|
&& !cmd.create // TODO
|
||||||
&& !cmd.list
|
&& !cmd.list
|
||||||
|
&& cmd.profile.is_none()
|
||||||
&& !cmd.active_name
|
&& !cmd.active_name
|
||||||
&& !cmd.active_data
|
&& !cmd.active_data
|
||||||
&& !cmd.profiles_data
|
&& !cmd.profiles_data
|
||||||
&& cmd.remove.is_none()
|
&& cmd.remove.is_none()
|
||||||
&& cmd.curve.is_none()
|
&& cmd.curve.is_none() // TODO
|
||||||
&& cmd.max_percentage.is_none()
|
&& cmd.fan_preset.is_none() // TODO
|
||||||
|
&& cmd.turbo.is_none() // TODO
|
||||||
|
&& cmd.max_percentage.is_none() // TODO
|
||||||
&& cmd.min_percentage.is_none()
|
&& cmd.min_percentage.is_none()
|
||||||
&& cmd.fan_preset.is_none()
|
// TODO
|
||||||
&& cmd.profile.is_none()
|
|
||||||
&& cmd.turbo.is_none()
|
|
||||||
{
|
{
|
||||||
if !cmd.help {
|
if !cmd.help {
|
||||||
println!("Missing arg or command\n");
|
println!("Missing arg or command\n");
|
||||||
@@ -456,6 +457,9 @@ fn handle_profile(
|
|||||||
if let Some(lst) = cmd.self_command_list() {
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
println!("\n{}", lst);
|
println!("\n{}", lst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Note: turbo, frequency, fan preset and fan curve options will apply to");
|
||||||
|
println!(" to the currently active profile unless a profile name is specified");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,10 +492,34 @@ fn handle_profile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This must come before the next block of actions so that changing a specific
|
||||||
|
// profile can be done
|
||||||
if cmd.profile.is_some() {
|
if cmd.profile.is_some() {
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.profile()
|
.profile()
|
||||||
.write_command(&ProfileEvent::Cli(cmd.clone()))?
|
.write_command(&ProfileEvent::Cli(cmd.clone()))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(turbo) = cmd.turbo {
|
||||||
|
dbus.proxies().profile().set_turbo(turbo)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(min) = cmd.min_percentage {
|
||||||
|
dbus.proxies().profile().set_min_frequency(min)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(max) = cmd.max_percentage {
|
||||||
|
dbus.proxies().profile().set_max_frequency(max)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref preset) = cmd.fan_preset {
|
||||||
|
dbus.proxies().profile().set_fan_preset(preset.into())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref curve) = cmd.curve {
|
||||||
|
let s = curve.as_config_string();
|
||||||
|
dbus.proxies().profile().set_fan_curve(&s)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use zbus::dbus_interface;
|
|||||||
use zvariant::ObjectPath;
|
use zvariant::ObjectPath;
|
||||||
use zvariant_derive::Type;
|
use zvariant_derive::Type;
|
||||||
|
|
||||||
use crate::{error::Error, user_config::{UserAnimeConfig, UserConfig}};
|
use crate::{error::Error, user_config::UserAnimeConfig};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
||||||
pub enum TimeType {
|
pub enum TimeType {
|
||||||
|
|||||||
@@ -46,8 +46,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
)?));
|
)?));
|
||||||
// Need new client object for dbus control part
|
// Need new client object for dbus control part
|
||||||
let (client, _) = AuraDbusClient::new().unwrap();
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
let anime_control =
|
let anime_control = CtrlAnime::new(
|
||||||
CtrlAnime::new(anime_config, inner.clone(), client, &ANIME_INNER_EARLY_RETURN)?;
|
anime_config,
|
||||||
|
inner.clone(),
|
||||||
|
client,
|
||||||
|
&ANIME_INNER_EARLY_RETURN,
|
||||||
|
)?;
|
||||||
anime_control.add_to_server(&mut server);
|
anime_control.add_to_server(&mut server);
|
||||||
// Thread using inner
|
// Thread using inner
|
||||||
let _anime_thread = thread::Builder::new()
|
let _anime_thread = thread::Builder::new()
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
use std::{fs::{create_dir, OpenOptions}, io::{Read, Write}, time::Duration};
|
use std::{
|
||||||
|
fs::{create_dir, OpenOptions},
|
||||||
|
io::{Read, Write},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use rog_anime::{AnimTime, AnimeAction, Sequences, Vec2};
|
use rog_anime::{AnimTime, AnimeAction, Sequences, Vec2};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
@@ -133,7 +137,7 @@ pub struct UserConfig {
|
|||||||
impl UserConfig {
|
impl UserConfig {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
active_anime: "anime-default".to_string()
|
active_anime: "anime-default".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ use crate::{
|
|||||||
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
||||||
};
|
};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_aura::{AuraEffect, LED_MSG_LEN, LedBrightness, usb::{LED_APPLY, LED_AWAKE_OFF, LED_AWAKE_ON, LED_SET, LED_SLEEP_OFF, LED_SLEEP_ON}};
|
use rog_aura::{
|
||||||
|
usb::{LED_APPLY, LED_AWAKE_OFF, LED_AWAKE_ON, LED_SET, LED_SLEEP_OFF, LED_SLEEP_ON},
|
||||||
|
AuraEffect, LedBrightness, LED_MSG_LEN,
|
||||||
|
};
|
||||||
use rog_types::supported::LedSupportedFunctions;
|
use rog_types::supported::LedSupportedFunctions;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
@@ -312,11 +315,7 @@ impl CtrlKbdLed {
|
|||||||
|
|
||||||
/// Set the keyboard LED to active if laptop is awake
|
/// Set the keyboard LED to active if laptop is awake
|
||||||
fn set_awake_enable(&self, enabled: bool) -> Result<(), RogError> {
|
fn set_awake_enable(&self, enabled: bool) -> Result<(), RogError> {
|
||||||
let bytes = if enabled {
|
let bytes = if enabled { LED_AWAKE_ON } else { LED_AWAKE_OFF };
|
||||||
LED_AWAKE_ON
|
|
||||||
} else {
|
|
||||||
LED_AWAKE_OFF
|
|
||||||
};
|
|
||||||
self.write_bytes(&bytes)?;
|
self.write_bytes(&bytes)?;
|
||||||
self.write_bytes(&LED_SET)?;
|
self.write_bytes(&LED_SET)?;
|
||||||
// Changes won't persist unless apply is set
|
// Changes won't persist unless apply is set
|
||||||
@@ -326,11 +325,7 @@ impl CtrlKbdLed {
|
|||||||
|
|
||||||
/// Set the keyboard suspend animation to on if plugged in
|
/// Set the keyboard suspend animation to on if plugged in
|
||||||
fn set_sleep_anim_enable(&self, enabled: bool) -> Result<(), RogError> {
|
fn set_sleep_anim_enable(&self, enabled: bool) -> Result<(), RogError> {
|
||||||
let bytes = if enabled {
|
let bytes = if enabled { LED_SLEEP_ON } else { LED_SLEEP_OFF };
|
||||||
LED_SLEEP_ON
|
|
||||||
} else {
|
|
||||||
LED_SLEEP_OFF
|
|
||||||
};
|
|
||||||
self.write_bytes(&bytes)?;
|
self.write_bytes(&bytes)?;
|
||||||
self.write_bytes(&LED_SET)?;
|
self.write_bytes(&LED_SET)?;
|
||||||
// Changes won't persist unless apply is set
|
// Changes won't persist unless apply is set
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
pub mod zbus;
|
||||||
|
|
||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
use crate::{config::Config, GetSupported};
|
use crate::{config::Config, GetSupported};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
@@ -10,8 +12,6 @@ use std::io::Write;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use zbus::{dbus_interface, fdo::Error};
|
|
||||||
use zvariant::ObjectPath;
|
|
||||||
|
|
||||||
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
|
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 FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
|
||||||
@@ -34,160 +34,6 @@ impl GetSupported for CtrlFanAndCpu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FanAndCpuZbus {
|
|
||||||
inner: Arc<Mutex<CtrlFanAndCpu>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FanAndCpuZbus {
|
|
||||||
pub fn new(inner: Arc<Mutex<CtrlFanAndCpu>>) -> Self {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl FanAndCpuZbus {
|
|
||||||
/// Set profile details
|
|
||||||
fn set_profile(&self, profile: String) {
|
|
||||||
if let Ok(event) = serde_json::from_str(&profile) {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
ctrl.handle_profile_event(&event, &mut cfg)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
|
||||||
if let Ok(json) = serde_json::to_string(profile) {
|
|
||||||
self.notify_profile(&json)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile name
|
|
||||||
fn next_profile(&mut self) {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
ctrl.do_next_profile(&mut cfg)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
|
||||||
if let Ok(json) = serde_json::to_string(profile) {
|
|
||||||
self.notify_profile(&json)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile name
|
|
||||||
fn active_profile_name(&mut self) -> zbus::fdo::Result<String> {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get active profile name".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Profile can't implement Type because of Curve
|
|
||||||
/// Fetch the active profile details
|
|
||||||
fn profile(&mut self) -> zbus::fdo::Result<String> {
|
|
||||||
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) {
|
|
||||||
if let Ok(json) = serde_json::to_string_pretty(profile) {
|
|
||||||
return Ok(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get active profile details".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch all profile data
|
|
||||||
fn profiles(&mut self) -> zbus::fdo::Result<String> {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
if let Ok(json) = serde_json::to_string_pretty(&cfg.power_profiles) {
|
|
||||||
return Ok(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::Failed(
|
|
||||||
"Failed to get all profile details".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn profile_names(&self) -> zbus::fdo::Result<Vec<String>> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(Error::Failed("Failed to get all profile names".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove(&self, profile: &str) -> 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 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(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(Error::Failed("Failed to lock configuration".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
|
||||||
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::ZbusAdd for FanAndCpuZbus {
|
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
|
||||||
server
|
|
||||||
.at(
|
|
||||||
&ObjectPath::from_str_unchecked("/org/asuslinux/Profile"),
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("DbusFanAndCpu: add_to_server {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlFanAndCpu {
|
impl crate::Reloadable for CtrlFanAndCpu {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if let Ok(mut config) = self.config.clone().try_lock() {
|
||||||
255
daemon/src/ctrl_profiles/zbus.rs
Normal file
255
daemon/src/ctrl_profiles/zbus.rs
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
use log::warn;
|
||||||
|
use rog_fan_curve::Curve;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use zbus::{dbus_interface, fdo::Error};
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
|
use super::CtrlFanAndCpu;
|
||||||
|
|
||||||
|
pub struct FanAndCpuZbus {
|
||||||
|
inner: Arc<Mutex<CtrlFanAndCpu>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FanAndCpuZbus {
|
||||||
|
pub fn new(inner: Arc<Mutex<CtrlFanAndCpu>>) -> Self {
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl FanAndCpuZbus {
|
||||||
|
/// Set profile details
|
||||||
|
fn set_profile(&self, profile: String) {
|
||||||
|
if let Ok(event) = serde_json::from_str(&profile) {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
ctrl.handle_profile_event(&event, &mut cfg)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
|
if let Ok(json) = serde_json::to_string(profile) {
|
||||||
|
self.notify_profile(&json)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_turbo(&self, enable: bool) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.turbo = enable;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_min_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.min_percentage = percentage;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_max_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.max_percentage = percentage;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_fan_preset(&self, preset: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if preset > 2 {
|
||||||
|
return Err(zbus::fdo::Error::InvalidArgs(
|
||||||
|
"Fan preset must be 0, 1, or 2".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.fan_preset = preset;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_fan_curve(&self, curve: String) -> zbus::fdo::Result<()> {
|
||||||
|
let curve = Curve::from_config_str(&curve)
|
||||||
|
.map_err(|err| zbus::fdo::Error::InvalidArgs(format!("Fan curve error: {}", err)))?;
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.fan_curve = Some(curve);
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the active profile name
|
||||||
|
fn next_profile(&mut self) {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
ctrl.do_next_profile(&mut cfg)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
|
if let Ok(json) = serde_json::to_string(profile) {
|
||||||
|
self.notify_profile(&json)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the active profile name
|
||||||
|
fn active_profile_name(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get active profile name".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Profile can't implement Type because of Curve
|
||||||
|
/// Fetch the active profile details
|
||||||
|
fn profile(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
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) {
|
||||||
|
if let Ok(json) = serde_json::to_string_pretty(profile) {
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get active profile details".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all profile data
|
||||||
|
fn profiles(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
if let Ok(json) = serde_json::to_string_pretty(&cfg.power_profiles) {
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get all profile details".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn profile_names(&self) -> zbus::fdo::Result<Vec<String>> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::Failed("Failed to get all profile names".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&self, profile: &str) -> 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 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(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::Failed("Failed to lock configuration".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::ZbusAdd for FanAndCpuZbus {
|
||||||
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
|
server
|
||||||
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Profile"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("DbusFanAndCpu: add_to_server {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ use zbus::dbus_interface;
|
|||||||
use zvariant::ObjectPath;
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_fan_cpu::CtrlFanAndCpu,
|
ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::CtrlKbdLed,
|
||||||
ctrl_leds::CtrlKbdLed, ctrl_rog_bios::CtrlRogBios, GetSupported,
|
ctrl_profiles::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios, GetSupported,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rog_types::supported::{
|
use rog_types::supported::{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use daemon::ctrl_leds::{CtrlKbdLed, CtrlKbdLedTask, CtrlKbdLedZbus, CtrlKbdLedReloader};
|
use daemon::ctrl_leds::{CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus};
|
||||||
use daemon::{
|
use daemon::{
|
||||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||||
};
|
};
|
||||||
use daemon::{config_anime::AnimeConfig, config_aura::AuraConfig, ctrl_charge::CtrlCharge};
|
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::gfx::CtrlGraphics};
|
||||||
use daemon::{
|
use daemon::{
|
||||||
ctrl_fan_cpu::{CtrlFanAndCpu, FanAndCpuZbus},
|
ctrl_profiles::{zbus::FanAndCpuZbus, CtrlFanAndCpu},
|
||||||
laptops::LaptopLedData,
|
laptops::LaptopLedData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,3 +96,10 @@ impl From<std::io::Error> for RogError {
|
|||||||
RogError::Io(err)
|
RogError::Io(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RogError> for zbus::fdo::Error {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: RogError) -> Self {
|
||||||
|
zbus::fdo::Error::Failed(format!("{}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ pub(crate) mod config_old;
|
|||||||
pub mod ctrl_anime;
|
pub mod ctrl_anime;
|
||||||
/// Control of battery charge level
|
/// Control of battery charge level
|
||||||
pub mod ctrl_charge;
|
pub mod ctrl_charge;
|
||||||
|
/// GPU switching and power
|
||||||
|
pub mod ctrl_gfx;
|
||||||
|
/// Keyboard LED brightness control, RGB, and LED display modes
|
||||||
|
pub mod ctrl_leds;
|
||||||
/// Control CPU min/max freq and turbo, fan mode, fan curves
|
/// Control CPU min/max freq and turbo, fan mode, fan curves
|
||||||
///
|
///
|
||||||
/// Intel machines can control:
|
/// Intel machines can control:
|
||||||
@@ -19,11 +23,7 @@ pub mod ctrl_charge;
|
|||||||
/// - CPU turbo enable/disable
|
/// - CPU turbo enable/disable
|
||||||
/// - Fan mode (normal, boost, silent)
|
/// - Fan mode (normal, boost, silent)
|
||||||
/// - Fan min/max RPM curve
|
/// - Fan min/max RPM curve
|
||||||
pub mod ctrl_fan_cpu;
|
pub mod ctrl_profiles;
|
||||||
/// GPU switching and power
|
|
||||||
pub mod ctrl_gfx;
|
|
||||||
/// Keyboard LED brightness control, RGB, and LED display modes
|
|
||||||
pub mod ctrl_leds;
|
|
||||||
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
|
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
|
||||||
pub mod ctrl_rog_bios;
|
pub mod ctrl_rog_bios;
|
||||||
/// Laptop matching to determine capabilities
|
/// Laptop matching to determine capabilities
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
use std::{
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@@ -27,7 +22,7 @@ impl Sequences {
|
|||||||
/// Use a base `AnimeAction` to generate the precomputed data and insert in to
|
/// Use a base `AnimeAction` to generate the precomputed data and insert in to
|
||||||
/// the run buffer
|
/// the run buffer
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert(&mut self, index: usize) -> Result<(), Error> {
|
pub fn insert(&mut self, _index: usize) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,4 +33,4 @@ pub const LED_SLEEP_ON: [u8; 17] = [
|
|||||||
/// Disable animations when the laptop is suspended while plugged in
|
/// Disable animations when the laptop is suspended while plugged in
|
||||||
pub const LED_SLEEP_OFF: [u8; 17] = [
|
pub const LED_SLEEP_OFF: [u8; 17] = [
|
||||||
0x5d, 0xbd, 0x01, 0xcf, 0x17, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0x5d, 0xbd, 0x01, 0xcf, 0x17, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -50,6 +50,21 @@ trait Daemon {
|
|||||||
/// SetProfile method
|
/// SetProfile method
|
||||||
fn set_profile(&self, profile: &str) -> zbus::Result<()>;
|
fn set_profile(&self, profile: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetFanCurve method
|
||||||
|
fn set_fan_curve(&self, curve: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetFanPreset method
|
||||||
|
fn set_fan_preset(&self, preset: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetMaxFrequency method
|
||||||
|
fn set_max_frequency(&self, percentage: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetMinFrequency method
|
||||||
|
fn set_min_frequency(&self, percentage: u8) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetTurbo method
|
||||||
|
fn set_turbo(&self, enable: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyProfile signal
|
/// NotifyProfile signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_profile(&self, profile: &str) -> zbus::Result<()>;
|
fn notify_profile(&self, profile: &str) -> zbus::Result<()>;
|
||||||
@@ -87,12 +102,44 @@ impl<'a> ProfileProxy<'a> {
|
|||||||
self.0.next_profile()
|
self.0.next_profile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SetFanCurve, set fan curve for active profile
|
||||||
|
#[inline]
|
||||||
|
pub fn set_fan_curve(&self, curve: &str) -> zbus::Result<()> {
|
||||||
|
self.0.set_fan_curve(curve)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SetFanPreset, set fan preset for active profile
|
||||||
|
#[inline]
|
||||||
|
pub fn set_fan_preset(&self, preset: u8) -> zbus::Result<()> {
|
||||||
|
self.0.set_fan_preset(preset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SetMaxFrequency, set max percentage of frequency for active profile
|
||||||
|
#[inline]
|
||||||
|
pub fn set_max_frequency(&self, percentage: u8) -> zbus::Result<()> {
|
||||||
|
self.0.set_max_frequency(percentage)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SetMinFrequency, set min percentage of frequency for active profile
|
||||||
|
#[inline]
|
||||||
|
pub fn set_min_frequency(&self, percentage: u8) -> zbus::Result<()> {
|
||||||
|
self.0.set_min_frequency(percentage)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SetTurbo, set turbo enable for active profile
|
||||||
|
#[inline]
|
||||||
|
pub fn set_turbo(&self, enable: bool) -> zbus::Result<()> {
|
||||||
|
self.0.set_turbo(enable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_fan_mode(&self, level: u8) -> Result<()> {
|
pub fn write_fan_mode(&self, level: u8) -> Result<()> {
|
||||||
self.0
|
self.0
|
||||||
.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level)).unwrap())
|
.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level)).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_command(&self, cmd: &ProfileEvent) -> Result<()> {
|
pub fn write_command(&self, cmd: &ProfileEvent) -> Result<()> {
|
||||||
self.0.set_profile(&serde_json::to_string(cmd).unwrap())
|
self.0.set_profile(&serde_json::to_string(cmd).unwrap())
|
||||||
|
|||||||
Reference in New Issue
Block a user