Refactor dbus commands and internal data structures

This commit is contained in:
Luke
2020-06-29 15:52:49 +12:00
parent f85c8cbc50
commit 32e9e63809
26 changed files with 720 additions and 653 deletions

View File

@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [Unreleased]
### Changed
- Dbus command LedWriteBytes renamed to SetKeyBacklight
- Dbus signal LedCancelEffect renamed to KeyBacklightChanged
- Dbus command SetKeyBacklight will now take a JSON string instead of an array of bytes
- Config file is now in JSON format, and will store only the LED modes that a laptop
supports rather than the whole set
## [0.12.2] - 2020-29-06 ## [0.12.2] - 2020-29-06
### Changed ### Changed

35
Cargo.lock generated
View File

@@ -419,6 +419,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]] [[package]]
name = "kernel32-sys" name = "kernel32-sys"
version = "0.2.2" version = "0.2.2"
@@ -736,6 +742,7 @@ dependencies = [
"gumdrop", "gumdrop",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json",
"thiserror", "thiserror",
"tinybmp", "tinybmp",
"yansi-term", "yansi-term",
@@ -755,10 +762,10 @@ dependencies = [
"rusb", "rusb",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json",
"sysfs-class", "sysfs-class",
"thiserror", "thiserror",
"tokio", "tokio",
"toml",
"uhid-virt", "uhid-virt",
] ]
@@ -799,6 +806,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "0.1.2" version = "0.1.2"
@@ -837,6 +850,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_json"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "0.1.1" version = "0.1.1"
@@ -1011,15 +1035,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "toml"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "uhid-virt" name = "uhid-virt"
version = "0.0.4" version = "0.0.4"

View File

@@ -54,6 +54,6 @@ vendor:
target/release/$(BIN): $(SRC) target/release/$(BIN): $(SRC)
ifeq ($(VENDORED),1) ifeq ($(VENDORED),1)
tar pxf vendor.tar.xz tar pxf vendor_rog-core_<version>.tar.xz
endif endif
cargo build $(ARGS) cargo build $(ARGS)

View File

