use core::task::Context; use embassy_net_driver::{Capabilities, Checksum, Driver, Medium, RxToken, TxToken}; use smoltcp::phy; use smoltcp::time::Instant; pub(crate) struct DriverAdapter<'d, 'c, T> where T: Driver, { // must be Some when actually using this to rx/tx pub cx: Option<&'d mut Context<'c>>, pub inner: &'d mut T, } impl<'d, 'c, T> phy::Device for DriverAdapter<'d, 'c, T> where T: Driver, { type RxToken<'a> = RxTokenAdapter> where Self: 'a; type TxToken<'a> = TxTokenAdapter> where Self: 'a; fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { self.inner .receive(self.cx.as_deref_mut().unwrap()) .map(|(rx, tx)| (RxTokenAdapter(rx), TxTokenAdapter(tx))) } /// Construct a transmit token. fn transmit(&mut self, _timestamp: Instant) -> Option> { self.inner.transmit(self.cx.as_deref_mut().unwrap()).map(TxTokenAdapter) } /// Get a description of device capabilities. fn capabilities(&self) -> phy::DeviceCapabilities { fn convert(c: Checksum) -> phy::Checksum { match c { Checksum::Both => phy::Checksum::Both, Checksum::Tx => phy::Checksum::Tx, Checksum::Rx => phy::Checksum::Rx, Checksum::None => phy::Checksum::None, } } let caps: Capabilities = self.inner.capabilities(); let mut smolcaps = phy::DeviceCapabilities::default(); smolcaps.max_transmission_unit = caps.max_transmission_unit; smolcaps.max_burst_size = caps.max_burst_size; smolcaps.medium = match caps.medium { #[cfg(feature = "medium-ethernet")] Medium::Ethernet => phy::Medium::Ethernet, #[cfg(feature = "medium-ip")] Medium::Ip => phy::Medium::Ip, #[allow(unreachable_patterns)] _ => panic!( "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", caps.medium ), }; smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4); smolcaps.checksum.tcp = convert(caps.checksum.tcp); smolcaps.checksum.udp = convert(caps.checksum.udp); #[cfg(feature = "proto-ipv4")] { smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4); } #[cfg(feature = "proto-ipv6")] { smolcaps.checksum.icmpv6 = convert(caps.checksum.icmpv6); } smolcaps } } pub(crate) struct RxTokenAdapter(T) where T: RxToken; impl phy::RxToken for RxTokenAdapter where T: RxToken, { fn consume(self, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { self.0.consume(|buf| f(buf)) } } pub(crate) struct TxTokenAdapter(T) where T: TxToken; impl phy::TxToken for TxTokenAdapter where T: TxToken, { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { self.0.consume(len, |buf| f(buf)) } }