mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90b0fc434d | |||
| 6743d5bc78 | |||
| def0259d24 | |||
| a678f54f59 | |||
| ebe7e61355 | |||
| bda58c9695 | |||
| e335133bf8 | |||
| 47432524e1 | |||
| 707b3bcc2d | |||
| 60014b8a40 | |||
| 2e4ce27f6b | |||
| b8384c55c3 | |||
| dfe1f02101 | |||
| 7c2fb0be81 | |||
| b05f680650 | |||
| 2a9a436f9c |
@@ -5,6 +5,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
# [3.1.4] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Notify through dbus if user changes profile manually
|
||||||
|
- Better help on CLI, show help only for supported items
|
||||||
|
- Bugfix to gfx switcher
|
||||||
|
|
||||||
|
# [3.1.3] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Hotfix: gracefully handle removing modules in use caused by display-manager not
|
||||||
|
fully shutdown at the time of trying to remove modules. It will now retry every
|
||||||
|
250ms per module
|
||||||
|
|
||||||
|
# [3.1.2] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Test and create /etc/X11/xorg.conf.d/ if it doesn't exist
|
||||||
|
- Hotfix to better report module issues
|
||||||
|
|
||||||
|
# [3.1.1] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Add missing nvidia module nvidia_uvm to gfx ctrl list
|
||||||
|
|
||||||
# [3.1.0] - 2021-03-09
|
# [3.1.0] - 2021-03-09
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Generated
+3
-2
@@ -33,8 +33,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.0"
|
version = "3.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"daemon",
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
@@ -187,7 +188,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.1.0"
|
version = "3.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"intel-pstate",
|
"intel-pstate",
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.0"
|
version = "3.1.1"
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ edition = "2018"
|
|||||||
serde_json = "^1.0"
|
serde_json = "^1.0"
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rog_types = { path = "../rog-types" }
|
rog_types = { path = "../rog-types" }
|
||||||
|
daemon = { path = "../daemon" }
|
||||||
gumdrop = "^0.8"
|
gumdrop = "^0.8"
|
||||||
yansi-term = "^0.1"
|
yansi-term = "^0.1"
|
||||||
|
|
||||||
|
|||||||
+149
-56
@@ -1,3 +1,7 @@
|
|||||||
|
use daemon::{
|
||||||
|
ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions,
|
||||||
|
ctrl_supported::SupportedFunctions,
|
||||||
|
};
|
||||||
use gumdrop::{Opt, Options};
|
use gumdrop::{Opt, Options};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
@@ -104,8 +108,7 @@ struct BiosCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut args: Vec<String> = args().collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
args.remove(0);
|
|
||||||
|
|
||||||
let parsed: CLIStart;
|
let parsed: CLIStart;
|
||||||
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
||||||
@@ -125,65 +128,28 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsed.help_requested() {
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
// As help option don't work with `parse_args_default`
|
|
||||||
// we will call `parse_args_default_or_exit` instead
|
let supported_tmp = dbus.proxies().supported().get_supported_functions()?;
|
||||||
CLIStart::parse_args_default_or_exit();
|
let supported = serde_json::from_str::<SupportedFunctions>(&supported_tmp)?;
|
||||||
|
|
||||||
|
if parsed.help {
|
||||||
|
print_supported_help(&supported, &parsed);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsed.version {
|
if parsed.version {
|
||||||
println!(" asusctl version {}", env!("CARGO_PKG_VERSION"));
|
println!(" asusctl v{}", env!("CARGO_PKG_VERSION"));
|
||||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
println!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||||
println!("rog-types version {}", rog_types::VERSION);
|
println!("rog-types v{}", rog_types::VERSION);
|
||||||
|
println!(" daemon v{}", daemon::VERSION);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
|
||||||
|
|
||||||
match parsed.command {
|
match parsed.command {
|
||||||
Some(CliCommand::LedMode(mode)) => {
|
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
|
||||||
if (mode.command.is_none() && !mode.prev_mode && !mode.next_mode) || mode.help {
|
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.fan_cpu_ctrl, &cmd)?,
|
||||||
println!("Missing arg or command\n\n{}", mode.self_usage());
|
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, cmd)?,
|
||||||
if let Some(lst) = mode.self_command_list() {
|
|
||||||
println!("\n{}", lst);
|
|
||||||
}
|
|
||||||
println!("\nHelp can also be requested on modes, e.g: static --help");
|
|
||||||
}
|
|
||||||
if mode.next_mode && mode.prev_mode {
|
|
||||||
println!("Please specify either next or previous")
|
|
||||||
}
|
|
||||||
if mode.next_mode {
|
|
||||||
dbus.proxies().led().next_led_mode()?;
|
|
||||||
} else if mode.prev_mode {
|
|
||||||
dbus.proxies().led().prev_led_mode()?;
|
|
||||||
} else if let Some(command) = mode.command {
|
|
||||||
dbus.proxies().led().set_led_mode(&command.into())?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(CliCommand::Profile(cmd)) => {
|
|
||||||
if (!cmd.next
|
|
||||||
&& !cmd.create
|
|
||||||
&& cmd.curve.is_none()
|
|
||||||
&& cmd.max_percentage.is_none()
|
|
||||||
&& cmd.min_percentage.is_none()
|
|
||||||
&& cmd.preset.is_none()
|
|
||||||
&& cmd.profile.is_none()
|
|
||||||
&& cmd.turbo.is_none())
|
|
||||||
|| cmd.help
|
|
||||||
{
|
|
||||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
|
||||||
if let Some(lst) = cmd.self_command_list() {
|
|
||||||
println!("\n{}", lst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cmd.next {
|
|
||||||
dbus.proxies().profile().next_fan()?;
|
|
||||||
} else {
|
|
||||||
dbus.proxies()
|
|
||||||
.profile()
|
|
||||||
.write_command(&ProfileEvent::Cli(cmd))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus)?,
|
|
||||||
Some(CliCommand::AniMe(cmd)) => {
|
Some(CliCommand::AniMe(cmd)) => {
|
||||||
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
||||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
@@ -282,10 +248,59 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_supported_help(supported: &SupportedFunctions, parsed: &CLIStart) {
|
||||||
|
// As help option don't work with `parse_args_default`
|
||||||
|
// we will call `parse_args_default_or_exit` instead
|
||||||
|
let usage: Vec<String> = parsed.self_usage().lines().map(|s| s.to_string()).collect();
|
||||||
|
for line in usage.iter().filter(|line| {
|
||||||
|
if line.contains("--fan-mode") && !supported.fan_cpu_ctrl.stock_fan_modes {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("--chg-limit") && !supported.charge_ctrl.charge_level_set {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// command strings are in order of the struct
|
||||||
|
let commands: Vec<String> = CliCommand::usage().lines().map(|s| s.to_string()).collect();
|
||||||
|
println!("\nCommands available");
|
||||||
|
for line in commands.iter().filter(|line| {
|
||||||
|
if line.contains("profile") && !supported.fan_cpu_ctrl.stock_fan_modes && !supported.fan_cpu_ctrl.fan_curve_set {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("led-mode") && supported.keyboard_led.stock_led_modes.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("bios") && (!supported.rog_bios_ctrl.dedicated_gfx_toggle || !supported.rog_bios_ctrl.post_sound_toggle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("anime") && !supported.anime_ctrl.0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supported.fan_cpu_ctrl.stock_fan_modes {
|
||||||
|
println!("Note: Fan mode control is not supported by this laptop");
|
||||||
|
}
|
||||||
|
if !supported.charge_ctrl.charge_level_set {
|
||||||
|
println!("Note: Charge control is not supported by this laptop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn do_gfx(
|
fn do_gfx(
|
||||||
command: GraphicsCommand,
|
|
||||||
dbus_client: &AuraDbusClient,
|
dbus_client: &AuraDbusClient,
|
||||||
|
command: GraphicsCommand,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if command.mode.is_none() || command.help {
|
||||||
|
println!("{}", command.self_usage());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(mode) = command.mode {
|
if let Some(mode) = command.mode {
|
||||||
println!("Changing graphics modes...");
|
println!("Changing graphics modes...");
|
||||||
println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`");
|
println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`");
|
||||||
@@ -331,3 +346,81 @@ fn do_gfx_action(no_confirm: bool, ask_msg: &str, ok_msg: &str) -> bool {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_led_mode(
|
||||||
|
dbus: &AuraDbusClient,
|
||||||
|
supported: &LedSupportedFunctions,
|
||||||
|
mode: &LedModeCommand,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
||||||
|
if !mode.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
println!("{}\n", mode.self_usage());
|
||||||
|
println!("Commands available");
|
||||||
|
|
||||||
|
let commands: Vec<String> = LedModeCommand::command_list().unwrap().lines().map(|s| s.to_string()).collect();
|
||||||
|
for (_, command) in commands.iter().enumerate().filter(|(mode_num, _)| {
|
||||||
|
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
||||||
|
return modes.contains(&(*mode_num as u8))
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}) {
|
||||||
|
println!("{}", command);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nHelp can also be requested on modes, e.g: static --help");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
if mode.next_mode && mode.prev_mode {
|
||||||
|
println!("Please specify either next or previous")
|
||||||
|
}
|
||||||
|
if mode.next_mode {
|
||||||
|
dbus.proxies().led().next_led_mode()?;
|
||||||
|
} else if mode.prev_mode {
|
||||||
|
dbus.proxies().led().prev_led_mode()?;
|
||||||
|
} else if let Some(command) = mode.command.as_ref() {
|
||||||
|
dbus.proxies().led().set_led_mode(&command.into())?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_profile(
|
||||||
|
dbus: &AuraDbusClient,
|
||||||
|
supported: &FanCpuSupportedFunctions,
|
||||||
|
cmd: &ProfileCommand,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if !cmd.next
|
||||||
|
&& !cmd.create
|
||||||
|
&& cmd.curve.is_none()
|
||||||
|
&& cmd.max_percentage.is_none()
|
||||||
|
&& cmd.min_percentage.is_none()
|
||||||
|
&& cmd.fan_preset.is_none()
|
||||||
|
&& cmd.profile.is_none()
|
||||||
|
&& cmd.turbo.is_none()
|
||||||
|
{
|
||||||
|
if !cmd.help {
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
}
|
||||||
|
let usage: Vec<String> = ProfileCommand::usage().lines().map(|s| s.to_string()).collect();
|
||||||
|
for line in usage.iter().filter(|line| {
|
||||||
|
!(line.contains("--curve") && !supported.fan_curve_set)
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
if cmd.next {
|
||||||
|
dbus.proxies().profile().next_fan()?;
|
||||||
|
} else {
|
||||||
|
dbus.proxies()
|
||||||
|
.profile()
|
||||||
|
.write_command(&ProfileEvent::Cli(cmd.clone()))?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.1.0"
|
version = "3.1.4"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use crate::GetSupported;
|
|||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct AnimeSupportedFunctions(bool);
|
pub struct AnimeSupportedFunctions(pub bool);
|
||||||
|
|
||||||
impl GetSupported for CtrlAnimeDisplay {
|
impl GetSupported for CtrlAnimeDisplay {
|
||||||
type A = AnimeSupportedFunctions;
|
type A = AnimeSupportedFunctions;
|
||||||
|
|||||||
@@ -62,7 +62,12 @@ impl DbusFanAndCpu {
|
|||||||
cfg.read();
|
cfg.read();
|
||||||
ctrl.handle_profile_event(&event, &mut cfg)
|
ctrl.handle_profile_event(&event, &mut cfg)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
self.notify_profile(&cfg.active_profile).unwrap_or(());
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,6 +77,7 @@ impl DbusFanAndCpu {
|
|||||||
fn next_profile(&mut self) {
|
fn next_profile(&mut self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
ctrl.do_next_profile(&mut cfg)
|
ctrl.do_next_profile(&mut cfg)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
@@ -258,7 +264,7 @@ impl CtrlFanAndCPU {
|
|||||||
if let Some(max_perc) = command.max_percentage {
|
if let Some(max_perc) = command.max_percentage {
|
||||||
profile.max_percentage = max_perc;
|
profile.max_percentage = max_perc;
|
||||||
}
|
}
|
||||||
if let Some(ref preset) = command.preset {
|
if let Some(ref preset) = command.fan_preset {
|
||||||
profile.fan_preset = preset.into();
|
profile.fan_preset = preset.into();
|
||||||
}
|
}
|
||||||
if let Some(ref curve) = command.curve {
|
if let Some(ref curve) = command.curve {
|
||||||
|
|||||||
@@ -6,13 +6,7 @@ use crate::error::RogError;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GfxError {
|
pub enum GfxError {
|
||||||
ParseVendor,
|
ParseVendor,
|
||||||
Path(String, std::io::Error),
|
|
||||||
Read(String, std::io::Error),
|
|
||||||
Write(String, std::io::Error),
|
|
||||||
Module(String, std::io::Error),
|
|
||||||
Bus(String, std::io::Error),
|
Bus(String, std::io::Error),
|
||||||
Command(String, std::io::Error),
|
|
||||||
Modprobe(String),
|
|
||||||
DisplayManager(String),
|
DisplayManager(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,13 +15,7 @@ impl fmt::Display for GfxError {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
||||||
GfxError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
|
||||||
GfxError::Read(path, error) => write!(f, "Read {}: {}", path, error),
|
|
||||||
GfxError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
|
||||||
GfxError::Module(func, error) => write!(f, "Module error: {}: {}", func, error),
|
|
||||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||||
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
|
||||||
GfxError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
|
||||||
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail),
|
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-37
@@ -2,10 +2,10 @@ use ctrl_gfx::error::GfxError;
|
|||||||
use ctrl_gfx::*;
|
use ctrl_gfx::*;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::gfx_vendors::GfxVendors;
|
use rog_types::gfx_vendors::GfxVendors;
|
||||||
use std::io::Write;
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::{io::Write, ops::Add, path::Path};
|
||||||
use std::{sync::Arc, sync::Mutex};
|
use std::{sync::Arc, sync::Mutex};
|
||||||
use sysfs_class::{PciDevice, SysClass};
|
use sysfs_class::{PciDevice, SysClass};
|
||||||
use system::{GraphicsDevice, PciBus};
|
use system::{GraphicsDevice, PciBus};
|
||||||
@@ -47,8 +47,9 @@ impl Dbus for CtrlGraphics {
|
|||||||
|
|
||||||
fn set_vendor(&mut self, vendor: String) {
|
fn set_vendor(&mut self, vendor: String) {
|
||||||
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
||||||
|
info!("Switching gfx mode to {}", vendor);
|
||||||
let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| {
|
let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| {
|
||||||
warn!("{}", err);
|
error!("{}", err);
|
||||||
format!("Failed: {}", err.to_string())
|
format!("Failed: {}", err.to_string())
|
||||||
});
|
});
|
||||||
self.notify_gfx(&vendor)
|
self.notify_gfx(&vendor)
|
||||||
@@ -173,7 +174,7 @@ impl CtrlGraphics {
|
|||||||
|
|
||||||
fn get_runtime_status() -> Result<String, RogError> {
|
fn get_runtime_status() -> Result<String, RogError> {
|
||||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||||
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
|
let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +191,7 @@ impl CtrlGraphics {
|
|||||||
.arg(action)
|
.arg(action)
|
||||||
.arg("nvidia-fallback.service")
|
.arg("nvidia-fallback.service")
|
||||||
.status()
|
.status()
|
||||||
.map_err(|err| GfxError::Command("systemctl".into(), err))?;
|
.map_err(|err| RogError::Command("systemctl".into(), err))?;
|
||||||
|
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
// Error is ignored in case this service is removed
|
// Error is ignored in case this service is removed
|
||||||
@@ -210,17 +211,22 @@ impl CtrlGraphics {
|
|||||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Writing {}", PRIMARY_GPU_XORG_PATH);
|
if !Path::new(XORG_PATH).exists() {
|
||||||
|
std::fs::create_dir(XORG_PATH).map_err(|err| RogError::Write(XORG_PATH.into(), err))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = XORG_PATH.to_string().add(XORG_FILE);
|
||||||
|
info!("Writing {}", file);
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(PRIMARY_GPU_XORG_PATH)
|
.open(&file)
|
||||||
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?;
|
.map_err(|err| RogError::Write(file, err))?;
|
||||||
|
|
||||||
file.write_all(&text)
|
file.write_all(&text)
|
||||||
.and_then(|_| file.sync_all())
|
.and_then(|_| file.sync_all())
|
||||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,11 +238,11 @@ impl CtrlGraphics {
|
|||||||
.truncate(true)
|
.truncate(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(MODPROBE_PATH)
|
.open(MODPROBE_PATH)
|
||||||
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?;
|
.map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
file.write_all(MODPROBE_BASE)
|
file.write_all(MODPROBE_BASE)
|
||||||
.and_then(|_| file.sync_all())
|
.and_then(|_| file.sync_all())
|
||||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -249,63 +255,87 @@ impl CtrlGraphics {
|
|||||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
||||||
|
|
||||||
Result::from_iter(unbinds.chain(removes))
|
Result::from_iter(unbinds.chain(removes))
|
||||||
.map_err(|err| GfxError::Command("device unbind error".into(), err))?;
|
.map_err(|err| RogError::Command("device unbind error".into(), err))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
||||||
let mut cmd = Command::new(action);
|
let mut cmd= Command::new(action);
|
||||||
cmd.arg(driver);
|
cmd.arg(driver);
|
||||||
|
|
||||||
let status = cmd
|
let mut count = 0;
|
||||||
.status()
|
const MAX_TRIES: i32 = 6;
|
||||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
loop {
|
||||||
if !status.success() {
|
if count > MAX_TRIES {
|
||||||
let msg = format!("{} {} failed: {:?}", action, driver, status);
|
let msg = format!("{} {} failed for unknown reason", action, driver);
|
||||||
error!("{}", msg);
|
error!("{}", msg);
|
||||||
return Err(GfxError::Modprobe(msg).into());
|
return Ok(()) //Err(RogError::Modprobe(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = cmd
|
||||||
|
.output()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if !output.status.success() {
|
||||||
|
if output.stderr.ends_with("is not currently loaded\n".as_bytes()) {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
|
||||||
|
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
|
||||||
|
warn!("{}", msg);
|
||||||
|
warn!("It may be safe to ignore the above error, run `lsmod |grep nvidia` to confirm modules loaded");
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
if count >= MAX_TRIES {
|
||||||
|
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
|
||||||
|
return Err(RogError::Modprobe(msg));
|
||||||
|
}
|
||||||
|
} else if output.status.success() {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_display_manager_action(action: &str) -> Result<(), RogError> {
|
fn do_display_manager_action(action: &str) -> Result<(), RogError> {
|
||||||
let service = "display-manager.service";
|
|
||||||
let mut cmd = Command::new("systemctl");
|
let mut cmd = Command::new("systemctl");
|
||||||
cmd.arg(action);
|
cmd.arg(action);
|
||||||
cmd.arg(service);
|
cmd.arg(DISPLAY_MANAGER);
|
||||||
|
|
||||||
let status = cmd
|
let status = cmd
|
||||||
.status()
|
.status()
|
||||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
let msg = format!("systemctl {} {} failed: {:?}", action, service, status);
|
let msg = format!(
|
||||||
error!("{}", msg);
|
"systemctl {} {} failed: {:?}",
|
||||||
|
action, DISPLAY_MANAGER, status
|
||||||
|
);
|
||||||
return Err(GfxError::DisplayManager(msg).into());
|
return Err(GfxError::DisplayManager(msg).into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_display_manager_inactive() -> Result<(), RogError> {
|
fn wait_display_manager_state(state: &str) -> Result<(), RogError> {
|
||||||
let service = "display-manager.service";
|
|
||||||
let mut cmd = Command::new("systemctl");
|
let mut cmd = Command::new("systemctl");
|
||||||
cmd.arg("is-active");
|
cmd.arg("is-active");
|
||||||
cmd.arg(service);
|
cmd.arg(DISPLAY_MANAGER);
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
while count <= 4 {
|
while count <= 5 {
|
||||||
let output = cmd
|
let output = cmd
|
||||||
.output()
|
.output()
|
||||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
if output.stdout.starts_with("inactive".as_bytes()) {
|
if output.stdout.starts_with(state.as_bytes()) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
return Err(
|
return Err(
|
||||||
GfxError::DisplayManager("display-manager did not completely stop".into()).into(),
|
GfxError::DisplayManager(format!("display-manager timed out waiting for {} state", state).into()).into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,18 +348,16 @@ impl CtrlGraphics {
|
|||||||
.rescan()
|
.rescan()
|
||||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
||||||
|
|
||||||
let drivers = vec!["nvidia_drm", "nvidia_modeset", "nvidia"]; // i2c_nvidia_gpu?
|
|
||||||
|
|
||||||
match vendor {
|
match vendor {
|
||||||
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||||
for driver in drivers {
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
Self::do_driver_action(driver, "modprobe")?;
|
Self::do_driver_action(driver, "modprobe")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: compute mode, needs different setup
|
// TODO: compute mode, needs different setup
|
||||||
// GfxVendors::Compute => {}
|
// GfxVendors::Compute => {}
|
||||||
GfxVendors::Integrated => {
|
GfxVendors::Integrated => {
|
||||||
for driver in drivers {
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
}
|
}
|
||||||
self.unbind_remove_nvidia()?;
|
self.unbind_remove_nvidia()?;
|
||||||
@@ -345,9 +373,13 @@ impl CtrlGraphics {
|
|||||||
/// Will stop and start display manager without warning
|
/// Will stop and start display manager without warning
|
||||||
pub fn set_gfx_config(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
pub fn set_gfx_config(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||||
Self::do_display_manager_action("stop")?;
|
Self::do_display_manager_action("stop")?;
|
||||||
Self::wait_display_manager_inactive()?;
|
Self::wait_display_manager_state("inactive")?;
|
||||||
self.do_vendor_tasks(vendor)?;
|
self.do_vendor_tasks(vendor)?;
|
||||||
Self::do_display_manager_action("start")?;
|
Self::do_display_manager_action("start")?;
|
||||||
|
if Self::wait_display_manager_state("active").is_err() {
|
||||||
|
Self::do_display_manager_action("restart")?;
|
||||||
|
}
|
||||||
|
Self::wait_display_manager_state("active")?;
|
||||||
// TODO: undo if failed? Save last mode, catch errors...
|
// TODO: undo if failed? Save last mode, catch errors...
|
||||||
let v: &str = vendor.into();
|
let v: &str = vendor.into();
|
||||||
Ok(format!("Graphics mode changed to {} successfully", v))
|
Ok(format!("Graphics mode changed to {} successfully", v))
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ pub mod gfx;
|
|||||||
|
|
||||||
pub mod system;
|
pub mod system;
|
||||||
|
|
||||||
|
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];
|
||||||
|
|
||||||
|
const DISPLAY_MANAGER: &str = "display-manager.service";
|
||||||
|
|
||||||
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
||||||
|
|
||||||
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
||||||
@@ -15,7 +19,8 @@ options nvidia NVreg_DynamicPowerManagement=0x02
|
|||||||
options nvidia-drm modeset=1
|
options nvidia-drm modeset=1
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
const PRIMARY_GPU_XORG_PATH: &str = "/etc/X11/xorg.conf.d/90-nvidia-primary.conf";
|
const XORG_FILE: &str = "90-nvidia-primary.conf";
|
||||||
|
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
|
||||||
|
|
||||||
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
||||||
Section "OutputClass"
|
Section "OutputClass"
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct SupportedFunctions {
|
pub struct SupportedFunctions {
|
||||||
anime_ctrl: AnimeSupportedFunctions,
|
pub anime_ctrl: AnimeSupportedFunctions,
|
||||||
charge_ctrl: ChargeSupportedFunctions,
|
pub charge_ctrl: ChargeSupportedFunctions,
|
||||||
fan_cpu_ctrl: FanCpuSupportedFunctions,
|
pub fan_cpu_ctrl: FanCpuSupportedFunctions,
|
||||||
keyboard_led: LedSupportedFunctions,
|
pub keyboard_led: LedSupportedFunctions,
|
||||||
rog_bios_ctrl: RogBiosSupportedFunctions,
|
pub rog_bios_ctrl: RogBiosSupportedFunctions,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.filter(None, LevelFilter::Info)
|
.filter(None, LevelFilter::Info)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
info!("daemon version {}", daemon::VERSION);
|
info!(" daemon v{}", daemon::VERSION);
|
||||||
info!(" rog-dbus version {}", rog_dbus::VERSION);
|
info!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||||
info!("rog-types version {}", rog_types::VERSION);
|
info!("rog-types v{}", rog_types::VERSION);
|
||||||
|
|
||||||
start_daemon()?;
|
start_daemon()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -121,7 +121,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctrl.reload()
|
ctrl.reload()
|
||||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
.unwrap_or_else(|err| error!("Gfx controller: {}", err));
|
||||||
ctrl.add_to_server(&mut object_server);
|
ctrl.add_to_server(&mut object_server);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ pub enum RogError {
|
|||||||
ReloadFail(String),
|
ReloadFail(String),
|
||||||
GfxSwitching(GfxError),
|
GfxSwitching(GfxError),
|
||||||
Initramfs(String),
|
Initramfs(String),
|
||||||
|
Modprobe(String),
|
||||||
|
Command(String, std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RogError {
|
impl fmt::Display for RogError {
|
||||||
@@ -50,6 +52,8 @@ impl fmt::Display for RogError {
|
|||||||
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
|
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
|
||||||
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
||||||
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
|
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
|
||||||
|
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||||
|
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "Zephyrus S"
|
prod_family = "Zephyrus S"
|
||||||
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "Zephyrus M"
|
prod_family = "Zephyrus M"
|
||||||
board_names = ["GU502GV"]
|
board_names = ["GU502GV"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "ROG Zephyrus M15"
|
prod_family = "ROG Zephyrus M15"
|
||||||
board_names = ["GU502LW"]
|
board_names = ["GU502LW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "ROG Zephyrus M15"
|
prod_family = "ROG Zephyrus M15"
|
||||||
@@ -26,7 +26,7 @@ led_modes = [0, 1, 2, 3, 10, 13]
|
|||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G531GW"]
|
board_names = ["G531GW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 255]
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,7 @@
|
|||||||
Description=ASUS Notebook Control
|
Description=ASUS Notebook Control
|
||||||
StartLimitInterval=200
|
StartLimitInterval=200
|
||||||
StartLimitBurst=2
|
StartLimitBurst=2
|
||||||
|
Before=display-manager.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/bin/asusd
|
ExecStart=/usr/bin/asusd
|
||||||
@@ -10,4 +11,3 @@ Restart=always
|
|||||||
RestartSec=1
|
RestartSec=1
|
||||||
Type=dbus
|
Type=dbus
|
||||||
BusName=org.asuslinux.Daemon
|
BusName=org.asuslinux.Daemon
|
||||||
Before=display-manager.service
|
|
||||||
@@ -223,6 +223,12 @@ impl From<SetAuraBuiltin> for AuraModes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&SetAuraBuiltin> for AuraModes {
|
||||||
|
fn from(mode: &SetAuraBuiltin) -> Self {
|
||||||
|
mode.clone().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
/// Very specific mode conversion required because numbering isn't linear
|
||||||
impl From<AuraModes> for u8 {
|
impl From<AuraModes> for u8 {
|
||||||
fn from(mode: AuraModes) -> Self {
|
fn from(mode: AuraModes) -> Self {
|
||||||
|
|||||||
@@ -81,16 +81,16 @@ pub struct ProfileCommand {
|
|||||||
#[options(help = "create the profile if it doesn't exist")]
|
#[options(help = "create the profile if it doesn't exist")]
|
||||||
pub create: bool,
|
pub create: bool,
|
||||||
|
|
||||||
#[options(help = "enable or disable cpu turbo")]
|
#[options(meta = "", help = "enable or disable cpu turbo")]
|
||||||
pub turbo: Option<bool>,
|
pub turbo: Option<bool>,
|
||||||
#[options(help = "set min cpu scaling (intel)")]
|
#[options(meta = "", help = "set min cpu scaling (intel)")]
|
||||||
pub min_percentage: Option<u8>,
|
pub min_percentage: Option<u8>,
|
||||||
#[options(help = "set max cpu scaling (intel)")]
|
#[options(meta = "", help = "set max cpu scaling (intel)")]
|
||||||
pub max_percentage: Option<u8>,
|
pub max_percentage: Option<u8>,
|
||||||
|
|
||||||
#[options(meta = "PWR", help = "<silent, normal, boost>")]
|
#[options(meta = "", help = "<silent, normal, boost>")]
|
||||||
pub preset: Option<FanLevel>,
|
pub fan_preset: Option<FanLevel>,
|
||||||
#[options(parse(try_from_str = "parse_fan_curve"), help = "set fan curve")]
|
#[options(meta = "", parse(try_from_str = "parse_fan_curve"), help = "set fan curve")]
|
||||||
pub curve: Option<Curve>,
|
pub curve: Option<Curve>,
|
||||||
#[options(free)]
|
#[options(free)]
|
||||||
pub profile: Option<String>,
|
pub profile: Option<String>,
|
||||||
|
|||||||
Reference in New Issue
Block a user