From aacf14b62a28277599871edf74106b1cd2e01795 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 01:04:51 +0200 Subject: net-ppp: Add it. --- embassy-net-ppp/src/fmt.rs | 257 +++++++++++++++++++++++++++++++++++++++++++++ embassy-net-ppp/src/lib.rs | 165 +++++++++++++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 embassy-net-ppp/src/fmt.rs create mode 100644 embassy-net-ppp/src/lib.rs (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs new file mode 100644 index 000000000..91984bde1 --- /dev/null +++ b/embassy-net-ppp/src/fmt.rs @@ -0,0 +1,257 @@ +#![macro_use] +#![allow(unused_macros)] + +use core::fmt::{Debug, Display, LowerHex}; + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unreachable { + ($($x:tt)*) => { + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*); + }; +} + +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} + +pub struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs new file mode 100644 index 000000000..7853e04ab --- /dev/null +++ b/embassy-net-ppp/src/lib.rs @@ -0,0 +1,165 @@ +#![no_std] +#![warn(missing_docs)] +#![doc = include_str!("../README.md")] + +// must be first +mod fmt; + +use core::convert::Infallible; +use core::mem::MaybeUninit; + +use embassy_futures::select::{select3, Either3}; +use embassy_net_driver_channel as ch; +use embassy_net_driver_channel::driver::LinkState; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::signal::Signal; +use embedded_io_async::{BufRead, Write, WriteAllError}; +use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; + +const MTU: usize = 1500; + +/// Type alias for the embassy-net driver. +pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; + +/// Internal state for the embassy-net integration. +pub struct State { + ch_state: ch::State, +} + +impl State { + /// Create a new `State`. + pub const fn new() -> Self { + Self { + ch_state: ch::State::new(), + } + } +} + +/// Background runner for the driver. +/// +/// You must call `.run()` in a background task for the driver to operate. +pub struct Runner<'d, R: BufRead, W: Write> { + ch: ch::Runner<'d, MTU>, + r: R, + w: W, +} + +/// Error returned by [`Runner::run`]. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum RunError { + /// Reading from the serial port failed. + Read(RE), + /// Writing to the serial port failed. + Write(WE), + /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. + WriteZero, + /// Writing to the serial got EOF. + Eof, +} + +impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { + /// You must call this in a background task for the driver to operate. + pub async fn run(mut self) -> Result> { + let config = ppproto::Config { + username: b"myuser", + password: b"mypass", + }; + let mut ppp = PPPoS::new(config); + ppp.open().unwrap(); + + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + state_chan.set_link_state(LinkState::Down); + let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); + + let mut rx_buf = [0; 2048]; + let mut tx_buf = [0; 2048]; + + let poll_signal: Signal = Signal::new(); + poll_signal.signal(()); + + loop { + let mut poll = false; + match select3(self.r.fill_buf(), tx_chan.tx_buf(), poll_signal.wait()).await { + Either3::First(r) => { + let data = r.map_err(RunError::Read)?; + if data.is_empty() { + return Err(RunError::Eof); + } + let n = ppp.consume(data, &mut rx_buf); + self.r.consume(n); + poll = true; + } + Either3::Second(pkt) => { + match ppp.send(pkt, &mut tx_buf) { + Ok(n) => match self.w.write_all(&tx_buf[..n]).await { + Ok(()) => {} + Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), + Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), + }, + Err(BufferFullError) => unreachable!(), + } + tx_chan.tx_done(); + } + Either3::Third(_) => poll = true, + } + + if poll { + match ppp.poll(&mut tx_buf, &mut rx_buf) { + PPPoSAction::None => {} + PPPoSAction::Received(rg) => { + let pkt = &rx_buf[rg]; + let buf = rx_chan.rx_buf().await; // TODO: fix possible deadlock + buf[..pkt.len()].copy_from_slice(pkt); + rx_chan.rx_done(pkt.len()); + + poll_signal.signal(()); + } + PPPoSAction::Transmit(n) => { + match self.w.write_all(&tx_buf[..n]).await { + Ok(()) => {} + Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), + Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), + } + poll_signal.signal(()); + } + } + + match ppp.status().phase { + ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), + _ => state_chan.set_link_state(LinkState::Down), + } + } + } + } +} + +/// Create a PPP embassy-net driver instance. +/// +/// This returns two structs: +/// - a `Device` that you must pass to the `embassy-net` stack. +/// - a `Runner`. You must call `.run()` on it in a background task. +pub fn new<'a, const N_RX: usize, const N_TX: usize, R: BufRead, W: Write>( + state: &'a mut State, + r: R, + w: W, +) -> (Device<'a>, Runner<'a, R, W>) { + let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); + (device, Runner { ch: runner, r, w }) +} + +struct OnDrop { + f: MaybeUninit, +} + +impl OnDrop { + fn new(f: F) -> Self { + Self { f: MaybeUninit::new(f) } + } +} + +impl Drop for OnDrop { + fn drop(&mut self) { + unsafe { self.f.as_ptr().read()() } + } +} -- cgit From 2303382dfd6f4e6275a699b938f465a1e6170449 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 15:39:25 +0200 Subject: net-ppp: nicer processing loop structure that can't deadlock. --- embassy-net-ppp/src/lib.rs | 82 ++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 42 deletions(-) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index 7853e04ab..af216c967 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -8,11 +8,9 @@ mod fmt; use core::convert::Infallible; use core::mem::MaybeUninit; -use embassy_futures::select::{select3, Either3}; +use embassy_futures::select::{select, Either}; use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::signal::Signal; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; @@ -75,59 +73,59 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let mut rx_buf = [0; 2048]; let mut tx_buf = [0; 2048]; - let poll_signal: Signal = Signal::new(); - poll_signal.signal(()); + let mut needs_poll = true; loop { - let mut poll = false; - match select3(self.r.fill_buf(), tx_chan.tx_buf(), poll_signal.wait()).await { - Either3::First(r) => { - let data = r.map_err(RunError::Read)?; - if data.is_empty() { - return Err(RunError::Eof); - } - let n = ppp.consume(data, &mut rx_buf); + let rx_fut = async { + let buf = rx_chan.rx_buf().await; + let rx_data = match needs_poll { + true => &[][..], + false => match self.r.fill_buf().await { + Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), + Ok(rx_data) => rx_data, + Err(e) => return Err(RunError::Read(e)), + }, + }; + Ok((buf, rx_data)) + }; + let tx_fut = tx_chan.tx_buf(); + match select(rx_fut, tx_fut).await { + Either::First(r) => { + needs_poll = false; + + let (buf, rx_data) = r?; + let n = ppp.consume(rx_data, &mut rx_buf); self.r.consume(n); - poll = true; - } - Either3::Second(pkt) => { - match ppp.send(pkt, &mut tx_buf) { - Ok(n) => match self.w.write_all(&tx_buf[..n]).await { + + match ppp.poll(&mut tx_buf, &mut rx_buf) { + PPPoSAction::None => {} + PPPoSAction::Received(rg) => { + let pkt = &rx_buf[rg]; + buf[..pkt.len()].copy_from_slice(pkt); + rx_chan.rx_done(pkt.len()); + } + PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), }, - Err(BufferFullError) => unreachable!(), } - tx_chan.tx_done(); - } - Either3::Third(_) => poll = true, - } - if poll { - match ppp.poll(&mut tx_buf, &mut rx_buf) { - PPPoSAction::None => {} - PPPoSAction::Received(rg) => { - let pkt = &rx_buf[rg]; - let buf = rx_chan.rx_buf().await; // TODO: fix possible deadlock - buf[..pkt.len()].copy_from_slice(pkt); - rx_chan.rx_done(pkt.len()); - - poll_signal.signal(()); + match ppp.status().phase { + ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), + _ => state_chan.set_link_state(LinkState::Down), } - PPPoSAction::Transmit(n) => { - match self.w.write_all(&tx_buf[..n]).await { + } + Either::Second(pkt) => { + match ppp.send(pkt, &mut tx_buf) { + Ok(n) => match self.w.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - } - poll_signal.signal(()); + }, + Err(BufferFullError) => unreachable!(), } - } - - match ppp.status().phase { - ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), - _ => state_chan.set_link_state(LinkState::Down), + tx_chan.tx_done(); } } } -- cgit From c2d601abeff6f9f911b8140f3ceb6806971dc7dd Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 15:57:02 +0200 Subject: net-ppp: take serial port and config in run(), allow calling it multiple times. --- embassy-net-ppp/src/lib.rs | 50 +++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index af216c967..df583fb37 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -13,6 +13,7 @@ use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; +pub use ppproto::Config; const MTU: usize = 1500; @@ -36,37 +37,44 @@ impl State { /// Background runner for the driver. /// /// You must call `.run()` in a background task for the driver to operate. -pub struct Runner<'d, R: BufRead, W: Write> { +pub struct Runner<'d> { ch: ch::Runner<'d, MTU>, - r: R, - w: W, } /// Error returned by [`Runner::run`]. #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum RunError { +pub enum RunError { /// Reading from the serial port failed. - Read(RE), + Read(E), /// Writing to the serial port failed. - Write(WE), + Write(E), /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. WriteZero, /// Writing to the serial got EOF. Eof, } -impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { +impl<'d> Runner<'d> { /// You must call this in a background task for the driver to operate. - pub async fn run(mut self) -> Result> { - let config = ppproto::Config { - username: b"myuser", - password: b"mypass", - }; + /// + /// If reading/writing to the underlying serial port fails, the link state + /// is set to Down and the error is returned. + /// + /// It is allowed to cancel this function's future (i.e. drop it). This will terminate + /// the PPP connection and set the link state to Down. + /// + /// After this function returns or is canceled, you can call it again to establish + /// a new PPP connection. + pub async fn run( + &mut self, + mut rw: RW, + config: ppproto::Config<'_>, + ) -> Result> { let mut ppp = PPPoS::new(config); ppp.open().unwrap(); - let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.borrow_split(); state_chan.set_link_state(LinkState::Down); let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); @@ -80,7 +88,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let buf = rx_chan.rx_buf().await; let rx_data = match needs_poll { true => &[][..], - false => match self.r.fill_buf().await { + false => match rw.fill_buf().await { Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), Ok(rx_data) => rx_data, Err(e) => return Err(RunError::Read(e)), @@ -95,7 +103,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let (buf, rx_data) = r?; let n = ppp.consume(rx_data, &mut rx_buf); - self.r.consume(n); + rw.consume(n); match ppp.poll(&mut tx_buf, &mut rx_buf) { PPPoSAction::None => {} @@ -104,7 +112,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { buf[..pkt.len()].copy_from_slice(pkt); rx_chan.rx_done(pkt.len()); } - PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { + PPPoSAction::Transmit(n) => match rw.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), @@ -118,7 +126,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { } Either::Second(pkt) => { match ppp.send(pkt, &mut tx_buf) { - Ok(n) => match self.w.write_all(&tx_buf[..n]).await { + Ok(n) => match rw.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), @@ -137,13 +145,9 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { /// This returns two structs: /// - a `Device` that you must pass to the `embassy-net` stack. /// - a `Runner`. You must call `.run()` on it in a background task. -pub fn new<'a, const N_RX: usize, const N_TX: usize, R: BufRead, W: Write>( - state: &'a mut State, - r: R, - w: W, -) -> (Device<'a>, Runner<'a, R, W>) { +pub fn new<'a, const N_RX: usize, const N_TX: usize>(state: &'a mut State) -> (Device<'a>, Runner<'a>) { let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); - (device, Runner { ch: runner, r, w }) + (device, Runner { ch: runner }) } struct OnDrop { -- cgit From a026db3f570cae504dc5da6c7055afc52e122930 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 16:04:22 +0200 Subject: net-ppp: use From and ? to handle write errors. --- embassy-net-ppp/src/lib.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index df583fb37..e3b208ee6 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -55,6 +55,15 @@ pub enum RunError { Eof, } +impl From> for RunError { + fn from(value: WriteAllError) -> Self { + match value { + WriteAllError::Other(e) => Self::Write(e), + WriteAllError::WriteZero => Self::WriteZero, + } + } +} + impl<'d> Runner<'d> { /// You must call this in a background task for the driver to operate. /// @@ -112,11 +121,7 @@ impl<'d> Runner<'d> { buf[..pkt.len()].copy_from_slice(pkt); rx_chan.rx_done(pkt.len()); } - PPPoSAction::Transmit(n) => match rw.write_all(&tx_buf[..n]).await { - Ok(()) => {} - Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), - Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - }, + PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await?, } match ppp.status().phase { @@ -126,11 +131,7 @@ impl<'d> Runner<'d> { } Either::Second(pkt) => { match ppp.send(pkt, &mut tx_buf) { - Ok(n) => match rw.write_all(&tx_buf[..n]).await { - Ok(()) => {} - Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), - Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - }, + Ok(n) => rw.write_all(&tx_buf[..n]).await?, Err(BufferFullError) => unreachable!(), } tx_chan.tx_done(); -- cgit From 623f37a27368c53d782cc9819c180bdf45f15612 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 19:49:28 +0200 Subject: net-ppp: add callback for IP configuration. --- embassy-net-ppp/src/lib.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index e3b208ee6..ca87fbaea 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -13,7 +13,7 @@ use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; -pub use ppproto::Config; +pub use ppproto::{Config, Ipv4Status}; const MTU: usize = 1500; @@ -79,6 +79,7 @@ impl<'d> Runner<'d> { &mut self, mut rw: RW, config: ppproto::Config<'_>, + mut on_ipv4_up: impl FnMut(Ipv4Status), ) -> Result> { let mut ppp = PPPoS::new(config); ppp.open().unwrap(); @@ -91,6 +92,7 @@ impl<'d> Runner<'d> { let mut tx_buf = [0; 2048]; let mut needs_poll = true; + let mut was_up = false; loop { let rx_fut = async { @@ -124,9 +126,19 @@ impl<'d> Runner<'d> { PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await?, } - match ppp.status().phase { - ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), - _ => state_chan.set_link_state(LinkState::Down), + let status = ppp.status(); + match status.phase { + ppproto::Phase::Open => { + if !was_up { + on_ipv4_up(status.ipv4.unwrap()); + } + was_up = true; + state_chan.set_link_state(LinkState::Up); + } + _ => { + was_up = false; + state_chan.set_link_state(LinkState::Down); + } } } Either::Second(pkt) => { -- cgit From 975f2f23c0256f192838a5a5cd995faa9ad88f34 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 30 Aug 2023 01:04:43 +0200 Subject: net-ppp: return error when PPP link gets terminated by the peer. --- embassy-net-ppp/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index ca87fbaea..66496ee0a 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -53,6 +53,8 @@ pub enum RunError { WriteZero, /// Writing to the serial got EOF. Eof, + /// PPP protocol was terminated by the peer + Terminated, } impl From> for RunError { @@ -128,6 +130,9 @@ impl<'d> Runner<'d> { let status = ppp.status(); match status.phase { + ppproto::Phase::Dead => { + return Err(RunError::Terminated); + } ppproto::Phase::Open => { if !was_up { on_ipv4_up(status.ipv4.unwrap()); -- cgit From 5e613d9abbb945e7fc7d4c895d645bfad6a3d2c8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 30 Aug 2023 01:37:18 +0200 Subject: Sync all fmt.rs files. --- embassy-net-ppp/src/fmt.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'embassy-net-ppp/src') diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs index 91984bde1..78e583c1c 100644 --- a/embassy-net-ppp/src/fmt.rs +++ b/embassy-net-ppp/src/fmt.rs @@ -93,7 +93,7 @@ macro_rules! unreachable { #[cfg(feature = "defmt")] macro_rules! unreachable { ($($x:tt)*) => { - ::defmt::unreachable!($($x)*); + ::defmt::unreachable!($($x)*) }; } @@ -229,7 +229,8 @@ impl Try for Result { } } -pub struct Bytes<'a>(pub &'a [u8]); +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { -- cgit