GFX control, no-tokio, no-async, dbus client refactor

- Working gfx modes <iGPU only, dGPU only, or hybrid>
- Add signal for gfx vendor change and make CLI wait for signal
- Add polling for led brightness to save to config
- Move daemon to zbus crate
- dbus client refactor
- Further dbus methods and updates
- Add basic notification user daemon and systemd service
This commit is contained in:
Luke D Jones
2020-09-13 15:05:59 +12:00
parent 4cdb06959b
commit fe6231ad4e
129 changed files with 2495 additions and 363398 deletions

View File

@@ -1,74 +1,84 @@
use crate::config::Config;
use log::{error, info, warn};
use std::error::Error;
use crate::{config::Config, error::RogError};
//use crate::dbus::DbusEvents;
use log::{info, warn};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::mpsc::Receiver;
use tokio::sync::Mutex;
use tokio::task::JoinHandle;
use std::sync::Mutex;
use zbus::dbus_interface;
static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
pub struct CtrlCharge {
path: &'static str,
config: Arc<Mutex<Config>>,
}
use ::dbus::{nonblock::SyncConnection, tree::Signal};
use async_trait::async_trait;
trait Dbus {
fn set_limit(&mut self, charge: u8);
fn limit(&self) -> i8;
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
}
#[async_trait]
impl crate::Controller for CtrlCharge {
type A = u8;
/// Spawns two tasks which continuously check for changes
fn spawn_task_loop(
self,
config: Arc<Mutex<Config>>,
mut recv: Receiver<Self::A>,
_: Option<Arc<SyncConnection>>,
_: Option<Arc<Signal<()>>>,
) -> Vec<JoinHandle<()>> {
vec![tokio::spawn(async move {
while let Some(n) = recv.recv().await {
let mut config = config.lock().await;
self.set_charge_limit(n, &mut config)
.unwrap_or_else(|err| warn!("charge_limit: {}", err));
}
})]
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlCharge {
fn set_limit(&mut self, limit: u8) {
if let Ok(mut config) = self.config.try_lock() {
self.set(limit, &mut config).unwrap();
self.notify_charge(limit).unwrap();
}
}
async fn reload_from_config(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
config.read();
info!("Reloaded battery charge limit");
self.set_charge_limit(config.bat_charge_limit, config)
fn limit(&self) -> i8 {
if let Ok(config) = self.config.try_lock() {
return config.bat_charge_limit as i8;
}
-1
}
#[dbus_interface(signal)]
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
}
impl crate::ZbusAdd for CtrlCharge {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Charge".try_into().unwrap(), self)
.unwrap();
}
}
impl crate::Reloadable for CtrlCharge {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.try_lock() {
config.read();
info!("Reloaded battery charge limit");
self.set(config.bat_charge_limit, &mut config)?;
}
Ok(())
}
}
impl CtrlCharge {
pub fn new() -> Result<Self, Box<dyn Error>> {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlCharge::get_battery_path()?;
info!("Device has battery charge threshold control");
Ok(CtrlCharge { path })
Ok(CtrlCharge { path, config })
}
fn get_battery_path() -> Result<&'static str, std::io::Error> {
fn get_battery_path() -> Result<&'static str, RogError> {
if Path::new(BAT_CHARGE_PATH).exists() {
Ok(BAT_CHARGE_PATH)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Charge control not available",
Err(RogError::MissingFunction(
"Charge control not available".into(),
))
}
}
pub(super) fn set_charge_limit(
&self,
limit: u8,
config: &mut Config,
) -> Result<(), Box<dyn Error>> {
pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> {
if limit < 20 || limit > 100 {
warn!(
"Unable to set battery charge limit, must be between 20-100: requested {}",
@@ -79,12 +89,9 @@ impl CtrlCharge {
let mut file = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| {
warn!("Failed to open battery charge limit path: {}", err);
err
})?;
.map_err(|err| RogError::Path(self.path.into(), err))?;
file.write_all(limit.to_string().as_bytes())
.unwrap_or_else(|err| error!("Could not write to {}, {}", BAT_CHARGE_PATH, err));
.map_err(|err| RogError::Write(self.path.into(), err))?;
info!("Battery charge limit: {}", limit);
config.read();