Dbus expand (#24)

* Dbus changes
  - Changed "FanMode", "ChargeLimit" to "SetFanMode", "SetChargeLimit"
  - Added dbus signals "FanModeChanged", "ChargeLimitChanged"
  - Added dbus methods "GetFanMode", "GetChargeLimit"
* Refactor of internal loop and tokio tasks
* Add support for ROG Strix G712LV_G712LV
* Correctly read the config before writing changes
This commit is contained in:
Luke Jones
2020-06-29 10:03:27 +12:00
committed by GitHub
parent 4922042432
commit 3ad15d61c9
12 changed files with 364 additions and 193 deletions

View File

@@ -66,15 +66,6 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
.do_command(AuraCommand::ReloadLast, &mut config)
.await?;
// Possible Animatrix
let mut animatrix_writer = None;
if laptop.support_animatrix() {
if let Ok(dev) = AniMeWriter::new() {
animatrix_writer = Some(dev);
info!("Device has an AniMe Matrix display");
}
}
// Set up the mutexes
let config = Arc::new(Mutex::new(config));
let (resource, connection) = connection::new_system_sync()?;
@@ -95,7 +86,9 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
fan_mode,
charge_limit,
effect_cancel_signal,
) = dbus_create_tree();
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);
@@ -107,6 +100,21 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
laptop.key_filter().to_owned(),
);
// Possible Animatrix
if laptop.support_animatrix() {
if let Ok(mut animatrix_writer) = AniMeWriter::new() {
info!("Device has an AniMe Matrix display");
tokio::spawn(async move {
while let Some(image) = animatrix_recv.recv().await {
animatrix_writer
.do_command(AnimatrixCommand::WriteImage(image))
.await
.unwrap_or_else(|err| warn!("{:?}", err));
}
});
}
}
let config1 = config.clone();
// start the keyboard reader and laptop-action loop
tokio::spawn(async move {
@@ -140,14 +148,36 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
}
});
// If animatrix is supported, try doing a write
let connection1 = connection.clone();
let config1 = config.clone();
tokio::spawn(async move {
if let Some(writer) = animatrix_writer.as_mut() {
while let Some(image) = animatrix_recv.recv().await {
writer
.do_command(AnimatrixCommand::WriteImage(image))
.await
.unwrap_or_else(|err| warn!("{:?}", err));
// Some small things we need to track, without passing all sorts of stuff around
let mut last_fan_mode = config1.lock().await.fan_mode;
let mut last_charge_limit = config1.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 = config1.lock().await;
if config.fan_mode != last_fan_mode {
last_fan_mode = config.fan_mode;
connection1
.send(
fanmode_signal
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
.append1(last_fan_mode),
)
.unwrap_or_else(|_| 0);
}
if config.bat_charge_limit != last_charge_limit {
last_charge_limit = config.bat_charge_limit;
connection1
.send(
charge_limit_signal
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
.append1(last_charge_limit),
)
.unwrap_or_else(|_| 0);
}
}
});
@@ -156,7 +186,6 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
loop {
connection.process_all();
// Check if a key press issued a command
while let Some(command) = aura_command_recv.recv().await {
let mut config = config.lock().await;
match command {
@@ -170,11 +199,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
.await
.unwrap_or_else(|err| warn!("{:?}", err));
connection
.send(
effect_cancel_signal
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
.append1(true),
)
.send(effect_cancel_signal.msg(&DBUS_PATH.into(), &DBUS_IFACE.into()))
.unwrap_or_else(|_| 0);
}
}

View File

@@ -41,6 +41,11 @@ pub(crate) fn match_laptop() -> LaptopBase {
fn choose_1866_device(prod: u16) -> LaptopBase {
let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name().expect("Could not get board_name");
let prod_name = dmi.product_name().expect("Could not get board_name");
info!("Product name: {}", prod_name.trim());
info!("Board name: {}", board_name.trim());
let mut laptop = LaptopBase {
usb_vendor: 0x0B05,
usb_product: prod,
@@ -55,50 +60,56 @@ fn choose_1866_device(prod: u16) -> LaptopBase {
support_animatrix: false,
//backlight: Backlight::new("intel_backlight").unwrap(),
};
match &board_name.as_str()[..5] {
"GA401" => {
// Has no RGB control
laptop.support_animatrix = true;
}
"GA502" => {
// Has no RGB control
}
"GX502" => {
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Star,
BuiltInModeByte::Rain,
BuiltInModeByte::Highlight,
BuiltInModeByte::Laser,
BuiltInModeByte::Ripple,
BuiltInModeByte::Pulse,
BuiltInModeByte::Comet,
BuiltInModeByte::Flash,
];
}
"GM501" => {
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
];
}
"GX531" | "G531G" => {
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Pulse,
];
}
_ => panic!("Unsupported laptop: {}, please request support at\nhttps://github.com/flukejones/rog-core", board_name),
// GA401
if board_name.starts_with("GA401") {
info!("No RGB control available");
laptop.support_animatrix = true;
// GA502
} else if board_name.starts_with("GA502") {
info!("No RGB control available");
// GX502, G712
} else if board_name.starts_with("GX502") {
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Star,
BuiltInModeByte::Rain,
BuiltInModeByte::Highlight,
BuiltInModeByte::Laser,
BuiltInModeByte::Ripple,
BuiltInModeByte::Pulse,
BuiltInModeByte::Comet,
BuiltInModeByte::Flash,
];
// GM501
} else if board_name.starts_with("GM501") {
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
];
// G531
} else if board_name.starts_with("GX531")
|| board_name.starts_with("G531")
|| board_name.starts_with("G712")
{
laptop.supported_modes = vec![
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Pulse,
];
} else {
panic!(
"Unsupported laptop, please request support at\nhttps://github.com/flukejones/rog-core"
);
}
info!("Board name: {}", board_name.as_str().trim());
laptop
}

