Much better use of async throughout

This commit is contained in:
Luke
2020-04-30 20:18:41 +12:00
parent 5ee57b21c9
commit 8b36f1ceec
5 changed files with 200 additions and 137 deletions

View File

@@ -53,9 +53,8 @@ opt-level = 3
panic = "abort" panic = "abort"
[profile.dev] [profile.dev]
lto = true
debug = false debug = false
opt-level = 3 opt-level = 2
#panic = "abort" #panic = "abort"
[profile.bench] [profile.bench]

View File

@@ -1,4 +1,4 @@
use daemon::aura::{BuiltInModeByte, Key, KeyColourArray}; use daemon::aura::{Key, KeyColourArray};
use daemon::daemon::{DBUS_IFACE, DBUS_NAME, DBUS_PATH}; use daemon::daemon::{DBUS_IFACE, DBUS_NAME, DBUS_PATH};
use dbus::Error as DbusError; use dbus::Error as DbusError;
use dbus::{ffidisp::Connection, Message}; use dbus::{ffidisp::Connection, Message};
@@ -6,7 +6,6 @@ use std::{thread, time};
pub fn dbus_led_builtin_write(bytes: &[u8]) -> Result<(), Box<dyn std::error::Error>> { pub fn dbus_led_builtin_write(bytes: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
let bus = Connection::new_system()?; let bus = Connection::new_system()?;
//let proxy = bus.with_proxy(DBUS_IFACE, "/", Duration::from_millis(5000));
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")? let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
.append1(bytes.to_vec()); .append1(bytes.to_vec());
let r = bus.send_with_reply_and_block(msg, 5000)?; let r = bus.send_with_reply_and_block(msg, 5000)?;
@@ -44,8 +43,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
per_key_led.push(key_colours.clone()); per_key_led.push(key_colours.clone());
} }
// It takes each interrupt at least 1ms. 10ms to write complete block. Plus any extra // It takes each interrupt at least 1ms. 10ms to write complete block.
// penalty time such as read waits
let time = time::Duration::from_millis(10); // aim for 100 per second let time = time::Duration::from_millis(10); // aim for 100 per second
let row = KeyColourArray::get_init_msg(); let row = KeyColourArray::get_init_msg();
@@ -58,7 +56,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
thread::sleep(time); thread::sleep(time);
for group in &per_key_led { for group in &per_key_led {
thread::sleep(time);
let group = group.get(); let group = group.get();
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")? let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")?
.append1(&group[0].to_vec()) .append1(&group[0].to_vec())
@@ -72,6 +69,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.append1(&group[8].to_vec()) .append1(&group[8].to_vec())
.append1(&group[9].to_vec()); .append1(&group[9].to_vec());
bus.send(msg).unwrap(); bus.send(msg).unwrap();
thread::sleep(time);
} }
let after = std::time::Instant::now(); let after = std::time::Instant::now();
let diff = after.duration_since(now); let diff = after.duration_since(now);

View File

