Add virtual keyboard so touchpad can be toggled :/

This commit is contained in:
Luke
2020-04-21 16:01:44 +12:00
parent 53cc265bbd
commit 44fb0ee139
7 changed files with 171 additions and 92 deletions

View File

@@ -62,10 +62,10 @@ Currently if no options are supplied for the CLI mode selection then a default i
+ [X] Airplane mode
+ [X] Screen off? Now mapped to a keycode but has no effect
+ [X] Screen brightness up/down
+ [ ] ROG key custom mapping (Can be done)
+ [ ] ROG key custom mapping (Can be done in source)
+ [ ] Fan/Performance mode
+ [ ] Screen off??
+ [ ] Touchpad toggle
+ [X] Touchpad toggle (using a virtual keyboard to emit F21...)
- [X] Capture and use hotkeys **Partially completed: aura keys work**
+ [X] Aura control by Aura keys
+ [X] Volume + media controls work

View File

@@ -1,6 +1,6 @@
[package]
name = "rog-core"
version = "0.3.2"
version = "0.3.3"
authors = ["Luke <luke@ljones.dev>"]
edition = "2018"

View File

@@ -1,6 +1,6 @@
[package]
name = "rog-lib"
version = "0.4.0"
version = "0.4.1"
authors = ["Luke <luke@ljones.dev>"]
edition = "2018"
@@ -14,4 +14,5 @@ sysfs-class = "0.1.2"
aho-corasick = "0.7"
thiserror = "1.0.15"
log = "0.4"
uhid-virt = "0.0.2"
uhid-virt = "0.0.2"
#keycode = "0.3"

View File

