aboutsummaryrefslogtreecommitdiff
path: root/embassy-net/src/device.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-net/src/device.rs')
-rw-r--r--embassy-net/src/device.rs163
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 @@
1use core::task::Waker; 1use core::task::Context;
2 2
3use smoltcp::phy::{Device as SmolDevice, DeviceCapabilities}; 3use smoltcp::phy;
4use smoltcp::time::Instant as SmolInstant; 4pub use smoltcp::phy::{Checksum, ChecksumCapabilities, DeviceCapabilities, Medium};
5
6use crate::packet_pool::PacketBoxExt;
7use crate::{Packet, PacketBox, PacketBuf};
8 5
9#[derive(PartialEq, Eq, Clone, Copy)] 6#[derive(PartialEq, Eq, Clone, Copy)]
10pub enum LinkState { 7pub enum LinkState {
@@ -13,115 +10,133 @@ pub enum LinkState {
13} 10}
14 11
15pub trait Device { 12pub 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
26impl<T: ?Sized + Device> Device for &mut T { 28impl<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
50pub struct DeviceAdapter<D: Device> { 53/// A token to receive a single network packet.
51 pub device: D, 54pub 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
55impl<D: Device> DeviceAdapter<D> { 64/// A token to transmit a single network packet.
56 pub(crate) fn new(device: D) -> Self { 65pub 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
79pub(crate) struct DeviceAdapter<'d, 'c, T>
80where
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
64impl<D: Device> SmolDevice for DeviceAdapter<D> { 88impl<'d, 'c, T> phy::Device for DeviceAdapter<'d, 'c, T>
65 type RxToken<'a> = RxToken where Self: 'a; 89where
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
99pub struct RxToken { 112pub(crate) struct RxTokenAdapter<T>(T)
100 pkt: PacketBuf, 113where
101} 114 T: RxToken;
102 115
103impl smoltcp::phy::RxToken for RxToken { 116impl<T> phy::RxToken for RxTokenAdapter<T>
104 fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> smoltcp::Result<R> 117where
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
112pub struct TxToken<'a, D: Device> { 128pub(crate) struct TxTokenAdapter<T>(T)
113 device: &'a mut D, 129where
114 pkt: PacketBox, 130 T: TxToken;
115}
116 131
117impl<'a, D: Device> smoltcp::phy::TxToken for TxToken<'a, D> { 132impl<T> phy::TxToken for TxTokenAdapter<T>
118 fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> smoltcp::Result<R> 133where
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}