use daemon::ctrl_leds::controller::{ CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus, }; use daemon::{ config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, }; use daemon::{config_anime::AnimeConfig, config_aura::AuraConfig, ctrl_charge::CtrlCharge}; use daemon::{ctrl_anime::*, ctrl_gfx::controller::CtrlGraphics}; use daemon::{ ctrl_profiles::{controller::CtrlFanAndCpu, zbus::FanAndCpuZbus}, laptops::LaptopLedData, }; use daemon::{CtrlTask, Reloadable, ZbusAdd}; use log::LevelFilter; use log::{error, info, warn}; use rog_dbus::DBUS_NAME; use rog_types::gfx_vendors::GfxVendors; use std::error::Error; use std::io::Write; use std::sync::Arc; use std::sync::Mutex; use std::env; use daemon::ctrl_rog_bios::CtrlRogBios; use std::convert::Into; use zbus::fdo; use zbus::Connection; use zvariant::ObjectPath; pub fn main() -> Result<(), Box> { let mut logger = env_logger::Builder::new(); logger .target(env_logger::Target::Stdout) .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) .filter(None, LevelFilter::Info) .init(); let is_service = match env::var_os("IS_SERVICE") { Some(val) => val == "1", None => false, }; if !is_service { println!("asusd schould be only run from the right systemd service"); println!("do not run in your terminal, if you need an logs please use journalctl -b -u asusd"); println!("asusd will now exit"); return Ok(()); } info!(" daemon v{}", daemon::VERSION); info!(" rog-anime v{}", rog_anime::VERSION); info!(" rog-aura v{}", rog_aura::VERSION); info!(" rog-dbus v{}", rog_dbus::VERSION); info!("rog-profiles v{}", rog_profiles::VERSION); info!(" rog-types v{}", rog_types::VERSION); start_daemon()?; Ok(()) } /// The actual main loop for the daemon fn start_daemon() -> Result<(), Box> { let supported = SupportedFunctions::get_supported(); print_board_info(); println!("{}", serde_json::to_string_pretty(&supported).unwrap()); // Collect tasks for task thread let mut tasks: Vec> = Vec::new(); // Start zbus server 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 = Config::load(); let enable_gfx_switching = config.gfx_managed; let config = Arc::new(Mutex::new(config)); supported.add_to_server(&mut object_server); match CtrlRogBios::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!("rog_bios_control: {}", err); } } 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 CtrlFanAndCpu::new(config.clone()) { Ok(mut ctrl) => { ctrl.reload() .unwrap_or_else(|err| warn!("Profile control: {}", err)); let tmp = Arc::new(Mutex::new(ctrl)); FanAndCpuZbus::new(tmp).add_to_server(&mut object_server); } Err(err) => { error!("Profile control: {}", err); } } match CtrlAnime::new(AnimeConfig::load()) { Ok(ctrl) => { let inner = Arc::new(Mutex::new(ctrl)); let mut reload = CtrlAnimeReloader(inner.clone()); reload .reload() .unwrap_or_else(|err| warn!("AniMe: {}", err)); let zbus = CtrlAnimeZbus(inner.clone()); zbus.add_to_server(&mut object_server); tasks.push(Box::new(CtrlAnimeTask::new(inner))); } Err(err) => { error!("AniMe control: {}", err); } } let laptop = LaptopLedData::get_data(); let aura_config = AuraConfig::load(&laptop); match CtrlKbdLed::new(laptop, aura_config) { Ok(ctrl) => { let inner = Arc::new(Mutex::new(ctrl)); let mut reload = CtrlKbdLedReloader(inner.clone()); reload .reload() .unwrap_or_else(|err| warn!("Keyboard LED control: {}", err)); CtrlKbdLedZbus::new(inner.clone()).add_to_server(&mut object_server); let task = CtrlKbdLedTask::new(inner); tasks.push(Box::new(task)); } Err(err) => { error!("Keyboard control: {}", err); } } // Graphics switching requires some checks on boot specifically for g-sync capable laptops if enable_gfx_switching { match CtrlGraphics::new(config.clone()) { Ok(mut ctrl) => { // Need to check if a laptop has the dedicated gfx switch if CtrlRogBios::has_dedicated_gfx_toggle() { if let Ok(ded) = CtrlRogBios::get_gfx_mode() { if let Ok(config) = config.lock() { if ded == 1 { warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode"); let devices = ctrl.devices(); let bus = ctrl.bus(); CtrlGraphics::do_mode_setup_tasks( GfxVendors::Nvidia, false, &devices, &bus, )?; } else if ded == 0 { info!("Dedicated GFX toggle is off"); let devices = ctrl.devices(); let bus = ctrl.bus(); CtrlGraphics::do_mode_setup_tasks( config.gfx_mode, false, &devices, &bus, )?; } } } } ctrl.reload() .unwrap_or_else(|err| error!("Gfx controller: {}", err)); ctrl.add_to_server(&mut object_server); } Err(err) => { error!("Gfx control: {}", err); } } } // TODO: implement messaging between threads to check fails // Run tasks let handle = std::thread::Builder::new() .name("asusd watch".to_string()) .spawn(move || loop { std::thread::sleep(std::time::Duration::from_millis(100)); for ctrl in tasks.iter() { ctrl.do_task() .map_err(|err| { warn!("do_task error: {}", err); }) .ok(); } }); // Run zbus server object_server .with( &ObjectPath::from_str_unchecked("/org/asuslinux/Charge"), |obj: &CtrlCharge| { let x = obj.limit(); obj.notify_charge(x as u8) }, ) .map_err(|err| { warn!("object_server notify_charge error: {}", err); }) .ok(); // Loop to check errors and iterate zbus server loop { if let Err(err) = &handle { error!("{}", err); } if let Err(err) = object_server.try_handle_next() { error!("{}", err); } } }