diff --git a/src/core.rs b/src/core.rs index e5a72be2..014c74f1 100644 --- a/src/core.rs +++ b/src/core.rs @@ -42,9 +42,6 @@ static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode /// - `LED_INIT4` pub(crate) struct RogCore { handle: DeviceHandle, - initialised: bool, - led_endpoint: u8, - config: Config, virt_keys: VirtKeys, } @@ -79,22 +76,19 @@ impl RogCore { Ok(RogCore { handle: dev_handle, - initialised: false, - led_endpoint, - config: Config::default().read(), virt_keys: VirtKeys::new(), }) } - pub(crate) async fn reload(&mut self) -> Result<(), Box> { - let mode_curr = self.config.current_mode[3]; - let mode = self - .config - .builtin_modes - .get_field_from(BuiltInModeByte::from(mode_curr).into()) - .unwrap() - .to_owned(); - self.aura_write_messages(&[&mode])?; + pub(crate) async fn reload(&mut self, config: &mut Config) -> Result<(), Box> { + // let mode_curr = self.config.current_mode[3]; + // let mode = self + // .config + // .builtin_modes + // .get_field_from(BuiltInModeByte::from(mode_curr).into()) + // .unwrap() + // .to_owned(); + // self.aura_write_messages(&[&mode])?; let path = if Path::new(FAN_TYPE_1_PATH).exists() { FAN_TYPE_1_PATH @@ -105,8 +99,8 @@ impl RogCore { }; let mut file = OpenOptions::new().write(true).open(path)?; - file.write_all(format!("{:?}\n", self.config.fan_mode).as_bytes())?; - self.set_pstate_for_fan_mode(FanLevel::from(self.config.fan_mode))?; + file.write_all(format!("{:?}\n", config.fan_mode).as_bytes())?; + self.set_pstate_for_fan_mode(FanLevel::from(config.fan_mode))?; info!("Reloaded last saved settings"); Ok(()) } @@ -128,174 +122,7 @@ impl RogCore { Err(AuraError::UsbError(rusb::Error::NoDevice)) } - pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { - match self - .handle - .write_interrupt(self.led_endpoint, message, Duration::from_millis(2)) - { - Ok(_) => {} - Err(err) => match err { - rusb::Error::Timeout => {} - _ => error!("Failed to read keyboard interrupt: {:?}", err), - }, - } - Ok(()) - } - - fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { - if !self.initialised { - 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)?; - self.aura_write(&LED_SET)?; - } - // Changes won't persist unless apply is set - self.aura_write(&LED_APPLY)?; - Ok(()) - } - - /// Write an effect block - /// - /// `aura_effect_init` must be called any effect routine, and called only once. - pub fn aura_write_effect(&mut self, effect: Vec>) -> Result<(), AuraError> { - for row in effect.iter() { - self.aura_write(row)?; - } - Ok(()) - } - - /// Write an effect block - /// - /// `aura_effect_init` must be called any effect routine, and called only once. - pub async fn async_write_effect( - handle: &DeviceHandle, - endpoint: u8, - effect: Vec>, - ) -> Result<(), AuraError> { - for row in effect.iter() { - match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) { - Ok(_) => {} - Err(err) => match err { - rusb::Error::Timeout => {} - _ => error!("Failed to write LED interrupt: {:?}", err), - }, - } - } - Ok(()) - } - - 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)?; - return Ok(()); - } else if supported_modes.contains(&mode) || bytes[1] == 0xba { - let messages = [bytes]; - self.aura_write_messages(&messages)?; - self.config.set_field_from(bytes); - self.config.write(); - return Ok(()); - } - warn!("{:?} not supported", mode); - Err(AuraError::NotSupported) - } - - pub(crate) fn aura_bright_inc( - &mut self, - supported_modes: &[BuiltInModeByte], - max_bright: u8, - ) -> Result<(), AuraError> { - let mut bright = self.config.brightness; - if bright < max_bright { - bright += 1; - self.config.brightness = bright; - let bytes = aura_brightness_bytes(bright); - self.aura_set_and_save(supported_modes, &bytes)?; - info!("Increased LED brightness to {:#?}", bright); - } - Ok(()) - } - - pub(crate) fn aura_bright_dec( - &mut self, - supported_modes: &[BuiltInModeByte], - min_bright: u8, - ) -> Result<(), AuraError> { - let mut bright = self.config.brightness; - if bright > min_bright { - bright -= 1; - self.config.brightness = bright; - let bytes = aura_brightness_bytes(bright); - self.aura_set_and_save(supported_modes, &bytes)?; - info!("Decreased LED brightness to {:#?}", bright); - } - Ok(()) - } - - /// Select next Aura effect - /// - /// If the current effect is the last one then the effect selected wraps around to the first. - pub(crate) fn aura_mode_next( - &mut self, - supported_modes: &[BuiltInModeByte], - ) -> Result<(), AuraError> { - // TODO: different path for multi-zone (byte 2 controlled, non-zero) - let mode_curr = self.config.current_mode[3]; - let idx = supported_modes.binary_search(&mode_curr.into()).unwrap(); - let idx_next = if idx < supported_modes.len() - 1 { - idx + 1 - } else { - 0 - }; - let mode_next = self - .config - .builtin_modes - .get_field_from(supported_modes[idx_next].into()) - .unwrap() - .to_owned(); - self.aura_set_and_save(supported_modes, &mode_next)?; - info!("Switched LED mode to {:#?}", supported_modes[idx_next]); - Ok(()) - } - - /// Select previous Aura effect - /// - /// If the current effect is the first one then the effect selected wraps around to the last. - pub(crate) fn aura_mode_prev( - &mut self, - supported_modes: &[BuiltInModeByte], - ) -> Result<(), AuraError> { - // TODO: different path for multi-zone (byte 2 controlled, non-zero) - let mode_curr = self.config.current_mode[3]; - let idx = supported_modes.binary_search(&mode_curr.into()).unwrap(); - let idx_next = if idx > 0 { - idx - 1 - } else { - supported_modes.len() - 1 - }; - let mode_next = self - .config - .builtin_modes - .get_field_from(supported_modes[idx_next].into()) - .unwrap() - .to_owned(); - self.aura_set_and_save(supported_modes, &mode_next)?; - info!("Switched LED mode to {:#?}", supported_modes[idx_next]); - Ok(()) - } - - pub(crate) fn fan_mode_step(&mut self) -> Result<(), Box> { + pub(crate) fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box> { let path = if Path::new(FAN_TYPE_1_PATH).exists() { FAN_TYPE_1_PATH } else if Path::new(FAN_TYPE_2_PATH).exists() { @@ -319,8 +146,8 @@ impl RogCore { info!("Fan mode stepped to: {:#?}", FanLevel::from(n)); fan_ctrl.write_all(format!("{:?}\n", n).as_bytes())?; self.set_pstate_for_fan_mode(FanLevel::from(n))?; - self.config.fan_mode = n; - self.config.write(); + config.fan_mode = n; + config.write(); } Ok(()) } @@ -435,60 +262,197 @@ impl RogCore { } } -// use sysfs_class::{Brightness, SysClass}; -// pub(crate) struct Backlight { -// backlight: sysfs_class::Backlight, -// step: u64, -// max: u64, -// } +/// UNSAFE: because we're holding a pointer to something that *may* go out of scope while the +/// pointer is held. We're relying on access to struct to be behind a Mutex, and for behaviour +/// that may cause invalididated pointer to cause the program to panic rather than continue. +pub(crate) struct LedWriter { + handle: *mut DeviceHandle, + led_endpoint: u8, + initialised: bool, +} -// impl Backlight { -// pub(crate) fn new(id: &str) -> Result { -// for bl in sysfs_class::Backlight::iter() { -// let bl = bl?; -// if bl.id() == id { -// let max = bl.max_brightness()?; -// let step = max / 50; -// return Ok(Backlight { -// backlight: bl, -// step, -// max, -// }); -// } -// } -// panic!("Backlight not found") -// } -// pub(crate) fn step_up(&self) { -// let brightness = self -// .backlight -// .brightness() -// .map_err(|err| warn!("Failed to fetch backlight level: {}", err)) -// .unwrap(); -// if brightness + self.step <= self.max { -// self.backlight -// .set_brightness(brightness + self.step) -// .map_or_else( -// |err| warn!("Failed to increment backlight level: {}", err), -// |_| {}, -// ); -// } -// } -// pub(crate) fn step_down(&self) { -// let brightness = self -// .backlight -// .brightness() -// .map_err(|err| warn!("Failed to fetch backlight level: {}", err)) -// .unwrap(); -// if brightness > self.step { -// self.backlight -// .set_brightness(brightness - self.step) -// .map_or_else( -// |err| warn!("Failed to increment backlight level: {}", err), -// |_| {}, -// ); -// } -// } -// } +/// UNSAFE +unsafe impl Send for LedWriter {} +unsafe impl Sync for LedWriter {} + +impl LedWriter { + pub fn new(device_handle: *mut DeviceHandle, led_endpoint: u8) -> Self { + LedWriter { + handle: device_handle, + led_endpoint, + initialised: false, + } + } + + pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { + let handle = unsafe { &*self.handle }; + match handle.write_interrupt(self.led_endpoint, message, Duration::from_millis(2)) { + Ok(_) => {} + Err(err) => match err { + rusb::Error::Timeout => {} + _ => error!("Failed to read keyboard interrupt: {:?}", err), + }, + } + Ok(()) + } + + fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { + if !self.initialised { + 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)?; + self.aura_write(&LED_SET)?; + } + // Changes won't persist unless apply is set + self.aura_write(&LED_APPLY)?; + Ok(()) + } + + /// Write an effect block + /// + /// `aura_effect_init` must be called any effect routine, and called only once. + pub fn aura_write_effect(&mut self, effect: Vec>) -> Result<(), AuraError> { + for row in effect.iter() { + self.aura_write(row)?; + } + Ok(()) + } + + /// Write an effect block + /// + /// `aura_effect_init` must be called any effect routine, and called only once. + pub async fn async_write_effect( + &self, + endpoint: u8, + effect: Vec>, + ) -> Result<(), AuraError> { + let handle = unsafe { &*self.handle }; + for row in effect.iter() { + match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) { + Ok(_) => {} + Err(err) => match err { + rusb::Error::Timeout => {} + _ => error!("Failed to write LED interrupt: {:?}", err), + }, + } + } + Ok(()) + } + + pub(crate) fn aura_set_and_save( + &mut self, + supported_modes: &[BuiltInModeByte], + bytes: &[u8], + config: &mut Config, + ) -> Result<(), AuraError> { + let mode = BuiltInModeByte::from(bytes[3]); + if bytes[1] == 0xbc { + self.aura_write(bytes)?; + return Ok(()); + } else if supported_modes.contains(&mode) || bytes[1] == 0xba { + let messages = [bytes]; + self.aura_write_messages(&messages)?; + config.set_field_from(bytes); + config.write(); + return Ok(()); + } + warn!("{:?} not supported", mode); + Err(AuraError::NotSupported) + } + + pub(crate) fn aura_bright_inc( + &mut self, + supported_modes: &[BuiltInModeByte], + max_bright: u8, + config: &mut Config, + ) -> Result<(), AuraError> { + let mut bright = config.brightness; + if bright < max_bright { + bright += 1; + config.brightness = bright; + let bytes = aura_brightness_bytes(bright); + self.aura_set_and_save(supported_modes, &bytes, config)?; + info!("Increased LED brightness to {:#?}", bright); + } + Ok(()) + } + + pub(crate) fn aura_bright_dec( + &mut self, + supported_modes: &[BuiltInModeByte], + min_bright: u8, + config: &mut Config, + ) -> Result<(), AuraError> { + let mut bright = config.brightness; + if bright > min_bright { + bright -= 1; + config.brightness = bright; + let bytes = aura_brightness_bytes(bright); + self.aura_set_and_save(supported_modes, &bytes, config)?; + info!("Decreased LED brightness to {:#?}", bright); + } + Ok(()) + } + + /// Select next Aura effect + /// + /// If the current effect is the last one then the effect selected wraps around to the first. + pub(crate) fn aura_mode_next( + &mut self, + supported_modes: &[BuiltInModeByte], + config: &mut Config, + ) -> Result<(), AuraError> { + // TODO: different path for multi-zone (byte 2 controlled, non-zero) + let mode_curr = config.current_mode[3]; + let idx = supported_modes.binary_search(&mode_curr.into()).unwrap(); + let idx_next = if idx < supported_modes.len() - 1 { + idx + 1 + } else { + 0 + }; + let mode_next = config + .builtin_modes + .get_field_from(supported_modes[idx_next].into()) + .unwrap() + .to_owned(); + self.aura_set_and_save(supported_modes, &mode_next, config)?; + info!("Switched LED mode to {:#?}", supported_modes[idx_next]); + Ok(()) + } + + /// Select previous Aura effect + /// + /// If the current effect is the first one then the effect selected wraps around to the last. + pub(crate) fn aura_mode_prev( + &mut self, + supported_modes: &[BuiltInModeByte], + config: &mut Config, + ) -> Result<(), AuraError> { + // TODO: different path for multi-zone (byte 2 controlled, non-zero) + let mode_curr = config.current_mode[3]; + let idx = supported_modes.binary_search(&mode_curr.into()).unwrap(); + let idx_next = if idx > 0 { + idx - 1 + } else { + supported_modes.len() - 1 + }; + let mode_next = config + .builtin_modes + .get_field_from(supported_modes[idx_next].into()) + .unwrap() + .to_owned(); + self.aura_set_and_save(supported_modes, &mode_next, config)?; + info!("Switched LED mode to {:#?}", supported_modes[idx_next]); + Ok(()) + } +} #[derive(Debug, Options)] pub struct LedBrightness { diff --git a/src/daemon.rs b/src/daemon.rs index ce0e53e0..15b8a82a 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -2,10 +2,7 @@ pub static DBUS_NAME: &'static str = "org.rogcore.Daemon"; pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon"; pub static DBUS_IFACE: &'static str = "org.rogcore.Daemon"; -use crate::{ - core::RogCore, - laptops::{match_laptop, Laptop}, -}; +use crate::{config::Config, core::*, laptops::match_laptop}; use dbus::{ nonblock::Process, tree::{Factory, MTSync, Method, MethodErr, Tree}, @@ -16,9 +13,10 @@ use log::{error, info}; use std::error::Error; use std::sync::Arc; use std::time::{Duration, Instant}; +use tokio::sync::Mutex; -type LedMsgType = Arc>>>; -type EffectType = Arc>>>>; +type LedMsgType = Arc>>>; +type EffectType = Arc>>>>; // Timing is such that: // - interrupt write is minimum 1ms (sometimes lower) @@ -31,6 +29,8 @@ type EffectType = Arc>>>>; // DBUS processing takes 6ms if not tokiod pub async fn start_daemon() -> Result<(), Box> { let laptop = match_laptop(); + let mut config = Config::default().read(); + let mut rogcore = RogCore::new( laptop.usb_vendor(), laptop.usb_product(), @@ -47,9 +47,16 @@ pub async fn start_daemon() -> Result<(), Box> { }, ); // Reload settings - rogcore.reload().await?; + rogcore.reload(&mut config).await?; let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) }; - let rogcore = Arc::new(tokio::sync::Mutex::new(Box::pin(rogcore))); + + // Set up the mutexes + let led_writer = Arc::new(Mutex::new(LedWriter::new( + rogcore.get_raw_device_handle(), + laptop.led_endpoint(), + ))); + let config = Arc::new(Mutex::new(config)); + let rogcore = Arc::new(Mutex::new(Box::pin(rogcore))); let (resource, connection) = connection::new_system_sync()?; tokio::spawn(async { @@ -73,6 +80,8 @@ pub async fn start_daemon() -> Result<(), Box> { let report_filter_bytes = laptop.key_filter().to_owned(); // This is *not* safe let rogcore = rogcore.clone(); + let led_writer = led_writer.clone(); + let config = config.clone(); tokio::spawn(async move { loop { let data = @@ -80,7 +89,7 @@ pub async fn start_daemon() -> Result<(), Box> { .await; if let Some(bytes) = data { let mut rogcore = rogcore.lock().await; - match laptop.run(&mut rogcore, bytes) { + match laptop.run(&mut rogcore, &led_writer, &config, bytes).await { Ok(_) => {} Err(err) => { error!("{:?}", err); @@ -96,10 +105,12 @@ pub async fn start_daemon() -> Result<(), Box> { loop { connection.process_all(); + let led_writer = led_writer.clone(); if let Ok(mut lock) = input.try_lock() { if let Some(bytes) = lock.take() { - let mut rogcore = rogcore.lock().await; - rogcore.aura_set_and_save(&supported, &bytes)?; + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_set_and_save(&supported, &bytes, &mut config)?; time_mark = Instant::now(); } } @@ -110,7 +121,9 @@ pub async fn start_daemon() -> Result<(), Box> { // Spawn a writer if let Some(stuff) = lock.take() { tokio::spawn(async move { - RogCore::async_write_effect(usb_dev_handle, led_endpoint, stuff) + let led_writer = led_writer.lock().await; + led_writer + .async_write_effect(led_endpoint, stuff) .await .unwrap(); }); @@ -196,8 +209,8 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method { } fn dbus_create_tree() -> (Tree, LedMsgType, EffectType) { - let input: LedMsgType = Arc::new(tokio::sync::Mutex::new(None)); - let effect: EffectType = Arc::new(tokio::sync::Mutex::new(None)); + let input: LedMsgType = Arc::new(Mutex::new(None)); + let effect: EffectType = Arc::new(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 50c48ae8..87442fc3 100644 --- a/src/laptops/mod.rs +++ b/src/laptops/mod.rs @@ -1,5 +1,6 @@ use crate::aura::BuiltInModeByte; -use crate::core::RogCore; +use crate::config::Config; +use crate::core::{LedWriter, RogCore}; use crate::error::AuraError; //use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState}; use crate::virt_device::ConsumerKeys; @@ -66,29 +67,6 @@ pub(crate) fn match_laptop() -> LaptopBase { panic!("could not match laptop"); } -/// All laptop models should implement this trait. The role of a `Laptop` is to -/// "drive" the `RogCore`. -/// -/// `do_hotkey_action` is passed the byte that a hotkey emits, and is expected to -/// perform whichever action matches that. For now the only key bytes passed in are -/// the ones which match `byte[0] == hotkey_group_byte`. On the GX502GW the keyboard -/// has 3 explicit groups: main, vol+media, and the ones that the Linux kernel doesn't -/// map. -/// -/// 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 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]; - fn usb_vendor(&self) -> u16; - fn usb_product(&self) -> u16; - // required for profiles which match more than one laptop - fn set_usb_product(&mut self, product: u16); - fn supported_modes(&self) -> &[BuiltInModeByte]; -} - pub(crate) type LaptopRunner = dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>; pub(super) struct LaptopBase { @@ -103,53 +81,84 @@ pub(super) struct LaptopBase { //backlight: Backlight, } -impl Laptop for LaptopBase { - fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { +use tokio::sync::Mutex; + +impl LaptopBase { + /// Pass in LedWriter as Mutex so it is only locked when required + pub(super) async fn run( + &self, + rogcore: &mut RogCore, + led_writer: &Mutex, + config: &Mutex, + key_buf: [u8; 32], + ) -> Result<(), AuraError> { match self.usb_product { - 0x1869 | 0x1866 => self.gx502_runner(rogcore, key_buf), - 0x1854 => self.gl753_runner(rogcore, key_buf), + 0x1869 | 0x1866 => { + self.gx502_runner(rogcore, led_writer, config, key_buf) + .await + } + 0x1854 => { + self.gl753_runner(rogcore, led_writer, config, key_buf) + .await + } _ => panic!("No runner available for this device"), } } - fn led_endpoint(&self) -> u8 { + pub(super) fn led_endpoint(&self) -> u8 { self.led_endpoint } - fn key_endpoint(&self) -> u8 { + pub(super) fn key_endpoint(&self) -> u8 { self.key_endpoint } - fn key_filter(&self) -> &[u8] { + pub(super) fn key_filter(&self) -> &[u8] { &self.report_filter_bytes } - fn usb_vendor(&self) -> u16 { + pub(super) fn usb_vendor(&self) -> u16 { self.usb_vendor } - fn usb_product(&self) -> u16 { + pub(super) fn usb_product(&self) -> u16 { self.usb_product } - fn set_usb_product(&mut self, product: u16) { + pub(super) fn set_usb_product(&mut self, product: u16) { self.usb_product = product; } - fn supported_modes(&self) -> &[BuiltInModeByte] { + pub(super) fn supported_modes(&self) -> &[BuiltInModeByte] { &self.supported_modes } -} -impl LaptopBase { // 0x1866, per-key LEDs, media-keys split from vendor specific - fn gx502_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { + async fn gx502_runner( + &self, + rogcore: &mut RogCore, + led_writer: &Mutex, + config: &Mutex, + 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(); match GX502Keys::from(key_buf[1]) { GX502Keys::LedBrightUp => { - rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?; } GX502Keys::LedBrightDown => { - rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?; + } + GX502Keys::AuraNext => { + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_mode_next(&supported_modes, &mut config)?; + } + GX502Keys::AuraPrevious => { + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_mode_prev(&supported_modes, &mut config)?; } - 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(), @@ -160,7 +169,8 @@ impl LaptopBase { GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(), GX502Keys::MicToggle => {} GX502Keys::Fan => { - rogcore.fan_mode_step().unwrap_or_else(|err| { + let mut config = config.lock().await; + rogcore.fan_mode_step(&mut config).unwrap_or_else(|err| { warn!("Couldn't toggle fan mode: {:?}", err); }); } @@ -192,16 +202,26 @@ impl LaptopBase { } // GL753VE == 0x1854, 4 zone keyboard - fn gl753_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> { + async fn gl753_runner( + &self, + rogcore: &mut RogCore, + led_writer: &Mutex, + config: &Mutex, + 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(); match GL753Keys::from(key_buf[1]) { GL753Keys::LedBrightUp => { - rogcore.aura_bright_inc(&supported_modes, max_led_bright)?; + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?; } GL753Keys::LedBrightDown => { - rogcore.aura_bright_dec(&supported_modes, min_led_bright)?; + let mut led_writer = led_writer.lock().await; + let mut config = config.lock().await; + led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?; } GL753Keys::ScreenBrightUp => { rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())