mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Virtual keyboard to repeat keys
This commit is contained in:
970
Cargo.lock
generated
970
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -12,3 +12,6 @@ serde_derive = "1.0"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
rog-lib = { path = "../rog-lib" }
|
rog-lib = { path = "../rog-lib" }
|
||||||
|
tokio-linux-uhid = "0.3"
|
||||||
|
tokio-core = "0.1.17"
|
||||||
|
tokio-io = "0.1.13"
|
||||||
@@ -4,10 +4,11 @@ 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::*;
|
||||||
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};
|
||||||
|
use tokio_linux_uhid::{Bus, CreateParams, UHIDDevice};
|
||||||
|
|
||||||
pub struct Daemon {
|
pub struct Daemon {
|
||||||
rogcore: RogCore,
|
rogcore: RogCore,
|
||||||
@@ -85,6 +86,28 @@ impl Daemon {
|
|||||||
// We add the tree to the connection so that incoming method calls will be handled.
|
// We add the tree to the connection so that incoming method calls will be handled.
|
||||||
tree.start_receive(&connection);
|
tree.start_receive(&connection);
|
||||||
|
|
||||||
|
let core = tokio_core::reactor::Core::new().unwrap();
|
||||||
|
let handle = core.handle();
|
||||||
|
|
||||||
|
let virt = Rc::new(RefCell::new(VirtKeys {
|
||||||
|
device: UHIDDevice::create(
|
||||||
|
&handle,
|
||||||
|
CreateParams {
|
||||||
|
name: String::from("Virtual ROG buttons"),
|
||||||
|
phys: String::from(""),
|
||||||
|
uniq: String::from(""),
|
||||||
|
bus: Bus::USB,
|
||||||
|
vendor: 0x0b05,
|
||||||
|
product: 0x1866,
|
||||||
|
version: 0,
|
||||||
|
country: 0,
|
||||||
|
data: CONSUMER.to_vec(),
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
}));
|
||||||
|
|
||||||
let mut key_buf = [0u8; 32];
|
let mut key_buf = [0u8; 32];
|
||||||
loop {
|
loop {
|
||||||
connection
|
connection
|
||||||
@@ -104,8 +127,13 @@ impl Daemon {
|
|||||||
let laptop = borrowed_daemon.rogcore.laptop();
|
let laptop = borrowed_daemon.rogcore.laptop();
|
||||||
|
|
||||||
if let Some(_count) = read {
|
if let Some(_count) = read {
|
||||||
|
let virt = virt.clone();
|
||||||
laptop
|
laptop
|
||||||
.do_hotkey_action(&mut rogcore, key_buf[1])
|
.do_hotkey_action(
|
||||||
|
&mut rogcore,
|
||||||
|
key_buf[1],
|
||||||
|
Box::new(move |input| virt.borrow_mut().press(input)),
|
||||||
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
warn!("{:?}", err);
|
warn!("{:?}", err);
|
||||||
});
|
});
|
||||||
@@ -116,3 +144,56 @@ impl Daemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct VirtKeys<T: std::io::Write + tokio_io::AsyncRead> {
|
||||||
|
pub device: UHIDDevice<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::io::Write + tokio_io::AsyncRead> VirtKeys<T> {
|
||||||
|
pub fn press(&mut self, key: u8) {
|
||||||
|
let mut bytes = [0u8; 8];
|
||||||
|
bytes[0] = 0x02;
|
||||||
|
bytes[1] = key;
|
||||||
|
// email button
|
||||||
|
// bytes[1] = 0x8a;
|
||||||
|
// bytes[2] = 0x01;
|
||||||
|
self.device.send_input(&bytes).unwrap();
|
||||||
|
bytes[1] = 0;
|
||||||
|
self.device.send_input(&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
|
||||||
|
pub enum ConsumerKeys {
|
||||||
|
VolUp = 0xe9, // USAGE (Volume up)
|
||||||
|
VolDown = 0xea, // USAGE (Volume down)
|
||||||
|
VolMute = 0xe2, // USAGE (Volume mute)
|
||||||
|
TrackNext = 0xb6, // USAGE (Track next)
|
||||||
|
PlayToggl = 0xcd, // USAGE (Play/Pause)
|
||||||
|
TrackPrev = 0xb5, // USAGE (Track prev)
|
||||||
|
TrackStop = 0xb7,
|
||||||
|
Power = 0x30,
|
||||||
|
Reset = 0x31,
|
||||||
|
Sleep = 0x32, // USAGE (Sleep)
|
||||||
|
BacklightInc = 0x6f, // USAGE (Backlight Inc)
|
||||||
|
BacklightDec = 0x70, // USAGE (Backlight Dec)
|
||||||
|
BacklightTog = 0x72, // USAGE (Backlight toggle? display toggle?)
|
||||||
|
}
|
||||||
|
|||||||
@@ -170,11 +170,10 @@ impl RogCore {
|
|||||||
let res =
|
let res =
|
||||||
match self
|
match self
|
||||||
.handle
|
.handle
|
||||||
.read_interrupt(self.keys_endpoint, buf, Duration::from_micros(10))
|
.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 self.laptop.borrow().hotkey_group_bytes().contains(&buf[0]) {
|
||||||
println!("{:?}", buf);
|
|
||||||
Ok(Some(o))
|
Ok(Some(o))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|||||||
@@ -23,7 +23,12 @@ pub fn match_laptop() -> Result<Box<dyn Laptop>, AuraError> {
|
|||||||
/// has 3 explicit groups: main, vol+media, and the ones that the Linux kernel doesn't
|
/// has 3 explicit groups: main, vol+media, and the ones that the Linux kernel doesn't
|
||||||
/// map.
|
/// map.
|
||||||
pub trait Laptop {
|
pub trait Laptop {
|
||||||
fn do_hotkey_action(&self, core: &mut RogCore, key_byte: u8) -> Result<(), AuraError>;
|
fn do_hotkey_action(
|
||||||
|
&self,
|
||||||
|
core: &mut RogCore,
|
||||||
|
key_byte: u8,
|
||||||
|
virt: Box<dyn Fn(u8)>,
|
||||||
|
) -> Result<(), AuraError>;
|
||||||
fn hotkey_group_bytes(&self) -> &[u8];
|
fn hotkey_group_bytes(&self) -> &[u8];
|
||||||
fn led_iface_num(&self) -> u8;
|
fn led_iface_num(&self) -> u8;
|
||||||
fn supported_modes(&self) -> &[BuiltInModeByte];
|
fn supported_modes(&self) -> &[BuiltInModeByte];
|
||||||
@@ -77,11 +82,13 @@ impl LaptopGX502GW {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Laptop for LaptopGX502GW {
|
impl Laptop for LaptopGX502GW {
|
||||||
fn do_hotkey_action(&self, rogcore: &mut RogCore, key_byte: u8) -> Result<(), AuraError> {
|
fn do_hotkey_action(
|
||||||
|
&self,
|
||||||
|
rogcore: &mut RogCore,
|
||||||
|
key_byte: u8,
|
||||||
|
virt: Box<dyn Fn(u8)>,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
match GX502GWKeys::from(key_byte) {
|
match GX502GWKeys::from(key_byte) {
|
||||||
GX502GWKeys::Rog => {
|
|
||||||
println!("ROG!");
|
|
||||||
}
|
|
||||||
GX502GWKeys::LedBrightUp => {
|
GX502GWKeys::LedBrightUp => {
|
||||||
let mut bright = rogcore.config().brightness;
|
let mut bright = rogcore.config().brightness;
|
||||||
if bright < self.max_led_bright {
|
if bright < self.max_led_bright {
|
||||||
@@ -139,13 +146,24 @@ impl Laptop for LaptopGX502GW {
|
|||||||
GX502GWKeys::AirplaneMode => {
|
GX502GWKeys::AirplaneMode => {
|
||||||
rogcore.toggle_airplane_mode();
|
rogcore.toggle_airplane_mode();
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
|
GX502GWKeys::MicToggle => {}
|
||||||
|
GX502GWKeys::Fan => {}
|
||||||
|
GX502GWKeys::ScreenToggle => {}
|
||||||
|
GX502GWKeys::TouchPadToggle => {}
|
||||||
|
GX502GWKeys::Rog => {}
|
||||||
|
|
||||||
|
GX502GWKeys::None => {
|
||||||
if key_byte != 0 {
|
if key_byte != 0 {
|
||||||
info!("Unmapped key: {:?}, {:X?}", &key_byte, &key_byte);
|
info!(
|
||||||
|
"Unmapped key, attempt to pass to virtual device: {:?}, {:X?}",
|
||||||
|
&key_byte, &key_byte
|
||||||
|
);
|
||||||
|
virt(key_byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("Pressed: {:?}, {:X?}", &key_byte, &key_byte);
|
//info!("Pressed: {:?}, {:X?}", &key_byte, &key_byte);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn hotkey_group_bytes(&self) -> &[u8] {
|
fn hotkey_group_bytes(&self) -> &[u8] {
|
||||||
|
|||||||
Reference in New Issue
Block a user