mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Code cleanup
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -660,9 +660,8 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||
|
||||
[[package]]
|
||||
name = "rog-daemon"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"dbus",
|
||||
"dbus-tokio",
|
||||
"env_logger",
|
||||
|
||||
41
Cargo.toml
41
Cargo.toml
@@ -1,7 +1,12 @@
|
||||
[package]
|
||||
name = "rog-daemon"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
repository = "https://github.com/flukejones/rog-core"
|
||||
homepage = "https://github.com/flukejones/rog-core"
|
||||
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
@@ -14,25 +19,47 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
rusb = "^0.5.5"
|
||||
# cli crate
|
||||
|
||||
# cli and logging
|
||||
gumdrop = "^0.8.0"
|
||||
log = "^0.4.8"
|
||||
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"] }
|
||||
|
||||
# serialisation
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
toml = "0.5"
|
||||
# used for backlight control mostly
|
||||
# sysfs-class = "^0.1.2"
|
||||
|
||||
# Device control
|
||||
# sysfs-class = "^0.1.2" # used for backlight control mostly
|
||||
# cpu power management
|
||||
intel-pstate = { git = "https://github.com/flukejones/intel-pstate" }
|
||||
#
|
||||
aho-corasick = "^0.7.10"
|
||||
thiserror = "^1.0.15"
|
||||
# virtualisation of HID, mainly for outputting consumer key codes
|
||||
uhid-virt = "^0.0.4"
|
||||
#keycode = "0.3"
|
||||
|
||||
#
|
||||
thiserror = "^1.0.15"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
debug = false
|
||||
opt-level = 3
|
||||
panic = "abort"
|
||||
|
||||
[profile.dev]
|
||||
lto = true
|
||||
debug = false
|
||||
opt-level = 3
|
||||
#panic = "abort"
|
||||
|
||||
[profile.bench]
|
||||
lto = true
|
||||
debug = false
|
||||
opt-level = 3
|
||||
#panic = "abort"
|
||||
93
src/core.rs
93
src/core.rs
@@ -6,7 +6,6 @@ use crate::{
|
||||
error::AuraError,
|
||||
virt_device::VirtKeys,
|
||||
};
|
||||
use aho_corasick::AhoCorasick;
|
||||
use gumdrop::Options;
|
||||
use log::{debug, error, info, warn};
|
||||
use rusb::DeviceHandle;
|
||||
@@ -50,12 +49,7 @@ pub(crate) struct RogCore {
|
||||
}
|
||||
|
||||
impl RogCore {
|
||||
pub(crate) fn new(
|
||||
vendor: u16,
|
||||
product: u16,
|
||||
led_endpoint: u8,
|
||||
key_endpoint: u8,
|
||||
) -> Result<RogCore, AuraError> {
|
||||
pub(crate) fn new(vendor: u16, product: u16, led_endpoint: u8) -> Result<RogCore, AuraError> {
|
||||
let mut dev_handle = RogCore::get_device(vendor, product)?;
|
||||
dev_handle.set_active_configuration(0).unwrap_or(());
|
||||
|
||||
@@ -65,11 +59,12 @@ impl RogCore {
|
||||
for iface in dev_config.interfaces() {
|
||||
for desc in iface.descriptors() {
|
||||
for endpoint in desc.endpoint_descriptors() {
|
||||
if endpoint.address() == key_endpoint {
|
||||
debug!("INTERVAL: {:?}", endpoint.interval());
|
||||
debug!("MAX: {:?}", endpoint.max_packet_size());
|
||||
debug!("SYNC: {:?}", endpoint.sync_type());
|
||||
debug!("TRANSFER_TYPE: {:?}", endpoint.transfer_type());
|
||||
if endpoint.address() == led_endpoint {
|
||||
info!("INTERVAL: {:?}", endpoint.interval());
|
||||
info!("MAX_PKT_SIZE: {:?}", endpoint.max_packet_size());
|
||||
info!("SYNC: {:?}", endpoint.sync_type());
|
||||
info!("TRANSFER_TYPE: {:?}", endpoint.transfer_type());
|
||||
info!("ENDPOINT: {:X?}", endpoint.address());
|
||||
interface = desc.interface_number();
|
||||
break;
|
||||
}
|
||||
@@ -110,7 +105,7 @@ impl RogCore {
|
||||
};
|
||||
|
||||
let mut file = OpenOptions::new().write(true).open(path)?;
|
||||
file.write(format!("{:?}\n", self.config.fan_mode).as_bytes())?;
|
||||
file.write_all(format!("{:?}\n", self.config.fan_mode).as_bytes())?;
|
||||
self.set_pstate_for_fan_mode(FanLevel::from(self.config.fan_mode))?;
|
||||
info!("Reloaded last saved settings");
|
||||
Ok(())
|
||||
@@ -176,6 +171,26 @@ impl RogCore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write an effect block
|
||||
///
|
||||
/// `aura_effect_init` must be called any effect routine, and called only once.
|
||||
pub async fn async_write_effect(
|
||||
handle: &DeviceHandle<rusb::GlobalContext>,
|
||||
endpoint: u8,
|
||||
effect: Vec<Vec<u8>>,
|
||||
) -> Result<(), AuraError> {
|
||||
for row in effect.iter() {
|
||||
match handle.write_interrupt(endpoint, row, Duration::from_millis(1)) {
|
||||
Ok(_) => {}
|
||||
Err(err) => match err {
|
||||
rusb::Error::Timeout => {}
|
||||
_ => error!("Failed to write LED interrupt: {:?}", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn aura_set_and_save(
|
||||
&mut self,
|
||||
supported_modes: &[BuiltInModeByte],
|
||||
@@ -205,9 +220,10 @@ impl RogCore {
|
||||
if bright < max_bright {
|
||||
bright += 1;
|
||||
self.config.brightness = bright;
|
||||
let bytes = aura_brightness_bytes(bright);
|
||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
||||
info!("Increased LED brightness to {:#?}", bright);
|
||||
}
|
||||
let bytes = aura_brightness_bytes(bright);
|
||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -220,9 +236,10 @@ impl RogCore {
|
||||
if bright > min_bright {
|
||||
bright -= 1;
|
||||
self.config.brightness = bright;
|
||||
let bytes = aura_brightness_bytes(bright);
|
||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
||||
info!("Decreased LED brightness to {:#?}", bright);
|
||||
}
|
||||
let bytes = aura_brightness_bytes(bright);
|
||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -300,7 +317,7 @@ impl RogCore {
|
||||
n = 0;
|
||||
}
|
||||
info!("Fan mode stepped to: {:#?}", FanLevel::from(n));
|
||||
fan_ctrl.write(format!("{:?}\n", n).as_bytes())?;
|
||||
fan_ctrl.write_all(format!("{:?}\n", n).as_bytes())?;
|
||||
self.set_pstate_for_fan_mode(FanLevel::from(n))?;
|
||||
self.config.fan_mode = n;
|
||||
self.config.write();
|
||||
@@ -384,26 +401,26 @@ impl RogCore {
|
||||
match Command::new("rfkill").arg("list").output() {
|
||||
Ok(output) => {
|
||||
if output.status.success() {
|
||||
let patterns = &["yes"];
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
if ac.earliest_find(output.stdout).is_some() {
|
||||
Command::new("rfkill")
|
||||
.arg("unblock")
|
||||
.arg("all")
|
||||
.spawn()
|
||||
.map_or_else(
|
||||
|err| warn!("Could not unblock rf devices: {}", err),
|
||||
|_| {},
|
||||
);
|
||||
} else {
|
||||
let _ = Command::new("rfkill")
|
||||
.arg("block")
|
||||
.arg("all")
|
||||
.spawn()
|
||||
.map_or_else(
|
||||
|err| warn!("Could not block rf devices: {}", err),
|
||||
|_| {},
|
||||
);
|
||||
if let Ok(out) = String::from_utf8(output.stdout) {
|
||||
if out.contains(": yes") {
|
||||
Command::new("rfkill")
|
||||
.arg("unblock")
|
||||
.arg("all")
|
||||
.spawn()
|
||||
.map_or_else(
|
||||
|err| warn!("Could not unblock rf devices: {}", err),
|
||||
|_| {},
|
||||
);
|
||||
} else {
|
||||
Command::new("rfkill")
|
||||
.arg("block")
|
||||
.arg("all")
|
||||
.spawn()
|
||||
.map_or_else(
|
||||
|err| warn!("Could not block rf devices: {}", err),
|
||||
|_| {},
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Could not list rf devices");
|
||||
|
||||
@@ -2,7 +2,10 @@ 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::{core::RogCore, laptops::match_laptop};
|
||||
use crate::{
|
||||
core::RogCore,
|
||||
laptops::{match_laptop, Laptop},
|
||||
};
|
||||
use dbus::{
|
||||
nonblock::Process,
|
||||
tree::{Factory, MTSync, Method, MethodErr, Tree},
|
||||
@@ -87,6 +90,8 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
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();
|
||||
|
||||
@@ -110,7 +115,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
if let Ok(mut lock) = key_buf.try_lock() {
|
||||
if let Some(bytes) = *lock {
|
||||
// this takes at least 10ms per colour block
|
||||
match laptop.run(&mut rogcore, bytes) {
|
||||
match laptop_actions(&mut rogcore, bytes) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
error!("{:?}", err);
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
use crate::aura::BuiltInModeByte;
|
||||
use crate::core::RogCore;
|
||||
use crate::error::AuraError;
|
||||
use crate::virt_device::ConsumerKeys;
|
||||
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||
use super::Laptop;
|
||||
use log::info;
|
||||
|
||||
pub(super) struct LaptopGL753 {
|
||||
usb_vendor: u16,
|
||||
usb_product: u16,
|
||||
board_name: &'static str,
|
||||
prod_family: &'static str,
|
||||
report_filter_bytes: [u8; 2],
|
||||
min_led_bright: u8,
|
||||
max_led_bright: u8,
|
||||
led_endpoint: u8,
|
||||
key_endpoint: u8,
|
||||
supported_modes: [BuiltInModeByte; 3],
|
||||
// backlight: Backlight,
|
||||
}
|
||||
|
||||
impl LaptopGL753 {
|
||||
pub(super) fn new() -> Self {
|
||||
LaptopGL753 {
|
||||
usb_vendor: 0x0B05,
|
||||
usb_product: 0x1854,
|
||||
// from `cat /sys/class/dmi/id/board_name`
|
||||
board_name: "LaptopGL753VE",
|
||||
// from `cat /sys/class/dmi/id/product_family`
|
||||
prod_family: "",
|
||||
report_filter_bytes: [0x5a, 0x02],
|
||||
min_led_bright: 0x00,
|
||||
max_led_bright: 0x03,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
led_endpoint: 0x04,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
key_endpoint: 0x83,
|
||||
supported_modes: [
|
||||
BuiltInModeByte::Single,
|
||||
BuiltInModeByte::Breathing,
|
||||
BuiltInModeByte::Cycle,
|
||||
],
|
||||
// backlight: Backlight::new("intel_backlight").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LaptopGL753 {
|
||||
fn do_keypress_actions(
|
||||
&self,
|
||||
rogcore: &mut RogCore,
|
||||
key_buf: [u8; 32],
|
||||
) -> Result<(), AuraError> {
|
||||
match GL753Keys::from(key_buf[1]) {
|
||||
GL753Keys::LedBrightUp => {
|
||||
rogcore.aura_bright_inc(&self.supported_modes, self.max_led_bright)?;
|
||||
}
|
||||
GL753Keys::LedBrightDown => {
|
||||
rogcore.aura_bright_dec(&self.supported_modes, self.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(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Laptop for LaptopGL753 {
|
||||
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
|
||||
self.do_keypress_actions(rogcore, key_buf)
|
||||
}
|
||||
fn led_endpoint(&self) -> u8 {
|
||||
self.led_endpoint
|
||||
}
|
||||
fn key_endpoint(&self) -> u8 {
|
||||
self.key_endpoint
|
||||
}
|
||||
fn key_filter(&self) -> &[u8] {
|
||||
&self.report_filter_bytes
|
||||
}
|
||||
fn usb_vendor(&self) -> u16 {
|
||||
self.usb_vendor
|
||||
}
|
||||
fn usb_product(&self) -> u16 {
|
||||
self.usb_product
|
||||
}
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||
&self.supported_modes
|
||||
}
|
||||
fn board_name(&self) -> &str {
|
||||
&self.board_name
|
||||
}
|
||||
fn prod_family(&self) -> &str {
|
||||
&self.prod_family
|
||||
}
|
||||
}
|
||||
|
||||
enum GL753Keys {
|
||||
Rog = 0x38,
|
||||
ScreenToggle = 0x35,
|
||||
ScreenBrightDown = 0x10,
|
||||
ScreenBrightUp = 0x20,
|
||||
TouchPadToggle = 0x6b,
|
||||
Sleep = 0x6C,
|
||||
AirplaneMode = 0x88,
|
||||
LedBrightUp = 0xC4,
|
||||
LedBrightDown = 0xC5,
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<u8> for GL753Keys {
|
||||
fn from(byte: u8) -> Self {
|
||||
match byte {
|
||||
0x38 => GL753Keys::Rog,
|
||||
0x35 => GL753Keys::ScreenToggle,
|
||||
0x10 => GL753Keys::ScreenBrightDown,
|
||||
0x20 => GL753Keys::ScreenBrightUp,
|
||||
0x6b => GL753Keys::TouchPadToggle,
|
||||
0x6C => GL753Keys::Sleep,
|
||||
0x88 => GL753Keys::AirplaneMode,
|
||||
0xC4 => GL753Keys::LedBrightUp,
|
||||
0xC5 => GL753Keys::LedBrightDown,
|
||||
_ => GL753Keys::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
use crate::aura::BuiltInModeByte;
|
||||
use crate::core::RogCore;
|
||||
use crate::error::AuraError;
|
||||
use crate::virt_device::ConsumerKeys;
|
||||
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||
use super::Laptop;
|
||||
use log::{info, warn};
|
||||
|
||||
pub(super) struct LaptopGX502 {
|
||||
usb_vendor: u16,
|
||||
usb_product: u16,
|
||||
board_name: &'static str,
|
||||
prod_family: &'static str,
|
||||
report_filter_bytes: [u8; 2],
|
||||
min_led_bright: u8,
|
||||
max_led_bright: u8,
|
||||
led_endpoint: u8,
|
||||
key_endpoint: u8,
|
||||
supported_modes: [BuiltInModeByte; 12],
|
||||
//backlight: Backlight,
|
||||
}
|
||||
|
||||
impl LaptopGX502 {
|
||||
pub(super) fn new() -> Self {
|
||||
// Find backlight
|
||||
LaptopGX502 {
|
||||
usb_vendor: 0x0B05,
|
||||
usb_product: 0x1866,
|
||||
// from `cat /sys/class/dmi/id/board_name`
|
||||
board_name: "GX502GW",
|
||||
// from `cat /sys/class/dmi/id/product_family`
|
||||
prod_family: "Zephyrus S",
|
||||
report_filter_bytes: [0x5a, 0x02],
|
||||
min_led_bright: 0x00,
|
||||
max_led_bright: 0x03,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
led_endpoint: 0x04,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
key_endpoint: 0x83,
|
||||
supported_modes: [
|
||||
BuiltInModeByte::Single,
|
||||
BuiltInModeByte::Breathing,
|
||||
BuiltInModeByte::Cycle,
|
||||
BuiltInModeByte::Rainbow,
|
||||
BuiltInModeByte::Rain,
|
||||
BuiltInModeByte::Random,
|
||||
BuiltInModeByte::Highlight,
|
||||
BuiltInModeByte::Laser,
|
||||
BuiltInModeByte::Ripple,
|
||||
BuiltInModeByte::Pulse,
|
||||
BuiltInModeByte::ThinZoomy,
|
||||
BuiltInModeByte::WideZoomy,
|
||||
],
|
||||
//backlight: Backlight::new("intel_backlight").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LaptopGX502 {
|
||||
fn do_keypress_actions(
|
||||
&self,
|
||||
rogcore: &mut RogCore,
|
||||
key_buf: [u8; 32],
|
||||
) -> Result<(), AuraError> {
|
||||
match GX502Keys::from(key_buf[1]) {
|
||||
GX502Keys::LedBrightUp => {
|
||||
rogcore.aura_bright_inc(&self.supported_modes, self.max_led_bright)?;
|
||||
}
|
||||
GX502Keys::LedBrightDown => {
|
||||
rogcore.aura_bright_dec(&self.supported_modes, self.min_led_bright)?;
|
||||
}
|
||||
GX502Keys::AuraNext => rogcore.aura_mode_next(&self.supported_modes)?,
|
||||
GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&self.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(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Laptop for LaptopGX502 {
|
||||
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
|
||||
self.do_keypress_actions(rogcore, key_buf)
|
||||
}
|
||||
fn led_endpoint(&self) -> u8 {
|
||||
self.led_endpoint
|
||||
}
|
||||
fn key_endpoint(&self) -> u8 {
|
||||
self.key_endpoint
|
||||
}
|
||||
fn key_filter(&self) -> &[u8] {
|
||||
&self.report_filter_bytes
|
||||
}
|
||||
fn usb_vendor(&self) -> u16 {
|
||||
self.usb_vendor
|
||||
}
|
||||
fn usb_product(&self) -> u16 {
|
||||
self.usb_product
|
||||
}
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||
&self.supported_modes
|
||||
}
|
||||
fn board_name(&self) -> &str {
|
||||
&self.board_name
|
||||
}
|
||||
fn prod_family(&self) -> &str {
|
||||
&self.prod_family
|
||||
}
|
||||
}
|
||||
|
||||
enum GX502Keys {
|
||||
Rog = 0x38,
|
||||
MicToggle = 0x7C,
|
||||
Fan = 0xAE,
|
||||
ScreenToggle = 0x35,
|
||||
ScreenBrightDown = 0x10,
|
||||
ScreenBrightUp = 0x20,
|
||||
TouchPadToggle = 0x6b,
|
||||
Sleep = 0x6C,
|
||||
AirplaneMode = 0x88,
|
||||
LedBrightUp = 0xC4,
|
||||
LedBrightDown = 0xC5,
|
||||
AuraPrevious = 0xB2,
|
||||
AuraNext = 0xB3,
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<u8> for GX502Keys {
|
||||
fn from(byte: u8) -> Self {
|
||||
match byte {
|
||||
0x38 => GX502Keys::Rog,
|
||||
0x7C => GX502Keys::MicToggle,
|
||||
0xAE => GX502Keys::Fan,
|
||||
0x35 => GX502Keys::ScreenToggle,
|
||||
0x10 => GX502Keys::ScreenBrightDown,
|
||||
0x20 => GX502Keys::ScreenBrightUp,
|
||||
0x6b => GX502Keys::TouchPadToggle,
|
||||
0x6C => GX502Keys::Sleep,
|
||||
0x88 => GX502Keys::AirplaneMode,
|
||||
0xC4 => GX502Keys::LedBrightUp,
|
||||
0xC5 => GX502Keys::LedBrightDown,
|
||||
0xB2 => GX502Keys::AuraPrevious,
|
||||
0xB3 => GX502Keys::AuraNext,
|
||||
_ => GX502Keys::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,53 +2,68 @@ use crate::aura::BuiltInModeByte;
|
||||
use crate::core::RogCore;
|
||||
use crate::error::AuraError;
|
||||
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||
use log::info;
|
||||
use crate::virt_device::ConsumerKeys;
|
||||
use log::{info, warn};
|
||||
|
||||
// GL753VE == 0x1854, 4 zone keyboard
|
||||
mod gl753;
|
||||
use gl753::LaptopGL753;
|
||||
|
||||
// 0x1866, per-key LEDs, media-keys split from vendor specific
|
||||
mod gx502;
|
||||
use gx502::LaptopGX502;
|
||||
|
||||
pub(crate) fn match_laptop() -> Box<dyn Laptop> {
|
||||
pub(crate) fn match_laptop() -> LaptopBase {
|
||||
for device in rusb::devices().unwrap().iter() {
|
||||
let device_desc = device.device_descriptor().unwrap();
|
||||
if device_desc.vendor_id() == 0x0b05 {
|
||||
match device_desc.product_id() {
|
||||
0x1869 | 0x1866 => {
|
||||
info!("Found GX502 or similar");
|
||||
return Box::new(LaptopGX502::new());
|
||||
return LaptopBase {
|
||||
usb_vendor: 0x0B05,
|
||||
usb_product: 0x1866,
|
||||
report_filter_bytes: vec![0x5a, 0x02],
|
||||
min_led_bright: 0x00,
|
||||
max_led_bright: 0x03,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
led_endpoint: 0x04,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
key_endpoint: 0x83,
|
||||
supported_modes: vec![
|
||||
BuiltInModeByte::Single,
|
||||
BuiltInModeByte::Breathing,
|
||||
BuiltInModeByte::Cycle,
|
||||
BuiltInModeByte::Rainbow,
|
||||
BuiltInModeByte::Rain,
|
||||
BuiltInModeByte::Random,
|
||||
BuiltInModeByte::Highlight,
|
||||
BuiltInModeByte::Laser,
|
||||
BuiltInModeByte::Ripple,
|
||||
BuiltInModeByte::Pulse,
|
||||
BuiltInModeByte::ThinZoomy,
|
||||
BuiltInModeByte::WideZoomy,
|
||||
],
|
||||
//backlight: Backlight::new("intel_backlight").unwrap(),
|
||||
};
|
||||
}
|
||||
0x1854 => {
|
||||
info!("Found GL753 or similar");
|
||||
return Box::new(LaptopGL753::new());
|
||||
return LaptopBase {
|
||||
usb_vendor: 0x0B05,
|
||||
usb_product: 0x1854,
|
||||
report_filter_bytes: vec![0x5a, 0x02],
|
||||
min_led_bright: 0x00,
|
||||
max_led_bright: 0x03,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
led_endpoint: 0x04,
|
||||
//from `lsusb -vd 0b05:1866`
|
||||
key_endpoint: 0x83,
|
||||
supported_modes: vec![
|
||||
BuiltInModeByte::Single,
|
||||
BuiltInModeByte::Breathing,
|
||||
BuiltInModeByte::Cycle,
|
||||
],
|
||||
// backlight: Backlight::new("intel_backlight").unwrap(),
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("could not match laptop");
|
||||
|
||||
// let dmi = sysfs_class::DmiId::default();
|
||||
// let board_name = dmi.board_name().unwrap();
|
||||
// match &board_name.as_str()[..5] {
|
||||
// // TODO: FX503VD - 0x1869,
|
||||
// // These two models seem to have the same characteristics
|
||||
// "GX502" | "GA502" | "GU502" => {
|
||||
// info!("Found GX502 or GA502 series");
|
||||
// Box::new(LaptopGX502::new())
|
||||
// }
|
||||
// // LED should work for this, but unsure of keys
|
||||
// "GL753" => {
|
||||
// info!("Found GL753 series");
|
||||
// Box::new(LaptopGL753::new())
|
||||
// }
|
||||
// _ => {
|
||||
// panic!("could not match laptop");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/// All laptop models should implement this trait. The role of a `Laptop` is to
|
||||
@@ -63,13 +78,235 @@ pub(crate) fn match_laptop() -> Box<dyn Laptop> {
|
||||
/// 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 board_name(&self) -> &str;
|
||||
fn prod_family(&self) -> &str;
|
||||
fn run(&self, core: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError>;
|
||||
fn get_runner(&self) -> Box<dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>>;
|
||||
fn led_endpoint(&self) -> u8;
|
||||
fn key_endpoint(&self) -> u8;
|
||||
fn key_filter(&self) -> &[u8];
|
||||
fn usb_vendor(&self) -> u16;
|
||||
fn usb_product(&self) -> u16;
|
||||
// required for profiles which match more than one laptop
|
||||
fn set_usb_product(&mut self, product: u16);
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte];
|
||||
}
|
||||
|
||||
pub(crate) type LaptopRunner = dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>;
|
||||
|
||||
pub(super) struct LaptopBase {
|
||||
usb_vendor: u16,
|
||||
usb_product: u16,
|
||||
report_filter_bytes: Vec<u8>,
|
||||
min_led_bright: u8,
|
||||
max_led_bright: u8,
|
||||
led_endpoint: u8,
|
||||
key_endpoint: u8,
|
||||
supported_modes: Vec<BuiltInModeByte>,
|
||||
//backlight: Backlight,
|
||||
}
|
||||
|
||||
impl Laptop for LaptopBase {
|
||||
fn get_runner(&self) -> Box<LaptopRunner> {
|
||||
match self.usb_product {
|
||||
0x1869 | 0x1866 => self.gx502_runner(),
|
||||
0x1854 => self.gl753_runner(),
|
||||
_ => panic!("No runner available for this device"),
|
||||
}
|
||||
}
|
||||
|
||||
fn led_endpoint(&self) -> u8 {
|
||||
self.led_endpoint
|
||||
}
|
||||
fn key_endpoint(&self) -> u8 {
|
||||
self.key_endpoint
|
||||
}
|
||||
fn key_filter(&self) -> &[u8] {
|
||||
&self.report_filter_bytes
|
||||
}
|
||||
fn usb_vendor(&self) -> u16 {
|
||||
self.usb_vendor
|
||||
}
|
||||
fn usb_product(&self) -> u16 {
|
||||
self.usb_product
|
||||
}
|
||||
fn set_usb_product(&mut self, product: u16) {
|
||||
self.usb_product = product;
|
||||
}
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||
&self.supported_modes
|
||||
}
|
||||
}
|
||||
|
||||
impl LaptopBase {
|
||||
// 0x1866, per-key LEDs, media-keys split from vendor specific
|
||||
fn gx502_runner(&self) -> Box<LaptopRunner> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
Box::new(function)
|
||||
}
|
||||
|
||||
// GL753VE == 0x1854, 4 zone keyboard
|
||||
fn gl753_runner(&self) -> Box<LaptopRunner> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
Box::new(function)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum GX502Keys {
|
||||
Rog = 0x38,
|
||||
MicToggle = 0x7C,
|
||||
Fan = 0xAE,
|
||||
ScreenToggle = 0x35,
|
||||
ScreenBrightDown = 0x10,
|
||||
ScreenBrightUp = 0x20,
|
||||
TouchPadToggle = 0x6b,
|
||||
Sleep = 0x6C,
|
||||
AirplaneMode = 0x88,
|
||||
LedBrightUp = 0xC4,
|
||||
LedBrightDown = 0xC5,
|
||||
AuraPrevious = 0xB2,
|
||||
AuraNext = 0xB3,
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<u8> for GX502Keys {
|
||||
fn from(byte: u8) -> Self {
|
||||
match byte {
|
||||
0x38 => GX502Keys::Rog,
|
||||
0x7C => GX502Keys::MicToggle,
|
||||
0xAE => GX502Keys::Fan,
|
||||
0x35 => GX502Keys::ScreenToggle,
|
||||
0x10 => GX502Keys::ScreenBrightDown,
|
||||
0x20 => GX502Keys::ScreenBrightUp,
|
||||
0x6b => GX502Keys::TouchPadToggle,
|
||||
0x6C => GX502Keys::Sleep,
|
||||
0x88 => GX502Keys::AirplaneMode,
|
||||
0xC4 => GX502Keys::LedBrightUp,
|
||||
0xC5 => GX502Keys::LedBrightDown,
|
||||
0xB2 => GX502Keys::AuraPrevious,
|
||||
0xB3 => GX502Keys::AuraNext,
|
||||
_ => GX502Keys::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum GL753Keys {
|
||||
Rog = 0x38,
|
||||
ScreenToggle = 0x35,
|
||||
ScreenBrightDown = 0x10,
|
||||
ScreenBrightUp = 0x20,
|
||||
TouchPadToggle = 0x6b,
|
||||
Sleep = 0x6C,
|
||||
AirplaneMode = 0x88,
|
||||
LedBrightUp = 0xC4,
|
||||
LedBrightDown = 0xC5,
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<u8> for GL753Keys {
|
||||
fn from(byte: u8) -> Self {
|
||||
match byte {
|
||||
0x38 => GL753Keys::Rog,
|
||||
0x35 => GL753Keys::ScreenToggle,
|
||||
0x10 => GL753Keys::ScreenBrightDown,
|
||||
0x20 => GL753Keys::ScreenBrightUp,
|
||||
0x6b => GL753Keys::TouchPadToggle,
|
||||
0x6C => GL753Keys::Sleep,
|
||||
0x88 => GL753Keys::AirplaneMode,
|
||||
0xC4 => GL753Keys::LedBrightUp,
|
||||
0xC5 => GL753Keys::LedBrightDown,
|
||||
_ => GL753Keys::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
src/main.rs
40
src/main.rs
@@ -10,7 +10,7 @@ use env_logger::{Builder, Target};
|
||||
use gumdrop::Options;
|
||||
use log::LevelFilter;
|
||||
|
||||
static VERSION: &'static str = "0.6.1";
|
||||
static VERSION: &'static str = "0.7.0";
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
struct CLIStart {
|
||||
@@ -42,7 +42,7 @@ struct LedModeCommand {
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut builder = Builder::from_env("ROGCORE_LOG");
|
||||
let mut builder = Builder::new();
|
||||
builder.target(Target::Stdout);
|
||||
builder.format_timestamp(None);
|
||||
builder.filter(None, LevelFilter::Info).init();
|
||||
@@ -55,32 +55,26 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Version: {}", VERSION);
|
||||
}
|
||||
|
||||
match parsed.command {
|
||||
Some(Command::LedMode(mode)) => {
|
||||
if let Some(command) = mode.command {
|
||||
// Check for special modes here, eg, per-key or multi-zone
|
||||
match command {
|
||||
SetAuraBuiltin::MultiStatic(_) => {
|
||||
let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command);
|
||||
for arr in byte_arr.iter() {
|
||||
dbus_led_builtin_write(arr)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mode = <[u8; LED_MSG_LEN]>::from(command);
|
||||
dbus_led_builtin_write(&mode)?;
|
||||
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
|
||||
match command {
|
||||
SetAuraBuiltin::MultiStatic(_) => {
|
||||
let byte_arr = <[[u8; LED_MSG_LEN]; 4]>::from(command);
|
||||
for arr in byte_arr.iter() {
|
||||
dbus_led_builtin_write(arr)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mode = <[u8; LED_MSG_LEN]>::from(command);
|
||||
dbus_led_builtin_write(&mode)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
match parsed.bright {
|
||||
Some(brightness) => {
|
||||
let bytes = aura_brightness_bytes(brightness.level());
|
||||
dbus_led_builtin_write(&bytes)?;
|
||||
}
|
||||
_ => {}
|
||||
if let Some(brightness) = parsed.bright {
|
||||
let bytes = aura_brightness_bytes(brightness.level());
|
||||
dbus_led_builtin_write(&bytes)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user