use crate::logging::info;
use crate::{
interface_manager::{
InterfaceState, Profile,
interface_impls::embassy_usb::EmbassyInterface,
profiles::direct_edge::{DirectEdge, process_frame},
},
net_stack::NetStackHandle,
};
use bbq2::traits::bbqhdl::BbqHandle;
use embassy_usb_0_5::driver::{Driver, Endpoint, EndpointError, EndpointOut};
pub type EmbassyUsbManager<Q> = DirectEdge<EmbassyInterface<Q>>;
pub struct RxWorker<Q, N, D>
where
N: NetStackHandle<Profile = EmbassyUsbManager<Q>>,
Q: BbqHandle + 'static,
D: Driver<'static>,
{
nsh: N,
rx: D::EndpointOut,
net_id: Option<u16>,
}
enum ReceiverError {
ReceivedMessageTooLarge,
ConnectionClosed,
}
impl<Q, N, D> RxWorker<Q, N, D>
where
N: NetStackHandle<Profile = EmbassyUsbManager<Q>>,
Q: BbqHandle + 'static,
D: Driver<'static>,
{
pub fn new(stack: N, rx: D::EndpointOut) -> Self {
Self {
nsh: stack,
rx,
net_id: None,
}
}
pub async fn run(mut self, frame: &mut [u8], max_usb_frame_size: usize) -> ! {
assert!(max_usb_frame_size.is_power_of_two());
loop {
self.rx.wait_enabled().await;
info!("Connection established");
_ = self
.nsh
.stack()
.manage_profile(|im| im.set_interface_state((), InterfaceState::Inactive));
self.one_conn(frame, max_usb_frame_size).await;
info!("Connection lost");
self.nsh.stack().manage_profile(|im| {
_ = im.set_interface_state((), InterfaceState::Down);
});
}
}
async fn one_conn(&mut self, frame: &mut [u8], max_usb_frame_size: usize) {
loop {
match self.one_frame(frame, max_usb_frame_size).await {
Ok(f) => {
process_frame(&mut self.net_id, f, &self.nsh, ());
}
Err(ReceiverError::ConnectionClosed) => break,
Err(_e) => {
continue;
}
}
}
}
async fn one_frame<'a>(
&mut self,
frame: &'a mut [u8],
max_frame_len: usize,
) -> Result<&'a mut [u8], ReceiverError> {
let buflen = frame.len();
let mut window = &mut frame[..];
while !window.is_empty() {
let n = match self.rx.read(window).await {
Ok(n) => n,
Err(EndpointError::BufferOverflow) => {
return Err(ReceiverError::ReceivedMessageTooLarge);
}
Err(EndpointError::Disabled) => return Err(ReceiverError::ConnectionClosed),
};
let (_now, later) = window.split_at_mut(n);
window = later;
if n != max_frame_len {
let wlen = window.len();
let len = buflen - wlen;
let frame = &mut frame[..len];
return Ok(frame);
}
}
loop {
match self.rx.read(frame).await {
Ok(n) if n == max_frame_len => {}
Ok(_) => return Err(ReceiverError::ReceivedMessageTooLarge),
Err(EndpointError::BufferOverflow) => {
return Err(ReceiverError::ReceivedMessageTooLarge);
}
Err(EndpointError::Disabled) => return Err(ReceiverError::ConnectionClosed),
};
}
}
}
impl<Q, N, D> Drop for RxWorker<Q, N, D>
where
N: NetStackHandle<Profile = EmbassyUsbManager<Q>>,
Q: BbqHandle + 'static,
D: Driver<'static>,
{
fn drop(&mut self) {
self.nsh.stack().manage_profile(|im| {
_ = im.set_interface_state((), InterfaceState::Down);
})
}
}