Bugfixes and improvements

- fix CLI feedback for reboot/restartx. Update readme
- dracut force driver include for nvidia dedicated
- change fan-mode CLI tag

Closes #48
This commit is contained in:
Luke
2021-01-27 14:05:06 +13:00
parent cd0b9fe350
commit cf13b4f71b
14 changed files with 146 additions and 63 deletions

View File

@@ -132,7 +132,7 @@ impl crate::ZbusAdd for DbusFanAndCpu {
server
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
.map_err(|err| {
warn!("DbusFanAndCpu: {}", err);
warn!("DbusFanAndCpu: add_to_server {}", err);
err
})
.ok();

View File

@@ -1,6 +1,8 @@
use std::error;
use std::fmt;
use crate::error::RogError;
#[derive(Debug)]
pub enum GfxError {
ParseVendor,
@@ -28,3 +30,9 @@ impl fmt::Display for GfxError {
}
impl error::Error for GfxError {}
impl From<GfxError> for RogError {
fn from(err: GfxError) -> Self {
RogError::GfxSwitching(err)
}
}

View File

@@ -7,7 +7,7 @@ use std::iter::FromIterator;
use std::path::Path;
use std::process::Command;
use std::str::FromStr;
use std::{error::Error, sync::Arc, sync::Mutex};
use std::{sync::Arc, sync::Mutex};
use sysfs_class::{PciDevice, SysClass};
use system::{GraphicsDevice, Module, PciBus};
use vendors::{GfxCtrlAction, GfxVendors};
@@ -66,6 +66,31 @@ impl Dbus for CtrlGraphics {
fn notify_action(&self, action: &str) -> zbus::Result<()> {}
}
impl ZbusAdd for CtrlGraphics {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(
&"/org/asuslinux/Gfx"
.try_into()
.expect("Couldn't add to zbus"),
self,
)
.map_err(|err| {
warn!("CtrlGraphics: add_to_server {}", err);
err
})
.ok();
}
}
impl Reloadable for CtrlGraphics {
fn reload(&mut self) -> Result<(), RogError> {
self.auto_power()?;
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
Ok(())
}
}
impl CtrlGraphics {
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
let bus = PciBus::new()?;
@@ -125,13 +150,12 @@ impl CtrlGraphics {
cmd.arg("-u");
initfs_cmd = Some(cmd);
info!("Using initramfs update command 'update-initramfs'");
} else if Path::new(DRACUT_PATH).exists() {
let mut cmd = Command::new("dracut");
cmd.arg("-f");
initfs_cmd = Some(cmd);
info!("Using initramfs update command 'dracut'");
}
// } else if Path::new(DRACUT_PATH).exists() {
// let mut cmd = Command::new("dracut");
// cmd.arg("-f");
// initfs_cmd = Some(cmd);
// info!("Using initramfs update command 'dracut'");
// }
Ok(CtrlGraphics {
bus,
@@ -144,26 +168,7 @@ impl CtrlGraphics {
})
}
pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(
&"/org/asuslinux/Gfx".try_into().expect("Some fail here"),
self,
)
.map_err(|err| {
warn!("CtrlGraphics: add_to_server {}", err);
err
})
.ok();
}
pub fn reload(&mut self) -> Result<(), Box<dyn Error>> {
self.auto_power()?;
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
Ok(())
}
fn get_prime_discrete() -> Result<String, GfxError> {
fn get_prime_discrete() -> Result<String, RogError> {
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
.trim()
@@ -171,14 +176,14 @@ impl CtrlGraphics {
Ok(s)
}
fn set_prime_discrete(mode: &str) -> Result<(), GfxError> {
fn set_prime_discrete(mode: &str) -> Result<(), RogError> {
std::fs::write(PRIME_DISCRETE_PATH, mode)
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
Ok(())
}
/// Associated method to get which vendor mode is set
pub fn get_vendor() -> Result<String, GfxError> {
pub fn get_vendor() -> Result<String, RogError> {
let mode = match Self::get_prime_discrete() {
Ok(m) => m,
Err(_) => "nvidia".to_string(),
@@ -214,14 +219,32 @@ impl CtrlGraphics {
Ok(vendor)
}
pub fn is_switching_prime_modes(vendor: &GfxVendors) -> Result<bool, GfxError> {
fn is_switching_prime_modes(&self, vendor: &GfxVendors) -> Result<bool, RogError> {
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
let x = (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia);
Ok(x)
if prev_mode == GfxVendors::Integrated
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia)
{
return Ok(true);
}
if (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
&& *vendor == GfxVendors::Integrated
{
return Ok(true);
}
if let Ok(config) = self.config.clone().try_lock() {
if CtrlRogBios::has_dedicated_gfx_toggle() && config.gfx_nv_mode_is_dedicated {
if prev_mode == GfxVendors::Hybrid && *vendor == GfxVendors::Nvidia {
return Ok(true);
}
if *vendor == GfxVendors::Hybrid && prev_mode == GfxVendors::Nvidia {
return Ok(true);
}
}
}
Ok(false)
}
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), GfxError> {
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), RogError> {
let mode = if vendor == GfxVendors::Hybrid {
"on-demand\n"
} else if vendor == GfxVendors::Nvidia {
@@ -305,7 +328,11 @@ impl CtrlGraphics {
}
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
pub fn set(&mut self, vendor: GfxVendors) -> Result<String, GfxError> {
fn set(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
// or a reboot.
let reboot = self.is_switching_prime_modes(&vendor)?;
if CtrlRogBios::has_dedicated_gfx_toggle() {
if let Ok(config) = self.config.clone().try_lock() {
// Switch to dedicated if config says to do so
@@ -322,40 +349,44 @@ impl CtrlGraphics {
}
}
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
// or a reboot.
let no_reboot = Self::is_switching_prime_modes(&vendor)?;
Self::set_gfx_config(vendor)?;
Self::set_gfx_config(vendor.clone())?;
let mut required_action = GfxCtrlAction::None;
if !no_reboot {
if reboot {
info!("Updating initramfs");
if let Some(cmd) = self.initfs_cmd.as_mut() {
// If switching to Nvidia dedicated we need these modules included
if Path::new(DRACUT_PATH).exists() && vendor == GfxVendors::Nvidia {
cmd.arg("--add-drivers");
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
info!("System uses dracut, forcing nvidia modules to be included in init");
}
let status = cmd
.status()
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
if !status.success() {
error!("Ram disk update failed");
return Ok("Ram disk update failed".into());
} else {
info!("Successfully updated iniramfs");
}
}
required_action = GfxCtrlAction::Reboot;
} else if no_reboot {
} else if !reboot {
required_action = GfxCtrlAction::RestartX;
}
Ok(required_action.into())
}
pub fn get_runtime_status() -> Result<String, GfxError> {
fn get_runtime_status() -> Result<String, RogError> {
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))?;
Ok(buf)
}
fn set_power(&self, power: bool) -> Result<(), GfxError> {
fn set_power(&self, power: bool) -> Result<(), RogError> {
if power {
info!("Enabling graphics power");
self.bus
@@ -377,7 +408,7 @@ impl CtrlGraphics {
Ok(())
}
fn auto_power(&self) -> Result<(), GfxError> {
fn auto_power(&self) -> Result<(), RogError> {
let vendor = CtrlGraphics::get_vendor()?;
self.set_power(vendor != "integrated")
}

View File

@@ -9,7 +9,7 @@ pub mod system;
const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete";
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
// const DRACUT_PATH: &str = "/usr/bin/dracut";
const DRACUT_PATH: &str = "/usr/bin/dracut";
static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID;

View File

@@ -15,7 +15,7 @@ use asus_nb::{
fancy::KeyColourArray,
LED_MSG_LEN,
};
use log::{info, warn};
use log::{error, info, warn};
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::sync::Arc;
@@ -91,6 +91,9 @@ impl crate::ZbusAdd for DbusKbdBacklight {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Led".try_into().unwrap(), self)
.map_err(|err| {
error!("DbusKbdBacklight: add_to_server {}", err);
})
.ok();
}
}
@@ -281,8 +284,16 @@ impl CtrlKbdBacklight {
let ctrl = CtrlKbdBacklight {
// Using `ok` here so we can continue without keyboard features but
// still get brightness control at least... maybe...
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
led_node: Some(Self::get_node_failover(
id_product,
None,
Self::scan_led_node,
)?),
kbd_node: Some(Self::get_node_failover(
id_product,
condev_iface,
Self::scan_kbd_node,
)?),
// TODO: Check for existance
bright_node: Self::get_kbd_bright_path()?.to_owned(),
supported_modes,

View File

@@ -112,7 +112,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
if ded == 1 && vendor != "nvidia" {
error!("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.set(GfxVendors::Nvidia)?;
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)?;
} else if ded == 0 {
info!("Dedicated GFX toggle is off");
}

View File

@@ -3,6 +3,8 @@ use rog_fan_curve::CurveError;
use std::convert::From;
use std::fmt;
use crate::ctrl_gfx::error::GfxError;
#[derive(Debug)]
pub enum RogError {
ParseFanLevel,
@@ -21,6 +23,7 @@ pub enum RogError {
MissingFunction(String),
MissingLedBrightNode(String, std::io::Error),
ReloadFail(String),
GfxSwitching(GfxError),
}
impl fmt::Display for RogError {
@@ -43,6 +46,7 @@ impl fmt::Display for RogError {
RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
}
}
}

View File

@@ -21,8 +21,11 @@ struct CLIStart {
show_supported: bool,
#[options(meta = "", help = "<off, low, med, high>")]
kbd_bright: Option<LedBrightness>,
#[options(meta = "", help = "<silent, normal, boost>")]
pwr_profile: Option<FanLevel>,
#[options(
meta = "",
help = "<silent, normal, boost>, set fan mode independent of profile"
)]
fan_mode: Option<FanLevel>,
#[options(meta = "", help = "<20-100>")]
chg_limit: Option<u8>,
#[options(command)]
@@ -246,7 +249,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
None => {
if (!parsed.show_supported
&& parsed.kbd_bright.is_none()
&& parsed.pwr_profile.is_none()
&& parsed.fan_mode.is_none()
&& parsed.chg_limit.is_none())
|| parsed.help
{
@@ -272,7 +275,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Supported laptop functions:\n{}", dat.to_string());
}
if let Some(fan_level) = parsed.pwr_profile {
if let Some(fan_level) = parsed.fan_mode {
dbus_client.write_fan_mode(fan_level.into())?;
}
if let Some(chg_limit) = parsed.chg_limit {
@@ -319,7 +322,10 @@ fn do_gfx(
)?;
std::process::exit(1)
}
_ => std::process::exit(-1),
_ => {
println!("{}", Red.paint(&format!("\n{}\n", res.as_str())),);
std::process::exit(-1);
}
}
std::process::exit(-1)
}