aboutsummaryrefslogtreecommitdiff
path: root/embassy-net/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-net/src')
-rw-r--r--embassy-net/src/device.rs117
-rw-r--r--embassy-net/src/lib.rs17
-rw-r--r--embassy-net/src/tcp.rs12
-rw-r--r--embassy-net/src/udp.rs5
4 files changed, 55 insertions, 96 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
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index afe0d6da0..b58c9cf36 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -18,6 +18,7 @@ use core::cell::RefCell;
18use core::future::{poll_fn, Future}; 18use core::future::{poll_fn, Future};
19use core::task::{Context, Poll}; 19use core::task::{Context, Poll};
20 20
21use embassy_net_driver::{Driver, LinkState, Medium};
21use embassy_sync::waitqueue::WakerRegistration; 22use embassy_sync::waitqueue::WakerRegistration;
22use embassy_time::{Instant, Timer}; 23use embassy_time::{Instant, Timer};
23use futures::pin_mut; 24use futures::pin_mut;
@@ -27,8 +28,6 @@ use smoltcp::iface::SocketHandle;
27use smoltcp::iface::{Interface, InterfaceBuilder, SocketSet, SocketStorage}; 28use smoltcp::iface::{Interface, InterfaceBuilder, SocketSet, SocketStorage};
28#[cfg(feature = "medium-ethernet")] 29#[cfg(feature = "medium-ethernet")]
29use smoltcp::iface::{Neighbor, NeighborCache, Route, Routes}; 30use smoltcp::iface::{Neighbor, NeighborCache, Route, Routes};
30#[cfg(feature = "medium-ethernet")]
31use smoltcp::phy::Medium;
32#[cfg(feature = "dhcpv4")] 31#[cfg(feature = "dhcpv4")]
33use smoltcp::socket::dhcpv4; 32use smoltcp::socket::dhcpv4;
34// smoltcp reexports 33// smoltcp reexports
@@ -41,7 +40,7 @@ pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr};
41#[cfg(feature = "udp")] 40#[cfg(feature = "udp")]
42pub use smoltcp::{socket::udp::PacketMetadata, wire::IpListenEndpoint}; 41pub use smoltcp::{socket::udp::PacketMetadata, wire::IpListenEndpoint};
43 42
44use crate::device::{Device, DeviceAdapter, LinkState}; 43use crate::device::DriverAdapter;
45 44
46const LOCAL_PORT_MIN: u16 = 1025; 45const LOCAL_PORT_MIN: u16 = 1025;
47const LOCAL_PORT_MAX: u16 = 65535; 46const LOCAL_PORT_MAX: u16 = 65535;
@@ -82,12 +81,12 @@ pub enum ConfigStrategy {
82 Dhcp, 81 Dhcp,
83} 82}
84 83
85pub struct Stack<D: Device> { 84pub struct Stack<D: Driver> {
86 pub(crate) socket: RefCell<SocketStack>, 85 pub(crate) socket: RefCell<SocketStack>,
87 inner: RefCell<Inner<D>>, 86 inner: RefCell<Inner<D>>,
88} 87}
89 88
90struct Inner<D: Device> { 89struct Inner<D: Driver> {
91 device: D, 90 device: D,
92 link_up: bool, 91 link_up: bool,
93 config: Option<Config>, 92 config: Option<Config>,
@@ -102,7 +101,7 @@ pub(crate) struct SocketStack {
102 next_local_port: u16, 101 next_local_port: u16,
103} 102}
104 103
105impl<D: Device + 'static> Stack<D> { 104impl<D: Driver + 'static> Stack<D> {
106 pub fn new<const ADDR: usize, const SOCK: usize, const NEIGH: usize>( 105 pub fn new<const ADDR: usize, const SOCK: usize, const NEIGH: usize>(
107 mut device: D, 106 mut device: D,
108 config: ConfigStrategy, 107 config: ConfigStrategy,
@@ -130,7 +129,7 @@ impl<D: Device + 'static> Stack<D> {
130 b = b.routes(Routes::new(&mut resources.routes[..])); 129 b = b.routes(Routes::new(&mut resources.routes[..]));
131 } 130 }
132 131
133 let iface = b.finalize(&mut DeviceAdapter { 132 let iface = b.finalize(&mut DriverAdapter {
134 inner: &mut device, 133 inner: &mut device,
135 cx: None, 134 cx: None,
136 }); 135 });
@@ -211,7 +210,7 @@ impl SocketStack {
211 } 210 }
212} 211}
213 212
214impl<D: Device + 'static> Inner<D> { 213impl<D: Driver + 'static> Inner<D> {
215 fn apply_config(&mut self, s: &mut SocketStack, config: Config) { 214 fn apply_config(&mut self, s: &mut SocketStack, config: Config) {
216 #[cfg(feature = "medium-ethernet")] 215 #[cfg(feature = "medium-ethernet")]
217 let medium = self.device.capabilities().medium; 216 let medium = self.device.capabilities().medium;
@@ -263,7 +262,7 @@ impl<D: Device + 'static> Inner<D> {
263 s.waker.register(cx.waker()); 262 s.waker.register(cx.waker());
264 263
265 let timestamp = instant_to_smoltcp(Instant::now()); 264 let timestamp = instant_to_smoltcp(Instant::now());
266 let mut smoldev = DeviceAdapter { 265 let mut smoldev = DriverAdapter {
267 cx: Some(cx), 266 cx: Some(cx),
268 inner: &mut self.device, 267 inner: &mut self.device,
269 }; 268 };
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index 0dc8da73a..0fbf0c91b 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -3,12 +3,12 @@ use core::future::poll_fn;
3use core::mem; 3use core::mem;
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_net_driver::Driver;
6use smoltcp::iface::{Interface, SocketHandle}; 7use smoltcp::iface::{Interface, SocketHandle};
7use smoltcp::socket::tcp; 8use smoltcp::socket::tcp;
8use smoltcp::time::Duration; 9use smoltcp::time::Duration;
9use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; 10use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
10 11
11use crate::device::Device;
12use crate::{SocketStack, Stack}; 12use crate::{SocketStack, Stack};
13 13
14#[derive(PartialEq, Eq, Clone, Copy, Debug)] 14#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -66,7 +66,7 @@ impl<'a> TcpWriter<'a> {
66} 66}
67 67
68impl<'a> TcpSocket<'a> { 68impl<'a> TcpSocket<'a> {
69 pub fn new<D: Device>(stack: &'a Stack<D>, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8]) -> Self { 69 pub fn new<D: Driver>(stack: &'a Stack<D>, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8]) -> Self {
70 let s = &mut *stack.socket.borrow_mut(); 70 let s = &mut *stack.socket.borrow_mut();
71 let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; 71 let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) };
72 let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; 72 let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) };
@@ -336,19 +336,19 @@ pub mod client {
336 use super::*; 336 use super::*;
337 337
338 /// TCP client capable of creating up to N multiple connections with tx and rx buffers according to TX_SZ and RX_SZ. 338 /// TCP client capable of creating up to N multiple connections with tx and rx buffers according to TX_SZ and RX_SZ.
339 pub struct TcpClient<'d, D: Device, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { 339 pub struct TcpClient<'d, D: Driver, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> {
340 stack: &'d Stack<D>, 340 stack: &'d Stack<D>,
341 state: &'d TcpClientState<N, TX_SZ, RX_SZ>, 341 state: &'d TcpClientState<N, TX_SZ, RX_SZ>,
342 } 342 }
343 343
344 impl<'d, D: Device, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpClient<'d, D, N, TX_SZ, RX_SZ> { 344 impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpClient<'d, D, N, TX_SZ, RX_SZ> {
345 /// Create a new TcpClient 345 /// Create a new TcpClient
346 pub fn new(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Self { 346 pub fn new(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Self {
347 Self { stack, state } 347 Self { stack, state }
348 } 348 }
349 } 349 }
350 350
351 impl<'d, D: Device, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_nal_async::TcpConnect 351 impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_nal_async::TcpConnect
352 for TcpClient<'d, D, N, TX_SZ, RX_SZ> 352 for TcpClient<'d, D, N, TX_SZ, RX_SZ>
353 { 353 {
354 type Error = Error; 354 type Error = Error;
@@ -386,7 +386,7 @@ pub mod client {
386 } 386 }
387 387
388 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnection<'d, N, TX_SZ, RX_SZ> { 388 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnection<'d, N, TX_SZ, RX_SZ> {
389 fn new<D: Device>(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Result<Self, Error> { 389 fn new<D: Driver>(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Result<Self, Error> {
390 let mut bufs = state.pool.alloc().ok_or(Error::ConnectionReset)?; 390 let mut bufs = state.pool.alloc().ok_or(Error::ConnectionReset)?;
391 Ok(Self { 391 Ok(Self {
392 socket: unsafe { TcpSocket::new(stack, &mut bufs.as_mut().0, &mut bufs.as_mut().1) }, 392 socket: unsafe { TcpSocket::new(stack, &mut bufs.as_mut().0, &mut bufs.as_mut().1) },
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs
index 2f5334df3..0ee8c6e19 100644
--- a/embassy-net/src/udp.rs
+++ b/embassy-net/src/udp.rs
@@ -3,11 +3,12 @@ use core::future::poll_fn;
3use core::mem; 3use core::mem;
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_net_driver::Driver;
6use smoltcp::iface::{Interface, SocketHandle}; 7use smoltcp::iface::{Interface, SocketHandle};
7use smoltcp::socket::udp::{self, PacketMetadata}; 8use smoltcp::socket::udp::{self, PacketMetadata};
8use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; 9use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
9 10
10use crate::{Device, SocketStack, Stack}; 11use crate::{SocketStack, Stack};
11 12
12#[derive(PartialEq, Eq, Clone, Copy, Debug)] 13#[derive(PartialEq, Eq, Clone, Copy, Debug)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))] 14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -31,7 +32,7 @@ pub struct UdpSocket<'a> {
31} 32}
32 33
33impl<'a> UdpSocket<'a> { 34impl<'a> UdpSocket<'a> {
34 pub fn new<D: Device>( 35 pub fn new<D: Driver>(
35 stack: &'a Stack<D>, 36 stack: &'a Stack<D>,
36 rx_meta: &'a mut [PacketMetadata], 37 rx_meta: &'a mut [PacketMetadata],
37 rx_buffer: &'a mut [u8], 38 rx_buffer: &'a mut [u8],