mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Start bringing up laptop detection
This commit is contained in:
2
.idea/.gitignore
generated
vendored
Normal file
2
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Default ignored files
|
||||
/workspace.xml
|
||||
7
.idea/dictionaries/luke.xml
generated
Normal file
7
.idea/dictionaries/luke.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="luke">
|
||||
<words>
|
||||
<w>hotkey</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/rog-core.iml" filepath="$PROJECT_DIR$/.idea/rog-core.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
24
.idea/rog-core.iml
generated
Normal file
24
.idea/rog-core.iml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-core/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-core/examples" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-core/tests" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-core/benches" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-lib/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-lib/examples" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-lib/tests" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rog-lib/benches" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/rog-core/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/rog-lib/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -4,21 +4,18 @@ use dbus::{
|
||||
tree::{Factory, MethodErr},
|
||||
};
|
||||
use rog_lib::core::RogCore;
|
||||
use rog_lib::hotkeys::*;
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
pub struct Daemon {
|
||||
rogcore: RogCore,
|
||||
hotkeys: Box<dyn Laptop>,
|
||||
}
|
||||
|
||||
impl Daemon {
|
||||
pub fn new() -> Self {
|
||||
Daemon {
|
||||
rogcore: RogCore::new().expect("Could not start RogCore"),
|
||||
hotkeys: Box::new(LaptopGX502GW::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +43,8 @@ impl Daemon {
|
||||
let bytes: Vec<u8> = m.msg.read1()?;
|
||||
let s = format!("Wrote {:x?}", bytes);
|
||||
|
||||
let supported =
|
||||
unsafe { (*daemon.as_ptr()).hotkeys.supported_modes() };
|
||||
let mut daemon = daemon.borrow_mut();
|
||||
match daemon.rogcore.aura_set_and_save(&bytes[..], supported) {
|
||||
match daemon.borrow_mut().rogcore.aura_set_and_save(&bytes[..])
|
||||
{
|
||||
Ok(_) => {
|
||||
let mret = m.msg.method_return().append1(s);
|
||||
Ok(vec![mret])
|
||||
@@ -73,14 +68,17 @@ impl Daemon {
|
||||
connection.process(Duration::from_millis(1))?;
|
||||
// READ KEYBOARD
|
||||
// TODO: this needs to move to a thread, but there is unsafety
|
||||
match daemon.borrow_mut().rogcore.poll_keyboard(&mut key_buf) {
|
||||
let borrowed_daemon = daemon.borrow();
|
||||
match borrowed_daemon.rogcore.poll_keyboard(&mut key_buf) {
|
||||
Ok(read) => {
|
||||
let hotkeys = unsafe { &mut (*daemon.as_ptr()).hotkeys };
|
||||
// Doing this because the Laptop trait takes RogCore, but RogCore contains laptop
|
||||
// and this makes the borrow checker unhappy, but it's safe for this
|
||||
let mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore };
|
||||
let laptop = borrowed_daemon.rogcore.laptop();
|
||||
|
||||
if let Some(_count) = read {
|
||||
if key_buf[0] == hotkeys.hotkey_group_byte() {
|
||||
hotkeys.do_hotkey_action(&mut rogcore, key_buf[1]);
|
||||
if key_buf[0] == laptop.hotkey_group_byte() {
|
||||
laptop.do_hotkey_action(&mut rogcore, key_buf[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// TODO: use /sys/class/dmi/id/board_name to detect model
|
||||
mod daemon;
|
||||
|
||||
use crate::daemon::*;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::aura::BuiltInModeByte;
|
||||
use crate::config::Config;
|
||||
use crate::error::AuraError;
|
||||
use crate::{aura::BuiltInModeByte, config::Config, error::AuraError, laptops::*};
|
||||
use gumdrop::Options;
|
||||
use rusb::{DeviceHandle, Error};
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -57,19 +56,22 @@ pub struct RogCore {
|
||||
handle: DeviceHandle<rusb::GlobalContext>,
|
||||
initialised: bool,
|
||||
led_interface_num: u8,
|
||||
pub config: Config,
|
||||
config: Config,
|
||||
laptop: RefCell<Box<dyn Laptop>>,
|
||||
}
|
||||
|
||||
impl RogCore {
|
||||
pub fn new() -> Result<RogCore, Error> {
|
||||
// TODO: make this more configurable
|
||||
let mut handle = RogCore::get_device(0x0B05, 0x1866)?;
|
||||
handle.set_active_configuration(0).unwrap_or(());
|
||||
// TODO: use /sys/class/dmi/id/board_name to detect model
|
||||
let laptop = LaptopGX502GW::new();
|
||||
|
||||
let config = handle.device().config_descriptor(0).unwrap();
|
||||
let mut dev_handle = RogCore::get_device(laptop.usb_vendor(), laptop.usb_product())?;
|
||||
dev_handle.set_active_configuration(0).unwrap_or(());
|
||||
|
||||
let dev_config = dev_handle.device().config_descriptor(0).unwrap();
|
||||
// Interface with outputs
|
||||
let mut led_interface_num = 0;
|
||||
for iface in config.interfaces() {
|
||||
for iface in dev_config.interfaces() {
|
||||
for desc in iface.descriptors() {
|
||||
for endpoint in desc.endpoint_descriptors() {
|
||||
if endpoint.address() == 0x81 {
|
||||
@@ -80,16 +82,29 @@ impl RogCore {
|
||||
}
|
||||
}
|
||||
|
||||
handle.set_auto_detach_kernel_driver(true).unwrap();
|
||||
dev_handle.set_auto_detach_kernel_driver(true).unwrap();
|
||||
|
||||
Ok(RogCore {
|
||||
handle,
|
||||
handle: dev_handle,
|
||||
initialised: false,
|
||||
led_interface_num,
|
||||
config: Config::default().read(),
|
||||
laptop: RefCell::new(Box::new(laptop)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn laptop(&self) -> Ref<Box<dyn Laptop>> {
|
||||
self.laptop.borrow()
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
pub fn config_mut(&mut self) -> &mut Config {
|
||||
&mut self.config
|
||||
}
|
||||
|
||||
fn get_device(vendor: u16, product: u16) -> Result<DeviceHandle<rusb::GlobalContext>, Error> {
|
||||
for device in rusb::devices().unwrap().iter() {
|
||||
let device_desc = device.device_descriptor().unwrap();
|
||||
@@ -138,13 +153,9 @@ impl RogCore {
|
||||
Ok(bright)
|
||||
}
|
||||
|
||||
pub fn aura_set_and_save(
|
||||
&mut self,
|
||||
bytes: &[u8],
|
||||
supported: &[BuiltInModeByte],
|
||||
) -> Result<(), Error> {
|
||||
pub fn aura_set_and_save(&mut self, bytes: &[u8]) -> Result<(), Error> {
|
||||
let mode = BuiltInModeByte::from(bytes[3]);
|
||||
if supported.contains(&mode) || bytes[1] == 0xba {
|
||||
if self.laptop().supported_modes().contains(&mode) || bytes[1] == 0xba {
|
||||
let messages = [bytes];
|
||||
self.aura_write_messages(&messages)?;
|
||||
self.config.set_field_from(bytes);
|
||||
@@ -163,7 +174,7 @@ impl RogCore {
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn poll_keyboard(&mut self, buf: &mut [u8; 32]) -> Result<Option<usize>, Error> {
|
||||
pub fn poll_keyboard(&self, buf: &mut [u8; 32]) -> Result<Option<usize>, Error> {
|
||||
match self
|
||||
.handle
|
||||
.read_interrupt(0x83, buf, Duration::from_micros(10))
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
use crate::aura::BuiltInModeByte;
|
||||
use crate::core::RogCore;
|
||||
|
||||
// ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="gdbus call
|
||||
// --session --dest org.gnome.SettingsDaemon.Power
|
||||
// --object-path /org/gnome/SettingsDaemon/Power
|
||||
// --method org.freedesktop.DBus.Properties.Set org.gnome.SettingsDaemon.Power.Screen Brightness '<int32 65>'"
|
||||
|
||||
const POWER_BUS_NAME: &'static str = "org.gnome.SettingsDaemon.Power";
|
||||
const POWER_IFACE_NAME: &'static str = "org.gnome.SettingsDaemon.Power.Screen";
|
||||
const POWER_PATH: &'static str = "/org/gnome/SettingsDaemon/Power";
|
||||
|
||||
pub trait Laptop {
|
||||
fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8);
|
||||
fn hotkey_group_byte(&self) -> u8;
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte];
|
||||
fn usb_vendor(&self) -> u16;
|
||||
fn usb_product(&self) -> u16;
|
||||
fn board_name(&self) -> &str;
|
||||
fn prod_family(&self) -> &str;
|
||||
}
|
||||
pub struct LaptopGX502GW {
|
||||
usb_vendor: u16,
|
||||
usb_product: u16,
|
||||
board_name: &'static str,
|
||||
prod_family: &'static str,
|
||||
hotkey_group_byte: u8,
|
||||
min_bright: u8,
|
||||
max_bright: u8,
|
||||
@@ -15,6 +32,10 @@ pub struct LaptopGX502GW {
|
||||
impl LaptopGX502GW {
|
||||
pub fn new() -> Self {
|
||||
LaptopGX502GW {
|
||||
usb_vendor: 0x0B05,
|
||||
usb_product: 0x1866,
|
||||
board_name: "GX502GW",
|
||||
prod_family: "Zephyrus S",
|
||||
hotkey_group_byte: 0x5a,
|
||||
min_bright: 0x00,
|
||||
max_bright: 0x03,
|
||||
@@ -42,43 +63,37 @@ impl Laptop for LaptopGX502GW {
|
||||
println!("ROG!");
|
||||
}
|
||||
GX502GWKeys::LedBrightUp => {
|
||||
let mut bright = rogcore.config.brightness;
|
||||
let mut bright = rogcore.config().brightness;
|
||||
if bright < self.max_bright {
|
||||
bright += 1;
|
||||
rogcore.config.brightness = bright;
|
||||
rogcore.config_mut().brightness = bright;
|
||||
}
|
||||
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
||||
rogcore
|
||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
||||
.unwrap();
|
||||
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||
}
|
||||
GX502GWKeys::LedBrightDown => {
|
||||
let mut bright = rogcore.config.brightness;
|
||||
let mut bright = rogcore.config().brightness;
|
||||
if bright > self.min_bright {
|
||||
bright -= 1;
|
||||
rogcore.config.brightness = bright;
|
||||
rogcore.config_mut().brightness = bright;
|
||||
}
|
||||
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
||||
rogcore
|
||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
||||
.unwrap();
|
||||
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||
}
|
||||
GX502GWKeys::AuraNext => {
|
||||
let mut mode = rogcore.config.current_mode[3] + 1;
|
||||
let mut mode = rogcore.config().current_mode[3] + 1;
|
||||
if mode > 0x0c {
|
||||
mode = 0x00
|
||||
} else if mode == 0x09 {
|
||||
mode = 0x0a
|
||||
}
|
||||
rogcore.config.current_mode[3] = mode;
|
||||
if let Some(bytes) = rogcore.config.get_current() {
|
||||
rogcore
|
||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
||||
.unwrap();
|
||||
rogcore.config_mut().current_mode[3] = mode;
|
||||
if let Some(bytes) = rogcore.config_mut().get_current() {
|
||||
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||
}
|
||||
}
|
||||
GX502GWKeys::AuraPrevious => {
|
||||
let mut mode = rogcore.config.current_mode[3];
|
||||
let mut mode = rogcore.config().current_mode[3];
|
||||
if mode == 0x00 {
|
||||
mode = 0x0c
|
||||
} else if mode - 1 == 0x09 {
|
||||
@@ -86,24 +101,40 @@ impl Laptop for LaptopGX502GW {
|
||||
} else {
|
||||
mode -= 1;
|
||||
}
|
||||
rogcore.config.current_mode[3] = mode;
|
||||
if let Some(bytes) = rogcore.config.get_current() {
|
||||
rogcore
|
||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
||||
.unwrap();
|
||||
rogcore.config.write();
|
||||
rogcore.config_mut().current_mode[3] = mode;
|
||||
if let Some(bytes) = rogcore.config_mut().get_current() {
|
||||
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||
rogcore.config().write();
|
||||
}
|
||||
}
|
||||
GX502GWKeys::ScreenBrightUp => {}
|
||||
_ => {
|
||||
if key_byte != 0 {
|
||||
dbg!(&key_byte);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn hotkey_group_byte(&self) -> u8 {
|
||||
self.hotkey_group_byte
|
||||
}
|
||||
|
||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||
&self.supported_modes
|
||||
}
|
||||
fn usb_vendor(&self) -> u16 {
|
||||
self.usb_vendor
|
||||
}
|
||||
|
||||
fn usb_product(&self) -> u16 {
|
||||
self.usb_product
|
||||
}
|
||||
fn board_name(&self) -> &str {
|
||||
&self.board_name
|
||||
}
|
||||
|
||||
fn prod_family(&self) -> &str {
|
||||
&self.prod_family
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GX502GWKeys {
|
||||
@@ -4,4 +4,4 @@ pub mod cli_options;
|
||||
pub mod config;
|
||||
pub mod core;
|
||||
mod error;
|
||||
pub mod hotkeys;
|
||||
pub mod laptops;
|
||||
|
||||
Reference in New Issue
Block a user