diff --git a/examples/embassy-net-tcp-client/Cargo.lock b/examples/embassy-net-tcp-client/Cargo.lock index 1a0f746..74d986f 100644 --- a/examples/embassy-net-tcp-client/Cargo.lock +++ b/examples/embassy-net-tcp-client/Cargo.lock @@ -358,7 +358,7 @@ dependencies = [ "embassy-net-driver", "embassy-sync", "embassy-time", - "embedded-io-async", + "embedded-io-async 0.6.1", "embedded-nal-async", "heapless", "managed", @@ -397,8 +397,8 @@ dependencies = [ "embassy-net", "embassy-nrf", "embassy-time", - "embedded-io", - "embedded-io-async", + "embedded-io 0.6.1", + "embedded-io-async 0.6.1", "heapless", "nrf-modem", "panic-probe", @@ -429,8 +429,8 @@ dependencies = [ "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-hal-async", - "embedded-io", - "embedded-io-async", + "embedded-io 0.6.1", + "embedded-io-async 0.6.1", "embedded-storage", "embedded-storage-async", "fixed", @@ -448,7 +448,7 @@ dependencies = [ "cfg-if", "critical-section", "defmt 1.0.1", - "embedded-io-async", + "embedded-io-async 0.6.1", "futures-core", "futures-sink", "heapless", @@ -497,7 +497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a" dependencies = [ "defmt 1.0.1", - "embedded-io-async", + "embedded-io-async 0.6.1", ] [[package]] @@ -534,6 +534,12 @@ dependencies = [ "defmt 0.3.100", ] +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" + [[package]] name = "embedded-io-async" version = "0.6.1" @@ -541,7 +547,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" dependencies = [ "defmt 0.3.100", - "embedded-io", + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-io-async" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564b9f813c544241430e147d8bc454815ef9ac998878d30cc3055449f7fd4c0" +dependencies = [ + "embedded-io 0.7.1", ] [[package]] @@ -559,7 +574,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" dependencies = [ - "embedded-io-async", + "embedded-io-async 0.6.1", "embedded-nal", ] @@ -827,7 +842,7 @@ dependencies = [ [[package]] name = "nrf-modem" -version = "0.9.0" +version = "0.10.1" dependencies = [ "arrayvec", "at-commands", @@ -838,7 +853,7 @@ dependencies = [ "embassy-net-driver-channel", "embassy-sync", "embassy-time", - "embedded-io-async", + "embedded-io-async 0.7.0", "futures", "grounded", "heapless", @@ -870,9 +885,9 @@ dependencies = [ [[package]] name = "nrfxlib-sys" -version = "2.9.2" +version = "3.0.3+3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1922de3a50ef4d37e7d5fec8ebc4c0c9c4a5a077cecc43e198bbbf8f5a16436a" +checksum = "573d7e42c0dc325e4631bc22346d5c046ed68c4253c3da8fc990b3380fa8633d" dependencies = [ "bindgen", "llvm-tools", diff --git a/examples/embassy-net-tcp-client/Cargo.toml b/examples/embassy-net-tcp-client/Cargo.toml index 28b6b32..6b343cd 100644 --- a/examples/embassy-net-tcp-client/Cargo.toml +++ b/examples/embassy-net-tcp-client/Cargo.toml @@ -46,11 +46,7 @@ embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } tinyrlibc = "0.5.0" # embassy-net branch -nrf-modem = { version = "0.9.0", path = "../../", features = [ - "embassy-net", - "nrf9160", - "defmt", -] } +nrf-modem = { path = "../../", features = ["embassy-net", "nrf9160", "defmt"] } [profile.release] debug = 2 diff --git a/src/embassy_net_modem/context.rs b/src/embassy_net_modem/context.rs index 66ea151..2026beb 100644 --- a/src/embassy_net_modem/context.rs +++ b/src/embassy_net_modem/context.rs @@ -9,15 +9,17 @@ use core::str::FromStr; use at_commands::builder::CommandBuilder; use at_commands::parser::CommandParser; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex}; use embassy_time::{Duration, Timer}; use heapless::Vec; -use crate::embassy_net_modem::CAP_SIZE; +use crate::{embassy_net_modem::CAP_SIZE, Error, LteLink}; /// Provides a higher level API for controlling a given context. pub struct Control<'a> { control: super::Control<'a>, cid: u8, + lte_link: Mutex>, } /// Authentication parameters for the Packet Data Network (PDN). @@ -78,24 +80,6 @@ pub enum AuthProt { Chap = 2, } -/// Error returned by control. -#[derive(Clone, Copy, PartialEq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Error { - /// Not enough space for command. - BufferTooSmall, - /// Error parsing response from modem. - AtParseError, - /// Error parsing IP addresses. - AddrParseError, -} - -impl From for Error { - fn from(_: at_commands::parser::ParseError) -> Self { - Self::AtParseError - } -} - /// Status of a given context. #[derive(PartialEq, Debug)] pub struct Status { @@ -131,7 +115,11 @@ impl<'a> Control<'a> { /// /// `cid` indicates which PDP context to use, range 0-10. pub async fn new(control: super::Control<'a>, cid: u8) -> Self { - Self { control, cid } + Self { + control, + cid, + lte_link: Mutex::new(None), + } } /// Perform a raw AT command @@ -148,15 +136,9 @@ impl<'a> Control<'a> { pub async fn configure(&self, config: &PdConfig<'_>, pin: Option<&[u8]>) -> Result<(), Error> { let mut cmd: [u8; 256] = [0; 256]; - let op = CommandBuilder::create_set(&mut cmd, true) - .named("+CFUN") - .with_int_parameter(0) - .finish() - .map_err(|_| Error::BufferTooSmall)?; - let n = self.control.at_command(op).await; - CommandParser::parse(n.as_bytes()) - .expect_identifier(b"OK") - .finish()?; + if let Some(link) = self.lte_link.lock().await.take() { + link.deactivate().await?; + } let mut op = CommandBuilder::create_set(&mut cmd, true) .named("+CGDCONT") @@ -165,7 +147,7 @@ impl<'a> Control<'a> { if let Some(apn) = config.apn { op = op.with_string_parameter(apn); } - let op = op.finish().map_err(|_| Error::BufferTooSmall)?; + let op = op.finish().map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; // info!("RES1: {}", unsafe { core::str::from_utf8_unchecked(&buf[..n]) }); @@ -183,7 +165,7 @@ impl<'a> Control<'a> { .with_string_parameter(username) .with_string_parameter(password); } - let op = op.finish().map_err(|_| Error::BufferTooSmall)?; + let op = op.finish().map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; // info!("RES2: {}", unsafe { core::str::from_utf8_unchecked(&buf[..n]) }); @@ -197,7 +179,7 @@ impl<'a> Control<'a> { .named("+CPIN") .with_string_parameter(pin) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let _ = self.control.at_command(op).await; // Ignore ERROR which means no pin required } @@ -212,7 +194,7 @@ impl<'a> Control<'a> { .named("+CGATT") .with_int_parameter(1) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; CommandParser::parse(n.as_bytes()) .expect_identifier(b"OK") @@ -227,7 +209,7 @@ impl<'a> Control<'a> { .named("+CGATT") .with_int_parameter(0) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; CommandParser::parse(n.as_bytes()) .expect_identifier(b"OK") @@ -241,7 +223,7 @@ impl<'a> Control<'a> { let op = CommandBuilder::create_query(&mut cmd, true) .named("+CGATT") .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; let (res,) = CommandParser::parse(n.as_bytes()) .expect_identifier(b"+CGATT: ") @@ -258,7 +240,7 @@ impl<'a> Control<'a> { let op = CommandBuilder::create_query(&mut cmd, true) .named("+CGATT") .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; let (res,) = CommandParser::parse(n.as_bytes()) .expect_identifier(b"+CGATT: ") @@ -280,7 +262,7 @@ impl<'a> Control<'a> { .named("+CGPADDR") .with_int_parameter(self.cid) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; let (_, ip1, ip2) = CommandParser::parse(n.as_bytes()) .expect_identifier(b"+CGPADDR: ") @@ -308,7 +290,7 @@ impl<'a> Control<'a> { .named("+CGCONTRDP") .with_int_parameter(self.cid) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; let (_cid, _bid, _apn, _mask, gateway, dns1, dns2, _, _, _, _, _mtu) = CommandParser::parse(n.as_bytes()) @@ -368,18 +350,9 @@ impl<'a> Control<'a> { /// Disable modem pub async fn disable(&self) -> Result<(), Error> { - let mut cmd: [u8; 256] = [0; 256]; - - let op = CommandBuilder::create_set(&mut cmd, true) - .named("+CFUN") - .with_int_parameter(0) - .finish() - .map_err(|_| Error::BufferTooSmall)?; - let n = self.control.at_command(op).await; - CommandParser::parse(n.as_bytes()) - .expect_identifier(b"OK") - .finish()?; - + if let Some(link) = self.lte_link.lock().await.take() { + link.deactivate().await?; + }; Ok(()) } @@ -387,22 +360,14 @@ impl<'a> Control<'a> { pub async fn enable(&self) -> Result<(), Error> { let mut cmd: [u8; 256] = [0; 256]; - let op = CommandBuilder::create_set(&mut cmd, true) - .named("+CFUN") - .with_int_parameter(1) - .finish() - .map_err(|_| Error::BufferTooSmall)?; - let n = self.control.at_command(op).await; - CommandParser::parse(n.as_bytes()) - .expect_identifier(b"OK") - .finish()?; + self.lte_link.lock().await.replace(LteLink::new().await?); // Make modem survive PDN detaches let op = CommandBuilder::create_set(&mut cmd, true) .named("%XPDNCFG") .with_int_parameter(1) .finish() - .map_err(|_| Error::BufferTooSmall)?; + .map_err(|s| Error::BufferTooSmall(Some(s)))?; let n = self.control.at_command(op).await; CommandParser::parse(n.as_bytes()) .expect_identifier(b"OK") diff --git a/src/error.rs b/src/error.rs index 2931f91..e6fb315 100644 --- a/src/error.rs +++ b/src/error.rs @@ -60,6 +60,9 @@ pub enum Error { DnsParseFailed, #[cfg(feature = "embedded-nal-async")] ReverseDnsLookupNotSupported, + /// The address resturned by the modem couldn't be parsed + #[cfg(feature = "embassy-net")] + AddrParseError, } impl Display for Error { @@ -115,6 +118,8 @@ impl embedded_io_async::Error for Error { Error::DnsParseFailed => embedded_io_async::ErrorKind::Other, #[cfg(feature = "embedded-nal-async")] Error::ReverseDnsLookupNotSupported => embedded_io_async::ErrorKind::Unsupported, + #[cfg(feature = "embassy-net")] + Error::AddrParseError => embedded_io_async::ErrorKind::InvalidInput, } } }