use core::task::Waker; use smoltcp::phy::Device as SmolDevice; use smoltcp::phy::DeviceCapabilities; use smoltcp::time::Instant as SmolInstant; use crate::packet_pool::PacketBoxExt; use crate::Result; use crate::{Packet, PacketBox, PacketBuf}; #[derive(PartialEq, Eq, Clone, Copy)] pub enum LinkState { Down, Up, } pub trait Device { fn is_transmit_ready(&mut self) -> bool; fn transmit(&mut self, pkt: PacketBuf); fn receive(&mut self) -> Option; fn register_waker(&mut self, waker: &Waker); fn capabilities(&mut self) -> DeviceCapabilities; fn link_state(&mut self) -> LinkState; fn ethernet_address(&self) -> [u8; 6]; } pub struct DeviceAdapter { pub device: &'static mut dyn Device, caps: DeviceCapabilities, } impl DeviceAdapter { pub(crate) fn new(device: &'static mut dyn Device) -> Self { Self { caps: device.capabilities(), device, } } } impl<'a> SmolDevice<'a> for DeviceAdapter { type RxToken = RxToken; type TxToken = TxToken<'a>; fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { let tx_pkt = PacketBox::new(Packet::new())?; let rx_pkt = self.device.receive()?; let rx_token = RxToken { pkt: rx_pkt }; let tx_token = TxToken { device: self.device, pkt: tx_pkt, }; Some((rx_token, tx_token)) } /// Construct a transmit token. fn transmit(&'a mut self) -> Option { if !self.device.is_transmit_ready() { return None; } let tx_pkt = PacketBox::new(Packet::new())?; Some(TxToken { device: self.device, pkt: tx_pkt, }) } /// Get a description of device capabilities. fn capabilities(&self) -> DeviceCapabilities { self.caps.clone() } } pub struct RxToken { pkt: PacketBuf, } impl smoltcp::phy::RxToken for RxToken { fn consume(mut self, _timestamp: SmolInstant, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result, { f(&mut self.pkt) } } pub struct TxToken<'a> { device: &'a mut dyn Device, pkt: PacketBox, } impl<'a> smoltcp::phy::TxToken for TxToken<'a> { fn consume(self, _timestamp: SmolInstant, len: usize, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result, { let mut buf = self.pkt.slice(0..len); let r = f(&mut buf)?; self.device.transmit(buf); Ok(r) } }