From 596d523a89ac3d69841bfe194276f55e003ad678 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 29 Apr 2020 22:39:12 +1200 Subject: [PATCH] Reorganise some async code --- Cargo.lock | 12 ++- Cargo.toml | 4 +- src/config.rs | 2 +- src/core.rs | 20 ++--- src/daemon.rs | 87 ++++++++++------------ src/laptops/mod.rs | 182 ++++++++++++++++++++++----------------------- 6 files changed, 151 insertions(+), 156 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 454aa95e..ee66e43b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,6 +223,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -376,8 +382,9 @@ dependencies = [ [[package]] name = "intel-pstate" -version = "0.2.0" -source = "git+https://github.com/flukejones/intel-pstate#f70ab9726bdada99f5cb01c64c056f2093f3a008" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0e7f68d8a6d149a5b2195ab645923c63ee35928fff58895b3c1d21541afe90c" dependencies = [ "err-derive", "smart-default", @@ -857,6 +864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c" dependencies = [ "bytes", + "fnv", "futures-core", "lazy_static", "mio", diff --git a/Cargo.toml b/Cargo.toml index f527bba2..a9693dd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ env_logger = "^0.7.1" # async dbus = { version = "^0.8.2", features = ["futures"] } dbus-tokio = "^0.5.1" -tokio = { version = "0.2.4", features = ["rt-threaded", "macros"] } +tokio = { version = "0.2.4", features = ["rt-threaded", "macros", "sync"] } # serialisation serde = "1.0" @@ -38,7 +38,7 @@ toml = "0.5" # Device control # sysfs-class = "^0.1.2" # used for backlight control mostly # cpu power management -intel-pstate = { git = "https://github.com/flukejones/intel-pstate" } +intel-pstate = "^0.2.1" # virtualisation of HID, mainly for outputting consumer key codes uhid-virt = "^0.0.4" #keycode = "0.3" diff --git a/src/config.rs b/src/config.rs index 56ffc8a5..f2ecd120 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,7 +3,7 @@ use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; -pub static CONFIG_PATH: &'static str = "/etc/rogcore.conf"; +pub static CONFIG_PATH: &str = "/etc/rogcore.conf"; #[derive(Default, Deserialize, Serialize)] pub struct Config { diff --git a/src/core.rs b/src/core.rs index 5e0a4ee1..e5a72be2 100644 --- a/src/core.rs +++ b/src/core.rs @@ -19,17 +19,17 @@ use std::time::Duration; pub const LED_MSG_LEN: usize = 17; static LED_INIT1: [u8; 2] = [0x5d, 0xb9]; -static LED_INIT2: &'static str = "]ASUS Tech.Inc."; // ] == 0x5d +static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08]; -static LED_INIT4: &'static str = "^ASUS Tech.Inc."; // ^ == 0x5e +static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08]; // Only these two packets must be 17 bytes static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; -static FAN_TYPE_1_PATH: &'static str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy"; -static FAN_TYPE_2_PATH: &'static str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode"; +static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy"; +static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode"; /// ROG device controller /// @@ -75,7 +75,7 @@ impl RogCore { dev_handle.set_auto_detach_kernel_driver(true).unwrap(); dev_handle .claim_interface(interface) - .map_err(|err| AuraError::UsbError(err))?; + .map_err(AuraError::UsbError)?; Ok(RogCore { handle: dev_handle, @@ -131,7 +131,7 @@ impl RogCore { pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { match self .handle - .write_interrupt(self.led_endpoint, message, Duration::from_millis(1)) + .write_interrupt(self.led_endpoint, message, Duration::from_millis(2)) { Ok(_) => {} Err(err) => match err { @@ -180,7 +180,7 @@ impl RogCore { effect: Vec>, ) -> Result<(), AuraError> { for row in effect.iter() { - match handle.write_interrupt(endpoint, row, Duration::from_millis(1)) { + match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) { Ok(_) => {} Err(err) => match err { rusb::Error::Timeout => {} @@ -207,7 +207,7 @@ impl RogCore { self.config.write(); return Ok(()); } - warn!("{:?} not supported", BuiltInModeByte::from(mode)); + warn!("{:?} not supported", mode); Err(AuraError::NotSupported) } @@ -365,7 +365,9 @@ impl RogCore { let mut buf = [0u8; 32]; match handle.read_interrupt(endpoint, &mut buf, Duration::from_millis(200)) { Ok(_) => { - if report_filter_bytes.contains(&buf[0]) { + if report_filter_bytes.contains(&buf[0]) + && (buf[1] != 0 || buf[2] != 0 || buf[3] != 0 || buf[4] != 0) + { return Some(buf); } } diff --git a/src/daemon.rs b/src/daemon.rs index 2153b37d..ce0e53e0 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -14,11 +14,11 @@ use dbus_tokio::connection; use log::{error, info}; use std::error::Error; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::time::{Duration, Instant}; -type LedMsgType = Arc>>>; -type EffectType = Arc>>>>; +type LedMsgType = Arc>>>; +type EffectType = Arc>>>>; // Timing is such that: // - interrupt write is minimum 1ms (sometimes lower) @@ -35,7 +35,6 @@ pub async fn start_daemon() -> Result<(), Box> { laptop.usb_vendor(), laptop.usb_product(), laptop.led_endpoint(), - laptop.key_endpoint(), ) .map_or_else( |err| { @@ -49,6 +48,8 @@ pub async fn start_daemon() -> Result<(), Box> { ); // Reload settings rogcore.reload().await?; + let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) }; + let rogcore = Arc::new(tokio::sync::Mutex::new(Box::pin(rogcore))); let (resource, connection) = connection::new_system_sync()?; tokio::spawn(async { @@ -64,65 +65,55 @@ pub async fn start_daemon() -> Result<(), Box> { // We add the tree to the connection so that incoming method calls will be handled. tree.start_receive_send(&*connection); - let key_buf: Arc>> = Arc::new(Mutex::new(None)); + let supported = Vec::from(laptop.supported_modes()); + let led_endpoint = laptop.led_endpoint(); + { - let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) }; let keyboard_endpoint = laptop.key_endpoint(); let report_filter_bytes = laptop.key_filter().to_owned(); - - let key_buf1 = key_buf.clone(); // This is *not* safe + let rogcore = rogcore.clone(); tokio::spawn(async move { loop { let data = RogCore::poll_keyboard(usb_dev_handle, keyboard_endpoint, &report_filter_bytes) .await; - if let Some(stuff) = data { - // If we have some data to show, we *must* lock - if let Ok(mut lock) = key_buf1.lock() { - lock.replace(stuff); + if let Some(bytes) = data { + let mut rogcore = rogcore.lock().await; + match laptop.run(&mut rogcore, bytes) { + Ok(_) => {} + Err(err) => { + error!("{:?}", err); + panic!("Force crash for systemd to restart service") + } } } } }); } - let supported = Vec::from(laptop.supported_modes()); - // When any action occurs this time is reset let mut time_mark = Instant::now(); - let laptop_actions = laptop.get_runner(); - loop { connection.process_all(); if let Ok(mut lock) = input.try_lock() { - if let Some(bytes) = &*lock { - // It takes up to 20 milliseconds to write a complete colour block here + if let Some(bytes) = lock.take() { + let mut rogcore = rogcore.lock().await; rogcore.aura_set_and_save(&supported, &bytes)?; - *lock = None; time_mark = Instant::now(); } } - if let Ok(mut lock) = effect.lock() { - if lock.is_some() { - let effect = lock.take(); - rogcore.aura_write_effect(effect.unwrap())?; - time_mark = Instant::now(); - } - } - - if let Ok(mut lock) = key_buf.try_lock() { - if let Some(bytes) = *lock { - // this takes at least 10ms per colour block - match laptop_actions(&mut rogcore, bytes) { - Ok(_) => {} - Err(err) => { - error!("{:?}", err); - panic!("Force crash for systemd to restart service") - } - } - *lock = None; + // Write a colour block + // Yank data out and drop lock quick (effect write takes 10ms) + if let Ok(mut lock) = effect.try_lock() { + // Spawn a writer + if let Some(stuff) = lock.take() { + tokio::spawn(async move { + RogCore::async_write_effect(usb_dev_handle, led_endpoint, stuff) + .await + .unwrap(); + }); time_mark = Instant::now(); } } @@ -130,11 +121,11 @@ pub async fn start_daemon() -> Result<(), Box> { let now = Instant::now(); // Cool-down steps if now.duration_since(time_mark).as_millis() > 500 { - std::thread::sleep(Duration::from_millis(100)); - } else if now.duration_since(time_mark).as_millis() > 20 { - std::thread::sleep(Duration::from_millis(20)); + std::thread::sleep(Duration::from_millis(200)); + } else if now.duration_since(time_mark).as_millis() > 100 { + std::thread::sleep(Duration::from_millis(50)); } else { - std::thread::sleep(Duration::from_micros(400)); + std::thread::sleep(Duration::from_micros(5)); } } } @@ -152,9 +143,9 @@ fn dbus_create_ledmsg_method(msg: LedMsgType) -> Method { .msg .method_return() .append1(&format!("Wrote {:x?}", bytes)); - return Ok(vec![mret]); + Ok(vec![mret]) } else { - return Err(MethodErr::failed("Could not lock daemon for access")); + Err(MethodErr::failed("Could not lock daemon for access")) } } }) @@ -185,9 +176,9 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method { *lock = Some(byte_array); let mret = m.msg.method_return().append1(&format!("Got effect part")); - return Ok(vec![mret]); + Ok(vec![mret]) } else { - return Err(MethodErr::failed("Could not lock daemon for access")); + Err(MethodErr::failed("Could not lock daemon for access")) } } }) @@ -205,8 +196,8 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method { } fn dbus_create_tree() -> (Tree, LedMsgType, EffectType) { - let input: LedMsgType = Arc::new(Mutex::new(None)); - let effect: EffectType = Arc::new(Mutex::new(None)); + let input: LedMsgType = Arc::new(tokio::sync::Mutex::new(None)); + let effect: EffectType = Arc::new(tokio::sync::Mutex::new(None)); let factory = Factory::new_sync::<()>(); let tree = factory.tree(()).add( diff --git a/src/laptops/mod.rs b/src/laptops/mod.rs index 390668b1..50c48ae8 100644 --- a/src/laptops/mod.rs +++ b/src/laptops/mod.rs @@ -78,7 +78,7 @@ pub(crate) fn match_laptop() -> LaptopBase { /// If using the `keycode` crate to build keyboard input, the report must be prefixed /// with the report ID (usually `0x01` for the virtual keyboard). pub(crate) trait Laptop { - fn get_runner(&self) -> Box Result<(), AuraError>>; + fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError>; fn led_endpoint(&self) -> u8; fn key_endpoint(&self) -> u8; fn key_filter(&self) -> &[u8]; @@ -104,10 +104,10 @@ pub(super) struct LaptopBase { } impl Laptop for LaptopBase { - fn get_runner(&self) -> Box { + fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { match self.usb_product { - 0x1869 | 0x1866 => self.gx502_runner(), - 0x1854 => self.gl753_runner(), + 0x1869 | 0x1866 => self.gx502_runner(rogcore, key_buf), + 0x1854 => self.gl753_runner(rogcore, key_buf), _ => panic!("No runner available for this device"), } } @@ -137,109 +137,103 @@ impl Laptop for LaptopBase { impl LaptopBase { // 0x1866, per-key LEDs, media-keys split from vendor specific - fn gx502_runner(&self) -> Box { + fn gx502_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { let max_led_bright = self.max_led_bright; let min_led_bright = self.min_led_bright; let supported_modes = self.supported_modes.to_owned(); - let function = move |rogcore: &mut RogCore, key_buf: [u8; 32]| { - match GX502Keys::from(key_buf[1]) { - GX502Keys::LedBrightUp => { - rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; - } - GX502Keys::LedBrightDown => { - rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; - } - GX502Keys::AuraNext => rogcore.aura_mode_next(&supported_modes)?, - GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&supported_modes)?, - GX502Keys::ScreenBrightUp => { - rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) - } //self.backlight.step_up(), - GX502Keys::ScreenBrightDown => { - rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()) - } //self.backlight.step_down(), - GX502Keys::Sleep => rogcore.suspend_with_systemd(), - GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(), - GX502Keys::MicToggle => {} - GX502Keys::Fan => { - rogcore.fan_mode_step().unwrap_or_else(|err| { - warn!("Couldn't toggle fan mode: {:?}", err); - }); - } - GX502Keys::ScreenToggle => { - rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into()); - } - GX502Keys::TouchPadToggle => { - let mut key = [0u8; 32]; - key[0] = 0x01; - key[3] = 0x070; - rogcore.virt_keys().press(key); - } - GX502Keys::Rog => { - //rogcore.aura_effect_init()?; - //rogcore.aura_write_effect(&self.per_key_led)?; - let mut key = [0u8; 32]; - key[0] = 0x01; - key[3] = 0x68; // XF86Tools? F13 - rogcore.virt_keys().press(key); - } - GX502Keys::None => { - if key_buf[0] != 0x5A { - info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]); - rogcore.virt_keys().press(key_buf); - } + match GX502Keys::from(key_buf[1]) { + GX502Keys::LedBrightUp => { + rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; + } + GX502Keys::LedBrightDown => { + rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; + } + GX502Keys::AuraNext => rogcore.aura_mode_next(&supported_modes)?, + GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&supported_modes)?, + GX502Keys::ScreenBrightUp => { + rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) + } //self.backlight.step_up(), + GX502Keys::ScreenBrightDown => { + rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()) + } //self.backlight.step_down(), + GX502Keys::Sleep => rogcore.suspend_with_systemd(), + GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(), + GX502Keys::MicToggle => {} + GX502Keys::Fan => { + rogcore.fan_mode_step().unwrap_or_else(|err| { + warn!("Couldn't toggle fan mode: {:?}", err); + }); + } + GX502Keys::ScreenToggle => { + rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into()); + } + GX502Keys::TouchPadToggle => { + let mut key = [0u8; 32]; + key[0] = 0x01; + key[3] = 0x070; + rogcore.virt_keys().press(key); + } + GX502Keys::Rog => { + //rogcore.aura_effect_init()?; + //rogcore.aura_write_effect(&self.per_key_led)?; + let mut key = [0u8; 32]; + key[0] = 0x01; + key[3] = 0x68; // XF86Tools? F13 + rogcore.virt_keys().press(key); + } + GX502Keys::None => { + if key_buf[0] != 0x5A { + info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]); + rogcore.virt_keys().press(key_buf); } } - Ok(()) - }; - Box::new(function) + } + Ok(()) } // GL753VE == 0x1854, 4 zone keyboard - fn gl753_runner(&self) -> Box { + fn gl753_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { let max_led_bright = self.max_led_bright; let min_led_bright = self.min_led_bright; let supported_modes = self.supported_modes.to_owned(); - let function = move |rogcore: &mut RogCore, key_buf: [u8; 32]| { - match GL753Keys::from(key_buf[1]) { - GL753Keys::LedBrightUp => { - rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; - } - GL753Keys::LedBrightDown => { - rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; - } - GL753Keys::ScreenBrightUp => { - rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) - } - GL753Keys::ScreenBrightDown => { - rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()) - } - GL753Keys::Sleep => rogcore.suspend_with_systemd(), - GL753Keys::AirplaneMode => rogcore.toggle_airplane_mode(), - GL753Keys::ScreenToggle => { - rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into()); - } - GL753Keys::TouchPadToggle => { - let mut key = [0u8; 32]; - key[0] = 0x01; - key[3] = 0x070; - rogcore.virt_keys().press(key); - } - GL753Keys::Rog => { - let mut key = [0u8; 32]; - key[0] = 0x01; - key[3] = 0x68; // XF86Tools? F13 - rogcore.virt_keys().press(key); - } - GL753Keys::None => { - if key_buf[0] != 0x5A { - info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]); - rogcore.virt_keys().press(key_buf); - } + match GL753Keys::from(key_buf[1]) { + GL753Keys::LedBrightUp => { + rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; + } + GL753Keys::LedBrightDown => { + rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; + } + GL753Keys::ScreenBrightUp => { + rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) + } + GL753Keys::ScreenBrightDown => { + rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()) + } + GL753Keys::Sleep => rogcore.suspend_with_systemd(), + GL753Keys::AirplaneMode => rogcore.toggle_airplane_mode(), + GL753Keys::ScreenToggle => { + rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into()); + } + GL753Keys::TouchPadToggle => { + let mut key = [0u8; 32]; + key[0] = 0x01; + key[3] = 0x070; + rogcore.virt_keys().press(key); + } + GL753Keys::Rog => { + let mut key = [0u8; 32]; + key[0] = 0x01; + key[3] = 0x68; // XF86Tools? F13 + rogcore.virt_keys().press(key); + } + GL753Keys::None => { + if key_buf[0] != 0x5A { + info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]); + rogcore.virt_keys().press(key_buf); } } - Ok(()) - }; - Box::new(function) + } + Ok(()) } }