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.rs117
1 files changed, 38 insertions, 79 deletions
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs
index 5d86ca91e..44f7dc7bd 100644
--- a/embassy-net/src/device.rs
+++ b/embassy-net/src/device.rs
@@ -1,93 +1,20 @@
1use core::task::Context; 1use core::task::Context;
2 2
3use embassy_net_driver::{Capabilities, Checksum, Driver, Medium, RxToken, TxToken};
3use smoltcp::phy; 4use smoltcp::phy;
4pub use smoltcp::phy::{Checksum, ChecksumCapabilities, DeviceCapabilities, Medium};
5 5
6#[derive(PartialEq, Eq, Clone, Copy)] 6pub(crate) struct DriverAdapter<'d, 'c, T>
7pub enum LinkState {
8 Down,
9 Up,
10}
11
12pub trait Device {
13 type RxToken<'a>: RxToken
14 where
15 Self: 'a;
16 type TxToken<'a>: TxToken
17 where
18 Self: 'a;
19
20 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>;
21 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>;
22 fn link_state(&mut self, cx: &mut Context) -> LinkState;
23
24 fn capabilities(&self) -> phy::DeviceCapabilities;
25 fn ethernet_address(&self) -> [u8; 6];
26}
27
28impl<T: ?Sized + Device> Device for &mut T {
29 type RxToken<'a> = T::RxToken<'a>
30 where
31 Self: 'a;
32 type TxToken<'a> = T::TxToken<'a>
33 where
34 Self: 'a;
35
36 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
37 T::transmit(self, cx)
38 }
39 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
40 T::receive(self, cx)
41 }
42 fn capabilities(&self) -> phy::DeviceCapabilities {
43 T::capabilities(self)
44 }
45 fn link_state(&mut self, cx: &mut Context) -> LinkState {
46 T::link_state(self, cx)
47 }
48 fn ethernet_address(&self) -> [u8; 6] {
49 T::ethernet_address(self)
50 }
51}
52
53/// A token to receive a single network packet.
54pub trait RxToken {
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;
62}
63
64/// A token to transmit a single network packet.
65pub trait TxToken {
66 /// Consumes the token to send a single network packet.
67 ///
68 /// This method constructs a transmit buffer of size `len` and calls the passed
69 /// closure `f` with a mutable reference to that buffer. The closure should construct
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 7where
81 T: Device, 8 T: Driver,
82{ 9{
83 // must be Some when actually using this to rx/tx 10 // must be Some when actually using this to rx/tx
84 pub cx: Option<&'d mut Context<'c>>, 11 pub cx: Option<&'d mut Context<'c>>,
85 pub inner: &'d mut T, 12 pub inner: &'d mut T,
86} 13}
87 14
88impl<'d, 'c, T> phy::Device for DeviceAdapter<'d, 'c, T> 15impl<'d, 'c, T> phy::Device for DriverAdapter<'d, 'c, T>
89where 16where
90 T: Device, 17 T: Driver,
91{ 18{
92 type RxToken<'a> = RxTokenAdapter<T::RxToken<'a>> where Self: 'a; 19 type RxToken<'a> = RxTokenAdapter<T::RxToken<'a>> where Self: 'a;
93 type TxToken<'a> = TxTokenAdapter<T::TxToken<'a>> where Self: 'a; 20 type TxToken<'a> = TxTokenAdapter<T::TxToken<'a>> where Self: 'a;
@@ -105,7 +32,39 @@ where
105 32
106 /// Get a description of device capabilities. 33 /// Get a description of device capabilities.
107 fn capabilities(&self) -> phy::DeviceCapabilities { 34 fn capabilities(&self) -> phy::DeviceCapabilities {
108 self.inner.capabilities() 35 fn convert(c: Checksum) -> phy::Checksum {
36 match c {
37 Checksum::Both => phy::Checksum::Both,
38 Checksum::Tx => phy::Checksum::Tx,
39 Checksum::Rx => phy::Checksum::Rx,
40 Checksum::None => phy::Checksum::None,
41 }
42 }
43 let caps: Capabilities = self.inner.capabilities();
44 let mut smolcaps = phy::DeviceCapabilities::default();
45
46 smolcaps.max_transmission_unit = caps.max_transmission_unit;
47 smolcaps.max_burst_size = caps.max_burst_size;
48 smolcaps.medium = match caps.medium {
49 #[cfg(feature = "medium-ethernet")]
50 Medium::Ethernet => phy::Medium::Ethernet,
51 #[cfg(feature = "medium-ip")]
52 Medium::Ip => phy::Medium::Ip,
53 _ => panic!(
54 "Unsupported medium {:?}. MAke sure to enable it in embassy-net's Cargo features.",
55 caps.medium
56 ),
57 };
58 smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4);
59 #[cfg(feature = "proto-ipv6")]
60 {
61 smolcaps.checksum.ipv6 = convert(caps.checksum.ipv6);
62 }
63 smolcaps.checksum.tcp = convert(caps.checksum.tcp);
64 smolcaps.checksum.udp = convert(caps.checksum.udp);
65 smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4);
66
67 smolcaps
109 } 68 }
110} 69}
111 70