From 3e109ef473fa30b466a34eab7165a21dcf309701 Mon Sep 17 00:00:00 2001 From: Michael Murphy Date: Mar 25 2019 17:57:23 +0000 Subject: Merge branch 'master' into power-client --- diff --git a/src/client.rs b/src/client.rs index b68ddf6..5371dc5 100644 --- a/src/client.rs +++ b/src/client.rs @@ -55,6 +55,12 @@ impl Power for PowerClient { r.get1().ok_or_else(|| "return value not found".to_string()) } + fn get_profile(&mut self) -> Result { + let m = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "GetProfile")?; + let r = self.bus.send_with_reply_and_block(m, TIMEOUT).map_err(err_str)?; + r.get1().ok_or_else(|| "return value not found".to_string()) + } + fn get_switchable(&mut self) -> Result { let r = self.call_method::("GetSwitchable", None)?; r.get1().ok_or_else(|| "return value not found".to_string()) @@ -81,7 +87,11 @@ impl Power for PowerClient { } } -fn profile() -> io::Result<()> { +fn profile(client: &mut PowerClient) -> io::Result<()> { + let profile = client.get_profile().ok(); + let profile = profile.as_ref().map_or("?", |s| s.as_str()); + println!("Power Profile: {}", profile); + if let Ok(pstate) = PState::new() { let min = pstate.min_perf_pct()?; let max = pstate.max_perf_pct()?; @@ -118,7 +128,7 @@ pub fn client(subcommand: &str, matches: &ArgMatches) -> Result<(), String> { Some("balanced") => client.balanced(), Some("battery") => client.battery(), Some("performance") => client.performance(), - _ => profile().map_err(err_str) + _ => profile(&mut client).map_err(err_str) }, "graphics" => match matches.subcommand() { ("intel", _) => client.set_graphics("intel"), diff --git a/src/daemon.rs b/src/daemon.rs index 0f61ce5..a76d1b9 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,5 +1,5 @@ use dbus::{Connection, BusType, NameFlag}; -use dbus::tree::{Factory, MethodErr}; +use dbus::tree::{Factory, MethodErr, Signal}; use std::cell::RefCell; use std::io; use std::rc::Rc; @@ -146,33 +146,64 @@ fn battery() -> io::Result<()> { } struct PowerDaemon { - graphics: Graphics + graphics: Graphics, + power_profile: String, + dbus_connection: Arc, + power_switch_signal: Arc> } impl PowerDaemon { - fn new() -> Result { + fn new(power_switch_signal: Arc>, dbus_connection: Arc) -> Result { let graphics = Graphics::new().map_err(err_str)?; - Ok(PowerDaemon { graphics }) + Ok(PowerDaemon { + graphics, + power_profile: String::new(), + power_switch_signal, + dbus_connection, + }) + } + + fn apply_profile(&mut self, func: F, name: &str) -> Result<(), String> + where F: Fn() -> io::Result<()>, + { + let res = func().map_err(err_str); + if res.is_ok() { + let message = self.power_switch_signal + .msg(&DBUS_PATH.into(), &DBUS_NAME.into()) + .append1(name); + + if let Err(()) = self.dbus_connection.send(message) { + error!("failed to send power profile switch message"); + } + + self.power_profile = name.into(); + } + + res } } impl Power for PowerDaemon { - fn performance(&mut self) -> Result<(), String> { - performance().map_err(err_str) + fn battery(&mut self) -> Result<(), String> { + self.apply_profile(battery, "Battery") } fn balanced(&mut self) -> Result<(), String> { - balanced().map_err(err_str) + self.apply_profile(balanced, "Balanced") } - fn battery(&mut self) -> Result<(), String> { - battery().map_err(err_str) + fn performance(&mut self) -> Result<(), String> { + self.apply_profile(performance, "Performance") } fn get_graphics(&mut self) -> Result { self.graphics.get_vendor().map_err(err_str) } + fn get_profile(&mut self) -> Result { + Ok(self.power_profile.clone()) + } + fn get_switchable(&mut self) -> Result { Ok(self.graphics.can_switch()) } @@ -197,7 +228,16 @@ impl Power for PowerDaemon { pub fn daemon(experimental: bool) -> Result<(), String> { info!("Starting daemon{}", if experimental { " with experimental enabled" } else { "" }); EXPERIMENTAL.store(experimental, Ordering::SeqCst); - let daemon = Rc::new(RefCell::new(PowerDaemon::new()?)); + + info!("Connecting to dbus system bus"); + let c = Arc::new(Connection::get_private(BusType::System).map_err(err_str)?); + + let f = Factory::new_fn::<()>(); + let hotplug_signal = Arc::new(f.signal("HotPlugDetect", ()).sarg::("port")); + let power_switch_signal = Arc::new(f.signal("PowerProfileSwitch", ()).sarg::<&str,_>("profile")); + + let daemon = PowerDaemon::new(power_switch_signal.clone(), c.clone())?; + let daemon = Rc::new(RefCell::new(daemon)); info!("Disabling NMI Watchdog (for kernel debugging only)"); NmiWatchdog::new().set(b"0"); @@ -211,16 +251,11 @@ pub fn daemon(experimental: bool) -> Result<(), String> { } info!("Initializing with the balanced profile"); - balanced().map_err(|why| format!("failed to set initial profile: {}", why))?; - - info!("Connecting to dbus system bus"); - let c = Connection::get_private(BusType::System).map_err(err_str)?; + daemon.borrow_mut().balanced().map_err(|why| format!("failed to set initial profile: {}", why))?; info!("Registering dbus name {}", DBUS_NAME); c.register_name(DBUS_NAME, NameFlag::ReplaceExisting as u32).map_err(err_str)?; - let f = Factory::new_fn::<()>(); - // Defines whether the value returned by the method should be appended. macro_rules! append { (true, $m:ident, $value:ident) => { $m.msg.method_return().append1($value) }; @@ -261,8 +296,6 @@ pub fn daemon(experimental: bool) -> Result<(), String> { }}; } - let signal = Arc::new(f.signal("HotPlugDetect", ()).sarg::("port")); - info!("Adding dbus path {} with interface {}", DBUS_PATH, DBUS_IFACE); let tree = f.tree(()).add(f.object_path(DBUS_PATH, ()).introspectable().add( f.interface(DBUS_IFACE, ()) @@ -270,12 +303,14 @@ pub fn daemon(experimental: bool) -> Result<(), String> { .add_m(method!(balanced, "Balanced", false, false)) .add_m(method!(battery, "Battery", false, false)) .add_m(method!(get_graphics, "GetGraphics", true, false).outarg::<&str,_>("vendor")) + .add_m(method!(get_profile, "GetProfile", true, false).outarg::<&str,_>("vendor")) .add_m(method!(set_graphics, "SetGraphics", false, true).inarg::<&str,_>("vendor")) .add_m(method!(get_switchable, "GetSwitchable", true, false).outarg::("switchable")) .add_m(method!(get_graphics_power, "GetGraphicsPower", true, false).outarg::("power")) .add_m(method!(set_graphics_power, "SetGraphicsPower", false, true).inarg::("power")) .add_m(method!(auto_graphics_power, "AutoGraphicsPower", false, false)) - .add_s(signal.clone()) + .add_s(hotplug_signal.clone()) + .add_s(power_switch_signal.clone()) )); tree.set_registered(&c, true).map_err(err_str)?; @@ -313,7 +348,7 @@ pub fn daemon(experimental: bool) -> Result<(), String> { if hpd[i] != last[i] && hpd[i] { info!("HotPlugDetect {}", i); c.send( - signal.msg(&DBUS_PATH.into(), &DBUS_NAME.into()).append1(i as u64) + hotplug_signal.msg(&DBUS_PATH.into(), &DBUS_NAME.into()).append1(i as u64) ).map_err(|()| "failed to send message".to_string())?; } } diff --git a/src/graphics.rs b/src/graphics.rs index fc4bb49..e227b42 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -83,6 +83,7 @@ impl GraphicsDevice { pub struct Graphics { pub bus: PciBus, + pub amd: Vec, pub intel: Vec, pub nvidia: Vec, pub other: Vec, @@ -112,6 +113,7 @@ impl Graphics { functions }; + let mut amd = Vec::new(); let mut intel = Vec::new(); let mut nvidia = Vec::new(); let mut other = Vec::new(); @@ -119,6 +121,10 @@ impl Graphics { let c = dev.class()?; match (c >> 16) & 0xFF { 0x03 => match dev.vendor()? { + 0x1002 => { + info!("{}: AMD graphics", dev.id()); + amd.push(GraphicsDevice::new(functions(&dev))); + } 0x10DE => { info!("{}: NVIDIA graphics", dev.id()); nvidia.push(GraphicsDevice::new(functions(&dev))); @@ -138,6 +144,7 @@ impl Graphics { Ok(Graphics { bus, + amd, intel, nvidia, other, diff --git a/src/lib.rs b/src/lib.rs index dc436c7..efe433b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ pub trait Power { fn balanced(&mut self) -> Result<(), String>; fn battery(&mut self) -> Result<(), String>; fn get_graphics(&mut self) -> Result; + fn get_profile(&mut self) -> Result; fn get_switchable(&mut self) -> Result; fn set_graphics(&mut self, vendor: &str) -> Result<(), String>; fn get_graphics_power(&mut self) -> Result;