@@ -1,32 +1,149 @@
fan_mode = 0 {
brightness = 1 "fan_mode": 1,
current_mode = [93, 179, 0, 0] "bat_charge_limit": 100,
"brightness": 1,
[builtin_modes] "current_mode": 0,
stable = [93, 179, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] "builtin_modes": [
breathe = [93, 179, 0, 1, 255, 0, 0, 235, 0, 0, 255, 0, 0, 0, 0, 0, 0] {
strobe = [93, 179, 0, 2, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] "Stable": {
rainbow = [93, 179, 0, 3, 0, 0, 0, 225, 2, 0, 0, 0, 0, 0, 0, 0, 0] "help": false,
star = [93, 179, 0, 4, 255, 255, 255, 225, 0, 255, 0, 0, 0, 0, 0, 0, 0] "colour": [
rain = [93, 179, 0, 5, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] 255,
highlight = [93, 179, 0, 6, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0,
laser = [93, 179, 0, 7, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0
ripple = [93, 179, 0, 8, 255, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]
pulse = [93, 179, 0, 10, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }
comet = [93, 179, 0, 11, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] },
flash = [93, 179, 0, 12, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] {
multi_static = [[93, 179, 1, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 2, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 3, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 179, 4, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] "Breathe": {
[mode_performance.normal] "help": false,
min_percentage = 0 "colour": [
max_percentage = 100 255,
no_turbo = false 0,
0
[mode_performance.boost] ],
min_percentage = 0 "colour2": [
max_percentage = 100 255,
no_turbo = false 0,
0
[mode_performance.silent] ],
min_percentage = 0 "speed": "Med"
max_percentage = 100 }
no_turbo = true },
{
"Strobe": {
"help": false,
"speed": "Med"
}
},
{
"Rainbow": {
"help": false,
"direction": "Up",
"speed": "Low"
}
},
{
"Star": {
"help": false,
"colour": [
255,
0,
0
],
"colour2": [
255,
0,
0
],
"speed": "Med"
}
},
{
"Rain": {
"help": false,
"speed": "Med"
}
},
{
"Highlight": {
"help": false,
"colour": [
255,
0,
0
],
"speed": "Med"
}
},
{
"Laser": {
"help": false,
"colour": [
255,
0,
0
],
"speed": "Med"
}
},
{
"Ripple": {
"help": false,
"colour": [
255,
0,
0
],
"speed": "Med"
}
},
{
"Pulse": {
"help": false,
"colour": [
255,
0,
0
]
}
},
{
"Comet": {
"help": false,
"colour": [
255,
0,
0
]
}
},
{
"Flash": {
"help": false,
"colour": [
255,
0,
0
]
}
}
],
"mode_performance": {
"normal": {
"min_percentage": 0,
"max_percentage": 100,
"no_turbo": false
},
"boost": {
"min_percentage": 0,
"max_percentage": 100,
"no_turbo": false
},
"silent": {
"min_percentage": 0,
"max_percentage": 80,
"no_turbo": false
}
}
}

View File

@@ -14,6 +14,7 @@ gumdrop = "^0.8.0"
dbus = { version = "^0.8.2" } dbus = { version = "^0.8.2" }
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0"
thiserror = "^1.0.15" thiserror = "^1.0.15"
yansi-term = "0.1.2" yansi-term = "0.1.2"

View File

@@ -1,4 +1,5 @@
use rog_client::{AniMeDbusWriter, AniMeMatrix, AniMePacketType, HEIGHT, WIDTH}; use rog_client::anime_dbus::AniMeDbusWriter;
use rog_client::anime_matrix::{AniMeMatrix, AniMePacketType, HEIGHT, WIDTH};
use tinybmp::{Bmp, Pixel}; use tinybmp::{Bmp, Pixel};
fn main() { fn main() {

View File

@@ -1,4 +1,7 @@
use rog_client::{AuraDbusWriter, GX502Layout, Key, KeyColourArray, KeyLayout}; use rog_client::{
core_dbus::AuraDbusWriter,
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
};
use std::collections::LinkedList; use std::collections::LinkedList;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@@ -1,4 +1,7 @@
use rog_client::{AuraDbusWriter, GX502Layout, KeyColourArray, KeyLayout}; use rog_client::{
core_dbus::AuraDbusWriter,
fancy::{GX502Layout, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusWriter::new()?; let mut writer = AuraDbusWriter::new()?;

View File

@@ -1,4 +1,7 @@
use rog_client::{AuraDbusWriter, GX502Layout, Key, KeyColourArray, KeyLayout}; use rog_client::{
core_dbus::AuraDbusWriter,
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusWriter::new()?; let mut writer = AuraDbusWriter::new()?;

View File

@@ -1,4 +1,7 @@
use rog_client::{AuraDbusWriter, Key, KeyColourArray}; use rog_client::{
core_dbus::AuraDbusWriter,
fancy::{Key, KeyColourArray},
};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusWriter::new()?; let mut writer = AuraDbusWriter::new()?;

View File

@@ -1,4 +1,7 @@
use rog_client::{AuraDbusWriter, GX502Layout, KeyColourArray, KeyLayout}; use rog_client::{
core_dbus::AuraDbusWriter,
fancy::{GX502Layout, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusWriter::new()?; let mut writer = AuraDbusWriter::new()?;

View File

@@ -1,4 +1,5 @@
use super::*; use crate::anime_matrix::AniMePacketType;
use crate::{DBUS_IFACE, DBUS_NAME, DBUS_PATH};
use dbus::channel::Sender; use dbus::channel::Sender;
use dbus::{blocking::Connection, Message}; use dbus::{blocking::Connection, Message};
use std::error::Error; use std::error::Error;

View File

@@ -153,7 +153,7 @@ impl From<AniMeMatrix> for AniMePacketType {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{AniMeMatrix, AniMePacketType}; use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
#[test] #[test]
fn check_data_alignment() { fn check_data_alignment() {

View File

@@ -1,150 +0,0 @@
use super::*;
use dbus::blocking::BlockingSender;
use dbus::channel::Sender;
use dbus::{blocking::Connection, Message};
use std::error::Error;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{thread, time::Duration};
/// Simplified way to write a effect block
pub struct AuraDbusWriter {
connection: Box<Connection>,
block_time: u64,
stop: Arc<AtomicBool>,
}
impl AuraDbusWriter {
#[inline]
pub fn new() -> Result<Self, Box<dyn Error>> {
let connection = Connection::new_system()?;
Ok(AuraDbusWriter {
connection: Box::new(connection),
block_time: 33333,
stop: Arc::new(AtomicBool::new(false)),
})
}
/// This method must always be called before the very first write to initialise
/// the keyboard LED EC in the correct mode
#[inline]
pub fn init_effect(&self) -> Result<String, Box<dyn std::error::Error>> {
let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "LedCancelEffect");
let stopper = self.stop.clone();
self.connection
.add_match(match_rule, move |_: (), _, msg| {
println!("GOT {:?}", msg);
if let Ok(stop) = msg.read1::<bool>() {
if stop {
stopper.store(true, Ordering::Relaxed);
}
}
true
})?;
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteBytes")?
.append1(KeyColourArray::get_init_msg());
let r = self
.connection
.send_with_reply_and_block(msg, Duration::from_millis(5000))?;
if let Some(reply) = r.get1::<&str>() {
return Ok(reply.to_owned());
}
Err(Box::new(dbus::Error::new_custom("name", "message")))
}
/// 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.
#[inline]
pub fn write_colour_block(
&mut self,
key_colour_array: &KeyColourArray,
) -> Result<(), Box<dyn Error>> {
let group = key_colour_array.get();
let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteEffect")?
.append3(&group[0].to_vec(), &group[1].to_vec(), &group[2].to_vec())
.append3(&group[3].to_vec(), &group[4].to_vec(), &group[5].to_vec())
.append3(&group[6].to_vec(), &group[7].to_vec(), &group[8].to_vec())
.append2(&group[9].to_vec(), &group[10].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_micros(self.block_time));
if self.stop.load(Ordering::Relaxed) {
panic!("Got signal to stop!");
}
Ok(())
}
#[inline]
pub fn write_multizone(
&mut self,
group: &[[u8; LED_MSG_LEN]; 4],
) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteMultizone")?
.append1(&group[0].to_vec())
.append1(&group[1].to_vec())
.append1(&group[2].to_vec())
.append1(&group[3].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
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, "LedWriteBytes")?
.append1(bytes.to_vec());
let r = self
.connection
.send_with_reply_and_block(msg, Duration::from_millis(5000))?;
if let Some(reply) = r.get1::<&str>() {
return Ok(reply.to_owned());
}
Err(Box::new(dbus::Error::new_custom("name", "message")))
}
#[inline]
pub fn write_fan_mode(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetFanMode")?
.append1(level);
let r = self
.connection
.send_with_reply_and_block(msg, Duration::from_millis(5000))?;
if let Some(reply) = r.get1::<&str>() {
return Ok(reply.to_owned());
}
Err(Box::new(dbus::Error::new_custom("name", "message")))
}
#[inline]
pub fn write_charge_limit(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
let msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetChargeLimit")?
.append1(level);
let r = self
.connection
.send_with_reply_and_block(msg, Duration::from_millis(5000))?;
if let Some(reply) = r.get1::<&str>() {
return Ok(reply.to_owned());
}
Err(Box::new(dbus::Error::new_custom("name", "message")))
}
#[inline]
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)
}
#[inline]
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
self.write_bytes(&aura_brightness_bytes(level))
}
}

View File

@@ -0,0 +1,107 @@
use crate::cli_options::*;
use serde_derive::{Deserialize, Serialize};
pub const SINGLE: u8 = 0x00;
pub const BREATHING: u8 = 0x01;
pub const STROBE: u8 = 0x02;
pub const RAINBOW: u8 = 0x03;
pub const STAR: u8 = 0x04;
pub const RAIN: u8 = 0x05;
pub const HIGHLIGHT: u8 = 0x06;
pub const LASER: u8 = 0x07;
pub const RIPPLE: u8 = 0x08;
pub const PULSE: u8 = 0x0a;
pub const COMET: u8 = 0x0b;
pub const FLASH: u8 = 0x0c;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum AuraModes {
Stable(SingleColour),
Breathe(TwoColourSpeed),
Strobe(SingleSpeed),
Rainbow(SingleSpeedDirection),
Star(TwoColourSpeed),
Rain(SingleSpeed),
Highlight(SingleColourSpeed),
Laser(SingleColourSpeed),
Ripple(SingleColourSpeed),
Pulse(SingleColour),
Comet(SingleColour),
Flash(SingleColour),
MultiStatic(MultiColour),
LedBrightness(u8),
Aura,
}
impl From<SetAuraBuiltin> for AuraModes {
fn from(mode: SetAuraBuiltin) -> Self {
match mode {
SetAuraBuiltin::Stable(x) => AuraModes::Stable(x),
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x),
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x),
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x),
SetAuraBuiltin::Star(x) => AuraModes::Star(x),
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x),
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x),
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x),
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x),
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x),
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x),
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x),
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x),
}
}
}
impl From<AuraModes> for u8 {
fn from(mode: AuraModes) -> Self {
u8::from(&mode)
}
}
impl From<&mut AuraModes> for u8 {
fn from(mode: &mut AuraModes) -> Self {
u8::from(&*mode)
}
}
impl From<&AuraModes> for u8 {
fn from(mode: &AuraModes) -> Self {
match mode {
AuraModes::Stable(_) => 0x00,
AuraModes::Breathe(_) => 0x01,
AuraModes::Strobe(_) => 0x02,
AuraModes::Rainbow(_) => 0x03,
AuraModes::Star(_) => 0x04,
AuraModes::Rain(_) => 0x05,
AuraModes::Highlight(_) => 0x06,
AuraModes::Laser(_) => 0x07,
AuraModes::Ripple(_) => 0x08,
AuraModes::Pulse(_) => 0x0a,
AuraModes::Comet(_) => 0x0b,
AuraModes::Flash(_) => 0x0c,
AuraModes::MultiStatic(_) => 0x0d,
_ => panic!("Invalid mode"),
}
}
}
impl From<u8> for AuraModes {
fn from(byte: u8) -> Self {
match byte {
SINGLE => AuraModes::Stable(SingleColour::default()),
BREATHING => AuraModes::Breathe(TwoColourSpeed::default()),
STROBE => AuraModes::Strobe(SingleSpeed::default()),
RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()),
STAR => AuraModes::Star(TwoColourSpeed::default()),
RAIN => AuraModes::Rain(SingleSpeed::default()),
HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()),
LASER => AuraModes::Laser(SingleColourSpeed::default()),
RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()),
PULSE => AuraModes::Pulse(SingleColour::default()),
COMET => AuraModes::Comet(SingleColour::default()),
FLASH => AuraModes::Flash(SingleColour::default()),
_ => panic!("Invalid mode byte"),
}
}
}

View File