@@ -1,6 +1,8 @@
// Return show-stopping errors, otherwise map error to a log level
use crate::{aura::BuiltInModeByte, config::Config, error::AuraError, laptops::*};
use crate::{
aura::BuiltInModeByte, config::Config, error::AuraError, laptops::*, virt_device::VirtKeys,
};
use aho_corasick::AhoCorasick;
use gumdrop::Options;
use log::{debug, warn};
@@ -9,7 +11,6 @@ use std::process::Command;
use std::str::FromStr;
use std::time::Duration;
use sysfs_class::{Brightness, SysClass};
use uhid_virt::{Bus, CreateParams, UHIDDevice};
pub const LED_MSG_LEN: usize = 17;
static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
@@ -310,83 +311,3 @@ impl FromStr for LedBrightness {
}
}
}
pub struct VirtKeys {
pub device: UHIDDevice<std::fs::File>,
}
impl VirtKeys {
pub fn new() -> Self {
VirtKeys {
device: UHIDDevice::create(CreateParams {
name: String::from("Virtual ROG buttons"),
phys: String::from(""),
uniq: String::from(""),
bus: Bus::USB,
vendor: 0x0b05,
product: 0x1866,
version: 0,
country: 0,
rd_data: CONSUMER.to_vec(),
})
.unwrap(),
}
}
pub fn press(&mut self, input: [u8; 2]) {
let mut bytes = [0u8; 8];
bytes[0] = 0x02;
bytes[1] = input[0];
bytes[2] = input[1];
self.device.write(&bytes).unwrap();
bytes[1] = 0;
bytes[2] = 0;
self.device.write(&bytes).unwrap();
}
}
pub const CONSUMER: [u8; 25] = [
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID (2)
0x19, 0x00, // Usage Minimum (Unassigned)
0x2A, 0x3C, 0x02, // Usage Maximum (AC Format)
0x15, 0x00, // Logical Minimum (0)
0x26, 0x3C, 0x02, // Logical Maximum (572)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,
];
// Usage 04 for microphone
// Needs another Usage (80) for system control
// B5 for toggle int/ext display
// b2 for external
#[derive(Copy, Clone)]
pub enum ConsumerKeys {
VolUp = 0x0e9, // USAGE (Volume up)
VolDown = 0x0ea, // USAGE (Volume down)
VolMute = 0x0e2, // USAGE (Volume mute)
TrackNext = 0x0b6, // USAGE (Track next)
PlayToggl = 0x0cd, // USAGE (Play/Pause)
TrackPrev = 0x0b5, // USAGE (Track prev)
TrackStop = 0x0b7,
Power = 0x030,
Reset = 0x031,
Sleep = 0x032, // USAGE (Sleep)
BacklightInc = 0x06f, // USAGE (Backlight Inc)
BacklightDec = 0x070, // USAGE (Backlight Dec)
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,6 +1,8 @@
use crate::aura::BuiltInModeByte;
use crate::core::{Backlight, ConsumerKeys, RogCore};
use crate::core::{Backlight, RogCore};
use crate::error::AuraError;
use crate::virt_device::ConsumerKeys;
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
use log::info;
pub fn match_laptop() -> Box<dyn Laptop> {
@@ -132,7 +134,11 @@ impl Laptop for LaptopGX502GW {
self.backlight.step_down();
}
GX502GWKeys::Sleep => {
// Direct call to systemd
rogcore.suspend();
//rogcore.virt_keys().press([0x01, 0, 0, 0x82, 0, 0, 0, 0]);
// Power menu
//rogcore.virt_keys().press([0x01, 0, 0, 0x66, 0, 0, 0, 0]);
}
GX502GWKeys::AirplaneMode => {
rogcore.toggle_airplane_mode();
@@ -143,8 +149,15 @@ impl Laptop for LaptopGX502GW {
GX502GWKeys::ScreenToggle => {
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
}
GX502GWKeys::TouchPadToggle => {}
GX502GWKeys::Rog => {}
GX502GWKeys::TouchPadToggle => {
// F21 key, Touchpad toggle
rogcore.virt_keys().press([0x01, 0, 0, 0x70, 0, 0, 0, 0]);
// rogcore.virt_keys().press([0x01, 0, 0, 0x71, 0, 0, 0, 0]); // Touchpad on F22
// rogcore.virt_keys().press([0x01, 0, 0, 0x72, 0, 0, 0, 0]); // Touchpad off F23
}
GX502GWKeys::Rog => {
rogcore.virt_keys().press([0x01, 0, 0, 0x68, 0, 0, 0, 0]); // XF86Tools? F13
}
GX502GWKeys::None => {
if key_byte != 0 {
@@ -152,11 +165,14 @@ impl Laptop for LaptopGX502GW {
"Unmapped key, attempt to pass to virtual device: {:?}, {:X?}",
&key_byte, &key_byte
);
rogcore.virt_keys().press([key_byte, 0]);
let mut bytes = [0u8; 8];
// TODO: code page
bytes[0] = 0x02;
bytes[1] = key_byte;
rogcore.virt_keys().press(bytes);
}
}
}
//info!("Pressed: {:?}, {:X?}", &key_byte, &key_byte);
Ok(())
}
fn hotkey_group_bytes(&self) -> &[u8] {

View File

@@ -5,3 +5,4 @@ pub mod config;
pub mod core;
mod error;
pub mod laptops;
mod virt_device;

140
rog-lib/src/virt_device.rs Normal file
View File

@@ -0,0 +1,140 @@
use uhid_virt::{Bus, CreateParams, UHIDDevice};
pub struct VirtKeys {
pub device: UHIDDevice<std::fs::File>,
}
impl VirtKeys {
pub fn new() -> Self {
VirtKeys {
device: UHIDDevice::create(CreateParams {
name: String::from("Virtual ROG buttons"),
phys: String::from(""),
uniq: String::from(""),
bus: Bus::USB,
vendor: 0x0b05,
product: 0x1866,
version: 0,
country: 0,
// This is a device which emits the usage code as a whole, rather than as bits
rd_data: [
// Consumer Device TLC
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID (2)
0x19, 0x00, // Usage Minimum (Unassigned)
0x2A, 0x3C, 0x02, // Usage Maximum (AC Format)
0x15, 0x00, // Logical Minimum (0)
0x26, 0x3C, 0x02, // Logical Maximum (572)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State)
0xC0, //
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maximum (Kana)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State)
0x95, 0x1E, // Report Count (30)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (0x00)
0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State)
0xC0, // End Collection
]
.to_vec(),
})
.unwrap(),
}
}
pub fn press(&mut self, input: [u8; 8]) {
self.device.write(&input).unwrap();
let mut reset = [0u8; 8];
reset[0] = input[0];
self.device.write(&reset).unwrap();
}
}
#[derive(Copy, Clone)]
pub enum ConsumerKeys {
Power = 0x30,
Sleep = 0x32,
Menu = 0x0040,
MediaRecord = 0xB2,
MediaFastFwd = 0xB3,
MediaRewind = 0xB4,
MediaNext = 0xB5,
MediaPrev = 0xB6,
MediaStop = 0xB7,
MediaPlayPause = 0xCD,
MediaPause = 0xB0,
MediaVolMute = 0xE2,
MediaVolUp = 0xE9,
MediaVolDown = 0xEA,
BacklightInc = 0x006F,
BacklightDec = 0x0070,
BacklightTog = 0x072, // USAGE (Backlight toggle? display toggle?)
BacklightMin = 0x73,
BacklightMax = 0x74,
ControlConfig = 0x183,
LaunchWordEditor = 0x184,
LaunchTextEditor = 0x185,
LaunchSpreadSheet = 0x186,
LaunchGraphicsEditor = 0x187,
LaunchPresentationApp = 0x188,
LaunchDatabaseEditor = 0x189,
LaunchEmailApp = 0x18A,
LaunchNewsReader = 0x18B,
LaunchCalendarApp = 0x018e,
LaunchTaskManagementApp = 0x18F,
LaunchWebBrowser = 0x196,
ControlPanel = 0x19F,
VideoOutStep = 0x82,
Documents = 0x1A7,
FileBrowser = 0x1B4,
ImageBrowser = 0x1B6,
AudioBrowser = 0x1B7,
MovieBrowser = 0x1B8,
}
impl From<ConsumerKeys> for [u8; 8] {
fn from(key: ConsumerKeys) -> Self {
let mut bytes = [0u8; 8];
bytes[0] = 0x02; // report ID for consumer
bytes[1] = key as u8;
bytes[2] = (key as u16 >> 8) as u8;
bytes
}
}