diff --git a/Cargo.lock b/Cargo.lock index b3902977..7d6c79a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,17 +24,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "async-trait" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "atty" version = "0.2.14" @@ -631,7 +620,6 @@ name = "rog-daemon" version = "0.6.1" dependencies = [ "aho-corasick", - "async-trait", "dbus", "dbus-tokio", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 0d6e4fb0..f4cec2c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,4 @@ thiserror = "^1.0.15" log = "^0.4.8" uhid-virt = "^0.0.4" #keycode = "0.3" -env_logger = "^0.7.1" - -async-trait = "0.1.30" \ No newline at end of file +env_logger = "^0.7.1" \ No newline at end of file diff --git a/examples/per-key-effect-2.rs b/examples/per-key-effect-2.rs index f427fe31..189e77d6 100644 --- a/examples/per-key-effect-2.rs +++ b/examples/per-key-effect-2.rs @@ -46,7 +46,7 @@ fn main() -> Result<(), Box> { // It takes each interrupt at least 1ms. 10ms to write complete block. Plus any extra // penalty time such as read waits - let time = time::Duration::from_millis(1); // aim for 60 per second + let time = time::Duration::from_millis(10); // aim for 100 per second let row = KeyColourArray::get_init_msg(); let msg = diff --git a/src/core.rs b/src/core.rs index 51339cb3..792fd70c 100644 --- a/src/core.rs +++ b/src/core.rs @@ -98,7 +98,7 @@ impl RogCore { .get_field_from(BuiltInModeByte::from(mode_curr).into()) .unwrap() .to_owned(); - self.aura_write_messages(&[&mode]).await?; + self.aura_write_messages(&[&mode])?; let path = if Path::new(FAN_TYPE_1_PATH).exists() { FAN_TYPE_1_PATH @@ -131,7 +131,7 @@ impl RogCore { Err(AuraError::UsbError(rusb::Error::NoDevice)) } - pub async fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { + pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { match self .handle .write_interrupt(self.led_endpoint, message, Duration::from_millis(1)) @@ -145,31 +145,31 @@ impl RogCore { Ok(()) } - async fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { + fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { if !self.initialised { - self.aura_write(&LED_INIT1).await?; - self.aura_write(LED_INIT2.as_bytes()).await?; - self.aura_write(&LED_INIT3).await?; - self.aura_write(LED_INIT4.as_bytes()).await?; - self.aura_write(&LED_INIT5).await?; + self.aura_write(&LED_INIT1)?; + self.aura_write(LED_INIT2.as_bytes())?; + self.aura_write(&LED_INIT3)?; + self.aura_write(LED_INIT4.as_bytes())?; + self.aura_write(&LED_INIT5)?; self.initialised = true; } for message in messages { - self.aura_write(*message).await?; - self.aura_write(&LED_SET).await?; + self.aura_write(*message)?; + self.aura_write(&LED_SET)?; } // Changes won't persist unless apply is set - self.aura_write(&LED_APPLY).await?; + self.aura_write(&LED_APPLY)?; Ok(()) } /// Initialise and clear the keyboard for custom effects - pub async fn aura_effect_init(&mut self) -> Result<(), AuraError> { + pub fn aura_effect_init(&mut self) -> Result<(), AuraError> { let mut init = [0u8; 64]; init[0] = 0x5d; // Report ID init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin - self.aura_write(&init).await?; + self.aura_write(&init)?; self.initialised = true; Ok(()) @@ -178,25 +178,25 @@ impl RogCore { /// Write an effect block /// /// `aura_effect_init` must be called any effect routine, and called only once. - pub async fn aura_write_effect(&mut self, effect: Vec>) -> Result<(), AuraError> { + pub fn aura_write_effect(&mut self, effect: Vec>) -> Result<(), AuraError> { for row in effect.iter() { - self.aura_write(row).await?; + self.aura_write(row)?; } Ok(()) } - pub(crate) async fn aura_set_and_save( + pub(crate) fn aura_set_and_save( &mut self, supported_modes: &[BuiltInModeByte], bytes: &[u8], ) -> Result<(), AuraError> { let mode = BuiltInModeByte::from(bytes[3]); if bytes[1] == 0xbc { - self.aura_write(bytes).await?; + self.aura_write(bytes)?; return Ok(()); } else if supported_modes.contains(&mode) || bytes[1] == 0xba { let messages = [bytes]; - self.aura_write_messages(&messages).await?; + self.aura_write_messages(&messages)?; self.config.set_field_from(bytes); self.config.write(); return Ok(()); @@ -205,7 +205,7 @@ impl RogCore { Err(AuraError::NotSupported) } - pub(crate) async fn aura_bright_inc( + pub(crate) fn aura_bright_inc( &mut self, supported_modes: &[BuiltInModeByte], max_bright: u8, @@ -216,11 +216,11 @@ impl RogCore { self.config.brightness = bright; } let bytes = aura_brightness_bytes(bright); - self.aura_set_and_save(supported_modes, &bytes).await?; + self.aura_set_and_save(supported_modes, &bytes)?; Ok(()) } - pub(crate) async fn aura_bright_dec( + pub(crate) fn aura_bright_dec( &mut self, supported_modes: &[BuiltInModeByte], min_bright: u8, @@ -231,14 +231,14 @@ impl RogCore { self.config.brightness = bright; } let bytes = aura_brightness_bytes(bright); - self.aura_set_and_save(supported_modes, &bytes).await?; + self.aura_set_and_save(supported_modes, &bytes)?; Ok(()) } /// Select next Aura effect /// /// If the current effect is the last one then the effect selected wraps around to the first. - pub(crate) async fn aura_mode_next( + pub(crate) fn aura_mode_next( &mut self, supported_modes: &[BuiltInModeByte], ) -> Result<(), AuraError> { @@ -256,7 +256,7 @@ impl RogCore { .get_field_from(supported_modes[idx_next].into()) .unwrap() .to_owned(); - self.aura_set_and_save(supported_modes, &mode_next).await?; + self.aura_set_and_save(supported_modes, &mode_next)?; info!("Switched LED mode to {:#?}", supported_modes[idx_next]); Ok(()) } @@ -264,7 +264,7 @@ impl RogCore { /// Select previous Aura effect /// /// If the current effect is the first one then the effect selected wraps around to the last. - pub(crate) async fn aura_mode_prev( + pub(crate) fn aura_mode_prev( &mut self, supported_modes: &[BuiltInModeByte], ) -> Result<(), AuraError> { @@ -282,7 +282,7 @@ impl RogCore { .get_field_from(supported_modes[idx_next].into()) .unwrap() .to_owned(); - self.aura_set_and_save(supported_modes, &mode_next).await?; + self.aura_set_and_save(supported_modes, &mode_next)?; info!("Switched LED mode to {:#?}", supported_modes[idx_next]); Ok(()) } @@ -322,12 +322,13 @@ impl RogCore { /// /// `report_filter_bytes` is used to filter the data read from the interupt so /// only the relevant byte array is returned. - pub(crate) async fn poll_keyboard(&mut self, report_filter_bytes: &[u8]) -> Option<[u8; 32]> { + pub(crate) async fn poll_keyboard( + handle: &DeviceHandle, + endpoint: u8, + report_filter_bytes: Vec, + ) -> Option<[u8; 32]> { let mut buf = [0u8; 32]; - match self - .handle - .read_interrupt(self.keys_endpoint, &mut buf, Duration::from_millis(50)) - { + match handle.read_interrupt(endpoint, &mut buf, Duration::from_millis(200)) { Ok(_) => { if report_filter_bytes.contains(&buf[0]) { return Some(buf); @@ -341,6 +342,11 @@ impl RogCore { None } + pub(crate) fn get_raw_device_handle(&mut self) -> *mut DeviceHandle { + // Breaking every damn lifetime guarantee rust gives us + &mut self.handle as *mut DeviceHandle + } + /// A direct call to systemd to suspend the PC. /// /// This avoids desktop environments being required to handle it diff --git a/src/daemon.rs b/src/daemon.rs index ba8e5149..f50a4502 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -12,7 +12,7 @@ use dbus_tokio::connection; use log::{error, info}; use std::error::Error; use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::time::{Duration, Instant}; pub async fn start_daemon() -> Result<(), Box> { let laptop = match_laptop(); @@ -28,7 +28,7 @@ pub async fn start_daemon() -> Result<(), Box> { ); // Reload settings rogcore.reload().await?; - println!("RELOADED"); + info!("Reloaded last saved settings"); let (resource, connection) = connection::new_system_sync()?; tokio::spawn(async { @@ -36,11 +36,9 @@ pub async fn start_daemon() -> Result<(), Box> { panic!("Lost connection to D-Bus: {}", err); }); - println!("CONN REQUEST"); connection .request_name(DBUS_IFACE, false, true, false) .await?; - println!("CONN REQUEST DONE"); let factory = Factory::new_sync::<()>(); @@ -127,6 +125,27 @@ pub async fn start_daemon() -> Result<(), Box> { tree.start_receive_send(&*connection); let supported = Vec::from(laptop.supported_modes()); + + let key_buf: Arc>> = Arc::new(Mutex::new(None)); + let handle = unsafe { &*(rogcore.get_raw_device_handle()) }; + let endpoint = laptop.key_endpoint(); + let report_filter_bytes = laptop.key_filter().to_owned(); + + let key_buf1 = key_buf.clone(); + // This is *not* safe + tokio::spawn(async move { + loop { + let data = RogCore::poll_keyboard(handle, endpoint, report_filter_bytes.clone()).await; + if let Some(stuff) = data { + if let Ok(mut lock) = key_buf1.lock() { + lock.replace(stuff); + } + } + } + }); + + // When any action occurs this time is reset + let mut time_mark = Instant::now(); loop { // Timing is such that: // - interrupt write is minimum 1ms (sometimes lower) @@ -143,26 +162,43 @@ pub async fn start_daemon() -> Result<(), Box> { 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 - rogcore.aura_set_and_save(&supported, &bytes).await?; + rogcore.aura_set_and_save(&supported, &bytes)?; *lock = None; + time_mark = Instant::now(); } } - if let Ok(mut lock) = effect.try_lock() { + if let Ok(mut lock) = effect.lock() { if lock.is_some() { let effect = lock.take(); - rogcore.aura_write_effect(effect.unwrap()).await?; + rogcore.aura_write_effect(effect.unwrap())?; + time_mark = Instant::now(); } } - match laptop.run(&mut rogcore).await { - Ok(_) => {} - Err(err) => { - error!("{:?}", err); - panic!("Force crash for systemd to restart service") + if let Ok(mut lock) = key_buf.try_lock() { + if let Some(bytes) = *lock { + // this takes at least 10ms per colour block + match laptop.run(&mut rogcore, bytes) { + Ok(_) => {} + Err(err) => { + error!("{:?}", err); + panic!("Force crash for systemd to restart service") + } + } + *lock = None; + time_mark = Instant::now(); } } - // When using an effect gen, 17-20ms is the min/max time to account for. - // If DBUS didn't take so long we could get this down to 11-12ms. + + 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)); + } else { + std::thread::sleep(Duration::from_micros(400)); + } } } diff --git a/src/laptops/gl753.rs b/src/laptops/gl753.rs index 783947ab..38336bbe 100644 --- a/src/laptops/gl753.rs +++ b/src/laptops/gl753.rs @@ -47,44 +47,42 @@ impl LaptopGL753 { } impl LaptopGL753 { - async fn do_keypress_actions(&self, rogcore: &mut RogCore) -> Result<(), AuraError> { - if let Some(key_buf) = rogcore.poll_keyboard(&self.report_filter_bytes).await { - match GL753Keys::from(key_buf[1]) { - GL753Keys::LedBrightUp => { - rogcore - .aura_bright_inc(&self.supported_modes, self.max_led_bright) - .await?; - } - GL753Keys::LedBrightDown => { - rogcore - .aura_bright_dec(&self.supported_modes, self.min_led_bright) - .await?; - } - GL753Keys::ScreenBrightUp => self.backlight.step_up(), - GL753Keys::ScreenBrightDown => self.backlight.step_down(), - 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 array: {:X?}", &key_buf); - info!("Attempting passthrough: {:X?}", &key_buf[1]); - rogcore.virt_keys().press(key_buf); - } + fn do_keypress_actions( + &self, + rogcore: &mut RogCore, + key_buf: [u8; 32], + ) -> Result<(), AuraError> { + match GL753Keys::from(key_buf[1]) { + GL753Keys::LedBrightUp => { + rogcore.aura_bright_inc(&self.supported_modes, self.max_led_bright)?; + } + GL753Keys::LedBrightDown => { + rogcore.aura_bright_dec(&self.supported_modes, self.min_led_bright)?; + } + GL753Keys::ScreenBrightUp => self.backlight.step_up(), + GL753Keys::ScreenBrightDown => self.backlight.step_down(), + 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 array: {:X?}", &key_buf); + info!("Attempting passthrough: {:X?}", &key_buf[1]); + rogcore.virt_keys().press(key_buf); } } } @@ -92,11 +90,9 @@ impl LaptopGL753 { } } -use async_trait::async_trait; -#[async_trait] impl Laptop for LaptopGL753 { - async fn run(&self, rogcore: &mut RogCore) -> Result<(), AuraError> { - self.do_keypress_actions(rogcore).await + fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { + self.do_keypress_actions(rogcore, key_buf) } fn led_endpoint(&self) -> u8 { self.led_endpoint @@ -104,6 +100,9 @@ impl Laptop for LaptopGL753 { fn key_endpoint(&self) -> u8 { self.key_endpoint } + fn key_filter(&self) -> &[u8] { + &self.report_filter_bytes + } fn usb_vendor(&self) -> u16 { self.usb_vendor } diff --git a/src/laptops/gx502.rs b/src/laptops/gx502.rs index 9c7796a5..2639741f 100644 --- a/src/laptops/gx502.rs +++ b/src/laptops/gx502.rs @@ -89,53 +89,51 @@ impl LaptopGX502 { } impl LaptopGX502 { - async fn do_keypress_actions(&self, rogcore: &mut RogCore) -> Result<(), AuraError> { - if let Some(key_buf) = rogcore.poll_keyboard(&self.report_filter_bytes).await { - match GX502Keys::from(key_buf[1]) { - GX502Keys::LedBrightUp => { - rogcore - .aura_bright_inc(&self.supported_modes, self.max_led_bright) - .await?; - } - GX502Keys::LedBrightDown => { - rogcore - .aura_bright_dec(&self.supported_modes, self.min_led_bright) - .await?; - } - GX502Keys::AuraNext => rogcore.aura_mode_next(&self.supported_modes).await?, - GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&self.supported_modes).await?, - GX502Keys::ScreenBrightUp => self.backlight.step_up(), - GX502Keys::ScreenBrightDown => 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); - } + fn do_keypress_actions( + &self, + rogcore: &mut RogCore, + key_buf: [u8; 32], + ) -> Result<(), AuraError> { + match GX502Keys::from(key_buf[1]) { + GX502Keys::LedBrightUp => { + rogcore.aura_bright_inc(&self.supported_modes, self.max_led_bright)?; + } + GX502Keys::LedBrightDown => { + rogcore.aura_bright_dec(&self.supported_modes, self.min_led_bright)?; + } + GX502Keys::AuraNext => rogcore.aura_mode_next(&self.supported_modes)?, + GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&self.supported_modes)?, + GX502Keys::ScreenBrightUp => self.backlight.step_up(), + GX502Keys::ScreenBrightDown => 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); } } } @@ -143,11 +141,9 @@ impl LaptopGX502 { } } -use async_trait::async_trait; -#[async_trait] impl Laptop for LaptopGX502 { - async fn run(&self, rogcore: &mut RogCore) -> Result<(), AuraError> { - self.do_keypress_actions(rogcore).await + fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { + self.do_keypress_actions(rogcore, key_buf) } fn led_endpoint(&self) -> u8 { self.led_endpoint @@ -155,6 +151,9 @@ impl Laptop for LaptopGX502 { fn key_endpoint(&self) -> u8 { self.key_endpoint } + fn key_filter(&self) -> &[u8] { + &self.report_filter_bytes + } fn usb_vendor(&self) -> u16 { self.usb_vendor } diff --git a/src/laptops/mod.rs b/src/laptops/mod.rs index 7b24971e..135c43b2 100644 --- a/src/laptops/mod.rs +++ b/src/laptops/mod.rs @@ -1,7 +1,6 @@ use crate::aura::BuiltInModeByte; use crate::core::RogCore; use crate::error::AuraError; -use async_trait::async_trait; //use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState}; use log::info; @@ -63,13 +62,13 @@ pub(crate) fn match_laptop() -> Box { /// /// If using the `keycode` crate to build keyboard input, the report must be prefixed /// with the report ID (usually `0x01` for the virtual keyboard). -#[async_trait] pub(crate) trait Laptop { fn board_name(&self) -> &str; fn prod_family(&self) -> &str; - async fn run(&self, core: &mut RogCore) -> Result<(), AuraError>; + fn run(&self, core: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError>; fn led_endpoint(&self) -> u8; fn key_endpoint(&self) -> u8; + fn key_filter(&self) -> &[u8]; fn usb_vendor(&self) -> u16; fn usb_product(&self) -> u16; fn supported_modes(&self) -> &[BuiltInModeByte];