2022-12-07 14:55:46 +00:00
|
|
|
use core::task::Context;
|
2022-06-12 20:15:44 +00:00
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
use smoltcp::phy;
|
|
|
|
pub use smoltcp::phy::{Checksum, ChecksumCapabilities, DeviceCapabilities, Medium};
|
2021-02-03 04:09:37 +00:00
|
|
|
|
|
|
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
|
|
|
pub enum LinkState {
|
|
|
|
Down,
|
|
|
|
Up,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Device {
|
2022-12-07 14:55:46 +00:00
|
|
|
type RxToken<'a>: RxToken
|
|
|
|
where
|
|
|
|
Self: 'a;
|
|
|
|
type TxToken<'a>: TxToken
|
|
|
|
where
|
|
|
|
Self: 'a;
|
2021-02-03 04:09:37 +00:00
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>;
|
|
|
|
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>;
|
|
|
|
fn link_state(&mut self, cx: &mut Context) -> LinkState;
|
|
|
|
|
|
|
|
fn capabilities(&self) -> phy::DeviceCapabilities;
|
2022-05-02 14:15:05 +00:00
|
|
|
fn ethernet_address(&self) -> [u8; 6];
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-06 23:28:38 +00:00
|
|
|
impl<T: ?Sized + Device> Device for &mut T {
|
2022-12-07 14:55:46 +00:00
|
|
|
type RxToken<'a> = T::RxToken<'a>
|
|
|
|
where
|
|
|
|
Self: 'a;
|
|
|
|
type TxToken<'a> = T::TxToken<'a>
|
|
|
|
where
|
|
|
|
Self: 'a;
|
|
|
|
|
|
|
|
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
|
|
|
|
T::transmit(self, cx)
|
2022-05-23 01:50:43 +00:00
|
|
|
}
|
2022-12-07 14:55:46 +00:00
|
|
|
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
|
|
|
T::receive(self, cx)
|
2022-05-23 01:50:43 +00:00
|
|
|
}
|
2022-12-07 14:55:46 +00:00
|
|
|
fn capabilities(&self) -> phy::DeviceCapabilities {
|
2022-05-23 01:50:43 +00:00
|
|
|
T::capabilities(self)
|
|
|
|
}
|
2022-12-07 14:55:46 +00:00
|
|
|
fn link_state(&mut self, cx: &mut Context) -> LinkState {
|
|
|
|
T::link_state(self, cx)
|
2022-05-23 01:50:43 +00:00
|
|
|
}
|
|
|
|
fn ethernet_address(&self) -> [u8; 6] {
|
|
|
|
T::ethernet_address(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
/// A token to receive a single network packet.
|
|
|
|
pub trait RxToken {
|
|
|
|
/// Consumes the token to receive a single network packet.
|
|
|
|
///
|
|
|
|
/// This method receives a packet and then calls the given closure `f` with the raw
|
|
|
|
/// packet bytes as argument.
|
|
|
|
fn consume<R, F>(self, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> R;
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
/// A token to transmit a single network packet.
|
|
|
|
pub trait TxToken {
|
|
|
|
/// Consumes the token to send a single network packet.
|
|
|
|
///
|
|
|
|
/// This method constructs a transmit buffer of size `len` and calls the passed
|
|
|
|
/// closure `f` with a mutable reference to that buffer. The closure should construct
|
|
|
|
/// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure
|
|
|
|
/// returns, the transmit buffer is sent out.
|
|
|
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> R;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
|
|
|
|
pub(crate) struct DeviceAdapter<'d, 'c, T>
|
|
|
|
where
|
|
|
|
T: Device,
|
|
|
|
{
|
|
|
|
// must be Some when actually using this to rx/tx
|
|
|
|
pub cx: Option<&'d mut Context<'c>>,
|
|
|
|
pub inner: &'d mut T,
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
impl<'d, 'c, T> phy::Device for DeviceAdapter<'d, 'c, T>
|
|
|
|
where
|
|
|
|
T: Device,
|
|
|
|
{
|
|
|
|
type RxToken<'a> = RxTokenAdapter<T::RxToken<'a>> where Self: 'a;
|
|
|
|
type TxToken<'a> = TxTokenAdapter<T::TxToken<'a>> where Self: 'a;
|
2021-02-03 04:09:37 +00:00
|
|
|
|
2022-12-06 23:28:38 +00:00
|
|
|
fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
2022-12-07 14:55:46 +00:00
|
|
|
self.inner
|
|
|
|
.receive(self.cx.as_deref_mut().unwrap())
|
|
|
|
.map(|(rx, tx)| (RxTokenAdapter(rx), TxTokenAdapter(tx)))
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a transmit token.
|
2022-12-06 23:28:38 +00:00
|
|
|
fn transmit(&mut self) -> Option<Self::TxToken<'_>> {
|
2022-12-07 14:55:46 +00:00
|
|
|
self.inner.transmit(self.cx.as_deref_mut().unwrap()).map(TxTokenAdapter)
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a description of device capabilities.
|
2022-12-07 14:55:46 +00:00
|
|
|
fn capabilities(&self) -> phy::DeviceCapabilities {
|
|
|
|
self.inner.capabilities()
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
pub(crate) struct RxTokenAdapter<T>(T)
|
|
|
|
where
|
|
|
|
T: RxToken;
|
2021-02-03 04:09:37 +00:00
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
impl<T> phy::RxToken for RxTokenAdapter<T>
|
|
|
|
where
|
|
|
|
T: RxToken,
|
|
|
|
{
|
|
|
|
fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, f: F) -> smoltcp::Result<R>
|
2021-02-03 04:09:37 +00:00
|
|
|
where
|
2022-05-04 18:48:37 +00:00
|
|
|
F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
|
2021-02-03 04:09:37 +00:00
|
|
|
{
|
2022-12-07 14:55:46 +00:00
|
|
|
self.0.consume(|buf| f(buf))
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
pub(crate) struct TxTokenAdapter<T>(T)
|
|
|
|
where
|
|
|
|
T: TxToken;
|
2021-02-03 04:09:37 +00:00
|
|
|
|
2022-12-07 14:55:46 +00:00
|
|
|
impl<T> phy::TxToken for TxTokenAdapter<T>
|
|
|
|
where
|
|
|
|
T: TxToken,
|
|
|
|
{
|
|
|
|
fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, len: usize, f: F) -> smoltcp::Result<R>
|
2021-02-03 04:09:37 +00:00
|
|
|
where
|
2022-05-04 18:48:37 +00:00
|
|
|
F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
|
2021-02-03 04:09:37 +00:00
|
|
|
{
|
2022-12-07 14:55:46 +00:00
|
|
|
self.0.consume(len, |buf| f(buf))
|
2021-02-03 04:09:37 +00:00
|
|
|
}
|
|
|
|
}
|