mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Much better use of async throughout
This commit is contained in:
@@ -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]
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
193
src/core.rs
193
src/core.rs
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
Reference in New Issue
Block a user