Refactor to prepare splitting out aura for CLI effects

This commit is contained in:
Luke
2020-05-01 21:15:50 +12:00
parent 37dd181230
commit 38ab4bc182
6 changed files with 151 additions and 118 deletions

View File

@@ -1,23 +1,7 @@
use daemon::aura::{Key, KeyColourArray};
use daemon::daemon::{DBUS_IFACE, DBUS_NAME, DBUS_PATH};
use dbus::Error as DbusError;
use dbus::{ffidisp::Connection, Message};
use std::{thread, time};
pub fn dbus_led_builtin_write(bytes: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
let bus = Connection::new_system()?;
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
.append1(bytes.to_vec());
let r = bus.send_with_reply_and_block(msg, 5000)?;
if let Some(reply) = r.get1::<&str>() {
println!("Success: {:x?}", reply);
return Ok(());
}
Err(Box::new(DbusError::new_custom("name", "message")))
}
use daemon::aura::{AuraDbusWriter, Key, KeyColourArray};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bus = Connection::new_system()?;
let writer = AuraDbusWriter::new()?;
let mut per_key_led = Vec::new();
let mut key_colours = KeyColourArray::new();
@@ -43,37 +27,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
per_key_led.push(key_colours.clone());
}
// It takes each interrupt at least 1ms. 10ms to write complete block.
let time = time::Duration::from_millis(10); // aim for 100 per second
let row = KeyColourArray::get_init_msg();
let msg =
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?.append1(row);
bus.send(msg).unwrap();
writer.init_effect()?;
loop {
let now = std::time::Instant::now();
thread::sleep(time);
for group in &per_key_led {
let group = group.get();
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")?
.append1(&group[0].to_vec())
.append1(&group[1].to_vec())
.append1(&group[2].to_vec())
.append1(&group[3].to_vec())
.append1(&group[4].to_vec())
.append1(&group[5].to_vec())
.append1(&group[6].to_vec())
.append1(&group[7].to_vec())
.append1(&group[8].to_vec())
.append1(&group[9].to_vec());
bus.send(msg).unwrap();
thread::sleep(time);
writer.write_colour_block(group)?;
}
let after = std::time::Instant::now();
let diff = after.duration_since(now);
dbg!(diff.as_millis());
dbg!(std::time::Instant::now().duration_since(now).as_millis());
//return Ok(());
}
}

View File

@@ -1,5 +1,9 @@
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";
pub const LED_MSG_LEN: usize = 17;
use crate::cli_options::*;
use crate::core::LED_MSG_LEN;
use serde_derive::{Deserialize, Serialize};
/// Writes aout the correct byte string for brightness
@@ -111,8 +115,8 @@ pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
/// ```
///
/// This descriptor is also used for the per-key LED settings
impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
fn from(mode: SetAuraBuiltin) -> Self {
impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] {
fn from(mode: &SetAuraBuiltin) -> Self {
let mut msg = [0u8; LED_MSG_LEN];
msg[0] = 0x5d;
msg[1] = 0xb3;
@@ -178,6 +182,12 @@ impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
}
}
impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] {
fn from(mode: SetAuraBuiltin) -> Self {
<[u8; LED_MSG_LEN]>::from(&mode)
}
}
impl From<SetAuraBuiltin> for [[u8; LED_MSG_LEN]; 4] {
fn from(mode: SetAuraBuiltin) -> Self {
let mut msg = [[0u8; LED_MSG_LEN]; 4];
@@ -627,3 +637,78 @@ pub enum Key {
Right,
RFn,
}
use dbus::{ffidisp::Connection, Message};
use std::error::Error;
use std::{thread, time::Duration};
/// Simplified way to write a effect block
pub struct AuraDbusWriter {
connection: Connection,
block_time: u64,
}
impl AuraDbusWriter {
pub fn new() -> Result<Self, Box<dyn Error>> {
Ok(AuraDbusWriter {
connection: Connection::new_system()?,
block_time: 10,
})
}
/// This method must always be called before the very first write to initialise
/// the keyboard LED EC in the correct mode
pub fn init_effect(&self) -> Result<(), Box<dyn Error>> {
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
.append1(KeyColourArray::get_init_msg());
self.connection.send(msg).unwrap();
Ok(())
}
/// Write a single colour block.
///
/// Intentionally blocks for 10ms after sending to allow the block to
/// be written to the keyboard EC. This should not be async.
pub fn write_colour_block(
&self,
key_colour_array: &KeyColourArray,
) -> Result<(), Box<dyn Error>> {
let group = key_colour_array.get();
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledeffect")?
.append1(&group[0].to_vec())
.append1(&group[1].to_vec())
.append1(&group[2].to_vec())
.append1(&group[3].to_vec())
.append1(&group[4].to_vec())
.append1(&group[5].to_vec())
.append1(&group[6].to_vec())
.append1(&group[7].to_vec())
.append1(&group[8].to_vec())
.append1(&group[9].to_vec());
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_millis(self.block_time));
Ok(())
}
pub fn write_bytes(&self, bytes: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "ledmessage")?
.append1(bytes.to_vec());
let r = self.connection.send_with_reply_and_block(msg, 5000)?;
if let Some(reply) = r.get1::<&str>() {
return Ok(reply.to_owned());
}
Err(Box::new(dbus::Error::new_custom("name", "message")))
}
pub fn write_builtin_mode(
&self,
mode: &SetAuraBuiltin,
) -> Result<String, Box<dyn std::error::Error>> {
let bytes = <[u8; LED_MSG_LEN]>::from(mode);
self.write_bytes(&bytes)
}
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
self.write_bytes(&aura_brightness_bytes(level))
}
}

