mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
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:
@@ -1,27 +1,24 @@
|
||||
use daemon::{
|
||||
config::Config, ctrl_anime::CtrlAnimeDisplay, ctrl_charge::CtrlCharge,
|
||||
ctrl_fan_cpu::CtrlFanAndCPU, ctrl_leds::CtrlKbdBacklight, dbus::dbus_create_tree,
|
||||
laptops::match_laptop,
|
||||
};
|
||||
use ctrl_gfx::ctrl_gfx::CtrlGraphics;
|
||||
use daemon::config::Config;
|
||||
use daemon::ctrl_anime::CtrlAnimeDisplay;
|
||||
use daemon::ctrl_charge::CtrlCharge;
|
||||
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
|
||||
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
||||
use daemon::laptops::match_laptop;
|
||||
|
||||
use dbus::{
|
||||
channel::Sender,
|
||||
nonblock::{Process, SyncConnection},
|
||||
tree::Signal,
|
||||
};
|
||||
use dbus_tokio::connection;
|
||||
|
||||
use asus_nb::{DBUS_IFACE, DBUS_NAME, DBUS_PATH};
|
||||
use daemon::Controller;
|
||||
use asus_nb::DBUS_NAME;
|
||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
||||
use log::LevelFilter;
|
||||
use log::{error, info, warn};
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
use zbus::fdo;
|
||||
use zbus::Connection;
|
||||
|
||||
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut logger = env_logger::Builder::new();
|
||||
logger
|
||||
.target(env_logger::Target::Stdout)
|
||||
@@ -30,7 +27,7 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.init();
|
||||
|
||||
info!("Version: {}", daemon::VERSION);
|
||||
start_daemon().await?;
|
||||
start_daemon()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -43,209 +40,100 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// as fast as 1ms per row of the matrix inside it. (10ms total time)
|
||||
//
|
||||
// DBUS processing takes 6ms if not tokiod
|
||||
pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
let laptop = match_laptop();
|
||||
let mut config = if let Some(laptop) = laptop.as_ref() {
|
||||
let config = if let Some(laptop) = laptop.as_ref() {
|
||||
Config::default().load(laptop.supported_modes())
|
||||
} else {
|
||||
Config::default().load(&[])
|
||||
};
|
||||
|
||||
let mut led_control = if let Some(laptop) = laptop {
|
||||
Some(CtrlKbdBacklight::new(
|
||||
let connection = Connection::new_system()?;
|
||||
fdo::DBusProxy::new(&connection)?
|
||||
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
|
||||
let mut object_server = zbus::ObjectServer::new(&connection);
|
||||
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
|
||||
match CtrlCharge::new(config.clone()) {
|
||||
Ok(mut ctrl) => {
|
||||
// Do a reload of any settings
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Battery charge limit: {}", err));
|
||||
// Then register to dbus server
|
||||
ctrl.add_to_server(&mut object_server);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("charge_control: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
match CtrlAnimeDisplay::new() {
|
||||
Ok(ctrl) => {
|
||||
ctrl.add_to_server(&mut object_server);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("AniMe control: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
match CtrlGraphics::new() {
|
||||
Ok(mut ctrl) => {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
ctrl.add_to_server(&mut object_server);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Gfx control: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect tasks for task thread
|
||||
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
||||
|
||||
match CtrlFanAndCPU::new(config.clone()) {
|
||||
Ok(mut ctrl) => {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
||||
let tmp = Arc::new(Mutex::new(ctrl));
|
||||
DbusFanAndCpu::new(tmp.clone()).add_to_server(&mut object_server);
|
||||
tasks.push(tmp);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Profile control: {}", err);
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(laptop) = laptop {
|
||||
let ctrl = CtrlKbdBacklight::new(
|
||||
laptop.usb_product(),
|
||||
laptop.condev_iface(),
|
||||
laptop.supported_modes().to_owned(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut charge_control = CtrlCharge::new().map_or_else(
|
||||
|err| {
|
||||
error!("{}", err);
|
||||
None
|
||||
},
|
||||
Some,
|
||||
);
|
||||
|
||||
let mut fan_control = CtrlFanAndCPU::new().map_or_else(
|
||||
|err| {
|
||||
error!("{}", err);
|
||||
None
|
||||
},
|
||||
Some,
|
||||
);
|
||||
|
||||
// Reload settings
|
||||
if let Some(ctrl) = fan_control.as_mut() {
|
||||
ctrl.reload_from_config(&mut config)
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("Fan mode: {}", err));
|
||||
config,
|
||||
);
|
||||
let tmp = Arc::new(Mutex::new(ctrl));
|
||||
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server);
|
||||
tasks.push(tmp);
|
||||
}
|
||||
|
||||
if let Some(ctrl) = charge_control.as_mut() {
|
||||
ctrl.reload_from_config(&mut config)
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("Battery charge limit: {}", err));
|
||||
}
|
||||
// TODO: implement messaging between threads to check fails
|
||||
// These tasks generally read a sys path or file to check for a
|
||||
// change
|
||||
let _handle = std::thread::Builder::new()
|
||||
.name("asusd watch".to_string())
|
||||
.spawn(move || loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
||||
if let Some(ctrl) = led_control.as_mut() {
|
||||
ctrl.reload_from_config(&mut config)
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("Reload settings: {}", err));
|
||||
}
|
||||
|
||||
let (resource, connection) = connection::new_system_sync()?;
|
||||
tokio::spawn(async {
|
||||
let err = resource.await;
|
||||
panic!("Lost connection to D-Bus: {}", err);
|
||||
});
|
||||
|
||||
connection
|
||||
.request_name(DBUS_NAME, false, true, true)
|
||||
.await?;
|
||||
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
let (
|
||||
tree,
|
||||
aura_command_recv,
|
||||
animatrix_recv,
|
||||
_fan_mode_recv,
|
||||
charge_limit_recv,
|
||||
profile_recv,
|
||||
led_changed_signal,
|
||||
fanmode_signal,
|
||||
charge_limit_signal,
|
||||
) = dbus_create_tree(config.clone());
|
||||
|
||||
// We add the tree to the connection so that incoming method calls will be handled.
|
||||
tree.start_receive_send(&*connection);
|
||||
|
||||
// Send boot signals
|
||||
send_boot_signals(
|
||||
connection.clone(),
|
||||
config.clone(),
|
||||
fanmode_signal.clone(),
|
||||
charge_limit_signal.clone(),
|
||||
led_changed_signal.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// For helping with processing signals
|
||||
start_signal_task(
|
||||
connection.clone(),
|
||||
config.clone(),
|
||||
fanmode_signal,
|
||||
charge_limit_signal,
|
||||
);
|
||||
|
||||
// Begin all tasks
|
||||
let mut handles = Vec::new();
|
||||
if let Ok(ctrl) = CtrlAnimeDisplay::new() {
|
||||
handles.append(&mut ctrl.spawn_task_loop(config.clone(), animatrix_recv, None, None));
|
||||
}
|
||||
|
||||
if let Some(ctrl) = fan_control.take() {
|
||||
handles.append(&mut ctrl.spawn_task_loop(config.clone(), profile_recv, None, None));
|
||||
}
|
||||
|
||||
if let Some(ctrl) = charge_control.take() {
|
||||
handles.append(&mut ctrl.spawn_task_loop(config.clone(), charge_limit_recv, None, None));
|
||||
}
|
||||
|
||||
if let Some(ctrl) = led_control.take() {
|
||||
handles.append(&mut ctrl.spawn_task_loop(
|
||||
config.clone(),
|
||||
aura_command_recv,
|
||||
Some(connection.clone()),
|
||||
Some(led_changed_signal),
|
||||
));
|
||||
}
|
||||
|
||||
connection.process_all();
|
||||
for handle in handles {
|
||||
handle.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: Move these in to the controllers tasks
|
||||
fn start_signal_task(
|
||||
connection: Arc<SyncConnection>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
fanmode_signal: Arc<Signal<()>>,
|
||||
charge_limit_signal: Arc<Signal<()>>,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
// Some small things we need to track, without passing all sorts of stuff around
|
||||
let mut last_fan_mode = config.lock().await.power_profile;
|
||||
let mut last_charge_limit = config.lock().await.bat_charge_limit;
|
||||
loop {
|
||||
// Use tokio sleep to not hold up other threads
|
||||
tokio::time::delay_for(std::time::Duration::from_millis(500)).await;
|
||||
|
||||
let config = config.lock().await;
|
||||
if config.power_profile != last_fan_mode {
|
||||
last_fan_mode = config.power_profile;
|
||||
connection
|
||||
.send(
|
||||
fanmode_signal
|
||||
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
|
||||
.append1(last_fan_mode),
|
||||
)
|
||||
.unwrap_or_else(|_| 0);
|
||||
for ctrl in tasks.iter() {
|
||||
if let Ok(mut lock) = ctrl.try_lock() {
|
||||
lock.do_task().unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if config.bat_charge_limit != last_charge_limit {
|
||||
last_charge_limit = config.bat_charge_limit;
|
||||
connection
|
||||
.send(
|
||||
charge_limit_signal
|
||||
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
|
||||
.append1(last_charge_limit),
|
||||
)
|
||||
.unwrap_or_else(|_| 0);
|
||||
}
|
||||
loop {
|
||||
if let Err(err) = object_server.try_handle_next() {
|
||||
eprintln!("{}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn send_boot_signals(
|
||||
connection: Arc<SyncConnection>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
fanmode_signal: Arc<Signal<()>>,
|
||||
charge_limit_signal: Arc<Signal<()>>,
|
||||
led_changed_signal: Arc<Signal<()>>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let config = config.lock().await;
|
||||
|
||||
if let Some(data) = config.get_led_mode_data(config.kbd_backlight_mode) {
|
||||
connection
|
||||
.send(
|
||||
led_changed_signal
|
||||
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
|
||||
.append1(serde_json::to_string(data)?),
|
||||
)
|
||||
.unwrap_or_else(|_| 0);
|
||||
}
|
||||
|
||||
connection
|
||||
.send(
|
||||
fanmode_signal
|
||||
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
|
||||
.append1(config.power_profile),
|
||||
)
|
||||
.unwrap_or_else(|_| 0);
|
||||
|
||||
connection
|
||||
.send(
|
||||
charge_limit_signal
|
||||
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
|
||||
.append1(config.bat_charge_limit),
|
||||
)
|
||||
.unwrap_or_else(|_| 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user