From 538e111e782e812eb4cb18adc6a34a8a02bc0bc8 Mon Sep 17 00:00:00 2001 From: Luke D Jones Date: Sat, 20 Mar 2021 23:26:03 +1300 Subject: [PATCH] VFIO mode enabled --- CHANGELOG.md | 1 + asus-notify/src/main.rs | 5 +- asusctl/src/aura_cli.rs | 19 ++- asusctl/src/main.rs | 25 ++-- daemon/src/ctrl_fan_cpu.rs | 4 +- daemon/src/ctrl_gfx/gfx.rs | 254 ++++++++++++++++++++-------------- daemon/src/ctrl_gfx/mod.rs | 10 ++ daemon/src/ctrl_gfx/system.rs | 4 + daemon/src/error.rs | 8 ++ rog-dbus/src/lib.rs | 13 +- rog-dbus/src/zbus_gfx.rs | 24 ++-- rog-dbus/src/zbus_led.rs | 2 +- rog-types/src/aura_modes.rs | 2 +- rog-types/src/cli_options.rs | 4 +- rog-types/src/gfx_vendors.rs | 44 ++---- 15 files changed, 240 insertions(+), 179 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b4f9ac9..5f2c3a3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactor keyboard LED handling - Added --list for profiles (Thanks @aqez) - Added --remove for profiles (Thanks @aqez) +- Added a graphics mode: vfio. This attaches Nvidia devices to vfio module. ### Broken - Per-key LED modes, which need thinking about how to go ahead with for future diff --git a/asus-notify/src/main.rs b/asus-notify/src/main.rs index 0331d6b7..2e791c27 100644 --- a/asus-notify/src/main.rs +++ b/asus-notify/src/main.rs @@ -30,7 +30,10 @@ fn main() -> Result<(), Box> { if let Some(notif) = last_gfx_notif.take() { notif.close(); } - let x = do_notif(&format!("Graphics mode changed to {}", vendor))?; + let x = do_notif(&format!( + "Graphics mode changed to {}", + <&str>::from(vendor) + ))?; last_gfx_notif = Some(x); } } diff --git a/asusctl/src/aura_cli.rs b/asusctl/src/aura_cli.rs index 999d9fce..c0326373 100644 --- a/asusctl/src/aura_cli.rs +++ b/asusctl/src/aura_cli.rs @@ -1,8 +1,8 @@ +use gumdrop::Options; use rog_types::{ - aura_modes::{Colour, Direction, Speed, AuraEffect, AuraModeNum, AuraZone}, + aura_modes::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed}, error::AuraError, }; -use gumdrop::Options; use std::str::FromStr; #[derive(Options)] @@ -165,7 +165,6 @@ impl Default for SetAuraBuiltin { } } - impl From<&SingleColour> for AuraEffect { fn from(aura: &SingleColour) -> Self { Self { @@ -294,15 +293,15 @@ impl From<&SetAuraBuiltin> for Vec { zones[1].mode = AuraModeNum::Static; zones[1].zone = AuraZone::Two; zones[1].colour1 = data.colour2; - + zones[2].mode = AuraModeNum::Static; zones[2].zone = AuraZone::Three; zones[2].colour1 = data.colour3; - + zones[3].mode = AuraModeNum::Static; zones[3].zone = AuraZone::Four; zones[3].colour1 = data.colour4; - }, + } SetAuraBuiltin::MultiBreathe(data) => { zones[0].mode = AuraModeNum::Breathe; zones[0].zone = AuraZone::One; @@ -313,19 +312,19 @@ impl From<&SetAuraBuiltin> for Vec { zones[1].zone = AuraZone::Two; zones[1].colour1 = data.colour2; zones[1].speed = data.speed; - + zones[2].mode = AuraModeNum::Breathe; zones[2].zone = AuraZone::Three; zones[2].colour1 = data.colour3; zones[2].speed = data.speed; - + zones[3].mode = AuraModeNum::Breathe; zones[3].zone = AuraZone::Four; zones[3].colour1 = data.colour4; zones[3].speed = data.speed; } - _ => {}, + _ => {} } zones } -} \ No newline at end of file +} diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index b11d040f..ec0c6ee6 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -1,5 +1,6 @@ mod aura_cli; +use crate::aura_cli::{LedBrightness, SetAuraBuiltin}; use daemon::{ ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions, ctrl_rog_bios::RogBiosSupportedFunctions, ctrl_supported::SupportedFunctions, @@ -16,7 +17,6 @@ use rog_types::{ use std::env::args; use yansi_term::Colour::Green; use yansi_term::Colour::Red; -use crate::aura_cli::{LedBrightness, SetAuraBuiltin}; #[derive(Default, Options)] struct CLIStart { @@ -286,19 +286,24 @@ fn do_gfx( std::process::exit(-1); } - println!( - "Your display-manager will restart in requested mode when all users are logged out" - ); - println!("If anything fails check `journalctl -b -u asusd`"); + println!("If anything fails check `journalctl -b -u asusd`\n"); - dbus.proxies().gfx().gfx_write_mode(mode.into())?; + dbus.proxies().gfx().gfx_write_mode(&mode).map_err(|err|{ + println!("Graphics mode change error. You may be in an invalid state."); + println!("Check mode with `asusctl graphics -g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n"); + err + })?; let res = dbus.gfx_wait_changed()?; - println!("{}", res); + println!( + "Graphics mode changed to {}. User action required is: {}", + <&str>::from(mode), + <&str>::from(&res) + ); std::process::exit(0) } if command.get { let res = dbus.proxies().gfx().gfx_get_mode()?; - println!("Current graphics mode: {}", res); + println!("Current graphics mode: {}", <&str>::from(res)); } if command.pow { let res = dbus.proxies().gfx().gfx_get_pwr()?; @@ -361,9 +366,7 @@ fn handle_led_mode( SetAuraBuiltin::MultiStatic(_) | SetAuraBuiltin::MultiBreathe(_) => { let zones = >::from(mode); for eff in zones { - dbus.proxies() - .led() - .set_led_mode(&eff)? + dbus.proxies().led().set_led_mode(&eff)? } } _ => dbus diff --git a/daemon/src/ctrl_fan_cpu.rs b/daemon/src/ctrl_fan_cpu.rs index e5b62734..134bd974 100644 --- a/daemon/src/ctrl_fan_cpu.rs +++ b/daemon/src/ctrl_fan_cpu.rs @@ -160,7 +160,9 @@ impl DbusFanAndCpu { } if cfg.active_profile == *profile { - return Err(Error::Failed("Cannot delete the active profile".to_string())); + return Err(Error::Failed( + "Cannot delete the active profile".to_string(), + )); } cfg.power_profiles.remove(profile); diff --git a/daemon/src/ctrl_gfx/gfx.rs b/daemon/src/ctrl_gfx/gfx.rs index 0046468f..24faf0bf 100644 --- a/daemon/src/ctrl_gfx/gfx.rs +++ b/daemon/src/ctrl_gfx/gfx.rs @@ -6,11 +6,11 @@ use logind_zbus::{ types::{SessionClass, SessionInfo, SessionType}, ManagerProxy, SessionProxy, }; -use rog_types::gfx_vendors::GfxVendors; +use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors}; +use std::sync::mpsc; use std::{io::Write, ops::Add, path::Path, time::Instant}; use std::{iter::FromIterator, thread::JoinHandle}; use std::{process::Command, thread::sleep, time::Duration}; -use std::{str::FromStr, sync::mpsc}; use std::{sync::Arc, sync::Mutex}; use sysfs_class::{PciDevice, SysClass}; use system::{GraphicsDevice, PciBus}; @@ -32,44 +32,44 @@ pub struct CtrlGraphics { } trait Dbus { - fn vendor(&self) -> String; + fn vendor(&self) -> zbus::fdo::Result; fn power(&self) -> String; - fn set_vendor(&mut self, vendor: String); - fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>; - fn notify_action(&self, action: &str) -> zbus::Result<()>; + fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result; + fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>; + fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>; } #[dbus_interface(name = "org.asuslinux.Daemon")] impl Dbus for CtrlGraphics { - fn vendor(&self) -> String { - self.get_gfx_mode() - .map(|gfx| (<&str>::from(gfx)).into()) - .unwrap_or_else(|err| format!("Get vendor failed: {}", err)) + fn vendor(&self) -> zbus::fdo::Result { + self.get_gfx_mode().map_err(|err| { + error!("GFX: {}", err); + zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) + }) } fn power(&self) -> String { Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err)) } - fn set_vendor(&mut self, vendor: String) { - if let Ok(tmp) = GfxVendors::from_str(&vendor) { - info!("GFX: Switching gfx mode to {}", vendor); - let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| { - error!("GFX: {}", err); - format!("Failed: {}", err.to_string()) - }); - self.notify_gfx(&vendor) - .unwrap_or_else(|err| warn!("GFX: {}", err)); - self.notify_action(&msg) - .unwrap_or_else(|err| warn!("GFX: {}", err)); - } + fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result { + info!("GFX: Switching gfx mode to {}", <&str>::from(vendor)); + let msg = self.set_gfx_config(vendor).map_err(|err| { + error!("GFX: {}", err); + zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) + })?; + self.notify_gfx(&vendor) + .unwrap_or_else(|err| warn!("GFX: {}", err)); + self.notify_action(&msg) + .unwrap_or_else(|err| warn!("GFX: {}", err)); + Ok(msg) } #[dbus_interface(signal)] - fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {} + fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()> {} #[dbus_interface(signal)] - fn notify_action(&self, action: &str) -> zbus::Result<()> {} + fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()> {} } impl ZbusAdd for CtrlGraphics { @@ -163,6 +163,7 @@ impl CtrlGraphics { self.nvidia.clone() } + /// Save the selected `Vendor` mode to config fn save_gfx_mode(vendor: GfxVendors, config: Arc>) { if let Ok(mut config) = config.lock() { config.gfx_mode = vendor; @@ -238,8 +239,40 @@ impl CtrlGraphics { Ok(()) } - fn write_modprobe_conf(content: &[u8]) -> Result<(), RogError> { + fn get_vfio_conf(devices: &[GraphicsDevice]) -> Vec { + let mut vifo = MODPROBE_VFIO.to_vec(); + for (d_count, dev) in devices.iter().enumerate() { + for (f_count, func) in dev.functions().iter().enumerate() { + let vendor = func.vendor().unwrap(); + let device = func.device().unwrap(); + unsafe { + vifo.append(format!("{:x}", vendor).as_mut_vec()); + } + vifo.append(&mut vec![b':']); + unsafe { + vifo.append(format!("{:x}", device).as_mut_vec()); + } + if f_count < dev.functions().len() - 1 { + vifo.append(&mut vec![b',']); + } + } + if d_count < dev.functions().len() - 1 { + vifo.append(&mut vec![b',']); + } + } + let mut conf = MODPROBE_INTEGRATED.to_vec(); + conf.append(&mut vifo); + conf + } + + fn write_modprobe_conf(vendor: GfxVendors, devices: &[GraphicsDevice]) -> Result<(), RogError> { info!("GFX: Writing {}", MODPROBE_PATH); + let content = match vendor { + GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => MODPROBE_BASE.to_vec(), + GfxVendors::Vfio => Self::get_vfio_conf(devices), + // GfxVendors::Compute => {} + GfxVendors::Integrated => MODPROBE_INTEGRATED.to_vec(), + }; let mut file = std::fs::OpenOptions::new() .create(true) @@ -248,7 +281,7 @@ impl CtrlGraphics { .open(MODPROBE_PATH) .map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?; - file.write_all(content) + file.write_all(&content) .and_then(|_| file.sync_all()) .map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?; @@ -258,34 +291,16 @@ impl CtrlGraphics { fn unbind_remove_nvidia(devices: &[GraphicsDevice]) -> Result<(), RogError> { // Unbind NVIDIA graphics devices and their functions let unbinds = devices.iter().map(|dev| dev.unbind()); - // Remove NVIDIA graphics devices and their functions let removes = devices.iter().map(|dev| dev.remove()); - Result::from_iter(unbinds.chain(removes)) - .map_err(|err| RogError::Command("device unbind error".into(), err))?; - - Ok(()) + .map_err(|err| RogError::Command("device unbind error".into(), err)) } - fn log_uses_of_nvidia() { - // lsof /dev/nvidia* - let mut cmd = Command::new("lsof"); - cmd.arg("/dev/nvidia*"); - - match cmd.output() { - Ok(output) => { - if !output.status.success() { - error!( - "Failed to list uses of nvidia devices: {}", - String::from_utf8_lossy(&output.stderr) - ); - } else if output.status.success() { - warn!("GFX: {}", String::from_utf8_lossy(&output.stdout)); - } - } - Err(err) => error!("GFX: Failed to list uses of nvidia devices: {}", err), - } + fn unbind_only(devices: &[GraphicsDevice]) -> Result<(), RogError> { + let unbinds = devices.iter().map(|dev| dev.unbind()); + Result::from_iter(unbinds) + .map_err(|err| RogError::Command("device unbind error".into(), err)) } fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> { @@ -312,14 +327,13 @@ impl CtrlGraphics { return Ok(()); } if output.stderr.ends_with("Permission denied\n".as_bytes()) { - let msg = format!( + warn!( "{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr) ); - warn!("GFX: {}", msg); - warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep nvidia` to confirm modules loaded"); + warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep {}` to confirm modules loaded", driver); return Ok(()); } if count >= MAX_TRIES { @@ -378,6 +392,20 @@ impl CtrlGraphics { Err(GfxError::DisplayManagerTimeout(state.into()).into()) } + /// Determine if we need to logout/thread. Integrated<->Vfio mode does not + /// require logout. + fn logout_required(&self, vendor: GfxVendors) -> GfxRequiredUserAction { + if let Ok(config) = self.config.lock() { + let current = config.gfx_mode; + if matches!(current, GfxVendors::Integrated | GfxVendors::Vfio) + && matches!(vendor, GfxVendors::Integrated | GfxVendors::Vfio) + { + return GfxRequiredUserAction::None; + } + } + GfxRequiredUserAction::Logout + } + /// Write the config changes and add/remove drivers and devices depending /// on selected mode: /// @@ -387,35 +415,40 @@ impl CtrlGraphics { /// - rescan for devices /// + add drivers /// + or remove drivers and devices + /// + /// The daemon needs direct access to this function when it detects that the pub fn do_vendor_tasks( vendor: GfxVendors, devices: &[GraphicsDevice], bus: &PciBus, ) -> Result<(), RogError> { + // Rescan before doing remove or add drivers + bus.rescan()?; + // Self::write_xorg_conf(vendor)?; // Write different modprobe to enable boot control to work - match vendor { - GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => { - Self::write_modprobe_conf(MODPROBE_BASE)? - } - // GfxVendors::Compute => {} - GfxVendors::Integrated => Self::write_modprobe_conf(MODPROBE_INTEGRATED)?, - } - - // Rescan before doing remove or add drivers - bus.rescan() - .map_err(|err| GfxError::Bus("bus rescan error".into(), err))?; + Self::write_modprobe_conf(vendor, devices)?; match vendor { GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => { + for driver in VFIO_DRIVERS.iter() { + Self::do_driver_action(driver, "rmmod")?; + } for driver in NVIDIA_DRIVERS.iter() { - Self::do_driver_action(driver, "modprobe").map_err(|err| { - Self::log_uses_of_nvidia(); - err - })?; + Self::do_driver_action(driver, "modprobe")?; } } + GfxVendors::Vfio => { + for driver in NVIDIA_DRIVERS.iter() { + Self::do_driver_action(driver, "rmmod")?; + } + Self::unbind_only(&devices)?; + Self::do_driver_action("vfio-pci", "modprobe")?; + } GfxVendors::Integrated => { + for driver in VFIO_DRIVERS.iter() { + Self::do_driver_action(driver, "rmmod")?; + } for driver in NVIDIA_DRIVERS.iter() { Self::do_driver_action(driver, "rmmod")?; } @@ -426,7 +459,7 @@ impl CtrlGraphics { Ok(()) } - fn graphical_session_active( + fn graphical_session_alive( connection: &Connection, sessions: &[SessionInfo], ) -> Result { @@ -435,9 +468,9 @@ impl CtrlGraphics { if session_proxy.get_class()? == SessionClass::User { match session_proxy.get_type()? { SessionType::X11 | SessionType::Wayland | SessionType::MIR => { - if session_proxy.get_active()? { - return Ok(true); - } + //if session_proxy.get_active()? { + return Ok(true); + //} } _ => {} } @@ -452,6 +485,7 @@ impl CtrlGraphics { devices: Vec, bus: PciBus, thread_stop: mpsc::Receiver, + config: Arc>, ) -> Result { info!("GFX: display-manager thread started"); @@ -470,7 +504,7 @@ impl CtrlGraphics { sessions = tmp; } - if !Self::graphical_session_active(&connection, &sessions)? { + if !Self::graphical_session_alive(&connection, &sessions)? { break; } @@ -510,6 +544,8 @@ impl CtrlGraphics { Self::do_display_manager_action("restart")?; Self::wait_display_manager_state("active")?; } + // Save selected mode in case of reboot + Self::save_gfx_mode(vendor, config); info!("GFX: display-manager started"); let v: &str = vendor.into(); @@ -517,18 +553,7 @@ impl CtrlGraphics { Ok(format!("Graphics mode changed to {} successfully", v)) } - /// Initiates a mode change by starting a thread that will wait until all - /// graphical sessions are exited before performing the tasks required - /// to switch modes. - /// - /// For manually calling (not on boot/startup) via dbus - pub fn set_gfx_config(&mut self, vendor: GfxVendors) -> Result { - if let Ok(gsync) = CtrlRogBios::get_gfx_mode() { - if gsync == 1 { - return Err(GfxError::GsyncModeActive.into()); - } - } - + fn cancel_thread(&self) { if let Ok(lock) = self.thread_kill.lock() { if let Some(tx) = lock.as_ref() { // Cancel the running thread @@ -540,7 +565,11 @@ impl CtrlGraphics { .ok(); } } + } + /// The thread is used only in cases where a logout is required + fn setup_thread(&mut self, vendor: GfxVendors) { + let config = self.config.clone(); let devices = self.nvidia.clone(); let bus = self.bus.clone(); let (tx, rx) = mpsc::channel(); @@ -549,11 +578,8 @@ impl CtrlGraphics { } let killer = self.thread_kill.clone(); - // Save selected mode in case of reboot - Self::save_gfx_mode(vendor, self.config.clone()); - let _join: JoinHandle<()> = std::thread::spawn(move || { - Self::fire_starter(vendor, devices, bus, rx) + Self::fire_starter(vendor, devices, bus, rx, config) .map_err(|err| { error!("GFX: {}", err); }) @@ -563,28 +589,42 @@ impl CtrlGraphics { *lock = None; } }); - - // TODO: undo if failed? Save last mode, catch errors... - let v: &str = vendor.into(); - Ok(format!("Graphics mode changed to {} successfully", v)) } - // if CtrlRogBios::has_dedicated_gfx_toggle() { - // if let Ok(config) = self.config.clone().try_lock() { - // // Switch to dedicated if config says to do so - // if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia { - // CtrlRogBios::set_gfx_mode(true) - // .unwrap_or_else(|err| warn!("GFX: Gfx controller: {}", err)); - // } else if let Ok(ded) = CtrlRogBios::get_gfx_mode() { - // // otherwise if switching to non-Nvidia mode turn off dedicated mode - // if ded == 1 && vendor != GfxVendors::Nvidia { - // CtrlRogBios::set_gfx_mode(false) - // .unwrap_or_else(|err| warn!("GFX: Gfx controller: {}", err)); - // } - // } - // } - // } + /// Initiates a mode change by starting a thread that will wait until all + /// graphical sessions are exited before performing the tasks required + /// to switch modes. + /// + /// For manually calling (not on boot/startup) via dbus + pub fn set_gfx_config( + &mut self, + vendor: GfxVendors, + ) -> Result { + if let Ok(gsync) = CtrlRogBios::get_gfx_mode() { + if gsync == 1 { + return Err(GfxError::GsyncModeActive.into()); + } + } + // Must always cancel any thread running + self.cancel_thread(); + // determine which method we need here + let action_required = self.logout_required(vendor); + if matches!(action_required, GfxRequiredUserAction::Logout) { + // Yeah need the thread to check if all users are logged out + info!("GFX: mode change requires a logout to complete"); + self.setup_thread(vendor); + } else { + // Okay cool, we can switch on/off vfio + info!("GFX: mode change does not require logout"); + let devices = self.nvidia.clone(); + let bus = self.bus.clone(); + Self::do_vendor_tasks(vendor, &devices, &bus)?; + } + // TODO: undo if failed? Save last mode, catch errors... + Ok(action_required) + } + /// Used only on boot to set correct mode fn auto_power(&mut self) -> Result<(), RogError> { let vendor = self.get_gfx_mode()?; let devices = self.nvidia.clone(); diff --git a/daemon/src/ctrl_gfx/mod.rs b/daemon/src/ctrl_gfx/mod.rs index 61699bf6..215f0325 100644 --- a/daemon/src/ctrl_gfx/mod.rs +++ b/daemon/src/ctrl_gfx/mod.rs @@ -6,6 +6,14 @@ pub mod system; const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"]; +const VFIO_DRIVERS: [&str; 5] = [ + "vfio-pci", + "vfio_iommu_type1", + "vfio_virqfd", + "vfio_mdev", + "vfio", +]; + const DISPLAY_MANAGER: &str = "display-manager.service"; const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf"; @@ -30,6 +38,8 @@ blacklist nouveau alias nouveau off "#; +static MODPROBE_VFIO: &[u8] = br#"options vfio-pci ids="#; + const XORG_FILE: &str = "90-nvidia-primary.conf"; const XORG_PATH: &str = "/etc/X11/xorg.conf.d/"; diff --git a/daemon/src/ctrl_gfx/system.rs b/daemon/src/ctrl_gfx/system.rs index 82f1f2bb..f730a9ae 100644 --- a/daemon/src/ctrl_gfx/system.rs +++ b/daemon/src/ctrl_gfx/system.rs @@ -72,6 +72,10 @@ impl GraphicsDevice { self.functions.iter().any(|func| func.path().exists()) } + pub fn functions(&self) -> &[PciDevice] { + &self.functions + } + pub fn unbind(&self) -> Result<(), std::io::Error> { for func in self.functions.iter() { if func.path().exists() { diff --git a/daemon/src/error.rs b/daemon/src/error.rs index 2a86675d..79140f57 100644 --- a/daemon/src/error.rs +++ b/daemon/src/error.rs @@ -28,6 +28,7 @@ pub enum RogError { Initramfs(String), Modprobe(String), Command(String, std::io::Error), + Io(std::io::Error), Zbus(zbus::Error), } @@ -55,6 +56,7 @@ impl fmt::Display for RogError { 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), + RogError::Io(detail) => write!(f, "std::io error: {}", detail), RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail), } } @@ -87,3 +89,9 @@ impl From for RogError { RogError::Zbus(err) } } + +impl From for RogError { + fn from(err: std::io::Error) -> Self { + RogError::Io(err) + } +} diff --git a/rog-dbus/src/lib.rs b/rog-dbus/src/lib.rs index 547d655d..3404d28f 100644 --- a/rog-dbus/src/lib.rs +++ b/rog-dbus/src/lib.rs @@ -11,7 +11,10 @@ pub mod zbus_profile; pub mod zbus_rogbios; pub mod zbus_supported; -use rog_types::aura_modes::AuraEffect; +use rog_types::{ + aura_modes::AuraEffect, + gfx_vendors::{GfxRequiredUserAction, GfxVendors}, +}; use std::sync::{Arc, Mutex}; use zbus::{Connection, Result, SignalReceiver}; @@ -86,8 +89,8 @@ impl<'a> DbusProxies<'a> { // Signals separated out pub struct Signals { - pub gfx_vendor: Arc>>, - pub gfx_action: Arc>>, + pub gfx_vendor: Arc>>, + pub gfx_action: Arc>>, pub profile: Arc>>, pub led_mode: Arc>>, pub charge: Arc>>, @@ -151,13 +154,13 @@ impl<'a> AuraDbusClient<'a> { /* * GFX */ - pub fn gfx_wait_changed(&self) -> Result { + pub fn gfx_wait_changed(&self) -> Result { loop { if let Ok(res) = self.proxies.gfx.proxy().next_signal() { if res.is_none() { if let Ok(lock) = self.signals.gfx_action.lock() { if let Some(stuff) = lock.as_ref() { - return Ok(stuff.to_string()); + return Ok(*stuff); } } // return Ok("Failed for unknown reason".to_owned()); diff --git a/rog-dbus/src/zbus_gfx.rs b/rog-dbus/src/zbus_gfx.rs index c62e0020..c0f726b9 100644 --- a/rog-dbus/src/zbus_gfx.rs +++ b/rog-dbus/src/zbus_gfx.rs @@ -21,6 +21,7 @@ use std::sync::{Arc, Mutex}; +use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors}; use zbus::{dbus_proxy, Connection, Result}; #[dbus_proxy( @@ -32,18 +33,18 @@ trait Daemon { fn power(&self) -> zbus::Result; /// SetVendor method - fn set_vendor(&self, vendor: &str) -> zbus::Result<()>; + fn set_vendor(&self, vendor: &GfxVendors) -> zbus::Result; /// Vendor method - fn vendor(&self) -> zbus::Result; + fn vendor(&self) -> zbus::Result; /// NotifyAction signal #[dbus_proxy(signal)] - fn notify_action(&self, action: &str) -> zbus::Result<()>; + fn notify_action(&self, action: GfxRequiredUserAction) -> zbus::Result<()>; /// NotifyGfx signal #[dbus_proxy(signal)] - fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>; + fn notify_gfx(&self, vendor: GfxVendors) -> zbus::Result<()>; } pub struct GfxProxy<'a>(DaemonProxy<'a>); @@ -64,33 +65,36 @@ impl<'a> GfxProxy<'a> { } #[inline] - pub fn gfx_get_mode(&self) -> Result { + pub fn gfx_get_mode(&self) -> Result { self.0.vendor() } #[inline] - pub fn gfx_write_mode(&self, vendor: &str) -> Result<()> { + pub fn gfx_write_mode(&self, vendor: &GfxVendors) -> Result { self.0.set_vendor(vendor) } #[inline] pub fn connect_notify_action( &self, - action: Arc>>, + action: Arc>>, ) -> zbus::fdo::Result<()> { self.0.connect_notify_action(move |data| { if let Ok(mut lock) = action.lock() { - *lock = Some(data.to_owned()); + *lock = Some(data); } Ok(()) }) } #[inline] - pub fn connect_notify_gfx(&self, vendor: Arc>>) -> zbus::fdo::Result<()> { + pub fn connect_notify_gfx( + &self, + vendor: Arc>>, + ) -> zbus::fdo::Result<()> { self.0.connect_notify_gfx(move |data| { if let Ok(mut lock) = vendor.lock() { - *lock = Some(data.to_owned()); + *lock = Some(data); } Ok(()) }) diff --git a/rog-dbus/src/zbus_led.rs b/rog-dbus/src/zbus_led.rs index f9161768..cd016531 100644 --- a/rog-dbus/src/zbus_led.rs +++ b/rog-dbus/src/zbus_led.rs @@ -45,7 +45,7 @@ trait Daemon { fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>; /// NotifyLed signal - /// NotifyLed signal + /// NotifyLed signal #[dbus_proxy(signal)] fn notify_led(&self, data: &str) -> zbus::Result<()>; diff --git a/rog-types/src/aura_modes.rs b/rog-types/src/aura_modes.rs index cf8b1e7e..42ed78da 100644 --- a/rog-types/src/aura_modes.rs +++ b/rog-types/src/aura_modes.rs @@ -4,8 +4,8 @@ // static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e // static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08]; -use crate::LED_MSG_LEN; use crate::error::AuraError; +use crate::LED_MSG_LEN; use serde_derive::{Deserialize, Serialize}; use std::str::FromStr; use zvariant_derive::Type; diff --git a/rog-types/src/cli_options.rs b/rog-types/src/cli_options.rs index fa7c072d..c186becc 100644 --- a/rog-types/src/cli_options.rs +++ b/rog-types/src/cli_options.rs @@ -1,6 +1,4 @@ -use crate::{ - error::AuraError, -}; +use crate::error::AuraError; use gumdrop::Options; use std::str::FromStr; diff --git a/rog-types/src/gfx_vendors.rs b/rog-types/src/gfx_vendors.rs index 54330c7e..dad441d8 100644 --- a/rog-types/src/gfx_vendors.rs +++ b/rog-types/src/gfx_vendors.rs @@ -1,12 +1,14 @@ use crate::error::GraphicsError; use serde_derive::{Deserialize, Serialize}; use std::str::FromStr; +use zvariant_derive::Type; -#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)] +#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)] pub enum GfxVendors { Nvidia, Integrated, Compute, + Vfio, Hybrid, } @@ -18,10 +20,12 @@ impl FromStr for GfxVendors { "nvidia" => Ok(GfxVendors::Nvidia), "hybrid" => Ok(GfxVendors::Hybrid), "compute" => Ok(GfxVendors::Compute), + "vfio" => Ok(GfxVendors::Vfio), "integrated" => Ok(GfxVendors::Integrated), "nvidia\n" => Ok(GfxVendors::Nvidia), "hybrid\n" => Ok(GfxVendors::Hybrid), "compute\n" => Ok(GfxVendors::Compute), + "vfio\n" => Ok(GfxVendors::Vfio), "integrated\n" => Ok(GfxVendors::Integrated), _ => Err(GraphicsError::ParseVendor), } @@ -34,6 +38,7 @@ impl From<&GfxVendors> for &str { GfxVendors::Nvidia => "nvidia", GfxVendors::Hybrid => "hybrid", GfxVendors::Compute => "compute", + GfxVendors::Vfio => "vfio", GfxVendors::Integrated => "integrated", } } @@ -45,38 +50,19 @@ impl From for &str { } } -#[derive(Debug)] -pub enum GfxCtrlAction { +#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)] +pub enum GfxRequiredUserAction { + Logout, Reboot, - RestartX, None, } -impl FromStr for GfxCtrlAction { - type Err = GraphicsError; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "reboot" => Ok(GfxCtrlAction::Reboot), - "restartx" => Ok(GfxCtrlAction::RestartX), - "none" => Ok(GfxCtrlAction::None), - _ => Err(GraphicsError::ParseVendor), +impl From<&GfxRequiredUserAction> for &str { + fn from(gfx: &GfxRequiredUserAction) -> &'static str { + match gfx { + GfxRequiredUserAction::Logout => "logout", + GfxRequiredUserAction::Reboot => "reboot", + GfxRequiredUserAction::None => "no action", } } } - -impl From<&GfxCtrlAction> for &str { - fn from(mode: &GfxCtrlAction) -> Self { - match mode { - GfxCtrlAction::Reboot => "reboot", - GfxCtrlAction::RestartX => "restartx", - GfxCtrlAction::None => "none", - } - } -} - -impl From for &str { - fn from(mode: GfxCtrlAction) -> Self { - (&mode).into() - } -}