@@ -1,164 +0,0 @@
use super::cli_options::*;
use super::LED_MSG_LEN;
use serde_derive::{Deserialize, Serialize};
/// Container for the byte strings used in modes. Generally useful for settings
/// and other usecases.
#[derive(Deserialize, Serialize)]
pub struct BuiltInModeBytes {
pub stable: [u8; LED_MSG_LEN],
pub breathe: [u8; LED_MSG_LEN],
pub strobe: [u8; LED_MSG_LEN],
pub rainbow: [u8; LED_MSG_LEN],
pub star: [u8; LED_MSG_LEN],
pub rain: [u8; LED_MSG_LEN],
pub highlight: [u8; LED_MSG_LEN],
pub laser: [u8; LED_MSG_LEN],
pub ripple: [u8; LED_MSG_LEN],
pub pulse: [u8; LED_MSG_LEN],
pub comet: [u8; LED_MSG_LEN],
pub flash: [u8; LED_MSG_LEN],
pub multi_static: [[u8; LED_MSG_LEN]; 4],
}
impl BuiltInModeBytes {
#[inline]
pub fn set_field_from(&mut self, bytes: &[u8]) {
if bytes[0] == 0x5d && bytes[1] == 0xb3 {
let b = BuiltInModeByte::from(bytes[3]);
match b {
BuiltInModeByte::Single => self.stable.copy_from_slice(bytes),
BuiltInModeByte::Breathing => self.breathe.copy_from_slice(bytes),
BuiltInModeByte::Strobe => self.strobe.copy_from_slice(bytes),
BuiltInModeByte::Rainbow => self.rainbow.copy_from_slice(bytes),
BuiltInModeByte::Star => self.star.copy_from_slice(bytes),
BuiltInModeByte::Rain => self.rain.copy_from_slice(bytes),
BuiltInModeByte::Highlight => self.highlight.copy_from_slice(bytes),
BuiltInModeByte::Laser => self.laser.copy_from_slice(bytes),
BuiltInModeByte::Ripple => self.ripple.copy_from_slice(bytes),
BuiltInModeByte::Pulse => self.pulse.copy_from_slice(bytes),
BuiltInModeByte::Comet => self.comet.copy_from_slice(bytes),
BuiltInModeByte::Flash => self.flash.copy_from_slice(bytes),
_ => {}
}
}
}
#[inline]
pub fn get_field_from(&self, byte: u8) -> Option<&[u8]> {
let bytes = match BuiltInModeByte::from(byte) {
BuiltInModeByte::Single => &self.stable,
BuiltInModeByte::Breathing => &self.breathe,
BuiltInModeByte::Strobe => &self.strobe,
BuiltInModeByte::Rainbow => &self.rainbow,
BuiltInModeByte::Star => &self.star,
BuiltInModeByte::Rain => &self.rain,
BuiltInModeByte::Highlight => &self.highlight,
BuiltInModeByte::Laser => &self.laser,
BuiltInModeByte::Ripple => &self.ripple,
BuiltInModeByte::Pulse => &self.pulse,
BuiltInModeByte::Comet => &self.comet,
BuiltInModeByte::Flash => &self.flash,
_ => return None,
};
Some(bytes)
}
}
impl Default for BuiltInModeBytes {
fn default() -> Self {
BuiltInModeBytes {
stable: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Stable(SingleColour::default())),
breathe: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Breathe(TwoColourSpeed::default())),
strobe: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Strobe(SingleSpeed::default())),
rainbow: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rainbow(
SingleSpeedDirection::default(),
)),
star: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Star(TwoColourSpeed::default())),
rain: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Rain(SingleSpeed::default())),
highlight: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Highlight(
SingleColourSpeed::default(),
)),
laser: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Laser(SingleColourSpeed::default())),
ripple: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Ripple(SingleColourSpeed::default())),
pulse: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Pulse(SingleColour::default())),
comet: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Comet(SingleColour::default())),
flash: <[u8; LED_MSG_LEN]>::from(SetAuraBuiltin::Flash(SingleColour::default())),
multi_static: <[[u8; LED_MSG_LEN]; 4]>::from(SetAuraBuiltin::MultiStatic(
MultiColour::default(),
)),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
pub enum BuiltInModeByte {
Single = 0x00,
Breathing = 0x01,
Strobe = 0x02,
Rainbow = 0x03,
Star = 0x04,
Rain = 0x05,
Highlight = 0x06,
Laser = 0x07,
Ripple = 0x08,
Pulse = 0x0a,
Comet = 0x0b,
Flash = 0x0c,
MultiStatic,
None,
}
impl Default for BuiltInModeByte {
#[inline]
fn default() -> Self {
BuiltInModeByte::Single
}
}
impl From<u8> for BuiltInModeByte {
#[inline]
fn from(byte: u8) -> Self {
match byte {
0x00 => Self::Single,
0x01 => Self::Breathing,
0x02 => Self::Strobe,
0x03 => Self::Rainbow,
0x04 => Self::Star,
0x05 => Self::Rain,
0x06 => Self::Highlight,
0x07 => Self::Laser,
0x08 => Self::Ripple,
0x0a => Self::Pulse,
0x0b => Self::Comet,
0x0c => Self::Flash,
_ => Self::None,
}
}
}
impl From<&u8> for BuiltInModeByte {
#[inline]
fn from(byte: &u8) -> Self {
Self::from(*byte)
}
}
impl From<BuiltInModeByte> for u8 {
#[inline]
fn from(byte: BuiltInModeByte) -> Self {
match byte {
BuiltInModeByte::Single => 0x00,
BuiltInModeByte::Breathing => 0x01,
BuiltInModeByte::Strobe => 0x02,
BuiltInModeByte::Rainbow => 0x03,
BuiltInModeByte::Star => 0x04,
BuiltInModeByte::Rain => 0x05,
BuiltInModeByte::Highlight => 0x06,
BuiltInModeByte::Laser => 0x07,
BuiltInModeByte::Ripple => 0x08,
BuiltInModeByte::Pulse => 0x0a,
BuiltInModeByte::Comet => 0x0b,
BuiltInModeByte::Flash => 0x0c,
BuiltInModeByte::MultiStatic => 0x00,
BuiltInModeByte::None => 0xff,
}
}
}

View File

