Reorganise some async code

This commit is contained in:
Luke
2020-04-29 22:39:12 +12:00
parent 4e78a5dbdd
commit 596d523a89
6 changed files with 151 additions and 156 deletions

12
Cargo.lock generated
View File

@@ -223,6 +223,12 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "fnv"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@@ -376,8 +382,9 @@ dependencies = [
[[package]]
name = "intel-pstate"
version = "0.2.0"
source = "git+https://github.com/flukejones/intel-pstate#f70ab9726bdada99f5cb01c64c056f2093f3a008"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0e7f68d8a6d149a5b2195ab645923c63ee35928fff58895b3c1d21541afe90c"
dependencies = [
"err-derive",
"smart-default",
@@ -857,6 +864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c"
dependencies = [
"bytes",
"fnv",
"futures-core",
"lazy_static",
"mio",

View File

@@ -28,7 +28,7 @@ env_logger = "^0.7.1"
# async
dbus = { version = "^0.8.2", features = ["futures"] }
dbus-tokio = "^0.5.1"
tokio = { version = "0.2.4", features = ["rt-threaded", "macros"] }
tokio = { version = "0.2.4", features = ["rt-threaded", "macros", "sync"] }
# serialisation
serde = "1.0"
@@ -38,7 +38,7 @@ toml = "0.5"
# Device control
# sysfs-class = "^0.1.2" # used for backlight control mostly
# cpu power management
intel-pstate = { git = "https://github.com/flukejones/intel-pstate" }
intel-pstate = "^0.2.1"
# virtualisation of HID, mainly for outputting consumer key codes
uhid-virt = "^0.0.4"
#keycode = "0.3"

View File

@@ -3,7 +3,7 @@ use serde_derive::{Deserialize, Serialize};
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
pub static CONFIG_PATH: &'static str = "/etc/rogcore.conf";
pub static CONFIG_PATH: &str = "/etc/rogcore.conf";
#[derive(Default, Deserialize, Serialize)]
pub struct Config {

View File

@@ -19,17 +19,17 @@ use std::time::Duration;
pub const LED_MSG_LEN: usize = 17;
static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
static LED_INIT2: &'static str = "]ASUS Tech.Inc."; // ] == 0x5d
static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
static LED_INIT4: &'static str = "^ASUS Tech.Inc."; // ^ == 0x5e
static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
// Only these two packets must be 17 bytes
static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
static FAN_TYPE_1_PATH: &'static str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
static FAN_TYPE_2_PATH: &'static str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
/// ROG device controller
///
@@ -75,7 +75,7 @@ impl RogCore {
dev_handle.set_auto_detach_kernel_driver(true).unwrap();
dev_handle
.claim_interface(interface)
.map_err(|err| AuraError::UsbError(err))?;
.map_err(AuraError::UsbError)?;
Ok(RogCore {
handle: dev_handle,
@@ -131,7 +131,7 @@ impl RogCore {
pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> {
match self
.handle
.write_interrupt(self.led_endpoint, message, Duration::from_millis(1))
.write_interrupt(self.led_endpoint, message, Duration::from_millis(2))
{
Ok(_) => {}
Err(err) => match err {
@@ -180,7 +180,7 @@ impl RogCore {
effect: Vec<Vec<u8>>,
) -> Result<(), AuraError> {
for row in effect.iter() {
match handle.write_interrupt(endpoint, row, Duration::from_millis(1)) {
match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) {
Ok(_) => {}
Err(err) => match err {
rusb::Error::Timeout => {}
@@ -207,7 +207,7 @@ impl RogCore {
self.config.write();
return Ok(());
}
warn!("{:?} not supported", BuiltInModeByte::from(mode));
warn!("{:?} not supported", mode);
Err(AuraError::NotSupported)
}
@@ -365,7 +365,9 @@ impl RogCore {
let mut buf = [0u8; 32];
match handle.read_interrupt(endpoint, &mut buf, Duration::from_millis(200)) {
Ok(_) => {
if report_filter_bytes.contains(&buf[0]) {
if report_filter_bytes.contains(&buf[0])
&& (buf[1] != 0 || buf[2] != 0 || buf[3] != 0 || buf[4] != 0)
{
return Some(buf);
}
}

View File

@@ -14,11 +14,11 @@ use dbus_tokio::connection;
use log::{error, info};
use std::error::Error;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::time::{Duration, Instant};
type LedMsgType = Arc<Mutex<Option<Vec<u8>>>>;
type EffectType = Arc<Mutex<Option<Vec<Vec<u8>>>>>;
type LedMsgType = Arc<tokio::sync::Mutex<Option<Vec<u8>>>>;
type EffectType = Arc<tokio::sync::Mutex<Option<Vec<Vec<u8>>>>>;
// Timing is such that:
// - interrupt write is minimum 1ms (sometimes lower)
@@ -35,7 +35,6 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
laptop.usb_vendor(),
laptop.usb_product(),
laptop.led_endpoint(),
laptop.key_endpoint(),
)
.map_or_else(
|err| {
@@ -49,6 +48,8 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
);
// Reload settings
rogcore.reload().await?;
let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) };
let rogcore = Arc::new(tokio::sync::Mutex::new(Box::pin(rogcore)));
let (resource, connection) = connection::new_system_sync()?;
tokio::spawn(async {
@@ -64,65 +65,55 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
// We add the tree to the connection so that incoming method calls will be handled.
tree.start_receive_send(&*connection);
let key_buf: Arc<Mutex<Option<[u8; 32]>>> = Arc::new(Mutex::new(None));
let supported = Vec::from(laptop.supported_modes());
let led_endpoint = laptop.led_endpoint();
{
let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) };
let keyboard_endpoint = laptop.key_endpoint();
let report_filter_bytes = laptop.key_filter().to_owned();
let key_buf1 = key_buf.clone();
// This is *not* safe
let rogcore = rogcore.clone();
tokio::spawn(async move {
loop {
let data =
RogCore::poll_keyboard(usb_dev_handle, keyboard_endpoint, &report_filter_bytes)
.await;
if let Some(stuff) = data {
// If we have some data to show, we *must* lock
if let Ok(mut lock) = key_buf1.lock() {
lock.replace(stuff);
if let Some(bytes) = data {
let mut rogcore = rogcore.lock().await;
match laptop.run(&mut rogcore, bytes) {
Ok(_) => {}
Err(err) => {
error!("{:?}", err);
panic!("Force crash for systemd to restart service")
}
}
}
}
});
}
let supported = Vec::from(laptop.supported_modes());
// When any action occurs this time is reset
let mut time_mark = Instant::now();
let laptop_actions = laptop.get_runner();
loop {
connection.process_all();
if let Ok(mut lock) = input.try_lock() {
if let Some(bytes) = &*lock {
// It takes up to 20 milliseconds to write a complete colour block here
if let Some(bytes) = lock.take() {
let mut rogcore = rogcore.lock().await;
rogcore.aura_set_and_save(&supported, &bytes)?;
*lock = None;
time_mark = Instant::now();
}
}
if let Ok(mut lock) = effect.lock() {
if lock.is_some() {
let effect = lock.take();
rogcore.aura_write_effect(effect.unwrap())?;
time_mark = Instant::now();
}
}
if let Ok(mut lock) = key_buf.try_lock() {
if let Some(bytes) = *lock {
// this takes at least 10ms per colour block
match laptop_actions(&mut rogcore, bytes) {
Ok(_) => {}
Err(err) => {
error!("{:?}", err);
panic!("Force crash for systemd to restart service")
}
}
*lock = None;
// Write a colour block
// Yank data out and drop lock quick (effect write takes 10ms)
if let Ok(mut lock) = effect.try_lock() {
// Spawn a writer
if let Some(stuff) = lock.take() {
tokio::spawn(async move {
RogCore::async_write_effect(usb_dev_handle, led_endpoint, stuff)
.await
.unwrap();
});
time_mark = Instant::now();
}
}
@@ -130,11 +121,11 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let now = Instant::now();
// Cool-down steps
if now.duration_since(time_mark).as_millis() > 500 {
std::thread::sleep(Duration::from_millis(100));
} else if now.duration_since(time_mark).as_millis() > 20 {
std::thread::sleep(Duration::from_millis(20));
std::thread::sleep(Duration::from_millis(200));
} else if now.duration_since(time_mark).as_millis() > 100 {
std::thread::sleep(Duration::from_millis(50));
} else {
std::thread::sleep(Duration::from_micros(400));
std::thread::sleep(Duration::from_micros(5));
}
}
}
@@ -152,9 +143,9 @@ fn dbus_create_ledmsg_method(msg: LedMsgType) -> Method<MTSync, ()> {
.msg
.method_return()
.append1(&format!("Wrote {:x?}", bytes));
return Ok(vec![mret]);
Ok(vec![mret])
} else {
return Err(MethodErr::failed("Could not lock daemon for access"));
Err(MethodErr::failed("Could not lock daemon for access"))
}
}
})
@@ -185,9 +176,9 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method<MTSync, ()> {
*lock = Some(byte_array);
let mret = m.msg.method_return().append1(&format!("Got effect part"));
return Ok(vec![mret]);
Ok(vec![mret])
} else {
return Err(MethodErr::failed("Could not lock daemon for access"));
Err(MethodErr::failed("Could not lock daemon for access"))
}
}
})
@@ -205,8 +196,8 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method<MTSync, ()> {
}
fn dbus_create_tree() -> (Tree<MTSync, ()>, LedMsgType, EffectType) {
let input: LedMsgType = Arc::new(Mutex::new(None));
let effect: EffectType = Arc::new(Mutex::new(None));
let input: LedMsgType = Arc::new(tokio::sync::Mutex::new(None));
let effect: EffectType = Arc::new(tokio::sync::Mutex::new(None));
let factory = Factory::new_sync::<()>();
let tree = factory.tree(()).add(

View File

@@ -78,7 +78,7 @@ pub(crate) fn match_laptop() -> LaptopBase {
/// If using the `keycode` crate to build keyboard input, the report must be prefixed
/// with the report ID (usually `0x01` for the virtual keyboard).
pub(crate) trait Laptop {
fn get_runner(&self) -> Box<dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>>;
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError>;
fn led_endpoint(&self) -> u8;
fn key_endpoint(&self) -> u8;
fn key_filter(&self) -> &[u8];
@@ -104,10 +104,10 @@ pub(super) struct LaptopBase {
}
impl Laptop for LaptopBase {
fn get_runner(&self) -> Box<LaptopRunner> {
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
match self.usb_product {
0x1869 | 0x1866 => self.gx502_runner(),
0x1854 => self.gl753_runner(),
0x1869 | 0x1866 => self.gx502_runner(rogcore, key_buf),
0x1854 => self.gl753_runner(rogcore, key_buf),
_ => panic!("No runner available for this device"),
}
}
@@ -137,109 +137,103 @@ impl Laptop for LaptopBase {
impl LaptopBase {
// 0x1866, per-key LEDs, media-keys split from vendor specific
fn gx502_runner(&self) -> Box<LaptopRunner> {
fn gx502_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
let max_led_bright = self.max_led_bright;
let min_led_bright = self.min_led_bright;
let supported_modes = self.supported_modes.to_owned();
let function = move |rogcore: &mut RogCore, key_buf: [u8; 32]| {
match GX502Keys::from(key_buf[1]) {
GX502Keys::LedBrightUp => {
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
}
GX502Keys::LedBrightDown => {
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
}
GX502Keys::AuraNext => rogcore.aura_mode_next(&supported_modes)?,
GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&supported_modes)?,
GX502Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
} //self.backlight.step_up(),
GX502Keys::ScreenBrightDown => {
rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into())
} //self.backlight.step_down(),
GX502Keys::Sleep => rogcore.suspend_with_systemd(),
GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
GX502Keys::MicToggle => {}
GX502Keys::Fan => {
rogcore.fan_mode_step().unwrap_or_else(|err| {
warn!("Couldn't toggle fan mode: {:?}", err);
});
}
GX502Keys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GX502Keys::TouchPadToggle => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x070;
rogcore.virt_keys().press(key);
}
GX502Keys::Rog => {
//rogcore.aura_effect_init()?;
//rogcore.aura_write_effect(&self.per_key_led)?;
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x68; // XF86Tools? F13
rogcore.virt_keys().press(key);
}
GX502Keys::None => {
if key_buf[0] != 0x5A {
info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]);
rogcore.virt_keys().press(key_buf);
}
match GX502Keys::from(key_buf[1]) {
GX502Keys::LedBrightUp => {
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
}
GX502Keys::LedBrightDown => {
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
}
GX502Keys::AuraNext => rogcore.aura_mode_next(&supported_modes)?,
GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&supported_modes)?,
GX502Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
} //self.backlight.step_up(),
GX502Keys::ScreenBrightDown => {
rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into())
} //self.backlight.step_down(),
GX502Keys::Sleep => rogcore.suspend_with_systemd(),
GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
GX502Keys::MicToggle => {}
GX502Keys::Fan => {
rogcore.fan_mode_step().unwrap_or_else(|err| {
warn!("Couldn't toggle fan mode: {:?}", err);
});
}
GX502Keys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GX502Keys::TouchPadToggle => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x070;
rogcore.virt_keys().press(key);
}
GX502Keys::Rog => {
//rogcore.aura_effect_init()?;
//rogcore.aura_write_effect(&self.per_key_led)?;
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x68; // XF86Tools? F13
rogcore.virt_keys().press(key);
}
GX502Keys::None => {
if key_buf[0] != 0x5A {
info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]);
rogcore.virt_keys().press(key_buf);
}
}
Ok(())
};
Box::new(function)
}
Ok(())
}
// GL753VE == 0x1854, 4 zone keyboard
fn gl753_runner(&self) -> Box<LaptopRunner> {
fn gl753_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
let max_led_bright = self.max_led_bright;
let min_led_bright = self.min_led_bright;
let supported_modes = self.supported_modes.to_owned();
let function = move |rogcore: &mut RogCore, key_buf: [u8; 32]| {
match GL753Keys::from(key_buf[1]) {
GL753Keys::LedBrightUp => {
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
}
GL753Keys::LedBrightDown => {
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
}
GL753Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
}
GL753Keys::ScreenBrightDown => {
rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into())
}
GL753Keys::Sleep => rogcore.suspend_with_systemd(),
GL753Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
GL753Keys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GL753Keys::TouchPadToggle => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x070;
rogcore.virt_keys().press(key);
}
GL753Keys::Rog => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x68; // XF86Tools? F13
rogcore.virt_keys().press(key);
}
GL753Keys::None => {
if key_buf[0] != 0x5A {
info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]);
rogcore.virt_keys().press(key_buf);
}
match GL753Keys::from(key_buf[1]) {
GL753Keys::LedBrightUp => {
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
}
GL753Keys::LedBrightDown => {
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
}
GL753Keys::ScreenBrightUp => {
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
}
GL753Keys::ScreenBrightDown => {
rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into())
}
GL753Keys::Sleep => rogcore.suspend_with_systemd(),
GL753Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
GL753Keys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GL753Keys::TouchPadToggle => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x070;
rogcore.virt_keys().press(key);
}
GL753Keys::Rog => {
let mut key = [0u8; 32];
key[0] = 0x01;
key[3] = 0x68; // XF86Tools? F13
rogcore.virt_keys().press(key);
}
GL753Keys::None => {
if key_buf[0] != 0x5A {
info!("Unmapped key, attempt passthrough: {:X?}", &key_buf[1]);
rogcore.virt_keys().press(key_buf);
}
}
Ok(())
};
Box::new(function)
}
Ok(())
}
}