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},
|
tree::{Factory, MethodErr},
|
||||||
};
|
};
|
||||||
use rog_lib::core::RogCore;
|
use rog_lib::core::RogCore;
|
||||||
use rog_lib::hotkeys::*;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
pub struct Daemon {
|
pub struct Daemon {
|
||||||
rogcore: RogCore,
|
rogcore: RogCore,
|
||||||
hotkeys: Box<dyn Laptop>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Daemon {
|
impl Daemon {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Daemon {
|
Daemon {
|
||||||
rogcore: RogCore::new().expect("Could not start RogCore"),
|
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 bytes: Vec<u8> = m.msg.read1()?;
|
||||||
let s = format!("Wrote {:x?}", bytes);
|
let s = format!("Wrote {:x?}", bytes);
|
||||||
|
|
||||||
let supported =
|
match daemon.borrow_mut().rogcore.aura_set_and_save(&bytes[..])
|
||||||
unsafe { (*daemon.as_ptr()).hotkeys.supported_modes() };
|
{
|
||||||
let mut daemon = daemon.borrow_mut();
|
|
||||||
match daemon.rogcore.aura_set_and_save(&bytes[..], supported) {
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let mret = m.msg.method_return().append1(s);
|
let mret = m.msg.method_return().append1(s);
|
||||||
Ok(vec![mret])
|
Ok(vec![mret])
|
||||||
@@ -73,14 +68,17 @@ impl Daemon {
|
|||||||
connection.process(Duration::from_millis(1))?;
|
connection.process(Duration::from_millis(1))?;
|
||||||
// READ KEYBOARD
|
// READ KEYBOARD
|
||||||
// TODO: this needs to move to a thread, but there is unsafety
|
// 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) => {
|
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 mut rogcore = unsafe { &mut (*daemon.as_ptr()).rogcore };
|
||||||
|
let laptop = borrowed_daemon.rogcore.laptop();
|
||||||
|
|
||||||
if let Some(_count) = read {
|
if let Some(_count) = read {
|
||||||
if key_buf[0] == hotkeys.hotkey_group_byte() {
|
if key_buf[0] == laptop.hotkey_group_byte() {
|
||||||
hotkeys.do_hotkey_action(&mut rogcore, key_buf[1]);
|
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;
|
mod daemon;
|
||||||
|
|
||||||
use crate::daemon::*;
|
use crate::daemon::*;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use crate::aura::BuiltInModeByte;
|
use crate::{aura::BuiltInModeByte, config::Config, error::AuraError, laptops::*};
|
||||||
use crate::config::Config;
|
|
||||||
use crate::error::AuraError;
|
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use rusb::{DeviceHandle, Error};
|
use rusb::{DeviceHandle, Error};
|
||||||
|
use std::cell::{Ref, RefCell};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -57,19 +56,22 @@ pub struct RogCore {
|
|||||||
handle: DeviceHandle<rusb::GlobalContext>,
|
handle: DeviceHandle<rusb::GlobalContext>,
|
||||||
initialised: bool,
|
initialised: bool,
|
||||||
led_interface_num: u8,
|
led_interface_num: u8,
|
||||||
pub config: Config,
|
config: Config,
|
||||||
|
laptop: RefCell<Box<dyn Laptop>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RogCore {
|
impl RogCore {
|
||||||
pub fn new() -> Result<RogCore, Error> {
|
pub fn new() -> Result<RogCore, Error> {
|
||||||
// TODO: make this more configurable
|
// TODO: use /sys/class/dmi/id/board_name to detect model
|
||||||
let mut handle = RogCore::get_device(0x0B05, 0x1866)?;
|
let laptop = LaptopGX502GW::new();
|
||||||
handle.set_active_configuration(0).unwrap_or(());
|
|
||||||
|
|
||||||
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
|
// Interface with outputs
|
||||||
let mut led_interface_num = 0;
|
let mut led_interface_num = 0;
|
||||||
for iface in config.interfaces() {
|
for iface in dev_config.interfaces() {
|
||||||
for desc in iface.descriptors() {
|
for desc in iface.descriptors() {
|
||||||
for endpoint in desc.endpoint_descriptors() {
|
for endpoint in desc.endpoint_descriptors() {
|
||||||
if endpoint.address() == 0x81 {
|
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 {
|
Ok(RogCore {
|
||||||
handle,
|
handle: dev_handle,
|
||||||
initialised: false,
|
initialised: false,
|
||||||
led_interface_num,
|
led_interface_num,
|
||||||
config: Config::default().read(),
|
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> {
|
fn get_device(vendor: u16, product: u16) -> Result<DeviceHandle<rusb::GlobalContext>, Error> {
|
||||||
for device in rusb::devices().unwrap().iter() {
|
for device in rusb::devices().unwrap().iter() {
|
||||||
let device_desc = device.device_descriptor().unwrap();
|
let device_desc = device.device_descriptor().unwrap();
|
||||||
@@ -138,13 +153,9 @@ impl RogCore {
|
|||||||
Ok(bright)
|
Ok(bright)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aura_set_and_save(
|
pub fn aura_set_and_save(&mut self, bytes: &[u8]) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
bytes: &[u8],
|
|
||||||
supported: &[BuiltInModeByte],
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mode = BuiltInModeByte::from(bytes[3]);
|
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];
|
let messages = [bytes];
|
||||||
self.aura_write_messages(&messages)?;
|
self.aura_write_messages(&messages)?;
|
||||||
self.config.set_field_from(bytes);
|
self.config.set_field_from(bytes);
|
||||||
@@ -163,7 +174,7 @@ impl RogCore {
|
|||||||
// Ok(())
|
// 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
|
match self
|
||||||
.handle
|
.handle
|
||||||
.read_interrupt(0x83, buf, Duration::from_micros(10))
|
.read_interrupt(0x83, buf, Duration::from_micros(10))
|
||||||
|
|||||||
@@ -1,12 +1,29 @@
|
|||||||
use crate::aura::BuiltInModeByte;
|
use crate::aura::BuiltInModeByte;
|
||||||
use crate::core::RogCore;
|
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 {
|
pub trait Laptop {
|
||||||
fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8);
|
fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8);
|
||||||
fn hotkey_group_byte(&self) -> u8;
|
fn hotkey_group_byte(&self) -> u8;
|
||||||
fn supported_modes(&self) -> &[BuiltInModeByte];
|
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 {
|
pub struct LaptopGX502GW {
|
||||||
|
usb_vendor: u16,
|
||||||
|
usb_product: u16,
|
||||||
|
board_name: &'static str,
|
||||||
|
prod_family: &'static str,
|
||||||
hotkey_group_byte: u8,
|
hotkey_group_byte: u8,
|
||||||
min_bright: u8,
|
min_bright: u8,
|
||||||
max_bright: u8,
|
max_bright: u8,
|
||||||
@@ -15,6 +32,10 @@ pub struct LaptopGX502GW {
|
|||||||
impl LaptopGX502GW {
|
impl LaptopGX502GW {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
LaptopGX502GW {
|
LaptopGX502GW {
|
||||||
|
usb_vendor: 0x0B05,
|
||||||
|
usb_product: 0x1866,
|
||||||
|
board_name: "GX502GW",
|
||||||
|
prod_family: "Zephyrus S",
|
||||||
hotkey_group_byte: 0x5a,
|
hotkey_group_byte: 0x5a,
|
||||||
min_bright: 0x00,
|
min_bright: 0x00,
|
||||||
max_bright: 0x03,
|
max_bright: 0x03,
|
||||||
@@ -42,43 +63,37 @@ impl Laptop for LaptopGX502GW {
|
|||||||
println!("ROG!");
|
println!("ROG!");
|
||||||
}
|
}
|
||||||
GX502GWKeys::LedBrightUp => {
|
GX502GWKeys::LedBrightUp => {
|
||||||
let mut bright = rogcore.config.brightness;
|
let mut bright = rogcore.config().brightness;
|
||||||
if bright < self.max_bright {
|
if bright < self.max_bright {
|
||||||
bright += 1;
|
bright += 1;
|
||||||
rogcore.config.brightness = bright;
|
rogcore.config_mut().brightness = bright;
|
||||||
}
|
}
|
||||||
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
||||||
rogcore
|
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
GX502GWKeys::LedBrightDown => {
|
GX502GWKeys::LedBrightDown => {
|
||||||
let mut bright = rogcore.config.brightness;
|
let mut bright = rogcore.config().brightness;
|
||||||
if bright > self.min_bright {
|
if bright > self.min_bright {
|
||||||
bright -= 1;
|
bright -= 1;
|
||||||
rogcore.config.brightness = bright;
|
rogcore.config_mut().brightness = bright;
|
||||||
}
|
}
|
||||||
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
let bytes = RogCore::aura_brightness_bytes(bright).unwrap();
|
||||||
rogcore
|
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
GX502GWKeys::AuraNext => {
|
GX502GWKeys::AuraNext => {
|
||||||
let mut mode = rogcore.config.current_mode[3] + 1;
|
let mut mode = rogcore.config().current_mode[3] + 1;
|
||||||
if mode > 0x0c {
|
if mode > 0x0c {
|
||||||
mode = 0x00
|
mode = 0x00
|
||||||
} else if mode == 0x09 {
|
} else if mode == 0x09 {
|
||||||
mode = 0x0a
|
mode = 0x0a
|
||||||
}
|
}
|
||||||
rogcore.config.current_mode[3] = mode;
|
rogcore.config_mut().current_mode[3] = mode;
|
||||||
if let Some(bytes) = rogcore.config.get_current() {
|
if let Some(bytes) = rogcore.config_mut().get_current() {
|
||||||
rogcore
|
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GX502GWKeys::AuraPrevious => {
|
GX502GWKeys::AuraPrevious => {
|
||||||
let mut mode = rogcore.config.current_mode[3];
|
let mut mode = rogcore.config().current_mode[3];
|
||||||
if mode == 0x00 {
|
if mode == 0x00 {
|
||||||
mode = 0x0c
|
mode = 0x0c
|
||||||
} else if mode - 1 == 0x09 {
|
} else if mode - 1 == 0x09 {
|
||||||
@@ -86,24 +101,40 @@ impl Laptop for LaptopGX502GW {
|
|||||||
} else {
|
} else {
|
||||||
mode -= 1;
|
mode -= 1;
|
||||||
}
|
}
|
||||||
rogcore.config.current_mode[3] = mode;
|
rogcore.config_mut().current_mode[3] = mode;
|
||||||
if let Some(bytes) = rogcore.config.get_current() {
|
if let Some(bytes) = rogcore.config_mut().get_current() {
|
||||||
rogcore
|
rogcore.aura_set_and_save(&bytes).unwrap();
|
||||||
.aura_set_and_save(&bytes, &self.supported_modes)
|
rogcore.config().write();
|
||||||
.unwrap();
|
}
|
||||||
rogcore.config.write();
|
}
|
||||||
|
GX502GWKeys::ScreenBrightUp => {}
|
||||||
|
_ => {
|
||||||
|
if key_byte != 0 {
|
||||||
|
dbg!(&key_byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn hotkey_group_byte(&self) -> u8 {
|
fn hotkey_group_byte(&self) -> u8 {
|
||||||
self.hotkey_group_byte
|
self.hotkey_group_byte
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||||
&self.supported_modes
|
&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 {
|
pub enum GX502GWKeys {
|
||||||
@@ -4,4 +4,4 @@ pub mod cli_options;
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
mod error;
|
mod error;
|
||||||
pub mod hotkeys;
|
pub mod laptops;
|
||||||
|
|||||||
Reference in New Issue
Block a user