@@ -1,5 +1,6 @@
use crate::error::AuraError; use crate::error::AuraError;
use gumdrop::Options; use gumdrop::Options;
use serde_derive::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use std::str::FromStr; use std::str::FromStr;
@@ -30,7 +31,7 @@ impl FromStr for LedBrightness {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Colour(pub u8, pub u8, pub u8); pub struct Colour(pub u8, pub u8, pub u8);
impl Default for Colour { impl Default for Colour {
fn default() -> Self { fn default() -> Self {
@@ -51,7 +52,7 @@ impl FromStr for Colour {
} }
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum Speed { pub enum Speed {
Low = 0xe1, Low = 0xe1,
Med = 0xeb, Med = 0xeb,
@@ -79,7 +80,7 @@ impl FromStr for Speed {
/// Used for Rainbow mode. /// Used for Rainbow mode.
/// ///
/// Enum corresponds to the required integer value /// Enum corresponds to the required integer value
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum Direction { pub enum Direction {
Right, Right,
Left, Left,
@@ -106,7 +107,7 @@ impl FromStr for Direction {
} }
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct TwoColourSpeed { pub struct TwoColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -118,7 +119,7 @@ pub struct TwoColourSpeed {
pub speed: Speed, pub speed: Speed,
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct SingleSpeed { pub struct SingleSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -126,7 +127,7 @@ pub struct SingleSpeed {
pub speed: Speed, pub speed: Speed,
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct SingleColour { pub struct SingleColour {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -134,7 +135,7 @@ pub struct SingleColour {
pub colour: Colour, pub colour: Colour,
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct MultiColour { pub struct MultiColour {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -148,7 +149,7 @@ pub struct MultiColour {
pub colour4: Colour, pub colour4: Colour,
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct SingleSpeedDirection { pub struct SingleSpeedDirection {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -162,7 +163,7 @@ pub struct SingleSpeedDirection {
pub speed: Speed, pub speed: Speed,
} }
#[derive(Debug, Default, Options)] #[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
pub struct SingleColourSpeed { pub struct SingleColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -172,10 +173,16 @@ pub struct SingleColourSpeed {
pub speed: Speed, pub speed: Speed,
} }
#[derive(Debug, Options, Clone, Deserialize, Serialize, Default)]
pub struct FreeOpts {
#[options(free)]
free: Vec<String>,
}
/// Byte value for setting the built-in mode. /// Byte value for setting the built-in mode.
/// ///
/// Enum corresponds to the required integer value /// Enum corresponds to the required integer value
#[derive(Debug, Options)] #[derive(Debug, Clone, Options, Deserialize, Serialize)]
pub enum SetAuraBuiltin { pub enum SetAuraBuiltin {
#[options(help = "set a single static colour")] #[options(help = "set a single static colour")]
Stable(SingleColour), Stable(SingleColour),

140
rog-client/src/core_dbus.rs Normal file
View File

@@ -0,0 +1,140 @@
use super::*;
use crate::fancy::KeyColourArray;
use dbus::channel::Sender;
use dbus::{blocking::Connection, channel::Token, Message};
use std::error::Error;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{thread, time::Duration};
/// Simplified way to write a effect block
pub struct AuraDbusWriter {
connection: Box<Connection>,
block_time: u64,
stop: Arc<AtomicBool>,
stop_token: Token,
}
impl AuraDbusWriter {
#[inline]
pub fn new() -> Result<Self, Box<dyn Error>> {
let connection = Connection::new_system()?;
let stop = Arc::new(AtomicBool::new(false));
let stopper2 = stop.clone();
let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "KeyBacklightChanged");
let stop_token = connection.add_match(match_rule, move |_: (), _, msg| {
dbg!(&msg);
if let Ok(stop) = msg.read1::<bool>() {
if stop {
stopper2.store(true, Ordering::Relaxed);
}
}
true
})?;
Ok(AuraDbusWriter {
connection: Box::new(connection),
block_time: 33333,
stop,
stop_token,
})
}
/// This method must always be called before the very first write to initialise
/// the keyboard LED EC in the correct mode
#[inline]
pub fn init_effect(&self) -> Result<(), Box<dyn std::error::Error>> {
let mode = AuraModes::Aura;
let mut msg =
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetKeyBacklight")?
.append1(serde_json::to_string(&mode)?);
msg.set_no_reply(true);
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.
#[inline]
pub fn write_colour_block(
&mut self,
key_colour_array: &KeyColourArray,
) -> Result<(), Box<dyn Error>> {
let group = key_colour_array.get();
let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteEffect")?
.append3(&group[0].to_vec(), &group[1].to_vec(), &group[2].to_vec())
.append3(&group[3].to_vec(), &group[4].to_vec(), &group[5].to_vec())
.append3(&group[6].to_vec(), &group[7].to_vec(), &group[8].to_vec())
.append2(&group[9].to_vec(), &group[10].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_micros(self.block_time));
self.connection.process(Duration::from_micros(500))?;
if self.stop.load(Ordering::Relaxed) {
self.connection.remove_match(self.stop_token)?;
println!("Keyboard backlight was changed, exiting");
std::process::exit(1)
}
Ok(())
}
#[inline]
pub fn write_multizone(
&mut self,
group: &[[u8; LED_MSG_LEN]; 4],
) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "LedWriteMultizone")?
.append1(&group[0].to_vec())
.append1(&group[1].to_vec())
.append1(&group[2].to_vec())
.append1(&group[3].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_bytes(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetKeyBacklight")?
.append1(serde_json::to_string(mode)?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_fan_mode(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetFanMode")?
.append1(level);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_charge_limit(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
let mut msg = Message::new_method_call(DBUS_NAME, DBUS_PATH, DBUS_IFACE, "SetChargeLimit")?
.append1(level);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_builtin_mode(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
self.write_bytes(mode)
}
#[inline]
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
self.write_bytes(&AuraModes::LedBrightness(level))?;
Ok(String::new())
}
}

View File

@@ -3,26 +3,25 @@ pub static DBUS_PATH: &str = "/org/rogcore/Daemon";
pub static DBUS_IFACE: &str = "org.rogcore.Daemon"; pub static DBUS_IFACE: &str = "org.rogcore.Daemon";
pub const LED_MSG_LEN: usize = 17; pub const LED_MSG_LEN: usize = 17;
mod builtins; pub mod aura_modes;
pub use builtins::*; use aura_modes::AuraModes;
/// Contains mostly only what is required for parsing CLI options /// Contains mostly only what is required for parsing CLI options
pub mod cli_options; pub mod cli_options;
mod fancy;
mod aura_dbus; /// Enables you to create fancy RGB effects
pub use aura_dbus::*; pub mod fancy;
pub use fancy::*; /// The main dbus group for system controls, e.g, fan control, keyboard LED's
pub mod core_dbus;
mod animatrix_dbus; /// Specific dbus for writing to the AniMe Matrix display (if supported)
pub use animatrix_dbus::*; pub mod anime_dbus;
mod anime_matrix; /// Helper functions for the AniMe display
pub use anime_matrix::*; pub mod anime_matrix;
pub mod error; pub mod error;
use crate::cli_options::*;
/// Writes aout the correct byte string for brightness /// Writes aout the correct byte string for brightness
/// ///
@@ -56,7 +55,7 @@ pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
] ]
} }
/// Parses `SetAuraBuiltin` in to packet data /// Parses `AuraCommands` in to packet data
/// ///
/// Byte structure: /// Byte structure:
/// ///
@@ -133,40 +132,41 @@ pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
/// ``` /// ```
/// ///
/// This descriptor is also used for the per-key LED settings /// This descriptor is also used for the per-key LED settings
impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] { impl From<&AuraModes> for [u8; LED_MSG_LEN] {
fn from(mode: &SetAuraBuiltin) -> Self { fn from(mode: &AuraModes) -> Self {
let mut msg = [0u8; LED_MSG_LEN]; let mut msg = [0u8; LED_MSG_LEN];
msg[0] = 0x5d; msg[0] = 0x5d;
msg[1] = 0xb3; msg[1] = 0xb3;
match mode { match mode {
SetAuraBuiltin::Stable(_) => msg[3] = 0x00, AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
SetAuraBuiltin::Breathe(_) => msg[3] = 0x01, AuraModes::Stable(_) => msg[3] = 0x00,
SetAuraBuiltin::Strobe(_) => msg[3] = 0x02, AuraModes::Breathe(_) => msg[3] = 0x01,
SetAuraBuiltin::Rainbow(_) => msg[3] = 0x03, AuraModes::Strobe(_) => msg[3] = 0x02,
SetAuraBuiltin::Star(_) => msg[3] = 0x04, AuraModes::Rainbow(_) => msg[3] = 0x03,
SetAuraBuiltin::Rain(_) => msg[3] = 0x05, AuraModes::Star(_) => msg[3] = 0x04,
SetAuraBuiltin::Highlight(_) => msg[3] = 0x06, AuraModes::Rain(_) => msg[3] = 0x05,
SetAuraBuiltin::Laser(_) => msg[3] = 0x07, AuraModes::Highlight(_) => msg[3] = 0x06,
SetAuraBuiltin::Ripple(_) => msg[3] = 0x08, AuraModes::Laser(_) => msg[3] = 0x07,
SetAuraBuiltin::Pulse(_) => msg[3] = 0x0a, AuraModes::Ripple(_) => msg[3] = 0x08,
SetAuraBuiltin::Comet(_) => msg[3] = 0x0b, AuraModes::Pulse(_) => msg[3] = 0x0a,
SetAuraBuiltin::Flash(_) => msg[3] = 0x0c, AuraModes::Comet(_) => msg[3] = 0x0b,
AuraModes::Flash(_) => msg[3] = 0x0c,
_ => panic!("Mode not convertable to array"), _ => panic!("Mode not convertable to array"),
} }
match mode { match mode {
SetAuraBuiltin::Rainbow(settings) => { AuraModes::Rainbow(settings) => {
msg[7] = settings.speed as u8; msg[7] = settings.speed as u8;
msg[8] = settings.direction as u8; msg[8] = settings.direction as u8;
} }
SetAuraBuiltin::Star(settings) => { AuraModes::Star(settings) => {
msg[4] = settings.colour.0; msg[4] = settings.colour.0;
msg[5] = settings.colour.1; msg[5] = settings.colour.1;
msg[6] = settings.colour.2; msg[6] = settings.colour.2;
msg[7] = settings.speed as u8; msg[7] = settings.speed as u8;
msg[9] = settings.colour2.2; msg[9] = settings.colour2.2;
} }
SetAuraBuiltin::Breathe(settings) => { AuraModes::Breathe(settings) => {
msg[4] = settings.colour.0; msg[4] = settings.colour.0;
msg[5] = settings.colour.1; msg[5] = settings.colour.1;
msg[6] = settings.colour.2; msg[6] = settings.colour.2;
@@ -175,21 +175,21 @@ impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] {
msg[11] = settings.colour2.1; msg[11] = settings.colour2.1;
msg[12] = settings.colour2.2; msg[12] = settings.colour2.2;
} }
SetAuraBuiltin::Strobe(settings) | SetAuraBuiltin::Rain(settings) => { AuraModes::Strobe(settings) | AuraModes::Rain(settings) => {
msg[7] = settings.speed as u8; msg[7] = settings.speed as u8;
} }
SetAuraBuiltin::Highlight(settings) AuraModes::Highlight(settings)
| SetAuraBuiltin::Laser(settings) | AuraModes::Laser(settings)
| SetAuraBuiltin::Ripple(settings) => { | AuraModes::Ripple(settings) => {
msg[4] = settings.colour.0; msg[4] = settings.colour.0;
msg[5] = settings.colour.1; msg[5] = settings.colour.1;
msg[6] = settings.colour.2; msg[6] = settings.colour.2;
msg[7] = settings.speed as u8; msg[7] = settings.speed as u8;
} }
SetAuraBuiltin::Stable(settings) AuraModes::Stable(settings)
| SetAuraBuiltin::Pulse(settings) | AuraModes::Pulse(settings)
| SetAuraBuiltin::Comet(settings) | AuraModes::Comet(settings)
| SetAuraBuiltin::Flash(settings) => { | AuraModes::Flash(settings) => {
msg[4] = settings.colour.0; msg[4] = settings.colour.0;
msg[5] = settings.colour.1; msg[5] = settings.colour.1;
msg[6] = settings.colour.2; msg[6] = settings.colour.2;
@@ -200,16 +200,16 @@ impl From<&SetAuraBuiltin> for [u8; LED_MSG_LEN] {
} }
} }
impl From<SetAuraBuiltin> for [u8; LED_MSG_LEN] { impl From<AuraModes> for [u8; LED_MSG_LEN] {
#[inline] #[inline]
fn from(mode: SetAuraBuiltin) -> Self { fn from(mode: AuraModes) -> Self {
<[u8; LED_MSG_LEN]>::from(&mode) <[u8; LED_MSG_LEN]>::from(&mode)
} }
} }
impl From<SetAuraBuiltin> for [[u8; LED_MSG_LEN]; 4] { impl From<AuraModes> for [[u8; LED_MSG_LEN]; 4] {
#[inline] #[inline]
fn from(mode: SetAuraBuiltin) -> Self { fn from(mode: AuraModes) -> Self {
let mut msg = [[0u8; LED_MSG_LEN]; 4]; let mut msg = [[0u8; LED_MSG_LEN]; 4];
for (i, row) in msg.iter_mut().enumerate() { for (i, row) in msg.iter_mut().enumerate() {
row[0] = 0x5d; row[0] = 0x5d;
@@ -218,7 +218,7 @@ impl From<SetAuraBuiltin> for [[u8; LED_MSG_LEN]; 4] {
} }
match mode { match mode {
SetAuraBuiltin::MultiStatic(settings) => { AuraModes::MultiStatic(settings) => {
msg[0][4] = settings.colour1.0; msg[0][4] = settings.colour1.0;
msg[0][5] = settings.colour1.1; msg[0][5] = settings.colour1.1;
msg[0][6] = settings.colour1.2; msg[0][6] = settings.colour1.2;

View File

@@ -34,7 +34,7 @@ tokio = { version = "0.2.4", features = ["rt-threaded", "sync"] }
# serialisation # serialisation
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
toml = "0.5" serde_json = "1.0"
# Device control # Device control
sysfs-class = "^0.1.2" # used for backlight control and baord ID sysfs-class = "^0.1.2" # used for backlight control and baord ID

View File

@@ -1,4 +1,4 @@
use rog_client::BuiltInModeBytes; use rog_client::aura_modes::AuraModes;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
@@ -10,15 +10,15 @@ pub struct Config {
pub fan_mode: u8, pub fan_mode: u8,
pub bat_charge_limit: u8, pub bat_charge_limit: u8,
pub brightness: u8, pub brightness: u8,
pub current_mode: [u8; 4], pub current_mode: u8,
pub builtin_modes: BuiltInModeBytes, pub builtin_modes: Vec<AuraModes>,
pub mode_performance: FanModeSettings, pub mode_performance: FanModeSettings,
} }
impl Config { impl Config {
/// `load` will attempt to read the config, but if it is not found it /// `load` will attempt to read the config, but if it is not found it
/// will create a new default config and write that out. /// will create a new default config and write that out.
pub fn load(mut self) -> Self { pub fn load(mut self, supported_led_modes: &[u8]) -> Self {
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
@@ -31,15 +31,20 @@ impl Config {
// create a default config here // create a default config here
let mut c = Config::default(); let mut c = Config::default();
c.bat_charge_limit = 100; c.bat_charge_limit = 100;
c.current_mode[0] = 0x5d; c.current_mode = 0;
c.current_mode[1] = 0xb3;
for n in supported_led_modes {
c.builtin_modes.push(AuraModes::from(*n))
}
dbg!(&c.builtin_modes);
// Should be okay to unwrap this as is since it is a Default // Should be okay to unwrap this as is since it is a Default
let toml = toml::to_string(&c).unwrap(); let json = serde_json::to_string_pretty(&c).unwrap();
file.write_all(toml.as_bytes()) file.write_all(json.as_bytes())
.unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH));
self = c; self = c;
} else { } else {
self = toml::from_str(&buf) self = serde_json::from_str(&buf)
.unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH));
} }
} }
@@ -56,7 +61,7 @@ impl Config {
if l == 0 { if l == 0 {
panic!("Missing {}", CONFIG_PATH); panic!("Missing {}", CONFIG_PATH);
} else { } else {
let x: Config = toml::from_str(&buf) let x: Config = serde_json::from_str(&buf)
.unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH)); .unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH));
*self = x; *self = x;
} }
@@ -65,19 +70,29 @@ impl Config {
pub fn write(&self) { pub fn write(&self) {
let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config"); let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config");
let toml = toml::to_string(self).expect("Parse config to JSON failed"); let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed");
file.write_all(toml.as_bytes()) file.write_all(json.as_bytes())
.expect("Saving config failed"); .expect("Saving config failed");
} }
pub fn set_field_from(&mut self, bytes: &[u8]) { pub fn set_mode_data(&mut self, mode: AuraModes) {
if bytes[0] == 0x5a && bytes[1] == 0xba { let byte: u8 = (&mode).into();
self.brightness = bytes[4]; for (index, n) in self.builtin_modes.iter().enumerate() {
} else if bytes[0] == 0x5d && bytes[1] == 0xb3 { if byte == u8::from(n) {
self.current_mode.copy_from_slice(&bytes[0..4]); self.builtin_modes[index] = mode;
self.builtin_modes.set_field_from(bytes); break;
}
} }
} }
pub fn get_led_mode_data(&self, num: u8) -> Option<&AuraModes> {
for mode in &self.builtin_modes {
if u8::from(mode) == num {
return Some(mode);
}
}
None
}
} }
#[derive(Default, Deserialize, Serialize)] #[derive(Default, Deserialize, Serialize)]

View File

@@ -11,7 +11,7 @@ use dbus::{channel::Sender, nonblock::Process};
use dbus_tokio::connection; use dbus_tokio::connection;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_client::{DBUS_IFACE, DBUS_NAME, DBUS_PATH}; use rog_client::{aura_modes::AuraModes, DBUS_IFACE, DBUS_NAME, DBUS_PATH};
use std::error::Error; use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
@@ -29,7 +29,8 @@ pub(super) type DbusU8Type = Arc<Mutex<Option<u8>>>;
// DBUS processing takes 6ms if not tokiod // DBUS processing takes 6ms if not tokiod
pub async fn start_daemon() -> Result<(), Box<dyn Error>> { pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let laptop = match_laptop(); let laptop = match_laptop();
let mut config = Config::default().load(); let mut config = Config::default().load(laptop.supported_modes());
info!("Config loaded"); info!("Config loaded");
let mut rogcore = RogCore::new( let mut rogcore = RogCore::new(
@@ -59,12 +60,9 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
let mut led_writer = LedWriter::new( let mut led_writer = LedWriter::new(
rogcore.get_raw_device_handle(), rogcore.get_raw_device_handle(),
laptop.led_endpoint(), laptop.led_endpoint(),
(laptop.min_led_bright(), laptop.max_led_bright()),
laptop.supported_modes().to_owned(), laptop.supported_modes().to_owned(),
); );
led_writer led_writer.reload_last_builtin(&mut config).await?;
.do_command(AuraCommand::ReloadLast, &mut config)
.await?;
// Set up the mutexes // Set up the mutexes
let config = Arc::new(Mutex::new(config)); let config = Arc::new(Mutex::new(config));
@@ -148,6 +146,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
}); });
// For helping with processing signals
let connection1 = connection.clone(); let connection1 = connection.clone();
let config1 = config.clone(); let config1 = config.clone();
tokio::spawn(async move { tokio::spawn(async move {
@@ -188,20 +187,39 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
while let Some(command) = aura_command_recv.recv().await { while let Some(command) = aura_command_recv.recv().await {
let mut config = config.lock().await; let mut config = config.lock().await;
match command { match &command {
AuraCommand::WriteEffect(_) | AuraCommand::WriteMultizone(_) => led_writer AuraCommand::WriteEffect(_) | AuraCommand::WriteMultizone(_) => led_writer
.do_command(command, &mut config) .do_command(command, &mut config)
.await .await
.unwrap_or_else(|err| warn!("{:?}", err)), .unwrap_or_else(|err| warn!("{:?}", err)),
_ => { AuraCommand::WriteMode(mode) => match mode {
led_writer AuraModes::Aura => {
.do_command(command, &mut config) led_writer
.await .do_command(command, &mut config)
.unwrap_or_else(|err| warn!("{:?}", err)); .await
connection .unwrap_or_else(|err| warn!("{:?}", err));
.send(effect_cancel_signal.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())) }
.unwrap_or_else(|_| 0); _ => {
} led_writer
.do_command(command, &mut config)
.await
.unwrap_or_else(|err| warn!("{:?}", err));
connection
.send(
effect_cancel_signal
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
.append1(true),
)
.unwrap_or_else(|_| 0);
connection
.send(
effect_cancel_signal
.msg(&DBUS_PATH.into(), &DBUS_IFACE.into())
.append1(false),
)
.unwrap_or_else(|_| 0);
}
},
} }
} }
} }

View File

@@ -1,5 +1,11 @@
use crate::{config::Config, led_control::AuraCommand, rogcore::RogCore}; use crate::{config::Config, led_control::AuraCommand, rogcore::RogCore};
use rog_client::{error::AuraError, BuiltInModeByte}; use rog_client::{
aura_modes::{
AuraModes, BREATHING, COMET, FLASH, HIGHLIGHT, LASER, PULSE, RAIN, RAINBOW, RIPPLE, SINGLE,
STAR, STROBE,
},
error::AuraError,
};
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState}; //use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
use crate::virt_device::ConsumerKeys; use crate::virt_device::ConsumerKeys;
use log::{info, warn}; use log::{info, warn};
@@ -22,11 +28,7 @@ pub(crate) fn match_laptop() -> LaptopBase {
led_endpoint: 0x04, led_endpoint: 0x04,
//from `lsusb -vd 0b05:1866` //from `lsusb -vd 0b05:1866`
key_endpoint: 0x83, key_endpoint: 0x83,
supported_modes: vec![ supported_modes: vec![SINGLE, BREATHING, STROBE],
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
],
support_animatrix: false, support_animatrix: false,
// backlight: Backlight::new("intel_backlight").unwrap(), // backlight: Backlight::new("intel_backlight").unwrap(),
}; };
@@ -71,39 +73,18 @@ fn choose_1866_device(prod: u16) -> LaptopBase {
// GX502, G712 // GX502, G712
} else if board_name.starts_with("GX502") { } else if board_name.starts_with("GX502") {
laptop.supported_modes = vec![ laptop.supported_modes = vec![
BuiltInModeByte::Single, SINGLE, BREATHING, STROBE, RAINBOW, STAR, RAIN, HIGHLIGHT, LASER, RIPPLE, PULSE, COMET,
BuiltInModeByte::Breathing, FLASH,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Star,
BuiltInModeByte::Rain,
BuiltInModeByte::Highlight,
BuiltInModeByte::Laser,
BuiltInModeByte::Ripple,
BuiltInModeByte::Pulse,
BuiltInModeByte::Comet,
BuiltInModeByte::Flash,
]; ];
// GM501 // GM501
} else if board_name.starts_with("GM501") { } else if board_name.starts_with("GM501") {
laptop.supported_modes = vec![ laptop.supported_modes = vec![SINGLE, BREATHING, STROBE, RAINBOW];
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
];
// G531 // G531
} else if board_name.starts_with("GX531") } else if board_name.starts_with("GX531")
|| board_name.starts_with("G531") || board_name.starts_with("G531")
|| board_name.starts_with("G712") || board_name.starts_with("G712")
{ {
laptop.supported_modes = vec![ laptop.supported_modes = vec![SINGLE, BREATHING, STROBE, RAINBOW, PULSE];
BuiltInModeByte::Single,
BuiltInModeByte::Breathing,
BuiltInModeByte::Strobe,
BuiltInModeByte::Rainbow,
BuiltInModeByte::Pulse,
];
} else { } else {
panic!( panic!(
"Unsupported laptop, please request support at\nhttps://github.com/flukejones/rog-core" "Unsupported laptop, please request support at\nhttps://github.com/flukejones/rog-core"
@@ -121,7 +102,7 @@ pub(super) struct LaptopBase {
max_led_bright: u8, max_led_bright: u8,
led_endpoint: u8, led_endpoint: u8,
key_endpoint: u8, key_endpoint: u8,
supported_modes: Vec<BuiltInModeByte>, supported_modes: Vec<u8>,
support_animatrix: bool, support_animatrix: bool,
//backlight: Backlight, //backlight: Backlight,
} }
@@ -137,30 +118,68 @@ impl LaptopBase {
key_buf: [u8; 32], key_buf: [u8; 32],
mut aura_command: mpsc::Sender<AuraCommand>, mut aura_command: mpsc::Sender<AuraCommand>,
) -> Result<(), AuraError> { ) -> Result<(), AuraError> {
let mut config = config.lock().await;
match FnKeys::from(key_buf[1]) { match FnKeys::from(key_buf[1]) {
FnKeys::LedBrightUp => { FnKeys::LedBrightUp => {
let mut bright = config.brightness;
if bright < self.max_led_bright {
bright += 1;
info!("Increased LED brightness to {:#?}", bright);
}
aura_command aura_command
.send(AuraCommand::BrightInc) .send(AuraCommand::WriteMode(AuraModes::LedBrightness(bright)))
.await .await
.unwrap_or_else(|err| warn!("LedBrightUp: {}", err)); .unwrap_or_else(|err| warn!("LedBrightUp: {}", err));
} }
FnKeys::LedBrightDown => { FnKeys::LedBrightDown => {
let mut bright = config.brightness;
if bright > self.min_led_bright {
bright -= 1;
}
aura_command aura_command
.send(AuraCommand::BrightDec) .send(AuraCommand::WriteMode(AuraModes::LedBrightness(bright)))
.await .await
.unwrap_or_else(|err| warn!("LedBrightDown: {}", err)); .unwrap_or_else(|err| warn!("LedBrightDown: {}", err));
} }
FnKeys::AuraNext => { FnKeys::AuraNext => {
aura_command if let Ok(idx) = self
.send(AuraCommand::BuiltinNext) .supported_modes
.await .binary_search(&config.current_mode.into())
.unwrap_or_else(|_| {}); {
let idx_next = if idx < self.supported_modes.len() - 1 {
idx + 1
} else {
0
};
if let Some(data) = config.get_led_mode_data(self.supported_modes[idx_next]) {
aura_command
.send(AuraCommand::WriteMode(data.to_owned()))
.await
.unwrap_or_else(|_| {});
}
} else {
warn!("Tried to step to next LED mode while in non-supported mode");
}
} }
FnKeys::AuraPrevious => { FnKeys::AuraPrevious => {
aura_command if let Ok(idx) = self
.send(AuraCommand::BuiltinPrev) .supported_modes
.await .binary_search(&config.current_mode.into())
.unwrap_or_else(|_| {}); {
let idx_next = if idx > 0 {
idx - 1
} else {
self.supported_modes.len() - 1
};
if let Some(data) = config.get_led_mode_data(self.supported_modes[idx_next]) {
aura_command
.send(AuraCommand::WriteMode(data.to_owned()))
.await
.unwrap_or_else(|_| {});
}
} else {
warn!("Tried to step to next LED mode while in non-supported mode");
}
} }
FnKeys::ScreenBrightUp => rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()), //self.backlight.step_up(), FnKeys::ScreenBrightUp => rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()), //self.backlight.step_up(),
FnKeys::ScreenBrightDn => rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()), FnKeys::ScreenBrightDn => rogcore.virt_keys().press(ConsumerKeys::BacklightDec.into()),
@@ -169,7 +188,6 @@ impl LaptopBase {
FnKeys::AirplaneMode => rogcore.toggle_airplane_mode(), FnKeys::AirplaneMode => rogcore.toggle_airplane_mode(),
FnKeys::MicToggle => {} FnKeys::MicToggle => {}
FnKeys::Fan => { FnKeys::Fan => {
let mut config = config.lock().await;
rogcore.fan_mode_step(&mut config).unwrap_or_else(|err| { rogcore.fan_mode_step(&mut config).unwrap_or_else(|err| {
warn!("Couldn't toggle fan mode: {:?}", err); warn!("Couldn't toggle fan mode: {:?}", err);
}); });
@@ -199,12 +217,6 @@ impl LaptopBase {
Ok(()) Ok(())
} }
pub(super) fn min_led_bright(&self) -> u8 {
self.min_led_bright
}
pub(super) fn max_led_bright(&self) -> u8 {
self.max_led_bright
}
pub(super) fn led_endpoint(&self) -> u8 { pub(super) fn led_endpoint(&self) -> u8 {
self.led_endpoint self.led_endpoint
} }
@@ -220,7 +232,7 @@ 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 supported_modes(&self) -> &[BuiltInModeByte] { pub(super) fn supported_modes(&self) -> &[u8] {
&self.supported_modes &self.supported_modes
} }
pub(super) fn support_animatrix(&self) -> bool { pub(super) fn support_animatrix(&self) -> bool {

View File

@@ -10,7 +10,10 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
use crate::config::Config; use crate::config::Config;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_client::{aura_brightness_bytes, error::AuraError, BuiltInModeByte}; use rog_client::{
aura_brightness_bytes, aura_modes::AuraModes, error::AuraError, fancy::KeyColourArray,
LED_MSG_LEN,
};
use rusb::DeviceHandle; use rusb::DeviceHandle;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr::NonNull; use std::ptr::NonNull;
@@ -18,13 +21,8 @@ use std::time::Duration;
#[derive(Clone)] #[derive(Clone)]
pub enum AuraCommand { pub enum AuraCommand {
BrightInc, WriteMode(AuraModes),
BrightDec,
BuiltinNext,
BuiltinPrev,
WriteBytes(Vec<u8>),
WriteEffect(Vec<Vec<u8>>), WriteEffect(Vec<Vec<u8>>),
ReloadLast,
WriteMultizone(Vec<Vec<u8>>), WriteMultizone(Vec<Vec<u8>>),
} }
@@ -38,8 +36,7 @@ where
C: rusb::UsbContext, C: rusb::UsbContext,
{ {
handle: NonNull<DeviceHandle<C>>, handle: NonNull<DeviceHandle<C>>,
bright_min_max: (u8, u8), supported_modes: Vec<u8>,
supported_modes: Vec<BuiltInModeByte>,
led_endpoint: u8, led_endpoint: u8,
initialised: bool, initialised: bool,
flip_effect_write: bool, flip_effect_write: bool,
@@ -58,13 +55,11 @@ where
pub fn new( pub fn new(
device_handle: NonNull<DeviceHandle<C>>, device_handle: NonNull<DeviceHandle<C>>,
led_endpoint: u8, led_endpoint: u8,
bright_min_max: (u8, u8), supported_modes: Vec<u8>,
supported_modes: Vec<BuiltInModeByte>,
) -> Self { ) -> Self {
LedWriter { LedWriter {
handle: device_handle, handle: device_handle,
led_endpoint, led_endpoint,
bright_min_max,
supported_modes, supported_modes,
initialised: false, initialised: false,
flip_effect_write: false, flip_effect_write: false,
@@ -87,60 +82,9 @@ where
} }
match command { match command {
AuraCommand::BrightInc => { AuraCommand::WriteMode(mode) => self.set_and_save(mode, config).await?,
let mut bright = config.brightness;
if bright < self.bright_min_max.1 {
bright += 1;
config.brightness = bright;
let bytes = aura_brightness_bytes(bright);
self.set_and_save(&bytes, config).await?;
info!("Increased LED brightness to {:#?}", bright);
}
}
AuraCommand::BrightDec => {
let mut bright = config.brightness;
if bright > self.bright_min_max.0 {
bright -= 1;
config.brightness = bright;
let bytes = aura_brightness_bytes(bright);
self.set_and_save(&bytes, config).await?;
info!("Decreased LED brightness to {:#?}", bright);
}
}
AuraCommand::BuiltinNext => {
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
let mode_curr = config.current_mode[3];
if let Ok(idx) = self.supported_modes.binary_search(&mode_curr.into()) {
let idx_next = if idx < self.supported_modes.len() - 1 {
idx + 1
} else {
0
};
self.set_builtin(config, idx_next).await?;
} else {
warn!("Tried to step to next LED mode while in non-supported mode");
self.set_builtin(config, 0).await?;
}
}
AuraCommand::BuiltinPrev => {
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
let mode_curr = config.current_mode[3];
if let Ok(idx) = self.supported_modes.binary_search(&mode_curr.into()) {
let idx_next = if idx > 0 {
idx - 1
} else {
self.supported_modes.len() - 1
};
self.set_builtin(config, idx_next).await?;
} else {
warn!("Tried to step to next LED mode while in non-supported mode");
self.set_builtin(config, 0).await?;
}
}
AuraCommand::WriteBytes(bytes) => self.set_and_save(&bytes, config).await?,
AuraCommand::WriteMultizone(effect) => self.write_multizone(effect).await?, AuraCommand::WriteMultizone(effect) => self.write_multizone(effect).await?,
AuraCommand::WriteEffect(effect) => self.write_effect(effect).await?, AuraCommand::WriteEffect(effect) => self.write_effect(effect).await?,
AuraCommand::ReloadLast => self.reload_last_builtin(&config).await?,
} }
Ok(()) Ok(())
} }
@@ -162,17 +106,6 @@ where
Ok(()) Ok(())
} }
#[inline]
async fn write_array_of_bytes(&self, messages: &[&[u8]]) -> Result<(), AuraError> {
for message in messages {
self.write_bytes(*message).await?;
self.write_bytes(&LED_SET).await?;
}
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY).await?;
Ok(())
}
/// Write an effect block /// Write an effect block
/// ///
/// `aura_effect_init` must be called any effect routine, and called only once. /// `aura_effect_init` must be called any effect routine, and called only once.
@@ -202,34 +135,55 @@ where
} }
/// Used to set a builtin mode and save the settings for it /// Used to set a builtin mode and save the settings for it
///
/// This needs to be universal so that settings applied by dbus stick
#[inline] #[inline]
async fn set_and_save(&self, bytes: &[u8], config: &mut Config) -> Result<(), AuraError> { async fn set_and_save(&self, mode: AuraModes, config: &mut Config) -> Result<(), AuraError> {
let mode = BuiltInModeByte::from(bytes[3]); match mode {
// safety pass-through of possible effect write AuraModes::Aura => {
if bytes[1] == 0xbc { let bytes = KeyColourArray::get_init_msg();
self.write_bytes(bytes).await?; self.write_bytes(&bytes).await?;
return Ok(()); return Ok(());
} else if self.supported_modes.contains(&mode) || bytes[1] == 0xba { }
let messages = [bytes]; AuraModes::LedBrightness(n) => {
self.write_array_of_bytes(&messages).await?; let bytes: [u8; LED_MSG_LEN] = (&mode).into();
config.set_field_from(bytes); self.write_bytes(&bytes).await?;
config.write(); config.brightness = n;
return Ok(()); config.write();
info!("LED brightness set to {:#?}", n);
return Ok(());
}
_ => {
let mode_num: u8 = u8::from(&mode).into();
if self.supported_modes.contains(&mode_num) {
let bytes: [u8; LED_MSG_LEN] = (&mode).into();
self.write_bytes(&bytes).await?;
self.write_bytes(&LED_SET).await?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY).await?;
config.current_mode = mode_num;
config.set_mode_data(mode);
config.write();
info!("Switched LED mode to {:#?}", config.current_mode);
return Ok(());
}
}
} }
warn!("{:?} not supported", mode); warn!("{:?} not supported", mode);
Err(AuraError::NotSupported) Err(AuraError::NotSupported)
} }
#[inline] #[inline]
async fn reload_last_builtin(&self, config: &Config) -> Result<(), AuraError> { pub async fn reload_last_builtin(&self, config: &Config) -> Result<(), AuraError> {
// set current mode (if any) // set current mode (if any)
if self.supported_modes.len() > 1 { if self.supported_modes.len() > 1 {
let mode_curr = config.current_mode[3];
let mode = config let mode = config
.builtin_modes .get_led_mode_data(config.current_mode)
.get_field_from(mode_curr)
.ok_or(AuraError::NotSupported)? .ok_or(AuraError::NotSupported)?
.to_owned(); .to_owned();
let mode: [u8; LED_MSG_LEN] = mode.into();
self.write_bytes(&mode).await?; self.write_bytes(&mode).await?;
info!("Reloaded last used mode"); info!("Reloaded last used mode");
} }
@@ -241,19 +195,4 @@ where
info!("Reloaded last used brightness"); info!("Reloaded last used brightness");
Ok(()) Ok(())
} }
#[inline]
async fn set_builtin(&self, config: &mut Config, index: usize) -> Result<(), AuraError> {
if let Some(mode) = self.supported_modes.get(index) {
let mode_next = config
.builtin_modes
.get_field_from(mode.to_owned().into())
.ok_or(AuraError::NotSupported)?
.to_owned();
self.set_and_save(&mode_next, config).await?;
info!("Switched LED mode to {:#?}", self.supported_modes[index]);
return Ok(());
}
Err(AuraError::NotSupported)
}
} }

View File

@@ -4,8 +4,10 @@ use env_logger::{Builder, Target};
use gumdrop::Options; use gumdrop::Options;
use log::LevelFilter; use log::LevelFilter;
use rog_client::{ use rog_client::{
aura_modes::AuraModes,
cli_options::{LedBrightness, SetAuraBuiltin}, cli_options::{LedBrightness, SetAuraBuiltin},
AuraDbusWriter, LED_MSG_LEN, core_dbus::AuraDbusWriter,
LED_MSG_LEN,
}; };
static VERSION: &str = "0.12.2"; static VERSION: &str = "0.12.2";
@@ -67,33 +69,22 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Check for special modes here, eg, per-key or multi-zone // Check for special modes here, eg, per-key or multi-zone
match command { match command {
SetAuraBuiltin::MultiStatic(_) => { SetAuraBuiltin::MultiStatic(_) => {
let command: AuraModes = command.into();
let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command); let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command);
writer.write_multizone(&byte_arr)?; writer.write_multizone(&byte_arr)?;
} }
_ => match writer.write_builtin_mode(&command) { _ => writer.write_builtin_mode(&command.into())?,
Ok(msg) => println!("Daemon response: {}", msg),
Err(err) => println!("Error: {}", err),
},
} }
} }
} }
if let Some(brightness) = parsed.bright { if let Some(brightness) = parsed.bright {
match writer.write_brightness(brightness.level()) { writer.write_brightness(brightness.level())?;
Ok(msg) => println!("Daemon response: {}", msg),
Err(err) => println!("Error: {}", err),
}
} }
if let Some(fan_level) = parsed.fan_mode { if let Some(fan_level) = parsed.fan_mode {
match writer.write_fan_mode(fan_level.into()) { writer.write_fan_mode(fan_level.into())?;
Ok(msg) => println!("Daemon response: {}", msg),
Err(err) => println!("Error: {}", err),
}
} }
if let Some(charge_limit) = parsed.charge_limit { if let Some(charge_limit) = parsed.charge_limit {
match writer.write_charge_limit(charge_limit) { writer.write_charge_limit(charge_limit)?;
Ok(msg) => println!("Daemon response: {}", msg),
Err(err) => println!("Error: {}", err),
}
} }
Ok(()) Ok(())
} }

View File

@@ -1,7 +1,6 @@
use crate::config::Config; use crate::config::Config;
use crate::daemon::DbusU8Type; use crate::daemon::DbusU8Type;
use crate::led_control::AuraCommand; use crate::led_control::AuraCommand;
use crate::rogcore::FanLevel;
use dbus::tree::{Factory, MTSync, Method, MethodErr, Signal, Tree}; use dbus::tree::{Factory, MTSync, Method, MethodErr, Signal, Tree};
use log::warn; use log::warn;
use rog_client::{DBUS_IFACE, DBUS_PATH}; use rog_client::{DBUS_IFACE, DBUS_PATH};
@@ -15,25 +14,26 @@ pub(super) fn dbus_set_ledmsg(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSy
let factory = Factory::new_sync::<()>(); let factory = Factory::new_sync::<()>();
factory factory
// method for ledmessage // method for ledmessage
.method("LedWriteBytes", (), { .method("SetKeyBacklight", (), {
move |m| { move |m| {
let bytes: Vec<u8> = m.msg.read1()?; let json: &str = m.msg.read1()?;
if let Ok(mut lock) = sender.try_lock() { if let Ok(mut lock) = sender.try_lock() {
let command = AuraCommand::WriteBytes(bytes.to_vec()); if let Ok(data) = serde_json::from_str(json) {
lock.try_send(command) let command = AuraCommand::WriteMode(data);
.unwrap_or_else(|err| warn!("LedWriteBytes over mpsc failed: {}", err)); lock.try_send(command).unwrap_or_else(|err| {
let mret = m warn!("SetKeyBacklight over mpsc failed: {}", err)
.msg });
.method_return() } else {
.append1(&format!("Wrote {:x?}", bytes)); warn!("SetKeyBacklight could not deserialise");
Ok(vec![mret]) }
Ok(vec![])
} else { } else {
Err(MethodErr::failed("Could not lock daemon for access")) Err(MethodErr::failed("Could not lock daemon for access"))
} }
} }
}) })
.outarg::<&str, _>("reply") .inarg::<&str, _>("json")
.inarg::<Vec<u8>, _>("bytearray") .annotate("org.freedesktop.DBus.Method.NoReply", "true")
} }
pub(super) fn dbus_set_ledmultizone(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> { pub(super) fn dbus_set_ledmultizone(sender: Mutex<Sender<AuraCommand>>) -> Method<MTSync, ()> {
@@ -145,18 +145,14 @@ pub(super) fn dbus_set_fan_mode(data: DbusU8Type) -> Method<MTSync, ()> {
let mut iter = m.msg.iter_init(); let mut iter = m.msg.iter_init();
let byte: u8 = iter.read()?; let byte: u8 = iter.read()?;
*lock = Some(byte); *lock = Some(byte);
let mret = m Ok(vec![])
.msg
.method_return()
.append1(format!("Fan level set to {:?}", FanLevel::from(byte)));
Ok(vec![mret])
} else { } else {
Err(MethodErr::failed("Could not lock daemon for access")) Err(MethodErr::failed("Could not lock daemon for access"))
} }
} }
}) })
.outarg::<&str, _>("reply")
.inarg::<u8, _>("byte") .inarg::<u8, _>("byte")
.annotate("org.freedesktop.DBus.Method.NoReply", "true")
} }
pub(super) fn dbus_get_fan_mode(config: Arc<Mutex<Config>>) -> Method<MTSync, ()> { pub(super) fn dbus_get_fan_mode(config: Arc<Mutex<Config>>) -> Method<MTSync, ()> {
@@ -201,18 +197,14 @@ pub(super) fn dbus_set_charge_limit(data: DbusU8Type) -> Method<MTSync, ()> {
let mut iter = m.msg.iter_init(); let mut iter = m.msg.iter_init();
let byte: u8 = iter.read()?; let byte: u8 = iter.read()?;
*lock = Some(byte); *lock = Some(byte);
let mret = m Ok(vec![])
.msg
.method_return()
.append1(format!("Battery charge limit set to {}", byte));
Ok(vec![mret])
} else { } else {
Err(MethodErr::failed("Could not lock daemon for access")) Err(MethodErr::failed("Could not lock daemon for access"))
} }
} }
}) })
.outarg::<&str, _>("reply")
.inarg::<u8, _>("byte") .inarg::<u8, _>("byte")
.annotate("org.freedesktop.DBus.Method.NoReply", "true")
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@@ -236,7 +228,11 @@ pub(super) fn dbus_create_tree(
let factory = Factory::new_sync::<()>(); let factory = Factory::new_sync::<()>();
let effect_cancel_sig = Arc::new(factory.signal("LedCancelEffect", ())); let builtin_mode_sig = Arc::new(
factory
.signal("KeyBacklightChanged", ())
.sarg::<bool, _>("value"),
);
let fanmode_changed_sig = Arc::new(factory.signal("FanModeChanged", ()).sarg::<u8, _>("value")); let fanmode_changed_sig = Arc::new(factory.signal("FanModeChanged", ()).sarg::<u8, _>("value"));
let chrg_limit_changed_sig = Arc::new( let chrg_limit_changed_sig = Arc::new(
factory factory
@@ -258,7 +254,7 @@ pub(super) fn dbus_create_tree(
.add_m(dbus_set_charge_limit(charge_limit.clone())) .add_m(dbus_set_charge_limit(charge_limit.clone()))
.add_m(dbus_get_fan_mode(config.clone())) .add_m(dbus_get_fan_mode(config.clone()))
.add_m(dbus_get_charge_limit(config)) .add_m(dbus_get_charge_limit(config))
.add_s(effect_cancel_sig.clone()) .add_s(builtin_mode_sig.clone())
.add_s(fanmode_changed_sig.clone()) .add_s(fanmode_changed_sig.clone())
.add_s(chrg_limit_changed_sig.clone()), .add_s(chrg_limit_changed_sig.clone()),
), ),
@@ -271,7 +267,7 @@ pub(super) fn dbus_create_tree(
animatrix_recv, animatrix_recv,
fan_mode, fan_mode,
charge_limit, charge_limit,
effect_cancel_sig, builtin_mode_sig,
fanmode_changed_sig, fanmode_changed_sig,
chrg_limit_changed_sig, chrg_limit_changed_sig,
) )