View File

@@ -24,7 +24,7 @@ impl FromStr for Colour {
}
}
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum Speed {
Low = 0xe1,
Med = 0xeb,
@@ -52,7 +52,7 @@ impl FromStr for Speed {
/// Used for Rainbow mode.
///
/// Enum corresponds to the required integer value
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum Direction {
Right,
Left,

View File

@@ -19,7 +19,6 @@ use std::ptr::NonNull;
use std::str::FromStr;
use std::time::Duration;
pub const LED_MSG_LEN: usize = 17;
static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
@@ -314,6 +313,7 @@ where
/// 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
@@ -524,6 +524,7 @@ impl FromStr for LedBrightness {
}
}
}
#[derive(Debug)]
enum FanLevel {
Normal,

View File

@@ -1,8 +1,4 @@
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::{config::Config, core::*, laptops::match_laptop};
use crate::{aura::*, config::Config, core::*, laptops::match_laptop};
use dbus::{
nonblock::Process,
tree::{Factory, MTSync, Method, MethodErr, Tree},
@@ -83,7 +79,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let led_writer1 = led_writer.clone();
let config1 = config.clone();
// start the keyboard reader and laptop-action loop
tokio::task::spawn(async move {
let key_read_handle = tokio::spawn(async move {
loop {
let data = keyboard_reader.poll_keyboard().await;
if let Some(bytes) = data {
@@ -97,48 +93,54 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
});
// start the LED writer loop
let mut time_mark = Instant::now();
loop {
connection.process_all();
let led_write_handle = tokio::spawn(async move {
let mut time_mark = Instant::now();
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 led_writer = led_writer.lock().await;
let mut config = config.lock().await;
led_writer
.aura_set_and_save(&supported, &bytes, &mut config)
.await
.map_err(|err| warn!("{:?}", err))
.unwrap();
time_mark = Instant::now();
let led_writer = led_writer.clone();
if let Ok(mut lock) = input.try_lock() {
if let Some(bytes) = lock.take() {
let mut led_writer = led_writer.lock().await;
let mut config = config.lock().await;
led_writer
.aura_set_and_save(&supported, &bytes, &mut config)
.await
.map_err(|err| warn!("{:?}", err))
.unwrap();
time_mark = Instant::now();
}
}
// Write a colour block
let led_writer = led_writer.clone();
if let Ok(mut lock) = effect.try_lock() {
// Spawn a writer
if let Some(stuff) = lock.take() {
let led_writer = led_writer.lock().await;
led_writer
.async_write_effect(led_endpoint, stuff)
.await
.map_err(|err| warn!("{:?}", err))
.unwrap();
time_mark = Instant::now();
}
}
let now = Instant::now();
// 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 {
std::thread::sleep(Duration::from_millis(200));
} else if now.duration_since(time_mark).as_millis() > 100 {
std::thread::sleep(Duration::from_millis(50));
}
}
});
// Write a colour block
let led_writer = led_writer.clone();
if let Ok(mut lock) = effect.try_lock() {
// Spawn a writer
if let Some(stuff) = lock.take() {
let led_writer = led_writer.lock().await;
led_writer
.async_write_effect(led_endpoint, stuff)
.await
.map_err(|err| warn!("{:?}", err))
.unwrap();
time_mark = Instant::now();
}
}
let now = Instant::now();
// 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 {
std::thread::sleep(Duration::from_millis(200));
} else if now.duration_since(time_mark).as_millis() > 100 {
std::thread::sleep(Duration::from_millis(50));
}
}
led_write_handle.await?;
key_read_handle.await?;
Ok(())
}
fn dbus_create_ledmsg_method(msg: LedMsgType) -> Method<MTSync, ()> {

View File

@@ -1,11 +1,9 @@
use daemon::{
aura::aura_brightness_bytes,
aura::{AuraDbusWriter, LED_MSG_LEN},
cli_options::SetAuraBuiltin,
core::{LedBrightness, LED_MSG_LEN},
daemon::{start_daemon, DBUS_IFACE, DBUS_NAME, DBUS_PATH},
core::LedBrightness,
daemon::start_daemon,
};
use dbus::Error as DbusError;
use dbus::{ffidisp::Connection, Message};
use env_logger::{Builder, Target};
use gumdrop::Options;
use log::LevelFilter;
@@ -55,6 +53,8 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Version: {}", VERSION);
}
let writer = AuraDbusWriter::new()?;
if let Some(Command::LedMode(mode)) = parsed.command {
if let Some(command) = mode.command {
// Check for special modes here, eg, per-key or multi-zone
@@ -62,32 +62,17 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
SetAuraBuiltin::MultiStatic(_) => {
let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command);
for arr in byte_arr.iter() {
dbus_led_builtin_write(arr)?;
writer.write_bytes(arr)?;
}
}
_ => {
let mode = <[u8; LED_MSG_LEN]>::from(command);
dbus_led_builtin_write(&mode)?;
writer.write_builtin_mode(&command)?;
}
}
}
}
if let Some(brightness) = parsed.bright {
let bytes = aura_brightness_bytes(brightness.level());
dbus_led_builtin_write(&bytes)?;
writer.write_brightness(brightness.level())?;
}
Ok(())
}
pub fn dbus_led_builtin_write(bytes: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
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")?
.append1(bytes.to_vec());
let r = bus.send_with_reply_and_block(msg, 5000)?;
if let Some(reply) = r.get1::<&str>() {
println!("Success: {:x?}", reply);
return Ok(());
}
Err(Box::new(DbusError::new_custom("name", "message")))
}