Compare commits

...

2 Commits
2.2.0 ... 2.2.1

Author SHA1 Message Date
Luke Jones
b3a555cab9 Merge branch 'fluke/asus_bios_settings' into 'next'
Bugfixes and improvements

Closes #48

See merge request asus-linux/asus-nb-ctrl!17
2021-01-27 01:16:39 +00:00
Luke
cf13b4f71b 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
2021-01-27 14:13:02 +13:00
14 changed files with 146 additions and 63 deletions

View File

@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
# [2.2.1] - 2021-01-27
### Added
- Add ROG Zephyrus M15 LED config
### Changed
- Bugfixes
- Fix reboot/restartx status for GFX switching
- Update readme
- Change CLI arg tag for fan modes
- Make dracut include the nvidia modules in initramfs
# [2.2.0] - 2021-01-26
### Added
- Dbus command to fetch all supported functions of the laptop. That is, all the
@@ -13,7 +23,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bios setting toggles for:
+ Dedicated gfx toggle (support depends on the laptop)
+ Bios boot POST sound toggle
### Changed
- added config option for dedicated gfx mode on laptops with it to enable
switching directly to dedicated using `asusctl graphics -m nvidia`

4
Cargo.lock generated
View File

@@ -29,7 +29,7 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "asus-nb"
version = "2.2.0"
version = "2.2.1"
dependencies = [
"dbus",
"gumdrop",
@@ -45,7 +45,7 @@ dependencies = [
[[package]]
name = "asus-nb-ctrl"
version = "2.2.0"
version = "2.2.1"
dependencies = [
"asus-nb",
"env_logger",

View File

@@ -7,6 +7,10 @@ but can also be used with non-asus laptops with reduced features.
This app is developed and tested on fedora only. Support is not provided for Arch or Arch based distros.
**NOTICE:**
The following is *not* required for 5.11 kernel versions, as this version includes
all the required patches.
---
This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied.
Alternatively you may use the dkms module for 'hid-asus-rog` from one of the
repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
@@ -53,13 +57,17 @@ will probably suffer another rename once it becomes generic enough to do so.
- [X] Set battery charge limit (with kernel supporting this)
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
- [X] Toggle bios setting for boot/POST sound
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
# FUNCTIONS
## Graphics switching
A new feature has been added to enable switching graphics modes. This can be disabled
in the config with `"manage_gfx": false,`. Please be aware it is a work in progress.
in the config with `"manage_gfx": false,`. Additionally there is an extra setting
for laptops capable of g-sync dedicated gfx mode to enable the graphics switching
to switch on dedicated gfx for "nvidia" mode.
The CLI option for this does not require root until it asks for it, and provides
instructions.
@@ -79,7 +87,8 @@ If you have installed the Nvidia driver manually you will require the
### fedora and openSUSE
You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed
to stop dracut including the nvidia modules in the ramdisk.
to stop dracut including the nvidia modules in the ramdisk. This is espeically
true if you manually installed the nvidia drivers.
```
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf

View File

@@ -1,6 +1,6 @@
[package]
name = "asus-nb-ctrl"
version = "2.2.0"
version = "2.2.1"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]

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)
}

View File

@@ -1,6 +1,6 @@
[package]
name = "asus-nb"
version = "2.2.0"
version = "2.2.1"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]

View File

@@ -8,6 +8,11 @@ prod_family = "Zephyrus M"
board_names = ["GU502GV"]
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
[[led_modes]]
prod_family = "ROG Zephyrus M15"
board_names = ["GU502LW"]
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
[[led_modes]]
prod_family = "Zephyrus"
board_names = ["GM501GM", "GX531"]