mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Add virtual keyboard so touchpad can be toggled :/
This commit is contained in:
@@ -62,10 +62,10 @@ Currently if no options are supplied for the CLI mode selection then a default i
|
|||||||
+ [X] Airplane mode
|
+ [X] Airplane mode
|
||||||
+ [X] Screen off? Now mapped to a keycode but has no effect
|
+ [X] Screen off? Now mapped to a keycode but has no effect
|
||||||
+ [X] Screen brightness up/down
|
+ [X] Screen brightness up/down
|
||||||
+ [ ] ROG key custom mapping (Can be done)
|
+ [ ] ROG key custom mapping (Can be done in source)
|
||||||
+ [ ] Fan/Performance mode
|
+ [ ] Fan/Performance mode
|
||||||
+ [ ] Screen off??
|
+ [ ] 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] Capture and use hotkeys **Partially completed: aura keys work**
|
||||||
+ [X] Aura control by Aura keys
|
+ [X] Aura control by Aura keys
|
||||||
+ [X] Volume + media controls work
|
+ [X] Volume + media controls work
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog-core"
|
name = "rog-core"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog-lib"
|
name = "rog-lib"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -14,4 +14,5 @@ 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 = "0.0.2"
|
uhid-virt = "0.0.2"
|
||||||
|
#keycode = "0.3"
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
// Return show-stopping errors, otherwise map error to a log level
|
// 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 aho_corasick::AhoCorasick;
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
@@ -9,7 +11,6 @@ use std::process::Command;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use sysfs_class::{Brightness, SysClass};
|
use sysfs_class::{Brightness, SysClass};
|
||||||
use uhid_virt::{Bus, CreateParams, UHIDDevice};
|
|
||||||
|
|
||||||
pub const LED_MSG_LEN: usize = 17;
|
pub const LED_MSG_LEN: usize = 17;
|
||||||
static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::aura::BuiltInModeByte;
|
use crate::aura::BuiltInModeByte;
|
||||||
use crate::core::{Backlight, ConsumerKeys, RogCore};
|
use crate::core::{Backlight, RogCore};
|
||||||
use crate::error::AuraError;
|
use crate::error::AuraError;
|
||||||
|
use crate::virt_device::ConsumerKeys;
|
||||||
|
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
pub fn match_laptop() -> Box<dyn Laptop> {
|
pub fn match_laptop() -> Box<dyn Laptop> {
|
||||||
@@ -132,7 +134,11 @@ impl Laptop for LaptopGX502GW {
|
|||||||
self.backlight.step_down();
|
self.backlight.step_down();
|
||||||
}
|
}
|
||||||
GX502GWKeys::Sleep => {
|
GX502GWKeys::Sleep => {
|
||||||
|
// Direct call to systemd
|
||||||
rogcore.suspend();
|
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 => {
|
GX502GWKeys::AirplaneMode => {
|
||||||
rogcore.toggle_airplane_mode();
|
rogcore.toggle_airplane_mode();
|
||||||
@@ -143,8 +149,15 @@ impl Laptop for LaptopGX502GW {
|
|||||||
GX502GWKeys::ScreenToggle => {
|
GX502GWKeys::ScreenToggle => {
|
||||||
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
|
rogcore.virt_keys().press(ConsumerKeys::BacklightTog.into());
|
||||||
}
|
}
|
||||||
GX502GWKeys::TouchPadToggle => {}
|
GX502GWKeys::TouchPadToggle => {
|
||||||
GX502GWKeys::Rog => {}
|
// 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 => {
|
GX502GWKeys::None => {
|
||||||
if key_byte != 0 {
|
if key_byte != 0 {
|
||||||
@@ -152,11 +165,14 @@ 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, 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn hotkey_group_bytes(&self) -> &[u8] {
|
fn hotkey_group_bytes(&self) -> &[u8] {
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ pub mod config;
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
mod error;
|
mod error;
|
||||||
pub mod laptops;
|
pub mod laptops;
|
||||||
|
mod virt_device;
|
||||||
|
|||||||
140
rog-lib/src/virt_device.rs
Normal file
140
rog-lib/src/virt_device.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user