@@ -12,8 +12,10 @@ use rusb::DeviceHandle;
use std::error::Error; use std::error::Error;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::marker::PhantomData;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use std::ptr::NonNull;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
@@ -179,36 +181,11 @@ impl RogCore {
Ok(()) Ok(())
} }
/// Write the bytes read from the device interrupt to the buffer arg, and returns the pub(crate) fn get_raw_device_handle(&mut self) -> NonNull<DeviceHandle<rusb::GlobalContext>> {
/// count of bytes written
///
/// `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(
handle: &DeviceHandle<rusb::GlobalContext>,
endpoint: u8,
report_filter_bytes: &[u8],
) -> Option<[u8; 32]> {
let mut buf = [0u8; 32];
match handle.read_interrupt(endpoint, &mut buf, Duration::from_millis(200)) {
Ok(_) => {
if report_filter_bytes.contains(&buf[0])
&& (buf[1] != 0 || buf[2] != 0 || buf[3] != 0 || buf[4] != 0)
{
return Some(buf);
}
}
Err(err) => match err {
rusb::Error::Timeout => {}
_ => error!("Failed to read keyboard interrupt: {:?}", err),
},
}
None
}
pub(crate) fn get_raw_device_handle(&mut self) -> *mut DeviceHandle<rusb::GlobalContext> {
// Breaking every damn lifetime guarantee rust gives us // Breaking every damn lifetime guarantee rust gives us
&mut self.handle as *mut DeviceHandle<rusb::GlobalContext> unsafe {
NonNull::new_unchecked(&mut self.handle as *mut DeviceHandle<rusb::GlobalContext>)
}
} }
/// A direct call to systemd to suspend the PC. /// A direct call to systemd to suspend the PC.
@@ -262,31 +239,104 @@ impl RogCore {
} }
} }
/// UNSAFE: because we're holding a pointer to something that *may* go out of scope while the /// UNSAFE: Must live as long as RogCore
///
/// 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 /// 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. /// that may cause invalididated pointer to cause the program to panic rather than continue.
pub(crate) struct LedWriter { pub(crate) struct KeyboardReader<'d, C: 'd>
handle: *mut DeviceHandle<rusb::GlobalContext>, where
led_endpoint: u8, C: rusb::UsbContext,
initialised: bool, {
handle: NonNull<DeviceHandle<C>>,
endpoint: u8,
filter: Vec<u8>,
_phantom: PhantomData<&'d DeviceHandle<C>>,
} }
/// UNSAFE /// UNSAFE
unsafe impl Send for LedWriter {} unsafe impl<'d, C> Send for KeyboardReader<'d, C> where C: rusb::UsbContext {}
unsafe impl Sync for LedWriter {} unsafe impl<'d, C> Sync for KeyboardReader<'d, C> where C: rusb::UsbContext {}
impl LedWriter { impl<'d, C> KeyboardReader<'d, C>
pub fn new(device_handle: *mut DeviceHandle<rusb::GlobalContext>, led_endpoint: u8) -> Self { where
C: rusb::UsbContext,
{
pub fn new(device_handle: NonNull<DeviceHandle<C>>, key_endpoint: u8, filter: Vec<u8>) -> Self {
KeyboardReader {
handle: device_handle,
endpoint: key_endpoint,
filter,
_phantom: PhantomData,
}
}
/// Write the bytes read from the device interrupt to the buffer arg, and returns the
/// count of bytes written
///
/// `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(&self) -> Option<[u8; 32]> {
let mut buf = [0u8; 32];
match unsafe { self.handle.as_ref() }.read_interrupt(
self.endpoint,
&mut buf,
Duration::from_millis(200),
) {
Ok(_) => {
if self.filter.contains(&buf[0])
&& (buf[1] != 0 || buf[2] != 0 || buf[3] != 0 || buf[4] != 0)
{
return Some(buf);
}
}
Err(err) => match err {
rusb::Error::Timeout => {}
_ => error!("Failed to read keyboard interrupt: {:?}", err),
},
}
None
}
}
/// UNSAFE: Must live as long as RogCore
///
/// 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<'d, C: 'd>
where
C: rusb::UsbContext,
{
handle: NonNull<DeviceHandle<C>>,
led_endpoint: u8,
initialised: bool,
_phantom: PhantomData<&'d DeviceHandle<C>>,
}
/// UNSAFE
unsafe impl<'d, C> Send for LedWriter<'d, C> where C: rusb::UsbContext {}
unsafe impl<'d, C> Sync for LedWriter<'d, C> where C: rusb::UsbContext {}
impl<'d, C> LedWriter<'d, C>
where
C: rusb::UsbContext,
{
pub fn new(device_handle: NonNull<DeviceHandle<C>>, led_endpoint: u8) -> Self {
LedWriter { LedWriter {
handle: device_handle, handle: device_handle,
led_endpoint, led_endpoint,
initialised: false, initialised: false,
_phantom: PhantomData,
} }
} }
pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> { async fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> {
let handle = unsafe { &*self.handle }; match unsafe { self.handle.as_ref() }.write_interrupt(
match handle.write_interrupt(self.led_endpoint, message, Duration::from_millis(2)) { self.led_endpoint,
message,
Duration::from_millis(1),
) {
Ok(_) => {} Ok(_) => {}
Err(err) => match err { Err(err) => match err {
rusb::Error::Timeout => {} rusb::Error::Timeout => {}
@@ -296,32 +346,22 @@ impl LedWriter {
Ok(()) Ok(())
} }
fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { async fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> {
if !self.initialised { if !self.initialised {
self.aura_write(&LED_INIT1)?; self.aura_write(&LED_INIT1).await?;
self.aura_write(LED_INIT2.as_bytes())?; self.aura_write(LED_INIT2.as_bytes()).await?;
self.aura_write(&LED_INIT3)?; self.aura_write(&LED_INIT3).await?;
self.aura_write(LED_INIT4.as_bytes())?; self.aura_write(LED_INIT4.as_bytes()).await?;
self.aura_write(&LED_INIT5)?; self.aura_write(&LED_INIT5).await?;
self.initialised = true; self.initialised = true;
} }
for message in messages { for message in messages {
self.aura_write(*message)?; self.aura_write(*message).await?;
self.aura_write(&LED_SET)?; self.aura_write(&LED_SET).await?;
} }
// Changes won't persist unless apply is set // Changes won't persist unless apply is set
self.aura_write(&LED_APPLY)?; self.aura_write(&LED_APPLY).await?;
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<Vec<u8>>) -> Result<(), AuraError> {
for row in effect.iter() {
self.aura_write(row)?;
}
Ok(()) Ok(())
} }
@@ -333,9 +373,12 @@ impl LedWriter {
endpoint: u8, endpoint: u8,
effect: Vec<Vec<u8>>, effect: Vec<Vec<u8>>,
) -> Result<(), AuraError> { ) -> Result<(), AuraError> {
let handle = unsafe { &*self.handle };
for row in effect.iter() { for row in effect.iter() {
match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) { match unsafe { self.handle.as_ref() }.write_interrupt(
endpoint,
row,
Duration::from_millis(1),
) {
Ok(_) => {} Ok(_) => {}
Err(err) => match err { Err(err) => match err {
rusb::Error::Timeout => {} rusb::Error::Timeout => {}
@@ -346,7 +389,7 @@ impl LedWriter {
Ok(()) Ok(())
} }
pub(crate) fn aura_set_and_save( pub(crate) async fn aura_set_and_save(
&mut self, &mut self,
supported_modes: &[BuiltInModeByte], supported_modes: &[BuiltInModeByte],
bytes: &[u8], bytes: &[u8],
@@ -354,11 +397,11 @@ impl LedWriter {
) -> Result<(), AuraError> { ) -> Result<(), AuraError> {
let mode = BuiltInModeByte::from(bytes[3]); let mode = BuiltInModeByte::from(bytes[3]);
if bytes[1] == 0xbc { if bytes[1] == 0xbc {
self.aura_write(bytes)?; self.aura_write(bytes).await?;
return Ok(()); return Ok(());
} else if supported_modes.contains(&mode) || bytes[1] == 0xba { } else if supported_modes.contains(&mode) || bytes[1] == 0xba {
let messages = [bytes]; let messages = [bytes];
self.aura_write_messages(&messages)?; self.aura_write_messages(&messages).await?;
config.set_field_from(bytes); config.set_field_from(bytes);
config.write(); config.write();
return Ok(()); return Ok(());
@@ -367,7 +410,7 @@ impl LedWriter {
Err(AuraError::NotSupported) Err(AuraError::NotSupported)
} }
pub(crate) fn aura_bright_inc( pub(crate) async fn aura_bright_inc(
&mut self, &mut self,
supported_modes: &[BuiltInModeByte], supported_modes: &[BuiltInModeByte],
max_bright: u8, max_bright: u8,
@@ -378,13 +421,14 @@ impl LedWriter {
bright += 1; bright += 1;
config.brightness = bright; config.brightness = bright;
let bytes = aura_brightness_bytes(bright); let bytes = aura_brightness_bytes(bright);
self.aura_set_and_save(supported_modes, &bytes, config)?; self.aura_set_and_save(supported_modes, &bytes, config)
.await?;
info!("Increased LED brightness to {:#?}", bright); info!("Increased LED brightness to {:#?}", bright);
} }
Ok(()) Ok(())
} }
pub(crate) fn aura_bright_dec( pub(crate) async fn aura_bright_dec(
&mut self, &mut self,
supported_modes: &[BuiltInModeByte], supported_modes: &[BuiltInModeByte],
min_bright: u8, min_bright: u8,
@@ -395,7 +439,8 @@ impl LedWriter {
bright -= 1; bright -= 1;
config.brightness = bright; config.brightness = bright;
let bytes = aura_brightness_bytes(bright); let bytes = aura_brightness_bytes(bright);
self.aura_set_and_save(supported_modes, &bytes, config)?; self.aura_set_and_save(supported_modes, &bytes, config)
.await?;
info!("Decreased LED brightness to {:#?}", bright); info!("Decreased LED brightness to {:#?}", bright);
} }
Ok(()) Ok(())
@@ -404,7 +449,7 @@ impl LedWriter {
/// Select next Aura effect /// Select next Aura effect
/// ///
/// If the current effect is the last one then the effect selected wraps around to the first. /// If the current effect is the last one then the effect selected wraps around to the first.
pub(crate) fn aura_mode_next( pub(crate) async fn aura_mode_next(
&mut self, &mut self,
supported_modes: &[BuiltInModeByte], supported_modes: &[BuiltInModeByte],
config: &mut Config, config: &mut Config,
@@ -422,7 +467,8 @@ impl LedWriter {
.get_field_from(supported_modes[idx_next].into()) .get_field_from(supported_modes[idx_next].into())
.unwrap() .unwrap()
.to_owned(); .to_owned();
self.aura_set_and_save(supported_modes, &mode_next, config)?; self.aura_set_and_save(supported_modes, &mode_next, config)
.await?;
info!("Switched LED mode to {:#?}", supported_modes[idx_next]); info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
Ok(()) Ok(())
} }
@@ -430,7 +476,7 @@ impl LedWriter {
/// Select previous Aura effect /// Select previous Aura effect
/// ///
/// If the current effect is the first one then the effect selected wraps around to the last. /// If the current effect is the first one then the effect selected wraps around to the last.
pub(crate) fn aura_mode_prev( pub(crate) async fn aura_mode_prev(
&mut self, &mut self,
supported_modes: &[BuiltInModeByte], supported_modes: &[BuiltInModeByte],
config: &mut Config, config: &mut Config,
@@ -448,7 +494,8 @@ impl LedWriter {
.get_field_from(supported_modes[idx_next].into()) .get_field_from(supported_modes[idx_next].into())
.unwrap() .unwrap()
.to_owned(); .to_owned();
self.aura_set_and_save(supported_modes, &mode_next, config)?; self.aura_set_and_save(supported_modes, &mode_next, config)
.await?;
info!("Switched LED mode to {:#?}", supported_modes[idx_next]); info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
Ok(()) Ok(())
} }

View File

@@ -9,7 +9,7 @@ use dbus::{
}; };
use dbus_tokio::connection; use dbus_tokio::connection;
use log::{error, info}; use log::{error, info, warn};
use std::error::Error; use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@@ -31,24 +31,25 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let laptop = match_laptop(); let laptop = match_laptop();
let mut config = Config::default().read(); let mut config = Config::default().read();
let mut rogcore = RogCore::new( let mut rogcore = Box::pin(
laptop.usb_vendor(), RogCore::new(
laptop.usb_product(), laptop.usb_vendor(),
laptop.led_endpoint(), laptop.usb_product(),
) laptop.led_endpoint(),
.map_or_else( )
|err| { .map_or_else(
error!("{}", err); |err| {
panic!("{}", err); error!("{}", err);
}, panic!("{}", err);
|daemon| { },
info!("RogCore loaded"); |daemon| {
daemon info!("RogCore loaded");
}, daemon
},
),
); );
// Reload settings // Reload settings
rogcore.reload(&mut config).await?; rogcore.reload(&mut config).await?;
let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) };
// Set up the mutexes // Set up the mutexes
let led_writer = Arc::new(Mutex::new(LedWriter::new( let led_writer = Arc::new(Mutex::new(LedWriter::new(
@@ -56,8 +57,6 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
laptop.led_endpoint(), laptop.led_endpoint(),
))); )));
let config = Arc::new(Mutex::new(config)); let config = Arc::new(Mutex::new(config));
let rogcore = Arc::new(Mutex::new(Box::pin(rogcore)));
let (resource, connection) = connection::new_system_sync()?; let (resource, connection) = connection::new_system_sync()?;
tokio::spawn(async { tokio::spawn(async {
let err = resource.await; let err = resource.await;
@@ -65,7 +64,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
}); });
connection connection
.request_name(DBUS_IFACE, false, true, false) .request_name(DBUS_IFACE, false, true, true)
.await?; .await?;
let (tree, input, effect) = dbus_create_tree(); let (tree, input, effect) = dbus_create_tree();
@@ -75,20 +74,22 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let supported = Vec::from(laptop.supported_modes()); let supported = Vec::from(laptop.supported_modes());
let led_endpoint = laptop.led_endpoint(); let led_endpoint = laptop.led_endpoint();
// Keyboard reader goes in separate task because we want a high interrupt timeout
// and don't want that to hold up other tasks, or miss keystrokes
{ {
let keyboard_endpoint = laptop.key_endpoint(); let keyboard_reader = KeyboardReader::new(
let report_filter_bytes = laptop.key_filter().to_owned(); rogcore.get_raw_device_handle(),
laptop.key_endpoint(),
laptop.key_filter().to_owned(),
);
// This is *not* safe // This is *not* safe
let rogcore = rogcore.clone();
let led_writer = led_writer.clone(); let led_writer = led_writer.clone();
let config = config.clone(); let config = config.clone();
// start the keyboard reader and laptop-action loop
tokio::spawn(async move { tokio::spawn(async move {
loop { loop {
let data = let data = unsafe { keyboard_reader.poll_keyboard().await };
RogCore::poll_keyboard(usb_dev_handle, keyboard_endpoint, &report_filter_bytes)
.await;
if let Some(bytes) = data { if let Some(bytes) = data {
let mut rogcore = rogcore.lock().await;
match laptop.run(&mut rogcore, &led_writer, &config, bytes).await { match laptop.run(&mut rogcore, &led_writer, &config, bytes).await {
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
@@ -101,6 +102,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
}); });
} }
// start the LED writer loop
let mut time_mark = Instant::now(); let mut time_mark = Instant::now();
loop { loop {
connection.process_all(); connection.process_all();
@@ -110,35 +112,36 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
if let Some(bytes) = lock.take() { if let Some(bytes) = lock.take() {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_set_and_save(&supported, &bytes, &mut config)?; led_writer
.aura_set_and_save(&supported, &bytes, &mut config)
.await
.map_err(|err| warn!("{:?}", err))
.unwrap();
time_mark = Instant::now(); time_mark = Instant::now();
} }
} }
// Write a colour block // Write a colour block
// Yank data out and drop lock quick (effect write takes 10ms)
if let Ok(mut lock) = effect.try_lock() { if let Ok(mut lock) = effect.try_lock() {
// Spawn a writer // Spawn a writer
if let Some(stuff) = lock.take() { if let Some(stuff) = lock.take() {
tokio::spawn(async move { let led_writer = led_writer.lock().await;
let led_writer = led_writer.lock().await; led_writer
led_writer .async_write_effect(led_endpoint, stuff)
.async_write_effect(led_endpoint, stuff) .await
.await .map_err(|err| warn!("{:?}", err))
.unwrap(); .unwrap();
});
time_mark = Instant::now(); time_mark = Instant::now();
} }
} }
let now = Instant::now(); let now = Instant::now();
// Cool-down steps // Cool-down steps
// This block is to prevent the loop spooling as fast as possible and saturating the CPU
if now.duration_since(time_mark).as_millis() > 500 { if now.duration_since(time_mark).as_millis() > 500 {
std::thread::sleep(Duration::from_millis(200)); std::thread::sleep(Duration::from_millis(200));
} else if now.duration_since(time_mark).as_millis() > 100 { } else if now.duration_since(time_mark).as_millis() > 100 {
std::thread::sleep(Duration::from_millis(50)); std::thread::sleep(Duration::from_millis(50));
} else {
std::thread::sleep(Duration::from_micros(5));
} }
} }
} }

View File

@@ -67,8 +67,6 @@ pub(crate) fn match_laptop() -> LaptopBase {
panic!("could not match laptop"); panic!("could not match laptop");
} }
pub(crate) type LaptopRunner = dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>;
pub(super) struct LaptopBase { pub(super) struct LaptopBase {
usb_vendor: u16, usb_vendor: u16,
usb_product: u16, usb_product: u16,
@@ -85,13 +83,16 @@ use tokio::sync::Mutex;
impl LaptopBase { impl LaptopBase {
/// Pass in LedWriter as Mutex so it is only locked when required /// Pass in LedWriter as Mutex so it is only locked when required
pub(super) async fn run( pub(super) async fn run<'a, C>(
&self, &self,
rogcore: &mut RogCore, rogcore: &mut RogCore,
led_writer: &Mutex<LedWriter>, led_writer: &Mutex<LedWriter<'a, C>>,
config: &Mutex<Config>, config: &Mutex<Config>,
key_buf: [u8; 32], key_buf: [u8; 32],
) -> Result<(), AuraError> { ) -> Result<(), AuraError>
where
C: rusb::UsbContext,
{
match self.usb_product { match self.usb_product {
0x1869 | 0x1866 => { 0x1869 | 0x1866 => {
self.gx502_runner(rogcore, led_writer, config, key_buf) self.gx502_runner(rogcore, led_writer, config, key_buf)
@@ -120,21 +121,21 @@ impl LaptopBase {
pub(super) fn usb_product(&self) -> u16 { pub(super) fn usb_product(&self) -> u16 {
self.usb_product self.usb_product
} }
pub(super) fn set_usb_product(&mut self, product: u16) {
self.usb_product = product;
}
pub(super) fn supported_modes(&self) -> &[BuiltInModeByte] { pub(super) fn supported_modes(&self) -> &[BuiltInModeByte] {
&self.supported_modes &self.supported_modes
} }
// 0x1866, per-key LEDs, media-keys split from vendor specific // 0x1866, per-key LEDs, media-keys split from vendor specific
async fn gx502_runner( async fn gx502_runner<'a, C>(
&self, &self,
rogcore: &mut RogCore, rogcore: &mut RogCore,
led_writer: &Mutex<LedWriter>, led_writer: &Mutex<LedWriter<'a, C>>,
config: &Mutex<Config>, config: &Mutex<Config>,
key_buf: [u8; 32], key_buf: [u8; 32],
) -> Result<(), AuraError> { ) -> Result<(), AuraError>
where
C: rusb::UsbContext,
{
let max_led_bright = self.max_led_bright; let max_led_bright = self.max_led_bright;
let min_led_bright = self.min_led_bright; let min_led_bright = self.min_led_bright;
let supported_modes = self.supported_modes.to_owned(); let supported_modes = self.supported_modes.to_owned();
@@ -142,22 +143,30 @@ impl LaptopBase {
GX502Keys::LedBrightUp => { GX502Keys::LedBrightUp => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?; led_writer
.aura_bright_inc(&supported_modes, max_led_bright, &mut config)
.await?;
} }
GX502Keys::LedBrightDown => { GX502Keys::LedBrightDown => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?; led_writer
.aura_bright_dec(&supported_modes, min_led_bright, &mut config)
.await?;
} }
GX502Keys::AuraNext => { GX502Keys::AuraNext => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_mode_next(&supported_modes, &mut config)?; led_writer
.aura_mode_next(&supported_modes, &mut config)
.await?;
} }
GX502Keys::AuraPrevious => { GX502Keys::AuraPrevious => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_mode_prev(&supported_modes, &mut config)?; led_writer
.aura_mode_prev(&supported_modes, &mut config)
.await?;
} }
GX502Keys::ScreenBrightUp => { GX502Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
@@ -202,13 +211,16 @@ impl LaptopBase {
} }
// GL753VE == 0x1854, 4 zone keyboard // GL753VE == 0x1854, 4 zone keyboard
async fn gl753_runner( async fn gl753_runner<'a, C>(
&self, &self,
rogcore: &mut RogCore, rogcore: &mut RogCore,
led_writer: &Mutex<LedWriter>, led_writer: &Mutex<LedWriter<'a, C>>,
config: &Mutex<Config>, config: &Mutex<Config>,
key_buf: [u8; 32], key_buf: [u8; 32],
) -> Result<(), AuraError> { ) -> Result<(), AuraError>
where
C: rusb::UsbContext,
{
let max_led_bright = self.max_led_bright; let max_led_bright = self.max_led_bright;
let min_led_bright = self.min_led_bright; let min_led_bright = self.min_led_bright;
let supported_modes = self.supported_modes.to_owned(); let supported_modes = self.supported_modes.to_owned();
@@ -216,12 +228,16 @@ impl LaptopBase {
GL753Keys::LedBrightUp => { GL753Keys::LedBrightUp => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?; led_writer
.aura_bright_inc(&supported_modes, max_led_bright, &mut config)
.await?;
} }
GL753Keys::LedBrightDown => { GL753Keys::LedBrightDown => {
let mut led_writer = led_writer.lock().await; let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await; let mut config = config.lock().await;
led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?; led_writer
.aura_bright_dec(&supported_modes, min_led_bright, &mut config)
.await?;
} }
GL753Keys::ScreenBrightUp => { GL753Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())