View File

@@ -16,6 +16,7 @@ use std::marker::PhantomData;
use std::ptr::NonNull;
use std::time::Duration;
#[derive(Clone)]
pub enum AuraCommand {
BrightInc,
BrightDec,

View File

@@ -8,7 +8,7 @@ use rog_client::{
AuraDbusWriter, LED_MSG_LEN,
};
static VERSION: &str = "0.11.1";
static VERSION: &str = "0.12.2";
#[derive(Debug, Options)]
struct CLIStart {

View File

@@ -1,3 +1,4 @@
use crate::config::Config;
use crate::daemon::DbusU8Type;
use crate::led_control::AuraCommand;
use crate::rogcore::FanLevel;
@@ -10,7 +11,7 @@ use tokio::sync::{
Mutex,
};
pub(super) fn dbus_create_ledmsg_method(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> {
pub(super) fn dbus_set_ledmsg(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
// method for ledmessage
@@ -35,9 +36,7 @@ pub(super) fn dbus_create_ledmsg_method(sender: Mutex<Sender<AuraCommand>>) -> M
.inarg::<Vec<u8>, _>("bytearray")
}
pub(super) fn dbus_create_ledmultizone_method(
sender: Mutex<Sender<AuraCommand>>,
) -> Method<MTSync, ()> {
pub(super) fn dbus_set_ledmultizone(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
// method for ledmessage
@@ -68,9 +67,7 @@ pub(super) fn dbus_create_ledmultizone_method(
.annotate("org.freedesktop.DBus.Method.NoReply", "true")
}
pub(super) fn dbus_create_ledeffect_method(
sender: Mutex<Sender<AuraCommand>>,
) -> Method<MTSync, ()> {
pub(super) fn dbus_set_ledeffect(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
// method for ledmessage
@@ -114,7 +111,7 @@ pub(super) fn dbus_create_ledeffect_method(
.annotate("org.freedesktop.DBus.Method.NoReply", "true")
}
pub(super) fn dbus_create_animatrix_method(
pub(super) fn dbus_set_animatrix(
sender: Mutex<Sender<Vec<Vec<u8>>>>, // need mutex only to get interior mutability in MTSync
) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
@@ -138,11 +135,11 @@ pub(super) fn dbus_create_animatrix_method(
.annotate("org.freedesktop.DBus.Method.NoReply", "true")
}
pub(super) fn dbus_create_fan_mode_method(data: DbusU8Type) -> Method<MTSync, ()> {
pub(super) fn dbus_set_fan_mode(data: DbusU8Type) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
// method for ledmessage
.method("FanMode", (), {
.method("SetFanMode", (), {
move |m| {
if let Ok(mut lock) = data.try_lock() {
let mut iter = m.msg.iter_init();
@@ -162,11 +159,43 @@ pub(super) fn dbus_create_fan_mode_method(data: DbusU8Type) -> Method<MTSync, ()
.inarg::<u8, _>("byte")
}
pub(super) fn dbus_create_charge_limit_method(data: DbusU8Type) -> Method<MTSync, ()> {
pub(super) fn dbus_get_fan_mode(config: Arc<Mutex<Config>>) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
.method("GetFanMode", (), {
move |m| {
if let Ok(lock) = config.try_lock() {
let mret = m.msg.method_return().append1(lock.fan_mode);
Ok(vec![mret])
} else {
Err(MethodErr::failed("Could not lock config for access"))
}
}
})
.outarg::<&str, _>("value")
}
pub(super) fn dbus_get_charge_limit(config: Arc<Mutex<Config>>) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
.method("GetChargeLimit", (), {
move |m| {
if let Ok(lock) = config.try_lock() {
let mret = m.msg.method_return().append1(lock.bat_charge_limit);
Ok(vec![mret])
} else {
Err(MethodErr::failed("Could not lock config for access"))
}
}
})
.outarg::<&str, _>("value")
}
pub(super) fn dbus_set_charge_limit(data: DbusU8Type) -> Method<MTSync, ()> {
let factory = Factory::new_sync::<()>();
factory
// method for ledmessage
.method("ChargeLimit", (), {
.method("SetChargeLimit", (), {
move |m| {
if let Ok(mut lock) = data.try_lock() {
let mut iter = m.msg.iter_init();
@@ -187,7 +216,9 @@ pub(super) fn dbus_create_charge_limit_method(data: DbusU8Type) -> Method<MTSync
}
#[allow(clippy::type_complexity)]
pub(super) fn dbus_create_tree() -> (
pub(super) fn dbus_create_tree(
config: Arc<Mutex<Config>>,
) -> (
Tree<MTSync, ()>,
Sender<AuraCommand>,
Receiver<AuraCommand>,
@@ -195,6 +226,8 @@ pub(super) fn dbus_create_tree() -> (
DbusU8Type,
DbusU8Type,
Arc<Signal<()>>,
Arc<Signal<()>>,
Arc<Signal<()>>,
) {
let (aura_command_send, aura_command_recv) = channel::<AuraCommand>(1);
let (animatrix_send, animatrix_recv) = channel::<Vec<Vec<u8>>>(1);
@@ -204,6 +237,12 @@ pub(super) fn dbus_create_tree() -> (
let factory = Factory::new_sync::<()>();
let effect_cancel_sig = Arc::new(factory.signal("LedCancelEffect", ()));
let fanmode_changed_sig = Arc::new(factory.signal("FanModeChanged", ()).sarg::<u8, _>("value"));
let chrg_limit_changed_sig = Arc::new(
factory
.signal("ChargeLimitChanged", ())
.sarg::<u8, _>("value"),
);
let tree = factory
.tree(())
@@ -211,19 +250,17 @@ pub(super) fn dbus_create_tree() -> (
factory.object_path(DBUS_PATH, ()).introspectable().add(
factory
.interface(DBUS_IFACE, ())
.add_m(dbus_create_ledmsg_method(Mutex::new(
aura_command_send.clone(),
)))
.add_m(dbus_create_ledmultizone_method(Mutex::new(
aura_command_send.clone(),
)))
.add_m(dbus_create_ledeffect_method(Mutex::new(
aura_command_send.clone(),
)))
.add_m(dbus_create_animatrix_method(Mutex::new(animatrix_send)))
.add_m(dbus_create_fan_mode_method(fan_mode.clone()))
.add_m(dbus_create_charge_limit_method(charge_limit.clone()))
.add_s(effect_cancel_sig.clone()),
.add_m(dbus_set_ledmsg(Mutex::new(aura_command_send.clone())))
.add_m(dbus_set_ledmultizone(Mutex::new(aura_command_send.clone())))
.add_m(dbus_set_ledeffect(Mutex::new(aura_command_send.clone())))
.add_m(dbus_set_animatrix(Mutex::new(animatrix_send)))
.add_m(dbus_set_fan_mode(fan_mode.clone()))
.add_m(dbus_set_charge_limit(charge_limit.clone()))
.add_m(dbus_get_fan_mode(config.clone()))
.add_m(dbus_get_charge_limit(config))
.add_s(effect_cancel_sig.clone())
.add_s(fanmode_changed_sig.clone())
.add_s(chrg_limit_changed_sig.clone()),
),
)
.add(factory.object_path("/", ()).introspectable());
@@ -235,5 +272,7 @@ pub(super) fn dbus_create_tree() -> (
fan_mode,
charge_limit,
effect_cancel_sig,
fanmode_changed_sig,
chrg_limit_changed_sig,
)
}

View File

@@ -154,8 +154,10 @@ impl RogCore {
}
pub fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
// re-read the config here in case a user changed the pstate settings
config.read();
let mut n = config.fan_mode;
info!("Current fan mode: {:?}", FanLevel::from(n));
// wrap around the step number
if n < 2 {
n += 1;
@@ -170,18 +172,15 @@ impl RogCore {
mode: FanLevel,
config: &mut Config,
) -> Result<(), Box<dyn Error>> {
// re-read the config here in case a user changed the pstate settings
config.read();
// Set CPU pstate
if let Ok(pstate) = intel_pstate::PState::new() {
info!("Setting pstate for Intel CPU");
match mode {
FanLevel::Normal => {
pstate.set_min_perf_pct(config.mode_performance.normal.min_percentage)?;
pstate.set_max_perf_pct(config.mode_performance.normal.max_percentage)?;
pstate.set_no_turbo(config.mode_performance.normal.no_turbo)?;
info!(
"CPU Power: min-freq: {:?}, max-freq: {:?}, turbo: {:?}",
"Intel CPU Power: min: {:?}%, max: {:?}%, turbo: {:?}",
config.mode_performance.normal.min_percentage,
config.mode_performance.normal.max_percentage,
!config.mode_performance.normal.no_turbo
@@ -192,7 +191,7 @@ impl RogCore {
pstate.set_max_perf_pct(config.mode_performance.boost.max_percentage)?;
pstate.set_no_turbo(config.mode_performance.boost.no_turbo)?;
info!(
"CPU Power: min-freq: {:?}, max-freq: {:?}, turbo: {:?}",
"Intel CPU Power: min: {:?}%, max: {:?}%, turbo: {:?}",
config.mode_performance.boost.min_percentage,
config.mode_performance.boost.max_percentage,
!config.mode_performance.boost.no_turbo
@@ -203,7 +202,7 @@ impl RogCore {
pstate.set_max_perf_pct(config.mode_performance.silent.max_percentage)?;
pstate.set_no_turbo(config.mode_performance.silent.no_turbo)?;
info!(
"CPU Power: min-freq: {:?}, max-freq: {:?}, turbo: {:?}",
"Intel CPU Power: min: {:?}%, max: {:?}%, turbo: {:?}",
config.mode_performance.silent.min_percentage,
config.mode_performance.silent.max_percentage,
!config.mode_performance.silent.no_turbo
@@ -230,7 +229,7 @@ impl RogCore {
file.write_all(boost.as_bytes()).unwrap_or_else(|err| {
error!("Could not write to {}, {:?}", AMD_BOOST_PATH, err)
});
info!("CPU Power: turbo: {:?}", boost);
info!("AMD CPU Turbo: {:?}", boost);
}
FanLevel::Boost => {
let boost = if config.mode_performance.boost.no_turbo {
@@ -241,7 +240,7 @@ impl RogCore {
file.write_all(boost.as_bytes()).unwrap_or_else(|err| {
error!("Could not write to {}, {:?}", AMD_BOOST_PATH, err)
});
info!("CPU Power: turbo: {:?}", boost);
info!("AMD CPU Turbo: {:?}", boost);
}
FanLevel::Silent => {
let boost = if config.mode_performance.silent.no_turbo {
@@ -252,7 +251,7 @@ impl RogCore {
file.write_all(boost.as_bytes()).unwrap_or_else(|err| {
error!("Could not write to {}, {:?}", AMD_BOOST_PATH, err)
});
info!("CPU Power: turbo: {:?}", boost);
info!("AMD CPU Turbo: {:?}", boost);
}
}
}