Compare commits

...

14 Commits

Author SHA1 Message Date
Luke D Jones 89f4dd6ec4 Prep release 2021-03-11 12:32:34 +13:00
Luke Jones 85e0b79fb9 Merge branch 'fluke/testing-gfx-switch' into 'main'
More verbose and thorough checks for gfx switching

See merge request asus-linux/asus-nb-ctrl!30
2021-03-10 23:28:02 +00:00
Luke D Jones fba5f26f7e More verbose and thorough checks for gfx switching
- Small fixes
- Cleanup bios help
- g-sync warnings on toggling
2021-03-11 12:24:01 +13:00
Luke D Jones 90b0fc434d Hotfix: graphics help display 2021-03-10 21:23:35 +13:00
Luke D Jones 6743d5bc78 Add display-manager restart check 2021-03-10 18:42:44 +13:00
Luke D Jones def0259d24 Bump version 2021-03-10 16:47:22 +13:00
Luke D Jones a678f54f59 :sadface: 2021-03-10 16:45:06 +13:00
Luke D Jones ebe7e61355 Slightly change how module load error is reported 2021-03-10 16:30:42 +13:00
Luke D Jones bda58c9695 Trial of logging for gfx switch 2021-03-10 16:21:53 +13:00
Luke D Jones e335133bf8 refactor help again 2021-03-10 16:17:22 +13:00
Luke D Jones 47432524e1 Further improve CLI feedback 2021-03-10 16:01:04 +13:00
Luke D Jones 707b3bcc2d Notify on manually select profile 2021-03-10 15:24:24 +13:00
Luke D Jones 60014b8a40 Customise initial help for laptop 2021-03-10 14:43:48 +13:00
Luke D Jones 2e4ce27f6b Hotfix: try to handle module remove gracefully
Try to handle module remove more gracefully if in-use when the
display manager is shutting down
2021-03-10 14:07:08 +13:00
16 changed files with 414 additions and 172 deletions
+18
View File
@@ -5,6 +5,24 @@ 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.5] - 2021-03-11
### Changed
- Further tweaks to gfx switching
- More logging on gfx switching
- Filter bios help according to supported modes
- Prevent gfx mode switching if in dedicated/G-Sync mode
# [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 # [3.1.2] - 2021-03-10
### Changed ### Changed
Generated
+3 -2
View File
@@ -33,8 +33,9 @@ dependencies = [
[[package]] [[package]]
name = "asusctl" name = "asusctl"
version = "3.1.0" version = "3.1.2"
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.2" version = "3.1.5"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"intel-pstate", "intel-pstate",
+2 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "asusctl" name = "asusctl"
version = "3.1.0" version = "3.1.2"
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"
+236 -99
View File
@@ -1,3 +1,4 @@
use daemon::{ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions, ctrl_rog_bios::RogBiosSupportedFunctions, 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::{
@@ -93,19 +94,18 @@ struct AniMeCommand {
struct BiosCommand { struct BiosCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
#[options(meta = "", no_long, help = "toggle bios POST sound")] #[options(meta = "", no_long, help = "set bios POST sound <true/false>")]
post_sound_set: Option<bool>, post_sound_set: Option<bool>,
#[options(no_long, help = "read bios POST sound")] #[options(no_long, help = "read bios POST sound")]
post_sound_get: bool, post_sound_get: bool,
#[options(meta = "", no_long, help = "toggle GPU to/from dedicated mode")] #[options(meta = "", no_long, help = "activate dGPU dedicated/G-Sync <true/false>")]
dedicated_gfx_set: Option<bool>, dedicated_gfx_set: Option<bool>,
#[options(no_long, help = "get GPU mode")] #[options(no_long, help = "get GPU mode")]
dedicated_gfx_get: bool, dedicated_gfx_get: bool,
} }
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 +125,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, &supported.rog_bios_ctrl, 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());
@@ -207,43 +170,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
} }
Some(CliCommand::Bios(cmd)) => { Some(CliCommand::Bios(cmd)) => handle_bios_option(&dbus, &supported.rog_bios_ctrl, &cmd)?,
if (cmd.dedicated_gfx_set.is_none()
&& !cmd.dedicated_gfx_get
&& cmd.post_sound_set.is_none()
&& !cmd.post_sound_get)
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
}
if let Some(opt) = cmd.post_sound_set {
dbus.proxies().rog_bios().set_post_sound(opt)?;
}
if cmd.post_sound_get {
let res = if dbus.proxies().rog_bios().get_post_sound()? == 1 {
true
} else {
false
};
println!("Bios POST sound on: {}", res);
}
if let Some(opt) = cmd.dedicated_gfx_set {
dbus.proxies().rog_bios().set_dedicated_gfx(opt)?;
}
if cmd.dedicated_gfx_get {
let res = if dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 {
true
} else {
false
};
println!("Bios dedicated GPU on: {}", res);
println!("You must reboot your system to activate dedicated Nvidia mode");
}
}
None => { None => {
if (!parsed.show_supported if (!parsed.show_supported
&& parsed.kbd_bright.is_none() && parsed.kbd_bright.is_none()
@@ -282,11 +209,74 @@ 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(
dbus: &AuraDbusClient,
supported: &RogBiosSupportedFunctions,
command: GraphicsCommand, command: GraphicsCommand,
dbus_client: &AuraDbusClient,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help {
println!("{}", command.self_usage());
}
if let Some(mode) = command.mode { if let Some(mode) = command.mode {
if supported.dedicated_gfx_toggle {
if dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 {
println!("You can not change modes until you turn dedicated/G-Sync off and reboot");
std::process::exit(-1);
}
}
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`");
@@ -295,19 +285,19 @@ fn do_gfx(
"This will restart your display-manager. Please save all work!", "This will restart your display-manager. Please save all work!",
"Setting graphics mode...", "Setting graphics mode...",
) { ) {
dbus_client.proxies().gfx().gfx_write_mode(mode.into())?; dbus.proxies().gfx().gfx_write_mode(mode.into())?;
let res = dbus_client.gfx_wait_changed()?; let res = dbus.gfx_wait_changed()?;
println!("{}", res); println!("{}", res);
std::process::exit(1) std::process::exit(1)
} }
std::process::exit(-1) std::process::exit(-1)
} }
if command.get { if command.get {
let res = dbus_client.proxies().gfx().gfx_get_mode()?; let res = dbus.proxies().gfx().gfx_get_mode()?;
println!("Current graphics mode: {}", res); println!("Current graphics mode: {}", res);
} }
if command.pow { if command.pow {
let res = dbus_client.proxies().gfx().gfx_get_pwr()?; let res = dbus.proxies().gfx().gfx_get_pwr()?;
if res.contains("active") { if res.contains("active") {
println!("Current power status: {}", Red.paint(&format!("{}", res))); println!("Current power status: {}", Red.paint(&format!("{}", res)));
} else { } else {
@@ -331,3 +321,150 @@ 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(())
}
fn handle_bios_option(
dbus: &AuraDbusClient,
supported: &RogBiosSupportedFunctions,
cmd: &BiosCommand,
) -> Result<(), Box<dyn std::error::Error>> {
{
if (cmd.dedicated_gfx_set.is_none()
&& !cmd.dedicated_gfx_get
&& cmd.post_sound_set.is_none()
&& !cmd.post_sound_get)
|| cmd.help
{
println!("Missing arg or command\n");
let usage: Vec<String> = BiosCommand::usage()
.lines()
.map(|s| s.to_string())
.collect();
for line in usage
.iter()
.filter(|line| !(line.contains("sound") && !supported.post_sound_toggle)
|| !(line.contains("GPU") && !supported.dedicated_gfx_toggle))
{
println!("{}", line);
}
}
if let Some(opt) = cmd.post_sound_set {
dbus.proxies().rog_bios().set_post_sound(opt)?;
}
if cmd.post_sound_get {
let res = if dbus.proxies().rog_bios().get_post_sound()? == 1 {
true
} else {
false
};
println!("Bios POST sound on: {}", res);
}
if let Some(opt) = cmd.dedicated_gfx_set {
println!("Rebuilding initrd to include drivers");
dbus.proxies().rog_bios().set_dedicated_gfx(opt)?;
println!("The mode change is not active until you reboot, on boot the bios will make the required change");
if opt {
println!("NOTE: on reboot your display manager will be forced to use Nvidia drivers");
} else {
println!("NOTE: after reboot you can then select regular graphics modes");
}
}
if cmd.dedicated_gfx_get {
let res = if dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 {
true
} else {
false
};
println!("Bios dedicated GPU on: {}", res);
}
}
Ok(())
}
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "daemon" name = "daemon"
version = "3.1.2" version = "3.1.5"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
@@ -40,4 +40,4 @@ toml = "^0.5"
sysfs-class = "^0.1.2" # used for backlight control and baord ID sysfs-class = "^0.1.2" # used for backlight control and baord ID
rog_fan_curve = { version = "0.1", features = ["serde"] } rog_fan_curve = { version = "0.1", features = ["serde"] }
# cpu power management # cpu power management
intel-pstate = "^0.2" intel-pstate = "^0.2"
+1 -1
View File
@@ -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;
+8 -2
View File
@@ -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 {
+11 -3
View File
@@ -1,5 +1,5 @@
use std::error;
use std::fmt; use std::fmt;
use std::{error, process::ExitStatus};
use crate::error::RogError; use crate::error::RogError;
@@ -7,7 +7,9 @@ use crate::error::RogError;
pub enum GfxError { pub enum GfxError {
ParseVendor, ParseVendor,
Bus(String, std::io::Error), Bus(String, std::io::Error),
DisplayManager(String), DisplayManagerAction(String, ExitStatus),
DisplayManagerTimeout(String),
GsyncModeActive,
} }
impl fmt::Display for GfxError { impl fmt::Display for GfxError {
@@ -16,7 +18,13 @@ impl fmt::Display for GfxError {
match self { match self {
GfxError::ParseVendor => write!(f, "Could not parse vendor name"), GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error), GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail), GfxError::DisplayManagerAction(action, status) => {
write!(f, "Display-manager action {} failed: {}", action, status)
}
GfxError::DisplayManagerTimeout(state) => {
write!(f, "Timed out waiting for display-manager {} state", state)
}
GfxError::GsyncModeActive => write!(f, "Can not switch gfx modes when dedicated/G-Sync mode is active"),
} }
} }
} }
+103 -42
View File
@@ -1,5 +1,6 @@
use ctrl_gfx::error::GfxError; use ctrl_gfx::error::GfxError;
use ctrl_gfx::*; use ctrl_gfx::*;
use ctrl_rog_bios::CtrlRogBios;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_types::gfx_vendors::GfxVendors; use rog_types::gfx_vendors::GfxVendors;
use std::iter::FromIterator; use std::iter::FromIterator;
@@ -260,34 +261,73 @@ impl CtrlGraphics {
Ok(()) Ok(())
} }
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> { fn log_uses_of_nvidia() {
let mut cmd; // lsof /dev/nvidia*
if Self::kmod_exists() { let mut cmd = Command::new("lsof");
info!("using kmod"); cmd.arg("/dev/nvidia*");
cmd = Command::new("kmod");
cmd.arg(action); match cmd.output() {
} else { Ok(output) => {
cmd = Command::new(action); if !output.status.success() {
error!("Failed to list uses of nvidia devices: {}", String::from_utf8_lossy(&output.stderr));
} else if output.status.success() {
warn!("{}", String::from_utf8_lossy(&output.stdout));
}
}
Err(err) => error!("Failed to list uses of nvidia devices: {}", err),
} }
}
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
let mut cmd = Command::new(action);
cmd.arg(driver); cmd.arg(driver);
let output = cmd let mut count = 0;
.output() const MAX_TRIES: i32 = 6;
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?; loop {
if !output.status.success() { if count > MAX_TRIES {
if output.stderr.ends_with("is not currently loaded\n".as_bytes()) { let msg = format!("{} {} failed for unknown reason", action, driver);
return Ok(()) error!("{}", msg);
return Ok(()); //Err(RogError::Modprobe(msg));
} }
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr)); let output = cmd
warn!("{}", msg); .output()
warn!("It may be safe to ignore the above error, run `lsmod |grep nvidia` to confirm modules loaded"); .map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
return Ok(()) 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(());
} }
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
return Err(RogError::Modprobe(msg)); 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> {
@@ -303,42 +343,29 @@ impl CtrlGraphics {
"systemctl {} {} failed: {:?}", "systemctl {} {} failed: {:?}",
action, DISPLAY_MANAGER, status action, DISPLAY_MANAGER, status
); );
return Err(GfxError::DisplayManager(msg).into()); return Err(GfxError::DisplayManagerAction(msg, status).into());
} }
Ok(()) Ok(())
} }
fn wait_display_manager_inactive() -> Result<(), RogError> { fn wait_display_manager_state(state: &str) -> Result<(), RogError> {
let mut cmd = Command::new("systemctl"); let mut cmd = Command::new("systemctl");
cmd.arg("is-active"); cmd.arg("is-active");
cmd.arg(DISPLAY_MANAGER); 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| RogError::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::DisplayManagerTimeout(state.into()).into());
GfxError::DisplayManager("display-manager did not completely stop".into()).into(),
);
}
fn kmod_exists() -> bool {
let mut cmd = Command::new("which");
cmd.arg("kmod");
if let Ok(output) = cmd
.output() {
return output.status.success() && output.stdout.ends_with("kmod".as_bytes())
}
//Path::new("/usr/bin/kmod").exists()
false
} }
pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> { pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> {
@@ -353,7 +380,10 @@ impl CtrlGraphics {
match vendor { match vendor {
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => { GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
for driver in NVIDIA_DRIVERS.iter() { for driver in NVIDIA_DRIVERS.iter() {
Self::do_driver_action(driver, "modprobe")?; Self::do_driver_action(driver, "modprobe").map_err(|err| {
Self::log_uses_of_nvidia();
err
})?;
} }
} }
// TODO: compute mode, needs different setup // TODO: compute mode, needs different setup
@@ -374,10 +404,41 @@ 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> {
if let Ok(gsync) = CtrlRogBios::get_gfx_mode() {
if gsync == 1{
return Err(GfxError::GsyncModeActive.into());
}
}
Self::do_display_manager_action("stop")?; Self::do_display_manager_action("stop")?;
Self::wait_display_manager_inactive()?; match Self::wait_display_manager_state("inactive") {
Ok(_) => info!("display-manager stopped"),
Err(err) => {
warn!("{}", err);
warn!("Retry stop display manager");
Self::do_display_manager_action("stop")?;
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")?;
match Self::wait_display_manager_state("active") {
Ok(_) => info!("display-manager started"),
Err(err) => {
warn!("{}", err);
warn!("Retry start display manager");
Self::do_display_manager_action("restart")?;
Self::wait_display_manager_state("active")?;
}
}
if Self::wait_display_manager_state("active").is_err() {
error!("display-manager failed to start normally, attempting restart");
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))
+2
View File
@@ -11,6 +11,8 @@ 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
# If you have issues with i2c_nvidia_gpu, copy the 2 lines below to a
# new blacklist file and uncomment
#blacklist i2c_nvidia_gpu #blacklist i2c_nvidia_gpu
#alias i2c_nvidia_gpu off #alias i2c_nvidia_gpu off
blacklist nouveau blacklist nouveau
+2 -3
View File
@@ -136,9 +136,7 @@ impl CtrlRogBios {
} }
} }
Ok(CtrlRogBios { Ok(CtrlRogBios { _config: config })
_config: config,
})
} }
fn set_path_mutable(path: &str) -> Result<(), RogError> { fn set_path_mutable(path: &str) -> Result<(), RogError> {
@@ -271,6 +269,7 @@ impl CtrlRogBios {
} else if Path::new(DRACUT_PATH).exists() { } else if Path::new(DRACUT_PATH).exists() {
let mut cmd = Command::new("dracut"); let mut cmd = Command::new("dracut");
cmd.arg("-f"); cmd.arg("-f");
cmd.arg("-q");
initfs_cmd = Some(cmd); initfs_cmd = Some(cmd);
info!("Using initramfs update command 'dracut'"); info!("Using initramfs update command 'dracut'");
} }
+5 -5
View File
@@ -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")]
+1 -2
View File
@@ -111,8 +111,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
if let Ok(ded) = CtrlRogBios::get_gfx_mode() { if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
if let Ok(vendor) = ctrl.get_gfx_mode() { if let Ok(vendor) = ctrl.get_gfx_mode() {
if ded == 1 && vendor != GfxVendors::Nvidia { if ded == 1 && vendor != GfxVendors::Nvidia {
error!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode"); warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
error!("You must reboot to enable Nvidia driver");
ctrl.do_vendor_tasks(GfxVendors::Nvidia)?; ctrl.do_vendor_tasks(GfxVendors::Nvidia)?;
} else if ded == 0 { } else if ded == 0 {
info!("Dedicated GFX toggle is off"); info!("Dedicated GFX toggle is off");
+4 -4
View File
@@ -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"
+6
View File
@@ -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 {
+10 -6
View File
@@ -81,16 +81,20 @@ 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>,