use std::fs::File;
use std::io::{self, Read};
use std::os::fd::AsRawFd;
use std::process::ExitCode;
use std::time::{Duration, Instant};
use deckhidraw::*;
unsafe extern "C" {
unsafe fn ioctl(fd: i32, op: u32, ...) -> i32;
}
fn set_feature_report(f: &File, buf: &[u8; 65]) -> io::Result<()> {
let ret = unsafe { ioctl(f.as_raw_fd(), 0xC0414806, buf.as_ptr()) };
if ret < 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
fn main() -> io::Result<ExitCode> {
println!("Hello world!");
let deck_hidraw = find_deck_hidraw()?;
if deck_hidraw.is_none() {
println!("Could not find Steam Deck hidraw controls!");
return Ok(ExitCode::FAILURE);
}
let deck_hidraw = deck_hidraw.unwrap();
println!("Opening {:?}", deck_hidraw);
let mut dev_node = File::open(deck_hidraw)?;
println!("Opened! {:?}", dev_node);
set_feature_report(&dev_node, &commands::turn_on_gyro())?;
let mut last_gyro_on = Instant::now();
let mut last_data = InputReport::from([0; 64]);
loop {
let mut buf = [0; 64];
dev_node.read(&mut buf)?;
let data = InputReport::from(buf);
println!("\x1b[2J\x1b[1;1H{:#}", data);
let time_now = Instant::now();
if time_now - last_gyro_on > Duration::from_secs(5) {
set_feature_report(&dev_node, &commands::turn_on_gyro())?;
last_gyro_on = time_now;
}
if last_data.buttons & buttons::A == 0 && data.buttons & buttons::A != 0 {
set_feature_report(&dev_node, &commands::beep(commands::PAD_BOTH, 1000.0, 0.4))?;
}
if last_data.buttons & buttons::B == 0 && data.buttons & buttons::B != 0 {
set_feature_report(&dev_node, &commands::tick(commands::PAD_BOTH, 4, 6))?;
}
if last_data.buttons & buttons::X == 0 && data.buttons & buttons::X != 0 {
set_feature_report(&dev_node, &&commands::rumble(0, 0x7fff, 0x7fff, 2, 0))?;
}
last_data = data;
}
}