mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Polling keyboard in daemon. Split into app/lib
This commit is contained in:
47
rog-core/src/config.rs
Normal file
47
rog-core/src/config.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use crate::CONFIG_PATH;
|
||||
use rog_lib::{aura::SetAuraBuiltin, core::LED_MSG_LEN};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
pub(crate) struct Config {
|
||||
pub brightness: u8,
|
||||
pub builtin: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn read(mut self) -> Self {
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&CONFIG_PATH)
|
||||
.expect("config file error");
|
||||
let mut buf = String::new();
|
||||
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||
if l == 0 {
|
||||
// create a default config here
|
||||
let d = SetAuraBuiltin::default();
|
||||
let c = Config {
|
||||
brightness: 1u8,
|
||||
builtin: (<[u8; LED_MSG_LEN]>::from(d)).to_vec(),
|
||||
};
|
||||
let toml = toml::to_string(&c).unwrap();
|
||||
file.write_all(toml.as_bytes())
|
||||
.expect("Writing default config failed");
|
||||
self = c;
|
||||
} else {
|
||||
self = toml::from_str(&buf).unwrap();
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn write(&self) {
|
||||
let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config");
|
||||
let toml = toml::to_string_pretty(self).expect("Parse config to JSON failed");
|
||||
file.write_all(toml.as_bytes())
|
||||
.expect("Saving config failed");
|
||||
}
|
||||
}
|
||||
112
rog-core/src/daemon.rs
Normal file
112
rog-core/src/daemon.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use crate::{config::Config, DBUS_IFACE, DBUS_PATH};
|
||||
use dbus::{
|
||||
blocking::Connection,
|
||||
tree::{Factory, MethodErr},
|
||||
};
|
||||
use rog_lib::core::RogCore;
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
pub struct Daemon {
|
||||
rogcore: RogCore,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Daemon {
|
||||
pub fn new() -> Self {
|
||||
Daemon {
|
||||
rogcore: RogCore::new().expect("Could not start RogCore"),
|
||||
config: Config::default().read(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config(mut self) -> Result<Self, Box<dyn Error>> {
|
||||
self.rogcore.aura_set_mode(&self.config.builtin)?;
|
||||
let bright = RogCore::aura_brightness_bytes(self.config.brightness)?;
|
||||
self.rogcore.aura_set_mode(&bright)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn write_config(&mut self, bytes: &[u8]) {
|
||||
// TODO: create statics out of header bytes
|
||||
if bytes[0] == 0x5a && bytes[1] == 0xba {
|
||||
self.config.brightness = bytes[4];
|
||||
} else if bytes[0] == 0x5d && bytes[1] == 0xb3 {
|
||||
self.config.builtin = bytes.to_vec();
|
||||
}
|
||||
self.config.write();
|
||||
}
|
||||
|
||||
pub fn start() -> Result<(), Box<dyn Error>> {
|
||||
let mut connection = Connection::new_system().expect("Could not set up dbus system");
|
||||
connection.request_name(DBUS_IFACE, false, true, false)?;
|
||||
let factory = Factory::new_fnmut::<()>();
|
||||
|
||||
let daemon = Self::new().load_config()?;
|
||||
let daemon = Rc::new(RefCell::new(daemon));
|
||||
|
||||
// We create a tree with one object path inside and make that path introspectable.
|
||||
let tree = factory.tree(()).add(
|
||||
factory.object_path(DBUS_PATH, ()).introspectable().add(
|
||||
// We add an interface to the object path...
|
||||
factory
|
||||
.interface(DBUS_IFACE, ())
|
||||
// ...and a method inside the interface
|
||||
.add_m(
|
||||
factory
|
||||
.method("ledmessage", (), {
|
||||
let daemon = daemon.clone();
|
||||
move |m| {
|
||||
// Reads the args passed to the method
|
||||
let bytes: Vec<u8> = m.msg.read1()?;
|
||||
let s = format!("Wrote {:x?}", bytes);
|
||||
|
||||
let mut daemon = daemon.borrow_mut();
|
||||
match daemon.rogcore.aura_set_mode(&bytes[..]) {
|
||||
Ok(_) => {
|
||||
daemon.write_config(&bytes);
|
||||
let mret = m.msg.method_return().append1(s);
|
||||
Ok(vec![mret])
|
||||
}
|
||||
Err(err) => Err(MethodErr::failed(&err)),
|
||||
}
|
||||
}
|
||||
})
|
||||
// Input?
|
||||
.outarg::<&str, _>("reply")
|
||||
.inarg::<Vec<u8>, _>("bytearray"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// We add the tree to the connection so that incoming method calls will be handled.
|
||||
tree.start_receive(&connection);
|
||||
|
||||
loop {
|
||||
connection.process(Duration::from_millis(5))?;
|
||||
// READ KEYBOARD
|
||||
// TODO: this needs to move to a thread
|
||||
match daemon.borrow_mut().rogcore.poll_keyboard() {
|
||||
Ok(buf) => {
|
||||
// [5d, 1, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] up
|
||||
// [5d, 1, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] down
|
||||
// [5d, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] left
|
||||
// [5d, 1, 0, 0, 4f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] right
|
||||
|
||||
// [5a, c4, ; 32 bytes long] fn+up
|
||||
// [5a, c5, ; 32 bytes long] fn+down
|
||||
// [5a, b2, ; 32 bytes long] fn+left
|
||||
// [5a, b3, ; 32 bytes long] fn+right
|
||||
|
||||
// To handle keys for aura:
|
||||
// read config + inc/dec brightness byte
|
||||
// write to aura
|
||||
// write config
|
||||
println!("{:x?}", buf);
|
||||
}
|
||||
Err(err) => println!("{:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
rog-core/src/main.rs
Normal file
79
rog-core/src/main.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
// TODO: use /sys/class/dmi/id/board_name to detect model
|
||||
mod config;
|
||||
mod daemon;
|
||||
|
||||
use crate::daemon::*;
|
||||
use dbus::Error as DbusError;
|
||||
use dbus::{ffidisp::Connection, Message};
|
||||
use gumdrop::Options;
|
||||
use rog_lib::aura::*;
|
||||
use rog_lib::core::{LedBrightness, RogCore, LED_MSG_LEN};
|
||||
|
||||
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 static CONFIG_PATH: &'static str = "/etc/rogcore.conf";
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
struct CLIStart {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(help = "start daemon")]
|
||||
daemon: bool,
|
||||
#[options(meta = "VAL", help = "<off, low, med, high>")]
|
||||
bright: Option<LedBrightness>,
|
||||
#[options(command)]
|
||||
command: Option<Command>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
enum Command {
|
||||
#[options(help = "Set the keyboard lighting from built-in modes")]
|
||||
LedMode(LedModeCommand),
|
||||
}
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
struct LedModeCommand {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(command, required)]
|
||||
command: Option<SetAuraBuiltin>,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let parsed = CLIStart::parse_args_default_or_exit();
|
||||
if parsed.daemon {
|
||||
Daemon::start()?;
|
||||
}
|
||||
|
||||
match parsed.command {
|
||||
Some(Command::LedMode(mode)) => {
|
||||
if let Some(command) = mode.command {
|
||||
let mode = <[u8; LED_MSG_LEN]>::from(command);
|
||||
dbus_led_builtin_write(&mode)?;
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
match parsed.bright {
|
||||
Some(brightness) => {
|
||||
let bytes = RogCore::aura_brightness_bytes(brightness.level())?;
|
||||
dbus_led_builtin_write(&bytes)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
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")))
|
||||
}
|
||||
Reference in New Issue
Block a user