Much better handling of keys

This commit is contained in:
Luke
2020-04-20 22:03:10 +12:00
parent 21f89807d0
commit d6f88e56aa
5 changed files with 83 additions and 57 deletions

2
Cargo.lock generated
View File

@@ -626,6 +626,8 @@ dependencies = [
[[package]] [[package]]
name = "uhid-virt" name = "uhid-virt"
version = "0.0.2" version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c6ade685b787ea3b980b5a47bdc54ef3943adbd41a72ea5352a12a0dc9d821"
dependencies = [ dependencies = [
"enumflags2", "enumflags2",
"libc", "libc",

View File

@@ -4,19 +4,25 @@ use dbus::{
tree::{Factory, MethodErr}, tree::{Factory, MethodErr},
}; };
use log::{error, info, warn}; use log::{error, info, warn};
use rog_lib::core::RogCore; use rog_lib::{
core::RogCore,
laptops::{match_laptop, Laptop},
};
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,
laptop: Box<dyn Laptop>,
} }
impl Daemon { impl Daemon {
pub fn new() -> Self { pub fn new() -> Self {
let laptop = match_laptop();
Daemon { Daemon {
rogcore: RogCore::new().map_or_else( rogcore: RogCore::new(&*laptop).map_or_else(
|err| { |err| {
error!("{}", err); error!("{}", err);
panic!("{}", err); panic!("{}", err);
@@ -26,6 +32,7 @@ impl Daemon {
daemon daemon
}, },
), ),
laptop,
} }
} }
@@ -60,8 +67,12 @@ impl Daemon {
move |m| { move |m| {
// Reads the args passed to the method // Reads the args passed to the method
let bytes: Vec<u8> = m.msg.read1()?; let bytes: Vec<u8> = m.msg.read1()?;
let supported =
match daemon.borrow_mut().rogcore.aura_set_and_save(&bytes[..]) Vec::from(daemon.borrow().laptop.supported_modes());
match daemon
.borrow_mut()
.rogcore
.aura_set_and_save(&supported, &bytes[..])
{ {
Ok(_) => { Ok(_) => {
let s = format!("Wrote {:x?}", bytes); let s = format!("Wrote {:x?}", bytes);
@@ -86,6 +97,7 @@ impl Daemon {
tree.start_receive(&connection); tree.start_receive(&connection);
let mut key_buf = [0u8; 32]; let mut key_buf = [0u8; 32];
let hotkey_group_bytes = Vec::from(daemon.borrow().laptop.hotkey_group_bytes());
loop { loop {
connection connection
.process(Duration::from_millis(10)) .process(Duration::from_millis(10))
@@ -96,15 +108,18 @@ impl Daemon {
// 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
let mut borrowed_daemon = daemon.borrow_mut(); let mut borrowed_daemon = daemon.borrow_mut();
match borrowed_daemon.rogcore.poll_keyboard(&mut key_buf) { match borrowed_daemon
.rogcore
.poll_keyboard(&hotkey_group_bytes, &mut key_buf)
{
Ok(read) => { Ok(read) => {
// Doing this because the Laptop trait takes RogCore, but RogCore contains laptop // 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 // 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 {
laptop borrowed_daemon
.laptop
.do_hotkey_action(&mut rogcore, key_buf[1]) .do_hotkey_action(&mut rogcore, key_buf[1])
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
warn!("{:?}", err); warn!("{:?}", err);

View File

@@ -14,4 +14,4 @@ sysfs-class = "0.1.2"
aho-corasick = "0.7" aho-corasick = "0.7"
thiserror = "1.0.15" thiserror = "1.0.15"
log = "0.4" log = "0.4"
uhid-virt = { path = "../../uhid-fs" } uhid-virt = "0.0.2"

View File

@@ -5,7 +5,6 @@ use aho_corasick::AhoCorasick;
use gumdrop::Options; use gumdrop::Options;
use log::{debug, warn}; use log::{debug, warn};
use rusb::DeviceHandle; use rusb::DeviceHandle;
use std::cell::{Ref, RefCell};
use std::process::Command; use std::process::Command;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
@@ -35,18 +34,14 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
pub struct RogCore { pub struct RogCore {
handle: DeviceHandle<rusb::GlobalContext>, handle: DeviceHandle<rusb::GlobalContext>,
initialised: bool, initialised: bool,
led_interface_num: u8, led_iface_num: u8,
keys_interface_num: u8,
keys_endpoint: u8, keys_endpoint: u8,
config: Config, config: Config,
laptop: RefCell<Box<dyn Laptop>>,
virt_keys: VirtKeys, virt_keys: VirtKeys,
} }
impl RogCore { impl RogCore {
pub fn new() -> Result<RogCore, AuraError> { pub fn new(laptop: &dyn Laptop) -> Result<RogCore, AuraError> {
let laptop = match_laptop()?;
let mut dev_handle = RogCore::get_device(laptop.usb_vendor(), laptop.usb_product())?; let mut dev_handle = RogCore::get_device(laptop.usb_vendor(), laptop.usb_product())?;
dev_handle.set_active_configuration(0).unwrap_or(()); dev_handle.set_active_configuration(0).unwrap_or(());
@@ -76,11 +71,9 @@ impl RogCore {
Ok(RogCore { Ok(RogCore {
handle: dev_handle, handle: dev_handle,
initialised: false, initialised: false,
led_interface_num, led_iface_num: led_interface_num,
keys_interface_num,
keys_endpoint, keys_endpoint,
config: Config::default().read(), config: Config::default().read(),
laptop: RefCell::new(laptop),
virt_keys: VirtKeys::new(), virt_keys: VirtKeys::new(),
}) })
} }
@@ -89,10 +82,6 @@ impl RogCore {
&mut self.virt_keys &mut self.virt_keys
} }
pub fn laptop(&self) -> Ref<Box<dyn Laptop>> {
self.laptop.borrow()
}
pub fn config(&self) -> &Config { pub fn config(&self) -> &Config {
&self.config &self.config
} }
@@ -123,7 +112,7 @@ impl RogCore {
fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> { fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> {
self.handle self.handle
.claim_interface(self.led_interface_num) .claim_interface(self.led_iface_num)
.map_err(|err| AuraError::UsbError(err))?; .map_err(|err| AuraError::UsbError(err))?;
if !self.initialised { if !self.initialised {
@@ -143,7 +132,7 @@ impl RogCore {
self.aura_write(&LED_APPLY)?; self.aura_write(&LED_APPLY)?;
self.handle self.handle
.release_interface(self.led_interface_num) .release_interface(self.led_iface_num)
.map_err(|err| AuraError::UsbError(err))?; .map_err(|err| AuraError::UsbError(err))?;
Ok(()) Ok(())
} }
@@ -159,28 +148,35 @@ impl RogCore {
Ok(bright) Ok(bright)
} }
pub fn aura_set_and_save(&mut self, bytes: &[u8]) -> Result<(), AuraError> { pub fn aura_set_and_save(
&mut self,
supported_modes: &[BuiltInModeByte],
bytes: &[u8],
) -> Result<(), AuraError> {
let mode = BuiltInModeByte::from(bytes[3]); let mode = BuiltInModeByte::from(bytes[3]);
if self.laptop().supported_modes().contains(&mode) || bytes[1] == 0xba { if 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);
self.config.write(); self.config.write();
debug!("Wrote: {:X?}", bytes);
return Ok(()); return Ok(());
} }
warn!("{:?} not supported", BuiltInModeByte::from(mode)); warn!("{:?} not supported", BuiltInModeByte::from(mode));
Err(AuraError::NotSupported) Err(AuraError::NotSupported)
} }
pub fn poll_keyboard(&mut self, buf: &mut [u8; 32]) -> Result<Option<usize>, AuraError> { pub fn poll_keyboard(
&mut self,
hotkey_group_bytes: &[u8],
buf: &mut [u8; 32],
) -> Result<Option<usize>, AuraError> {
let res = let res =
match self match self
.handle .handle
.read_interrupt(self.keys_endpoint, buf, Duration::from_micros(1)) .read_interrupt(self.keys_endpoint, buf, Duration::from_micros(1))
{ {
Ok(o) => { Ok(o) => {
if self.laptop.borrow().hotkey_group_bytes().contains(&buf[0]) { if hotkey_group_bytes.contains(&buf[0]) {
Ok(Some(o)) Ok(Some(o))
} else { } else {
Ok(None) Ok(None)
@@ -337,15 +333,14 @@ impl VirtKeys {
} }
} }
pub fn press(&mut self, key: u8) { pub fn press(&mut self, input: [u8; 2]) {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
bytes[0] = 0x02; bytes[0] = 0x02;
bytes[1] = key; bytes[1] = input[0];
// email button bytes[2] = input[1];
// bytes[1] = 0x8a;
// bytes[2] = 0x01;
self.device.write(&bytes).unwrap(); self.device.write(&bytes).unwrap();
bytes[1] = 0; bytes[1] = 0;
bytes[2] = 0;
self.device.write(&bytes).unwrap(); self.device.write(&bytes).unwrap();
} }
} }
@@ -369,18 +364,29 @@ pub const CONSUMER: [u8; 25] = [
// Needs another Usage (80) for system control // Needs another Usage (80) for system control
// B5 for toggle int/ext display // B5 for toggle int/ext display
// b2 for external // b2 for external
#[derive(Copy, Clone)]
pub enum ConsumerKeys { pub enum ConsumerKeys {
VolUp = 0xe9, // USAGE (Volume up) VolUp = 0x0e9, // USAGE (Volume up)
VolDown = 0xea, // USAGE (Volume down) VolDown = 0x0ea, // USAGE (Volume down)
VolMute = 0xe2, // USAGE (Volume mute) VolMute = 0x0e2, // USAGE (Volume mute)
TrackNext = 0xb6, // USAGE (Track next) TrackNext = 0x0b6, // USAGE (Track next)
PlayToggl = 0xcd, // USAGE (Play/Pause) PlayToggl = 0x0cd, // USAGE (Play/Pause)
TrackPrev = 0xb5, // USAGE (Track prev) TrackPrev = 0x0b5, // USAGE (Track prev)
TrackStop = 0xb7, TrackStop = 0x0b7,
Power = 0x30, Power = 0x030,
Reset = 0x31, Reset = 0x031,
Sleep = 0x32, // USAGE (Sleep) Sleep = 0x032, // USAGE (Sleep)
BacklightInc = 0x6f, // USAGE (Backlight Inc) BacklightInc = 0x06f, // USAGE (Backlight Inc)
BacklightDec = 0x70, // USAGE (Backlight Dec) BacklightDec = 0x070, // USAGE (Backlight Dec)
BacklightTog = 0x72, // USAGE (Backlight toggle? display toggle?) BacklightTog = 0x072, // USAGE (Backlight toggle? display toggle?)
Present = 0x188,
}
impl From<ConsumerKeys> for [u8; 2] {
fn from(key: ConsumerKeys) -> Self {
let mut bytes = [0u8; 2];
bytes[0] = key as u8;
bytes[1] = (key as u16 >> 8) as u8;
bytes
}
} }

View File

@@ -1,14 +1,14 @@
use crate::aura::BuiltInModeByte; use crate::aura::BuiltInModeByte;
use crate::core::{Backlight, RogCore}; use crate::core::{Backlight, ConsumerKeys, RogCore};
use crate::error::AuraError; use crate::error::AuraError;
use log::info; use log::info;
pub fn match_laptop() -> Result<Box<dyn Laptop>, AuraError> { pub fn match_laptop() -> Box<dyn Laptop> {
let dmi = sysfs_class::DmiId::default(); let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name()?; let board_name = dmi.board_name().unwrap();
match board_name.as_str() { match board_name.as_str() {
// The hell does it have a \n for anyway? // The hell does it have a \n for anyway?
"GX502GW\n" => Ok(Box::new(LaptopGX502GW::new())), "GX502GW\n" => Box::new(LaptopGX502GW::new()),
_ => { _ => {
panic!("could not match laptop"); panic!("could not match laptop");
} }
@@ -77,6 +77,7 @@ impl LaptopGX502GW {
} }
} }
impl Laptop for LaptopGX502GW { impl Laptop for LaptopGX502GW {
// TODO: This really needs to match against u16 in future
fn do_hotkey_action(&self, rogcore: &mut RogCore, key_byte: u8) -> Result<(), AuraError> { fn do_hotkey_action(&self, rogcore: &mut RogCore, key_byte: u8) -> Result<(), AuraError> {
match GX502GWKeys::from(key_byte) { match GX502GWKeys::from(key_byte) {
GX502GWKeys::LedBrightUp => { GX502GWKeys::LedBrightUp => {
@@ -86,7 +87,7 @@ impl Laptop for LaptopGX502GW {
rogcore.config_mut().brightness = bright; rogcore.config_mut().brightness = bright;
} }
let bytes = RogCore::aura_brightness_bytes(bright)?; let bytes = RogCore::aura_brightness_bytes(bright)?;
rogcore.aura_set_and_save(&bytes)?; rogcore.aura_set_and_save(&self.supported_modes, &bytes)?;
} }
GX502GWKeys::LedBrightDown => { GX502GWKeys::LedBrightDown => {
let mut bright = rogcore.config().brightness; let mut bright = rogcore.config().brightness;
@@ -95,7 +96,7 @@ impl Laptop for LaptopGX502GW {
rogcore.config_mut().brightness = bright; rogcore.config_mut().brightness = bright;
} }
let bytes = RogCore::aura_brightness_bytes(bright)?; let bytes = RogCore::aura_brightness_bytes(bright)?;
rogcore.aura_set_and_save(&bytes)?; rogcore.aura_set_and_save(&self.supported_modes, &bytes)?;
} }
GX502GWKeys::AuraNext => { GX502GWKeys::AuraNext => {
let mut mode = rogcore.config().current_mode[3] + 1; let mut mode = rogcore.config().current_mode[3] + 1;
@@ -106,7 +107,7 @@ impl Laptop for LaptopGX502GW {
} }
rogcore.config_mut().current_mode[3] = mode; rogcore.config_mut().current_mode[3] = mode;
if let Some(bytes) = rogcore.config_mut().get_current() { if let Some(bytes) = rogcore.config_mut().get_current() {
rogcore.aura_set_and_save(&bytes)?; rogcore.aura_set_and_save(&self.supported_modes, &bytes)?;
} }
} }
GX502GWKeys::AuraPrevious => { GX502GWKeys::AuraPrevious => {
@@ -120,7 +121,7 @@ impl Laptop for LaptopGX502GW {
} }
rogcore.config_mut().current_mode[3] = mode; rogcore.config_mut().current_mode[3] = mode;
if let Some(bytes) = rogcore.config_mut().get_current() { if let Some(bytes) = rogcore.config_mut().get_current() {
rogcore.aura_set_and_save(&bytes)?; rogcore.aura_set_and_save(&self.supported_modes, &bytes)?;
rogcore.config().write(); rogcore.config().write();
} }
} }
@@ -139,7 +140,9 @@ impl Laptop for LaptopGX502GW {
GX502GWKeys::MicToggle => {} GX502GWKeys::MicToggle => {}
GX502GWKeys::Fan => {} GX502GWKeys::Fan => {}
GX502GWKeys::ScreenToggle => {} GX502GWKeys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GX502GWKeys::TouchPadToggle => {} GX502GWKeys::TouchPadToggle => {}
GX502GWKeys::Rog => {} GX502GWKeys::Rog => {}
@@ -149,7 +152,7 @@ impl Laptop for LaptopGX502GW {
"Unmapped key, attempt to pass to virtual device: {:?}, {:X?}", "Unmapped key, attempt to pass to virtual device: {:?}, {:X?}",
&key_byte, &key_byte &key_byte, &key_byte
); );
rogcore.virt_keys().press(key_byte); rogcore.virt_keys().press([key_byte, 0]);
} }
} }
} }