diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-25 15:57:02 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-08-25 20:45:23 +0200 |
| commit | c2d601abeff6f9f911b8140f3ceb6806971dc7dd (patch) | |
| tree | 8acc8794ae058a402b83145ea11195622d48cf15 /embassy-net-ppp | |
| parent | 2303382dfd6f4e6275a699b938f465a1e6170449 (diff) | |
net-ppp: take serial port and config in run(), allow calling it multiple times.
Diffstat (limited to 'embassy-net-ppp')
| -rw-r--r-- | embassy-net-ppp/src/lib.rs | 50 |
1 files changed, 27 insertions, 23 deletions
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; | |||
| 13 | use embassy_net_driver_channel::driver::LinkState; | 13 | use embassy_net_driver_channel::driver::LinkState; |
| 14 | use embedded_io_async::{BufRead, Write, WriteAllError}; | 14 | use embedded_io_async::{BufRead, Write, WriteAllError}; |
| 15 | use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; | 15 | use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; |
| 16 | pub use ppproto::Config; | ||
| 16 | 17 | ||
| 17 | const MTU: usize = 1500; | 18 | const MTU: usize = 1500; |
| 18 | 19 | ||
| @@ -36,37 +37,44 @@ impl<const N_RX: usize, const N_TX: usize> State<N_RX, N_TX> { | |||
| 36 | /// Background runner for the driver. | 37 | /// Background runner for the driver. |
| 37 | /// | 38 | /// |
| 38 | /// You must call `.run()` in a background task for the driver to operate. | 39 | /// You must call `.run()` in a background task for the driver to operate. |
| 39 | pub struct Runner<'d, R: BufRead, W: Write> { | 40 | pub struct Runner<'d> { |
| 40 | ch: ch::Runner<'d, MTU>, | 41 | ch: ch::Runner<'d, MTU>, |
| 41 | r: R, | ||
| 42 | w: W, | ||
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | /// Error returned by [`Runner::run`]. | 44 | /// Error returned by [`Runner::run`]. |
| 46 | #[derive(Debug)] | 45 | #[derive(Debug)] |
| 47 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 46 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 48 | pub enum RunError<RE, WE> { | 47 | pub enum RunError<E> { |
| 49 | /// Reading from the serial port failed. | 48 | /// Reading from the serial port failed. |
| 50 | Read(RE), | 49 | Read(E), |
| 51 | /// Writing to the serial port failed. | 50 | /// Writing to the serial port failed. |
| 52 | Write(WE), | 51 | Write(E), |
| 53 | /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. | 52 | /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. |
| 54 | WriteZero, | 53 | WriteZero, |
| 55 | /// Writing to the serial got EOF. | 54 | /// Writing to the serial got EOF. |
| 56 | Eof, | 55 | Eof, |
| 57 | } | 56 | } |
| 58 | 57 | ||
| 59 | impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | 58 | impl<'d> Runner<'d> { |
| 60 | /// You must call this in a background task for the driver to operate. | 59 | /// You must call this in a background task for the driver to operate. |
| 61 | pub async fn run(mut self) -> Result<Infallible, RunError<R::Error, W::Error>> { | 60 | /// |
| 62 | let config = ppproto::Config { | 61 | /// If reading/writing to the underlying serial port fails, the link state |
| 63 | username: b"myuser", | 62 | /// is set to Down and the error is returned. |
| 64 | password: b"mypass", | 63 | /// |
| 65 | }; | 64 | /// It is allowed to cancel this function's future (i.e. drop it). This will terminate |
| 65 | /// the PPP connection and set the link state to Down. | ||
| 66 | /// | ||
| 67 | /// After this function returns or is canceled, you can call it again to establish | ||
| 68 | /// a new PPP connection. | ||
| 69 | pub async fn run<RW: BufRead + Write>( | ||
| 70 | &mut self, | ||
| 71 | mut rw: RW, | ||
| 72 | config: ppproto::Config<'_>, | ||
| 73 | ) -> Result<Infallible, RunError<RW::Error>> { | ||
| 66 | let mut ppp = PPPoS::new(config); | 74 | let mut ppp = PPPoS::new(config); |
| 67 | ppp.open().unwrap(); | 75 | ppp.open().unwrap(); |
| 68 | 76 | ||
| 69 | let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); | 77 | let (state_chan, mut rx_chan, mut tx_chan) = self.ch.borrow_split(); |
| 70 | state_chan.set_link_state(LinkState::Down); | 78 | state_chan.set_link_state(LinkState::Down); |
| 71 | let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); | 79 | let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); |
| 72 | 80 | ||
| @@ -80,7 +88,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 80 | let buf = rx_chan.rx_buf().await; | 88 | let buf = rx_chan.rx_buf().await; |
| 81 | let rx_data = match needs_poll { | 89 | let rx_data = match needs_poll { |
| 82 | true => &[][..], | 90 | true => &[][..], |
| 83 | false => match self.r.fill_buf().await { | 91 | false => match rw.fill_buf().await { |
| 84 | Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), | 92 | Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), |
| 85 | Ok(rx_data) => rx_data, | 93 | Ok(rx_data) => rx_data, |
| 86 | Err(e) => return Err(RunError::Read(e)), | 94 | Err(e) => return Err(RunError::Read(e)), |
| @@ -95,7 +103,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 95 | 103 | ||
| 96 | let (buf, rx_data) = r?; | 104 | let (buf, rx_data) = r?; |
| 97 | let n = ppp.consume(rx_data, &mut rx_buf); | 105 | let n = ppp.consume(rx_data, &mut rx_buf); |
| 98 | self.r.consume(n); | 106 | rw.consume(n); |
| 99 | 107 | ||
| 100 | match ppp.poll(&mut tx_buf, &mut rx_buf) { | 108 | match ppp.poll(&mut tx_buf, &mut rx_buf) { |
| 101 | PPPoSAction::None => {} | 109 | PPPoSAction::None => {} |
| @@ -104,7 +112,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 104 | buf[..pkt.len()].copy_from_slice(pkt); | 112 | buf[..pkt.len()].copy_from_slice(pkt); |
| 105 | rx_chan.rx_done(pkt.len()); | 113 | rx_chan.rx_done(pkt.len()); |
| 106 | } | 114 | } |
| 107 | PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { | 115 | PPPoSAction::Transmit(n) => match rw.write_all(&tx_buf[..n]).await { |
| 108 | Ok(()) => {} | 116 | Ok(()) => {} |
| 109 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), | 117 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), |
| 110 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), | 118 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), |
| @@ -118,7 +126,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 118 | } | 126 | } |
| 119 | Either::Second(pkt) => { | 127 | Either::Second(pkt) => { |
| 120 | match ppp.send(pkt, &mut tx_buf) { | 128 | match ppp.send(pkt, &mut tx_buf) { |
| 121 | Ok(n) => match self.w.write_all(&tx_buf[..n]).await { | 129 | Ok(n) => match rw.write_all(&tx_buf[..n]).await { |
| 122 | Ok(()) => {} | 130 | Ok(()) => {} |
| 123 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), | 131 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), |
| 124 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), | 132 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), |
| @@ -137,13 +145,9 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 137 | /// This returns two structs: | 145 | /// This returns two structs: |
| 138 | /// - a `Device` that you must pass to the `embassy-net` stack. | 146 | /// - a `Device` that you must pass to the `embassy-net` stack. |
| 139 | /// - a `Runner`. You must call `.run()` on it in a background task. | 147 | /// - a `Runner`. You must call `.run()` on it in a background task. |
| 140 | pub fn new<'a, const N_RX: usize, const N_TX: usize, R: BufRead, W: Write>( | 148 | pub fn new<'a, const N_RX: usize, const N_TX: usize>(state: &'a mut State<N_RX, N_TX>) -> (Device<'a>, Runner<'a>) { |
| 141 | state: &'a mut State<N_RX, N_TX>, | ||
| 142 | r: R, | ||
| 143 | w: W, | ||
| 144 | ) -> (Device<'a>, Runner<'a, R, W>) { | ||
| 145 | let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); | 149 | let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); |
| 146 | (device, Runner { ch: runner, r, w }) | 150 | (device, Runner { ch: runner }) |
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | struct OnDrop<F: FnOnce()> { | 153 | struct OnDrop<F: FnOnce()> { |
