diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..81fa7a8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,138 @@ +use std::{ + env::{self}, + pin::pin, + time::Duration, +}; + +use bluer::{Session, Uuid}; +use tokio::{select, time::interval}; +use tokio_stream::StreamExt; +use uinput_tokio::event::{controller::Mouse, relative}; + +const HID_SERVICE: Result<Uuid, uuid::Error> = + Uuid::try_parse("00001812-0000-1000-8000-00805f9b34fb"); + +const REPORT_REF: Result<Uuid, uuid::Error> = + Uuid::try_parse("00002908-0000-1000-8000-00805f9b34fb"); + +const MAGIC_REPORT: u8 = 240; +const BUTTON_REPORT: u8 = 251; +const TOUCH_REPORT: u8 = 252; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> bluer::Result<()> { + let mut udevice = uinput_tokio::default() + .unwrap() + .name("siriremote") + .unwrap() + .event(Mouse::Left) + .unwrap() + .event(relative::Position::X) + .unwrap() + .event(relative::Position::Y) + .unwrap() + .create() + .await + .unwrap(); + + let session = Session::new().await?; + let adapter = session.default_adapter().await?; + + let addr = env::args() + .nth(1) + .expect("must pass address") + .parse() + .expect("invalid address"); + + eprintln!("connecting..."); + let device = adapter.device(addr)?; + device.connect().await?; + + let mut touch_char = None; + let mut button_char = None; + for service in device.services().await? { + if service.uuid().await? == HID_SERVICE.unwrap() { + for characteristic in service.characteristics().await? { + for descriptor in characteristic.descriptors().await? { + if descriptor.uuid().await? == REPORT_REF.unwrap() { + let resp = descriptor.read().await?; + match resp[0] { + MAGIC_REPORT => characteristic.write(&[0xf0, 0x00]).await?, + TOUCH_REPORT => touch_char = Some(characteristic.clone()), + BUTTON_REPORT => button_char = Some(characteristic.clone()), + _ => {} + } + } + } + } + } + } + + eprintln!("connected"); + let mut touch = pin!(touch_char.unwrap().notify().await?); + let mut button = pin!(button_char.unwrap().notify().await?); + let mut last = None; + let mut sdx = 0f32; + let mut sdy = 0f32; + let mut timer = interval(Duration::from_millis(1)); + loop { + select! { + _ = timer.tick() => { + udevice.send(relative::Position::X, sdx as i32).await.unwrap(); + udevice.send(relative::Position::Y, sdy as i32).await.unwrap(); + udevice.synchronize().await.unwrap(); + + sdx *= 0.97; + sdy *= 0.97; + }, + v = button.next() => { + let v = v.unwrap(); + match (v[0], v[1]) { + (8, 0) => { + udevice.send(Mouse::Left, 1).await.unwrap(); + }, + (0, 0) => { + udevice.send(Mouse::Left, 0).await.unwrap(); + }, + (_, _) => (), + } + } + v = touch.next() => { + let v = v.unwrap(); + let ts = (((v[2] as u16) << 8) + (v[1] as u16)) as i32; + let touched = v[3] > 0; + + let x = ((((v[5] & 15) as u16) << 8) + v[4] as u16) as i32; + let y = ((((v[5] & !15) as u16) >> 4) + ((v[6] as u16) << 4)) as i32; + + if touched { + if let Some(&(xp, yp, tsp)) = last.as_ref() { + let mut dx: i32 = x - xp; + let mut dy: i32 = y - yp; + let mut dts: i32 = ts - tsp; + if dx >= 2048 { + dx -= 4096; + } + if dx <= -2048 { + dx += 4096; + } + if dy >= -2048 { + dy -= 4096; + } + if dy <= -2048 { + dy += 4096; + } + if dts <= -32768 { + dts += 65536; + } + sdx += (dx as f32) / (dts as f32); + sdy -= (dy as f32) / (dts as f32); + } + last = Some((x, y, ts)); + } else { + last = None; + } + } + } + } +} |