mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -697,6 +697,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"sysfs-class",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml",
|
||||
"uhid-virt",
|
||||
|
||||
@@ -147,6 +147,12 @@ If the daemon service is enabled then on boot the following will be reloaded fro
|
||||
The daemon also saves the settings per mode as the keyboard does not do this itself - this means cycling through modes
|
||||
with the Aura keys will use the settings that were used via CLI.
|
||||
|
||||
### DBUS Input
|
||||
|
||||
Commands: `FanMode`, `LedWriteBytes`, `LedWriteMultizone`, `LedWriteEffect`
|
||||
|
||||
TODO: fill in this info
|
||||
|
||||
### Wireshark captures
|
||||
|
||||
TODO: see `./wireshark_data/` for some captures.
|
||||
|
||||
@@ -89,7 +89,7 @@ impl AuraDbusWriter {
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
self.connection.process(Duration::from_micros(300))?;
|
||||
|
||||
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteEffect")?
|
||||
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteMultizone")?
|
||||
.append1(&group[0].to_vec())
|
||||
.append1(&group[1].to_vec())
|
||||
.append1(&group[2].to_vec())
|
||||
@@ -115,6 +115,19 @@ impl AuraDbusWriter {
|
||||
Err(Box::new(dbus::Error::new_custom("name", "message")))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_fan_mode(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let msg =
|
||||
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "FanMode")?.append1(level);
|
||||
let r = self
|
||||
.connection
|
||||
.send_with_reply_and_block(msg, Duration::from_millis(5000))?;
|
||||
if let Some(reply) = r.get1::<&str>() {
|
||||
return Ok(reply.to_owned());
|
||||
}
|
||||
Err(Box::new(dbus::Error::new_custom("name", "message")))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_builtin_mode(
|
||||
&self,
|
||||
|
||||
@@ -43,3 +43,5 @@ intel-pstate = "^0.2.1"
|
||||
# virtualisation of HID, mainly for outputting consumer key codes
|
||||
uhid-virt = "^0.0.4"
|
||||
#keycode = "0.3"
|
||||
|
||||
thiserror = "^1.0.15"
|
||||
@@ -19,6 +19,7 @@ use std::sync::{mpsc, Arc};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
type FanModeType = Arc<Mutex<Option<u8>>>;
|
||||
type LedMsgType = Arc<Mutex<Option<Vec<u8>>>>;
|
||||
type EffectType = Arc<Mutex<Option<Vec<Vec<u8>>>>>;
|
||||
|
||||
@@ -81,7 +82,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let (aura_command_send, aura_command_recv) = mpsc::sync_channel::<AuraCommand>(1);
|
||||
|
||||
let (tree, input, effect, effect_cancel_signal) = dbus_create_tree();
|
||||
let (tree, input, effect, fan_mode, effect_cancel_signal) = dbus_create_tree();
|
||||
// We add the tree to the connection so that incoming method calls will be handled.
|
||||
tree.start_receive_send(&*connection);
|
||||
|
||||
@@ -97,6 +98,15 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
// start the keyboard reader and laptop-action loop
|
||||
let key_read_handle = tokio::spawn(async move {
|
||||
loop {
|
||||
// Fan mode
|
||||
if let Ok(mut lock) = fan_mode.try_lock() {
|
||||
if let Some(n) = lock.take() {
|
||||
let mut config = config1.lock().await;
|
||||
rogcore
|
||||
.fan_mode_set(n, &mut config)
|
||||
.unwrap_or_else(|err| warn!("{:?}", err));
|
||||
}
|
||||
}
|
||||
let acs = aura_command_send.clone();
|
||||
let data = keyboard_reader.poll_keyboard().await;
|
||||
if let Some(bytes) = data {
|
||||
@@ -227,7 +237,10 @@ fn dbus_create_ledmultizone_method(effect: EffectType) -> Method<MTSync, ()> {
|
||||
let byte_array: Vec<Vec<u8>> =
|
||||
vec![iter.read()?, iter.read()?, iter.read()?, iter.read()?];
|
||||
*lock = Some(byte_array);
|
||||
let mret = m.msg.method_return().append1(&format!("Got effect part"));
|
||||
let mret = m
|
||||
.msg
|
||||
.method_return()
|
||||
.append1(&"Got effect part".to_string());
|
||||
Ok(vec![mret])
|
||||
} else {
|
||||
Err(MethodErr::failed("Could not lock daemon for access"))
|
||||
@@ -263,14 +276,12 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method<MTSync, ()> {
|
||||
iter.read()?,
|
||||
];
|
||||
*lock = Some(byte_array);
|
||||
let mret = m.msg.method_return().append1(&format!("Got effect part"));
|
||||
Ok(vec![mret])
|
||||
Ok(vec![])
|
||||
} else {
|
||||
Err(MethodErr::failed("Could not lock daemon for access"))
|
||||
}
|
||||
}
|
||||
})
|
||||
.outarg::<&str, _>("reply")
|
||||
.inarg::<Vec<u8>, _>("bytearray")
|
||||
.inarg::<Vec<u8>, _>("bytearray")
|
||||
.inarg::<Vec<u8>, _>("bytearray")
|
||||
@@ -284,9 +295,40 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method<MTSync, ()> {
|
||||
.inarg::<Vec<u8>, _>("bytearray")
|
||||
}
|
||||
|
||||
fn dbus_create_tree() -> (Tree<MTSync, ()>, LedMsgType, EffectType, Arc<Signal<()>>) {
|
||||
fn dbus_create_fan_mode_method(fan_mode: FanModeType) -> Method<MTSync, ()> {
|
||||
let factory = Factory::new_sync::<()>();
|
||||
factory
|
||||
// method for ledmessage
|
||||
.method("FanMode", (), {
|
||||
move |m| {
|
||||
if let Ok(mut lock) = fan_mode.try_lock() {
|
||||
let mut iter = m.msg.iter_init();
|
||||
let byte: u8 = iter.read()?;
|
||||
*lock = Some(byte);
|
||||
let mret = m
|
||||
.msg
|
||||
.method_return()
|
||||
.append1(format!("Fan level set to {:?}", FanLevel::from(byte)));
|
||||
Ok(vec![mret])
|
||||
} else {
|
||||
Err(MethodErr::failed("Could not lock daemon for access"))
|
||||
}
|
||||
}
|
||||
})
|
||||
.outarg::<&str, _>("reply")
|
||||
.inarg::<u8, _>("byte")
|
||||
}
|
||||
|
||||
fn dbus_create_tree() -> (
|
||||
Tree<MTSync, ()>,
|
||||
LedMsgType,
|
||||
EffectType,
|
||||
FanModeType,
|
||||
Arc<Signal<()>>,
|
||||
) {
|
||||
let input_bytes: LedMsgType = Arc::new(Mutex::new(None));
|
||||
let input_effect: EffectType = Arc::new(Mutex::new(None));
|
||||
let fan_mode: FanModeType = Arc::new(Mutex::new(None));
|
||||
|
||||
let factory = Factory::new_sync::<()>();
|
||||
let effect_cancel_sig = Arc::new(factory.signal("LedCancelEffect", ()));
|
||||
@@ -297,8 +339,9 @@ fn dbus_create_tree() -> (Tree<MTSync, ()>, LedMsgType, EffectType, Arc<Signal<(
|
||||
.add_m(dbus_create_ledmsg_method(input_bytes.clone()))
|
||||
.add_m(dbus_create_ledmultizone_method(input_effect.clone()))
|
||||
.add_m(dbus_create_ledeffect_method(input_effect.clone()))
|
||||
.add_m(dbus_create_fan_mode_method(fan_mode.clone()))
|
||||
.add_s(effect_cancel_sig.clone()),
|
||||
),
|
||||
);
|
||||
(tree, input_bytes, input_effect, effect_cancel_sig)
|
||||
(tree, input_bytes, input_effect, fan_mode, effect_cancel_sig)
|
||||
}
|
||||
|
||||
10
rog-core/src/error.rs
Normal file
10
rog-core/src/error.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use std::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RogError {
|
||||
#[error("unable to parse string to fan mode")]
|
||||
ParseFanLevel,
|
||||
#[error("mode not supported")]
|
||||
NotSupported,
|
||||
}
|
||||
@@ -12,3 +12,5 @@ mod led_control;
|
||||
pub mod rogcore;
|
||||
/// A virtual "consumer device" to help emit the correct key codes
|
||||
mod virt_device;
|
||||
|
||||
mod error;
|
||||
|
||||
@@ -69,7 +69,7 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
writer.write_multizone(&byte_arr)?;
|
||||
}
|
||||
_ => match writer.write_builtin_mode(&command) {
|
||||
Ok(msg) => println!("Response: {}", msg),
|
||||
Ok(msg) => println!("Daemon response: {}", msg),
|
||||
Err(err) => println!("Error: {}", err),
|
||||
},
|
||||
}
|
||||
@@ -77,7 +77,13 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
if let Some(brightness) = parsed.bright {
|
||||
match writer.write_brightness(brightness.level()) {
|
||||
Ok(msg) => println!("Response: {}", msg),
|
||||
Ok(msg) => println!("Daemon response: {}", msg),
|
||||
Err(err) => println!("Error: {}", err),
|
||||
}
|
||||
}
|
||||
if let Some(fan_level) = parsed.fan_mode {
|
||||
match writer.write_fan_mode(fan_level.into()) {
|
||||
Ok(msg) => println!("Daemon response: {}", msg),
|
||||
Err(err) => println!("Error: {}", err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Return show-stopping errors, otherwise map error to a log level
|
||||
|
||||
use crate::{config::Config, virt_device::VirtKeys};
|
||||
use crate::{config::Config, error::RogError, virt_device::VirtKeys};
|
||||
use log::{error, info, warn};
|
||||
use rusb::DeviceHandle;
|
||||
use std::error::Error;
|
||||
@@ -10,6 +10,7 @@ use std::marker::{PhantomData, PhantomPinned};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::ptr::NonNull;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
|
||||
@@ -118,10 +119,21 @@ impl RogCore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||
pub fn fan_mode_set(&mut self, n: u8, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||
let path = RogCore::get_fan_path()?;
|
||||
let mut fan_ctrl = OpenOptions::new().read(true).write(true).open(path)?;
|
||||
|
||||
info!("Fan mode set to: {:?}", FanLevel::from(n));
|
||||
config.fan_mode = n;
|
||||
fan_ctrl
|
||||
.write_all(format!("{:?}", config.fan_mode).as_bytes())
|
||||
.unwrap_or_else(|err| error!("Could not write to {}, {:?}", path, err));
|
||||
self.set_pstate_for_fan_mode(FanLevel::from(n), config)?;
|
||||
config.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||
let mut n = config.fan_mode;
|
||||
info!("Current fan mode: {:?}", FanLevel::from(n));
|
||||
// wrap around the step number
|
||||
@@ -130,15 +142,7 @@ impl RogCore {
|
||||
} else {
|
||||
n = 0;
|
||||
}
|
||||
info!("Fan mode stepped to: {:?}", FanLevel::from(n));
|
||||
fan_ctrl
|
||||
.write_all(format!("{:?}", config.fan_mode).as_bytes())
|
||||
.unwrap_or_else(|err| error!("Could not write to {}, {:?}", path, err));
|
||||
self.set_pstate_for_fan_mode(FanLevel::from(n), config)?;
|
||||
config.fan_mode = n;
|
||||
config.write();
|
||||
|
||||
Ok(())
|
||||
self.fan_mode_set(n, config)
|
||||
}
|
||||
|
||||
fn set_pstate_for_fan_mode(
|
||||
@@ -310,6 +314,19 @@ pub enum FanLevel {
|
||||
Silent,
|
||||
}
|
||||
|
||||
impl FromStr for FanLevel {
|
||||
type Err = RogError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, RogError> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"normal" => Ok(FanLevel::Normal),
|
||||
"boost" => Ok(FanLevel::Boost),
|
||||
"silent" => Ok(FanLevel::Silent),
|
||||
_ => Err(RogError::ParseFanLevel),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for FanLevel {
|
||||
fn from(n: u8) -> Self {
|
||||
match n {
|
||||
|
||||
Reference in New Issue
Block a user