2025-06-02 20:41:36 -05:00
|
|
|
//! navka-server — receive HidReport and write to /dev/hidg0
|
2025-06-01 16:04:00 -05:00
|
|
|
#![forbid(unsafe_code)]
|
2025-06-01 13:31:22 -05:00
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
use std::{pin::Pin, sync::Arc};
|
|
|
|
|
use tokio::{fs::OpenOptions, io::AsyncWriteExt};
|
|
|
|
|
use tokio_stream::{wrappers::ReceiverStream, Stream, StreamExt};
|
|
|
|
|
use tonic::{transport::Server, Request, Response, Status};
|
2025-06-05 22:44:27 -05:00
|
|
|
use tracing::{info, error};
|
2025-06-01 21:26:57 -05:00
|
|
|
|
2025-06-01 16:04:00 -05:00
|
|
|
use navka_common::navka::{
|
2025-06-01 21:26:57 -05:00
|
|
|
relay_server::{Relay, RelayServer},
|
|
|
|
|
HidReport,
|
2025-06-01 16:04:00 -05:00
|
|
|
};
|
2025-06-02 20:24:00 -05:00
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
struct Handler {
|
|
|
|
|
/// shared async handle to /dev/hidg0
|
|
|
|
|
hid: Arc<tokio::sync::Mutex<tokio::fs::File>>,
|
2025-06-01 16:04:00 -05:00
|
|
|
}
|
2025-06-01 13:31:22 -05:00
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
#[tonic::async_trait]
|
|
|
|
|
impl Relay for Handler {
|
|
|
|
|
type StreamStream =
|
|
|
|
|
Pin<Box<dyn Stream<Item = Result<HidReport, Status>> + Send + 'static>>;
|
2025-06-01 13:31:22 -05:00
|
|
|
|
|
|
|
|
async fn stream(
|
|
|
|
|
&self,
|
|
|
|
|
request: Request<tonic::Streaming<HidReport>>,
|
2025-06-02 20:24:30 -05:00
|
|
|
) -> Result<Response<Self::StreamStream>, Status> {
|
2025-06-02 20:41:36 -05:00
|
|
|
let mut in_stream = request.into_inner();
|
|
|
|
|
let hid = self.hid.clone();
|
|
|
|
|
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
|
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
while let Some(msg) = in_stream.next().await.transpose()? {
|
2025-06-06 00:21:20 -05:00
|
|
|
let data = msg.data.get(..8).ok_or_else(|| Status::invalid_argument("short"))?;
|
|
|
|
|
{
|
|
|
|
|
let mut f = hid.lock().await;
|
|
|
|
|
if let Err(e) = f.write_all(data).await {
|
|
|
|
|
error!("USB write failed: {e}");
|
|
|
|
|
return Err(Status::internal(e.to_string()));
|
|
|
|
|
}
|
|
|
|
|
f.flush().await.ok();
|
|
|
|
|
}
|
|
|
|
|
info!(bytes=?data, len=data.len(), "HID report received");
|
|
|
|
|
let _ = tx.send(Ok(msg)).await;
|
2025-06-01 13:31:22 -05:00
|
|
|
}
|
2025-06-02 20:41:36 -05:00
|
|
|
Ok::<_, Status>(())
|
2025-06-01 13:31:22 -05:00
|
|
|
});
|
|
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
Ok(Response::new(Box::pin(ReceiverStream::new(rx))))
|
2025-06-01 13:31:22 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::main]
|
2025-06-02 20:41:36 -05:00
|
|
|
async fn main() -> anyhow::Result<()> {
|
2025-06-06 00:21:20 -05:00
|
|
|
tracing_subscriber::fmt::init();
|
2025-06-05 22:44:27 -05:00
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
let file = OpenOptions::new()
|
|
|
|
|
.write(true)
|
2025-06-06 00:04:55 -05:00
|
|
|
.read(true)
|
|
|
|
|
.custom_flags(libc::O_NONBLOCK)
|
2025-06-02 20:41:36 -05:00
|
|
|
.open("/dev/hidg0")
|
|
|
|
|
.await?;
|
|
|
|
|
let hid = Arc::new(tokio::sync::Mutex::new(file));
|
|
|
|
|
let handler = Handler { hid };
|
2025-06-01 16:04:00 -05:00
|
|
|
|
2025-06-02 20:41:36 -05:00
|
|
|
println!("🌐 navka-server listening on 0.0.0.0:50051");
|
2025-06-01 13:31:22 -05:00
|
|
|
Server::builder()
|
2025-06-02 20:41:36 -05:00
|
|
|
.add_service(RelayServer::new(handler))
|
|
|
|
|
.serve(([0, 0, 0, 0], 50051).into())
|
2025-06-01 13:31:22 -05:00
|
|
|
.await?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|