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] 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog-core"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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] {
|
||||
|
||||
@@ -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
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