diff options
Diffstat (limited to 'embassy-net/src/device.rs')
| -rw-r--r-- | embassy-net/src/device.rs | 163 |
1 files changed, 89 insertions, 74 deletions
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 4bdfd7720..5d86ca91e 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs | |||
| @@ -1,10 +1,7 @@ | |||
| 1 | use core::task::Waker; | 1 | use core::task::Context; |
| 2 | 2 | ||
| 3 | use smoltcp::phy::{Device as SmolDevice, DeviceCapabilities}; | 3 | use smoltcp::phy; |
| 4 | use smoltcp::time::Instant as SmolInstant; | 4 | pub use smoltcp::phy::{Checksum, ChecksumCapabilities, DeviceCapabilities, Medium}; |
| 5 | |||
| 6 | use crate::packet_pool::PacketBoxExt; | ||
| 7 | use crate::{Packet, PacketBox, PacketBuf}; | ||
| 8 | 5 | ||
| 9 | #[derive(PartialEq, Eq, Clone, Copy)] | 6 | #[derive(PartialEq, Eq, Clone, Copy)] |
| 10 | pub enum LinkState { | 7 | pub enum LinkState { |
| @@ -13,115 +10,133 @@ pub enum LinkState { | |||
| 13 | } | 10 | } |
| 14 | 11 | ||
| 15 | pub trait Device { | 12 | pub trait Device { |
| 16 | fn is_transmit_ready(&mut self) -> bool; | 13 | type RxToken<'a>: RxToken |
| 17 | fn transmit(&mut self, pkt: PacketBuf); | 14 | where |
| 18 | fn receive(&mut self) -> Option<PacketBuf>; | 15 | Self: 'a; |
| 16 | type TxToken<'a>: TxToken | ||
| 17 | where | ||
| 18 | Self: 'a; | ||
| 19 | 19 | ||
| 20 | fn register_waker(&mut self, waker: &Waker); | 20 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>; |
| 21 | fn capabilities(&self) -> DeviceCapabilities; | 21 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>; |
| 22 | fn link_state(&mut self) -> LinkState; | 22 | fn link_state(&mut self, cx: &mut Context) -> LinkState; |
| 23 | |||
| 24 | fn capabilities(&self) -> phy::DeviceCapabilities; | ||
| 23 | fn ethernet_address(&self) -> [u8; 6]; | 25 | fn ethernet_address(&self) -> [u8; 6]; |
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | impl<T: ?Sized + Device> Device for &mut T { | 28 | impl<T: ?Sized + Device> Device for &mut T { |
| 27 | fn is_transmit_ready(&mut self) -> bool { | 29 | type RxToken<'a> = T::RxToken<'a> |
| 28 | T::is_transmit_ready(self) | 30 | where |
| 29 | } | 31 | Self: 'a; |
| 30 | fn transmit(&mut self, pkt: PacketBuf) { | 32 | type TxToken<'a> = T::TxToken<'a> |
| 31 | T::transmit(self, pkt) | 33 | where |
| 32 | } | 34 | Self: 'a; |
| 33 | fn receive(&mut self) -> Option<PacketBuf> { | 35 | |
| 34 | T::receive(self) | 36 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { |
| 37 | T::transmit(self, cx) | ||
| 35 | } | 38 | } |
| 36 | fn register_waker(&mut self, waker: &Waker) { | 39 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { |
| 37 | T::register_waker(self, waker) | 40 | T::receive(self, cx) |
| 38 | } | 41 | } |
| 39 | fn capabilities(&self) -> DeviceCapabilities { | 42 | fn capabilities(&self) -> phy::DeviceCapabilities { |
| 40 | T::capabilities(self) | 43 | T::capabilities(self) |
| 41 | } | 44 | } |
| 42 | fn link_state(&mut self) -> LinkState { | 45 | fn link_state(&mut self, cx: &mut Context) -> LinkState { |
| 43 | T::link_state(self) | 46 | T::link_state(self, cx) |
| 44 | } | 47 | } |
| 45 | fn ethernet_address(&self) -> [u8; 6] { | 48 | fn ethernet_address(&self) -> [u8; 6] { |
| 46 | T::ethernet_address(self) | 49 | T::ethernet_address(self) |
| 47 | } | 50 | } |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | pub struct DeviceAdapter<D: Device> { | 53 | /// A token to receive a single network packet. |
| 51 | pub device: D, | 54 | pub trait RxToken { |
| 52 | caps: DeviceCapabilities, | 55 | /// Consumes the token to receive a single network packet. |
| 56 | /// | ||
| 57 | /// This method receives a packet and then calls the given closure `f` with the raw | ||
| 58 | /// packet bytes as argument. | ||
| 59 | fn consume<R, F>(self, f: F) -> R | ||
| 60 | where | ||
| 61 | F: FnOnce(&mut [u8]) -> R; | ||
| 53 | } | 62 | } |
| 54 | 63 | ||
| 55 | impl<D: Device> DeviceAdapter<D> { | 64 | /// A token to transmit a single network packet. |
| 56 | pub(crate) fn new(device: D) -> Self { | 65 | pub trait TxToken { |
| 57 | Self { | 66 | /// Consumes the token to send a single network packet. |
| 58 | caps: device.capabilities(), | 67 | /// |
| 59 | device, | 68 | /// This method constructs a transmit buffer of size `len` and calls the passed |
| 60 | } | 69 | /// closure `f` with a mutable reference to that buffer. The closure should construct |
| 61 | } | 70 | /// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure |
| 71 | /// returns, the transmit buffer is sent out. | ||
| 72 | fn consume<R, F>(self, len: usize, f: F) -> R | ||
| 73 | where | ||
| 74 | F: FnOnce(&mut [u8]) -> R; | ||
| 75 | } | ||
| 76 | |||
| 77 | /////////////////////////// | ||
| 78 | |||
| 79 | pub(crate) struct DeviceAdapter<'d, 'c, T> | ||
| 80 | where | ||
| 81 | T: Device, | ||
| 82 | { | ||
| 83 | // must be Some when actually using this to rx/tx | ||
| 84 | pub cx: Option<&'d mut Context<'c>>, | ||
| 85 | pub inner: &'d mut T, | ||
| 62 | } | 86 | } |
| 63 | 87 | ||
| 64 | impl<D: Device> SmolDevice for DeviceAdapter<D> { | 88 | impl<'d, 'c, T> phy::Device for DeviceAdapter<'d, 'c, T> |
| 65 | type RxToken<'a> = RxToken where Self: 'a; | 89 | where |
| 66 | type TxToken<'a> = TxToken<'a, D> where Self: 'a; | 90 | T: Device, |
| 91 | { | ||
| 92 | type RxToken<'a> = RxTokenAdapter<T::RxToken<'a>> where Self: 'a; | ||
| 93 | type TxToken<'a> = TxTokenAdapter<T::TxToken<'a>> where Self: 'a; | ||
| 67 | 94 | ||
| 68 | fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { | 95 | fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { |
| 69 | let tx_pkt = PacketBox::new(Packet::new())?; | 96 | self.inner |
| 70 | let rx_pkt = self.device.receive()?; | 97 | .receive(self.cx.as_deref_mut().unwrap()) |
| 71 | let rx_token = RxToken { pkt: rx_pkt }; | 98 | .map(|(rx, tx)| (RxTokenAdapter(rx), TxTokenAdapter(tx))) |
| 72 | let tx_token = TxToken { | ||
| 73 | device: &mut self.device, | ||
| 74 | pkt: tx_pkt, | ||
| 75 | }; | ||
| 76 | |||
| 77 | Some((rx_token, tx_token)) | ||
| 78 | } | 99 | } |
| 79 | 100 | ||
| 80 | /// Construct a transmit token. | 101 | /// Construct a transmit token. |
| 81 | fn transmit(&mut self) -> Option<Self::TxToken<'_>> { | 102 | fn transmit(&mut self) -> Option<Self::TxToken<'_>> { |
| 82 | if !self.device.is_transmit_ready() { | 103 | self.inner.transmit(self.cx.as_deref_mut().unwrap()).map(TxTokenAdapter) |
| 83 | return None; | ||
| 84 | } | ||
| 85 | |||
| 86 | let tx_pkt = PacketBox::new(Packet::new())?; | ||
| 87 | Some(TxToken { | ||
| 88 | device: &mut self.device, | ||
| 89 | pkt: tx_pkt, | ||
| 90 | }) | ||
| 91 | } | 104 | } |
| 92 | 105 | ||
| 93 | /// Get a description of device capabilities. | 106 | /// Get a description of device capabilities. |
| 94 | fn capabilities(&self) -> DeviceCapabilities { | 107 | fn capabilities(&self) -> phy::DeviceCapabilities { |
| 95 | self.caps.clone() | 108 | self.inner.capabilities() |
| 96 | } | 109 | } |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 99 | pub struct RxToken { | 112 | pub(crate) struct RxTokenAdapter<T>(T) |
| 100 | pkt: PacketBuf, | 113 | where |
| 101 | } | 114 | T: RxToken; |
| 102 | 115 | ||
| 103 | impl smoltcp::phy::RxToken for RxToken { | 116 | impl<T> phy::RxToken for RxTokenAdapter<T> |
| 104 | fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> smoltcp::Result<R> | 117 | where |
| 118 | T: RxToken, | ||
| 119 | { | ||
| 120 | fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, f: F) -> smoltcp::Result<R> | ||
| 105 | where | 121 | where |
| 106 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, | 122 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 107 | { | 123 | { |
| 108 | f(&mut self.pkt) | 124 | self.0.consume(|buf| f(buf)) |
| 109 | } | 125 | } |
| 110 | } | 126 | } |
| 111 | 127 | ||
| 112 | pub struct TxToken<'a, D: Device> { | 128 | pub(crate) struct TxTokenAdapter<T>(T) |
| 113 | device: &'a mut D, | 129 | where |
| 114 | pkt: PacketBox, | 130 | T: TxToken; |
| 115 | } | ||
| 116 | 131 | ||
| 117 | impl<'a, D: Device> smoltcp::phy::TxToken for TxToken<'a, D> { | 132 | impl<T> phy::TxToken for TxTokenAdapter<T> |
| 118 | fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> smoltcp::Result<R> | 133 | where |
| 134 | T: TxToken, | ||
| 135 | { | ||
| 136 | fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, len: usize, f: F) -> smoltcp::Result<R> | ||
| 119 | where | 137 | where |
| 120 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, | 138 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 121 | { | 139 | { |
| 122 | let mut buf = self.pkt.slice(0..len); | 140 | self.0.consume(len, |buf| f(buf)) |
| 123 | let r = f(&mut buf)?; | ||
| 124 | self.device.transmit(buf); | ||
| 125 | Ok(r) | ||
| 126 | } | 141 | } |
| 127 | } | 142 | } |
