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::try_parse("00001812-0000-1000-8000-00805f9b34fb"); const REPORT_REF: Result = 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; } } } } }