update to main

This commit is contained in:
Brad Stein 2025-06-01 21:26:57 -05:00
parent 685ace2dff
commit bed03404fe

View File

@ -1,30 +1,25 @@
//! navka-server bridge HID reports between client (gRPC) and /dev/hidg0 //! navka-server echoes HID reports back to every client
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
use anyhow::Result; use anyhow::Result;
use navka_common::navka::{ use tokio::{sync::mpsc, task};
hid_report::*, relay_server::Relay, HidReport, RelayServer, use tokio_stream::wrappers::ReceiverStream;
}; use tonic::{Request, Response, Status, transport::Server};
use std::{path::Path, sync::Arc}; use tonic::async_trait;
use tokio::{
fs::OpenOptions,
io::AsyncWriteExt,
signal,
sync::{mpsc, Mutex},
};
use tonic::{transport::Server, Request, Response, Status};
/// Implementation of the gRPC service generated by tonic-build. use navka_common::navka::{
#[derive(Debug)] relay_server::{Relay, RelayServer},
pub struct RelaySvc { HidReport,
/// Shared handle to /dev/hidg0 (protected by a mutex because several };
/// gRPC streams may write concurrently).
hidg: Arc<Mutex<tokio::fs::File>>, struct RelaySvc {
// shared broadcast channel (unused for now, but kept for future fan-out)
_hub_tx: mpsc::Sender<HidReport>,
} }
#[tonic::async_trait] #[async_trait]
impl Relay for RelaySvc { impl Relay for RelaySvc {
type StreamStream = tokio_stream::wrappers::ReceiverStream<Result<HidReport, Status>>; type StreamStream = ReceiverStream<Result<HidReport, Status>>;
async fn stream( async fn stream(
&self, &self,
@ -32,42 +27,34 @@ impl Relay for RelaySvc {
) -> Result<Response<Self::StreamStream>, Status> { ) -> Result<Response<Self::StreamStream>, Status> {
let mut inbound = request.into_inner(); let mut inbound = request.into_inner();
// Channel well use if one day we need to send something back. // each connected client gets its own outbound channel
let (tx, rx) = mpsc::channel(32); let (tx, rx) = mpsc::channel::<Result<HidReport, Status>>(32);
let outbound = ReceiverStream::new(rx);
let hidg = self.hidg.clone(); // task: read → echo
tokio::spawn(async move { task::spawn(async move {
while let Some(report) = inbound.message().await.transpose()? { while let Some(report) = inbound.message().await? {
// Write raw 8-byte packet to the gadget device // errors here just mean the client hung up stop the loop
hidg.lock().await.write_all(&report.data).await?; if tx.send(Ok(report)).await.is_err() {
break;
}
} }
Ok::<(), anyhow::Error>(()) Ok::<(), Status>(())
}); });
Ok(Response::new(tokio_stream::wrappers::ReceiverStream::new(rx))) Ok(Response::new(outbound))
} }
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
// Open /dev/hidg0 once and share it. // placeholder hub youll reuse this when you forward to the OTG gadget
let hid_dev = if Path::new("/dev/hidg0").exists() { let (hub_tx, _hub_rx) = mpsc::channel::<HidReport>(32);
OpenOptions::new().write(true).open("/dev/hidg0").await?
} else {
anyhow::bail!("/dev/hidg0 not found is navka-gadget running?");
};
let svc = RelayServer::new(RelaySvc { println!("🌀 navka-server listening on 0.0.0.0:50051");
hidg: Arc::new(Mutex::new(hid_dev)),
});
println!("🛰️ navka-server listening on 0.0.0.0:50051");
Server::builder() Server::builder()
.add_service(svc) .add_service(RelayServer::new(RelaySvc { _hub_tx: hub_tx }))
.serve_with_shutdown("0.0.0.0:50051".parse()?, async { .serve("0.0.0.0:50051".parse().unwrap())
signal::ctrl_c().await.ok();
})
.await?; .await?;
Ok(()) Ok(())
} }