From bfdc2482efc711a21298852239e204f813bd6357 Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 1 Jul 2024 20:10:59 +0200 Subject: [PATCH] Fix internal-network-stack compiling --- .vscode/settings.json | 1 + Cargo.toml | 2 +- Design_diagram.drawio | 1 - Design_diagram.png | Bin 135242 -> 0 bytes README.md | 26 +- rust-toolchain.toml | 2 +- src/asynch/mod.rs | 6 +- src/asynch/ublox_stack/device.rs | 11 + src/asynch/ublox_stack/dns.rs | 5 +- src/asynch/ublox_stack/mod.rs | 105 ++-- src/{ => asynch/ublox_stack}/peer_builder.rs | 0 src/asynch/ublox_stack/tcp.rs | 41 +- src/asynch/ublox_stack/tls.rs | 43 +- src/asynch/ublox_stack/udp.rs | 5 +- src/config.rs | 2 + src/connection.rs | 13 +- src/error.rs | 8 +- src/fmt.rs | 54 +- src/lib.rs | 3 - src/network.rs | 2 +- src/wifi/ap.rs | 227 ------- src/wifi/mod.rs | 86 --- src/wifi/options.rs | 137 ----- src/wifi/supplicant.rs | 603 ------------------- 24 files changed, 182 insertions(+), 1201 deletions(-) delete mode 100644 Design_diagram.drawio delete mode 100644 Design_diagram.png create mode 100644 src/asynch/ublox_stack/device.rs rename src/{ => asynch/ublox_stack}/peer_builder.rs (100%) delete mode 100644 src/wifi/ap.rs delete mode 100644 src/wifi/mod.rs delete mode 100644 src/wifi/options.rs delete mode 100644 src/wifi/supplicant.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index b297366..1b2bf72 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "rust-analyzer.linkedProjects": [], "rust-analyzer.cargo.features": [ "odin_w2xx", + // "internal-network-stack" "ppp" ], "rust-analyzer.server.extraEnv": { diff --git a/Cargo.toml b/Cargo.toml index df7be4c..5d31af1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ name = "ublox_short_range" doctest = false [dependencies] -atat = { version = "0.22", features = ["derive", "bytes"] } +atat = { version = "0.23", features = ["derive", "bytes"] } heapless = { version = "^0.8", features = ["serde"] } no-std-net = { version = "0.6", features = ["serde"] } diff --git a/Design_diagram.drawio b/Design_diagram.drawio deleted file mode 100644 index 016b7ea..0000000 --- a/Design_diagram.drawio +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/Design_diagram.png b/Design_diagram.png deleted file mode 100644 index e73bc905ee4f8cfc3c2d60fcd095a2ec59f0b7fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135242 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

(_#$PkcfV+@iQa8 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 Z@|`iG@k(En + [no-std-badge]: https://img.shields.io/badge/no__std-yes-blue [test]: https://github.com/BlackbirdHQ/ublox-short-range-rs/workflows/Test/badge.svg [codecov-badge]: https://codecov.io/gh/BlackbirdHQ/ublox-short-range-rs/branch/master/graph/badge.svg diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b4220cb..1dca89f 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.75" +channel = "1.79" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv6m-none-eabi", diff --git a/src/asynch/mod.rs b/src/asynch/mod.rs index a6ef5fb..49ace50 100644 --- a/src/asynch/mod.rs +++ b/src/asynch/mod.rs @@ -1,18 +1,18 @@ +#[cfg(feature = "ppp")] mod at_udp_socket; pub mod control; pub mod network; mod resources; pub mod runner; -#[cfg(feature = "ublox-sockets")] +#[cfg(feature = "internal-network-stack")] pub mod ublox_stack; pub(crate) mod state; pub use resources::Resources; pub use runner::Runner; +pub use state::LinkState; -#[cfg(feature = "internal-network-stack")] -mod internal_stack; use embedded_io_async::{BufRead, Error as _, ErrorKind, Read, Write}; #[cfg(feature = "edm")] diff --git a/src/asynch/ublox_stack/device.rs b/src/asynch/ublox_stack/device.rs new file mode 100644 index 0000000..bf728c5 --- /dev/null +++ b/src/asynch/ublox_stack/device.rs @@ -0,0 +1,11 @@ +use core::cell::RefCell; + +use atat::UrcChannel; + +use crate::asynch::{control::ProxyClient, runner::URC_SUBSCRIBERS, state, UbloxUrc}; + +pub struct Device<'a, const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize> { + pub(crate) state_ch: state::Runner<'a>, + pub(crate) at_client: RefCell>, + pub(crate) urc_channel: &'a UrcChannel, +} diff --git a/src/asynch/ublox_stack/dns.rs b/src/asynch/ublox_stack/dns.rs index ab28ee2..b3aed1e 100644 --- a/src/asynch/ublox_stack/dns.rs +++ b/src/asynch/ublox_stack/dns.rs @@ -1,6 +1,5 @@ use core::{cell::RefCell, future::poll_fn, task::Poll}; -use atat::asynch::AtatClient; use embassy_sync::waitqueue::WakerRegistration; use embedded_nal_async::AddrType; use no_std_net::IpAddr; @@ -115,8 +114,8 @@ pub struct DnsSocket<'a> { impl<'a> DnsSocket<'a> { /// Create a new DNS socket using the provided stack. - pub fn new( - stack: &'a UbloxStack, + pub fn new( + stack: &'a UbloxStack, ) -> Self { Self { stack: &stack.socket, diff --git a/src/asynch/ublox_stack/mod.rs b/src/asynch/ublox_stack/mod.rs index b5f3b8d..06d9533 100644 --- a/src/asynch/ublox_stack/mod.rs +++ b/src/asynch/ublox_stack/mod.rs @@ -5,37 +5,37 @@ pub mod tls; #[cfg(feature = "socket-udp")] pub mod udp; +mod device; pub mod dns; +mod peer_builder; + +pub use device::Device; use core::cell::RefCell; use core::future::poll_fn; use core::ops::{DerefMut, Rem}; use core::task::Poll; -use crate::asynch::state::Device; use crate::command::data_mode::responses::ConnectPeerResponse; use crate::command::data_mode::urc::PeerDisconnected; use crate::command::data_mode::{ClosePeerConnection, ConnectPeer}; use crate::command::edm::types::{DataEvent, Protocol}; use crate::command::edm::urc::EdmEvent; -use crate::command::edm::EdmDataCommand; +use crate::command::edm::{EdmAtCmdWrapper, EdmDataCommand}; use crate::command::ping::types::PingError; use crate::command::ping::urc::{PingErrorResponse, PingResponse}; use crate::command::ping::Ping; use crate::command::Urc; -use crate::peer_builder::{PeerUrlBuilder, SecurityCredentials}; +use peer_builder::{PeerUrlBuilder, SecurityCredentials}; use self::dns::{DnsSocket, DnsState, DnsTable}; -use super::state::{self, LinkState}; -use super::AtHandle; +use super::control::ProxyClient; -use atat::asynch::AtatClient; use embassy_futures::select; use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Duration, Ticker}; use embedded_nal_async::SocketAddr; -use futures::pin_mut; use no_std_net::IpAddr; use portable_atomic::{AtomicBool, AtomicU8, Ordering}; use ublox_sockets::{ @@ -68,15 +68,14 @@ impl StackResources { } } -pub struct UbloxStack { +pub struct UbloxStack { socket: RefCell, - device: RefCell>, + device: Device<'static, INGRESS_BUF_SIZE, URC_CAPACITY>, last_tx_socket: AtomicU8, should_tx: AtomicBool, - link_up: AtomicBool, } -struct SocketStack { +pub(crate) struct SocketStack { sockets: SocketSet<'static>, waker: WakerRegistration, dns_table: DnsTable, @@ -84,9 +83,11 @@ struct SocketStack { credential_map: heapless::FnvIndexMap, } -impl UbloxStack { +impl + UbloxStack +{ pub fn new( - device: state::Device<'static, AT, URC_CAPACITY>, + device: Device<'static, INGRESS_BUF_SIZE, URC_CAPACITY>, resources: &'static mut StackResources, ) -> Self { let sockets = SocketSet::new(&mut resources.sockets[..]); @@ -101,9 +102,8 @@ impl UbloxStack UbloxStack ! { let mut tx_buf = [0u8; MAX_EGRESS_SIZE]; + let Device { + urc_channel, + state_ch, + at_client, + } = &self.device; + + let mut urc_subscription = urc_channel.subscribe().unwrap(); + loop { // FIXME: It feels like this can be written smarter/simpler? let should_tx = poll_fn(|cx| match self.should_tx.load(Ordering::Relaxed) { @@ -126,46 +134,21 @@ impl UbloxStack Poll::Ready(LinkState::Down), - (false, LinkState::Up) => Poll::Ready(LinkState::Up), - _ => Poll::Pending, - }, - ), ) .await { - select::Either4::First(event) => { + select::Either3::First(event) => { Self::socket_rx(event, &self.socket); } - select::Either4::Second(_) | select::Either4::Third(_) => { + select::Either3::Second(_) | select::Either3::Third(_) => { if let Some(ev) = self.tx_event(&mut tx_buf) { - Self::socket_tx(ev, &self.socket, at).await; - } - } - select::Either4::Fourth(new_state) => { - // Update link up - let old_link_up = self.link_up.load(Ordering::Relaxed); - let new_link_up = new_state == LinkState::Up; - self.link_up.store(new_link_up, Ordering::Relaxed); - - // Print when changed - if old_link_up != new_link_up { - info!("link_up = {:?}", new_link_up); + Self::socket_tx(ev, &self.socket, &at_client).await; } } } @@ -325,13 +308,14 @@ impl UbloxStack UbloxStack( ev: TxEvent<'data>, socket: &RefCell, - at: &mut AtHandle<'_, AT>, + at_client: &RefCell>, ) { + use atat::asynch::AtatClient; + + let mut at = at_client.borrow_mut(); match ev { TxEvent::Connect { socket_handle, url } => { - match at.send_edm(ConnectPeer { url: &url }).await { + match at.send(&EdmAtCmdWrapper(ConnectPeer { url: &url })).await { Ok(ConnectPeerResponse { peer_handle }) => { let mut s = socket.borrow_mut(); let tcp = s @@ -436,7 +423,7 @@ impl UbloxStack { warn!("Sending {} bytes on {}", data.len(), edm_channel); - at.send(EdmDataCommand { + at.send(&EdmDataCommand { channel: edm_channel, data, }) @@ -444,14 +431,16 @@ impl UbloxStack { - at.send_edm(ClosePeerConnection { peer_handle }).await.ok(); + at.send(&EdmAtCmdWrapper(ClosePeerConnection { peer_handle })) + .await + .ok(); } TxEvent::Dns { hostname } => { match at - .send_edm(Ping { + .send(&EdmAtCmdWrapper(Ping { hostname: &hostname, retry_num: 1, - }) + })) .await { Ok(_) => {} diff --git a/src/peer_builder.rs b/src/asynch/ublox_stack/peer_builder.rs similarity index 100% rename from src/peer_builder.rs rename to src/asynch/ublox_stack/peer_builder.rs diff --git a/src/asynch/ublox_stack/tcp.rs b/src/asynch/ublox_stack/tcp.rs index 6283ff6..8706313 100644 --- a/src/asynch/ublox_stack/tcp.rs +++ b/src/asynch/ublox_stack/tcp.rs @@ -3,7 +3,6 @@ use core::future::poll_fn; use core::mem; use core::task::Poll; -use atat::asynch::AtatClient; use embassy_time::Duration; use embedded_nal_async::SocketAddr; use ublox_sockets::{tcp, SocketHandle, TcpState}; @@ -123,8 +122,8 @@ impl<'a> TcpWriter<'a> { impl<'a> TcpSocket<'a> { /// Create a new TCP socket on the given stack, with the given buffers. - pub fn new( - stack: &'a UbloxStack, + pub fn new( + stack: &'a UbloxStack, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8], ) -> Self { @@ -331,7 +330,7 @@ impl<'a> TcpSocket<'a> { self.io.with(|s| s.may_send()) } - /// return whether the recieve half of the full-duplex connection is open. + /// return whether the receive half of the full-duplex connection is open. /// This function returns true if it’s possible to receive data from the remote endpoint. /// It will return true while there is data in the receive buffer, and if there isn’t, /// as long as the remote endpoint has not closed the connection. @@ -481,7 +480,7 @@ impl<'d> TcpIo<'d> { s.register_recv_waker(cx.waker()); Poll::Pending } else { - // if we can't receive because the recieve half of the duplex connection is closed then return an error + // if we can't receive because the receive half of the duplex connection is closed then return an error Poll::Ready(Err(Error::ConnectionReset)) } } else { @@ -631,24 +630,25 @@ pub mod client { /// The pool is capable of managing up to N concurrent connections with tx and rx buffers according to TX_SZ and RX_SZ. pub struct TcpClient< 'd, - AT: AtatClient + 'static, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024, > { - pub(crate) stack: &'d UbloxStack, + pub(crate) stack: &'d UbloxStack, pub(crate) state: &'d TcpClientState, } impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > embedded_nal_async::Dns for TcpClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > embedded_nal_async::Dns + for TcpClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { type Error = crate::asynch::ublox_stack::dns::Error; @@ -671,16 +671,16 @@ pub mod client { impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > TcpClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > TcpClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { /// Create a new `TcpClient`. pub fn new( - stack: &'d UbloxStack, + stack: &'d UbloxStack, state: &'d TcpClientState, ) -> Self { Self { stack, state } @@ -689,12 +689,13 @@ pub mod client { impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > embedded_nal_async::TcpConnect for TcpClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > embedded_nal_async::TcpConnect + for TcpClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { type Error = Error; type Connection<'m> = TcpConnection<'m, N, TX_SZ, RX_SZ> where Self: 'm; @@ -724,8 +725,8 @@ pub mod client { impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnection<'d, N, TX_SZ, RX_SZ> { - fn new( - stack: &'d UbloxStack, + fn new( + stack: &'d UbloxStack, state: &'d TcpClientState, ) -> Result { let mut bufs = state.pool.alloc().ok_or(Error::ConnectionReset)?; diff --git a/src/asynch/ublox_stack/tls.rs b/src/asynch/ublox_stack/tls.rs index 7caa78a..327f811 100644 --- a/src/asynch/ublox_stack/tls.rs +++ b/src/asynch/ublox_stack/tls.rs @@ -1,9 +1,8 @@ -use atat::asynch::AtatClient; use embassy_time::Duration; use no_std_net::SocketAddr; use ublox_sockets::TcpState as State; -use crate::peer_builder::SecurityCredentials; +use super::peer_builder::SecurityCredentials; use super::{ tcp::{ConnectError, Error, TcpIo, TcpReader, TcpSocket, TcpWriter}, @@ -16,8 +15,8 @@ pub struct TlsSocket<'a> { impl<'a> TlsSocket<'a> { /// Create a new TCP socket on the given stack, with the given buffers. - pub fn new( - stack: &'a UbloxStack, + pub fn new( + stack: &'a UbloxStack, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8], credentials: SecurityCredentials, @@ -28,7 +27,7 @@ impl<'a> TlsSocket<'a> { let s = &mut *stack.borrow_mut(); info!("Associating credentials {} with {}", credentials, handle); - s.credential_map.insert(handle, credentials); + s.credential_map.insert(handle, credentials).unwrap(); Self { inner: tcp_socket } } @@ -204,7 +203,7 @@ impl<'a> TlsSocket<'a> { self.inner.may_send() } - /// return whether the recieve half of the full-duplex connection is open. + /// return whether the receive half of the full-duplex connection is open. /// This function returns true if it’s possible to receive data from the remote endpoint. /// It will return true while there is data in the receive buffer, and if there isn’t, /// as long as the remote endpoint has not closed the connection. @@ -275,25 +274,26 @@ pub mod client { /// The pool is capable of managing up to N concurrent connections with tx and rx buffers according to TX_SZ and RX_SZ. pub struct TlsClient< 'd, - AT: AtatClient + 'static, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024, > { - pub(crate) stack: &'d UbloxStack, + pub(crate) stack: &'d UbloxStack, pub(crate) state: &'d TcpClientState, pub(crate) credentials: SecurityCredentials, } impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > embedded_nal_async::Dns for TlsClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > embedded_nal_async::Dns + for TlsClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { type Error = crate::asynch::ublox_stack::dns::Error; @@ -316,16 +316,16 @@ pub mod client { impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > TlsClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > TlsClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { /// Create a new `TlsClient`. pub fn new( - stack: &'d UbloxStack, + stack: &'d UbloxStack, state: &'d TcpClientState, credentials: SecurityCredentials, ) -> Self { @@ -339,12 +339,13 @@ pub mod client { impl< 'd, - AT: AtatClient, - const N: usize, + const INGRESS_BUF_SIZE: usize, const URC_CAPACITY: usize, + const N: usize, const TX_SZ: usize, const RX_SZ: usize, - > embedded_nal_async::TcpConnect for TlsClient<'d, AT, N, URC_CAPACITY, TX_SZ, RX_SZ> + > embedded_nal_async::TcpConnect + for TlsClient<'d, INGRESS_BUF_SIZE, URC_CAPACITY, N, TX_SZ, RX_SZ> { type Error = Error; type Connection<'m> = TlsConnection<'m, N, TX_SZ, RX_SZ> where Self: 'm; @@ -374,8 +375,8 @@ pub mod client { impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TlsConnection<'d, N, TX_SZ, RX_SZ> { - fn new( - stack: &'d UbloxStack, + fn new( + stack: &'d UbloxStack, state: &'d TcpClientState, credentials: SecurityCredentials, ) -> Result { diff --git a/src/asynch/ublox_stack/udp.rs b/src/asynch/ublox_stack/udp.rs index 8348b3d..f561f69 100644 --- a/src/asynch/ublox_stack/udp.rs +++ b/src/asynch/ublox_stack/udp.rs @@ -3,7 +3,6 @@ use core::cell::RefCell; use core::mem; -use atat::asynch::AtatClient; use embedded_nal_async::SocketAddr; use ublox_sockets::{udp, SocketHandle, UdpState}; @@ -45,8 +44,8 @@ pub struct UdpSocket<'a> { impl<'a> UdpSocket<'a> { /// Create a new UDP socket using the provided stack and buffers. - pub fn new( - stack: &'a UbloxStack, + pub fn new( + stack: &'a UbloxStack, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8], ) -> Self { diff --git a/src/config.rs b/src/config.rs index 8589684..44fce23 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,7 +5,9 @@ pub trait WifiConfig<'a> { const FLOW_CONTROL: bool = false; + #[cfg(feature = "internal-network-stack")] const TLS_IN_BUFFER_SIZE: Option = None; + #[cfg(feature = "internal-network-stack")] const TLS_OUT_BUFFER_SIZE: Option = None; #[cfg(feature = "ppp")] diff --git a/src/connection.rs b/src/connection.rs index 8136e8d..a309f11 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -6,19 +6,14 @@ pub enum WiFiState { Inactive, /// Searching for Wifi NotConnected, + SecurityProblems, Connected, } -// Fold into wifi connectivity pub struct WifiConnection { - /// Keeps track of connection state on module pub wifi_state: WiFiState, pub network_up: bool, pub network: Option, - /// Number from 0-9. 255 used for unknown - pub config_id: u8, - /// Keeps track of activation of the config by driver - pub activated: bool, } impl WifiConnection { @@ -27,11 +22,10 @@ impl WifiConnection { wifi_state: WiFiState::Inactive, network_up: false, network: None, - config_id: 255, - activated: false, } } + #[allow(dead_code)] pub fn is_station(&self) -> bool { match self.network { Some(ref n) => n.mode == WifiMode::Station, @@ -39,11 +33,12 @@ impl WifiConnection { } } + #[allow(dead_code)] pub fn is_access_point(&self) -> bool { !self.is_station() } pub fn is_connected(&self) -> bool { - self.network_up + self.network_up && self.wifi_state == WiFiState::Connected } } diff --git a/src/error.rs b/src/error.rs index c770c9b..ea7bf9d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "ublox-sockets")] +#[cfg(feature = "internal-network-stack")] pub use ublox_sockets::Error as SocketError; #[derive(Debug)] @@ -18,7 +18,7 @@ pub enum Error { // NetworkState(crate::wifi::connection::NetworkState), NoWifiSetup, // WifiState(crate::wifi::connection::WiFiState), - #[cfg(feature = "ublox-sockets")] + #[cfg(feature = "internal-network-stack")] Socket(ublox_sockets::Error), AT(atat::Error), Busy, @@ -42,7 +42,7 @@ impl From for Error { } } -#[cfg(feature = "ublox-sockets")] +#[cfg(feature = "internal-network-stack")] impl From for Error { fn from(e: ublox_sockets::Error) -> Self { Error::Socket(e) @@ -97,7 +97,7 @@ pub enum WifiError { #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiHotspotError { - /// Failed to ceate wireless hotspot. + /// Failed to create wireless hotspot. CreationFailed, /// Failed to stop wireless hotspot service. Try turning off /// the wireless interface via ```wifi.turn_off()```. diff --git a/src/fmt.rs b/src/fmt.rs index 81c9940..35b929f 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -1,11 +1,12 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] -use core::fmt::Debug; +use core::fmt::{Debug, Display, LowerHex}; #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); +#[collapse_debuginfo(yes)] macro_rules! assert { ($($x:tt)*) => { { @@ -17,6 +18,7 @@ macro_rules! assert { }; } +#[collapse_debuginfo(yes)] macro_rules! assert_eq { ($($x:tt)*) => { { @@ -28,6 +30,7 @@ macro_rules! assert_eq { }; } +#[collapse_debuginfo(yes)] macro_rules! assert_ne { ($($x:tt)*) => { { @@ -39,39 +42,43 @@ macro_rules! assert_ne { }; } +#[collapse_debuginfo(yes)] macro_rules! debug_assert { ($($x:tt)*) => { { #[cfg(not(feature = "defmt"))] ::core::debug_assert!($($x)*); #[cfg(feature = "defmt")] - ::debug_assert!($($x)*); + ::defmt::debug_assert!($($x)*); } }; } +#[collapse_debuginfo(yes)] macro_rules! debug_assert_eq { ($($x:tt)*) => { { #[cfg(not(feature = "defmt"))] ::core::debug_assert_eq!($($x)*); #[cfg(feature = "defmt")] - ::debug_assert_eq!($($x)*); + ::defmt::debug_assert_eq!($($x)*); } }; } +#[collapse_debuginfo(yes)] macro_rules! debug_assert_ne { ($($x:tt)*) => { { #[cfg(not(feature = "defmt"))] ::core::debug_assert_ne!($($x)*); #[cfg(feature = "defmt")] - ::debug_assert_ne!($($x)*); + ::defmt::debug_assert_ne!($($x)*); } }; } +#[collapse_debuginfo(yes)] macro_rules! todo { ($($x:tt)*) => { { @@ -84,6 +91,7 @@ macro_rules! todo { } #[cfg(not(feature = "defmt"))] +#[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { ::core::unreachable!($($x)*) @@ -91,12 +99,14 @@ macro_rules! unreachable { } #[cfg(feature = "defmt")] +#[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { ::defmt::unreachable!($($x)*) }; } +#[collapse_debuginfo(yes)] macro_rules! panic { ($($x:tt)*) => { { @@ -108,6 +118,7 @@ macro_rules! panic { }; } +#[collapse_debuginfo(yes)] macro_rules! trace { ($s:literal $(, $x:expr)* $(,)?) => { { @@ -121,6 +132,7 @@ macro_rules! trace { }; } +#[collapse_debuginfo(yes)] macro_rules! debug { ($s:literal $(, $x:expr)* $(,)?) => { { @@ -134,6 +146,7 @@ macro_rules! debug { }; } +#[collapse_debuginfo(yes)] macro_rules! info { ($s:literal $(, $x:expr)* $(,)?) => { { @@ -147,6 +160,7 @@ macro_rules! info { }; } +#[collapse_debuginfo(yes)] macro_rules! warn { ($s:literal $(, $x:expr)* $(,)?) => { { @@ -160,6 +174,7 @@ macro_rules! warn { }; } +#[collapse_debuginfo(yes)] macro_rules! error { ($s:literal $(, $x:expr)* $(,)?) => { { @@ -174,6 +189,7 @@ macro_rules! error { } #[cfg(feature = "defmt")] +#[collapse_debuginfo(yes)] macro_rules! unwrap { ($($x:tt)*) => { ::defmt::unwrap!($($x)*) @@ -181,6 +197,7 @@ macro_rules! unwrap { } #[cfg(not(feature = "defmt"))] +#[collapse_debuginfo(yes)] macro_rules! unwrap { ($arg:expr) => { match $crate::fmt::Try::into_result($arg) { @@ -228,3 +245,30 @@ impl Try for Result { self } } + +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 { + 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/src/lib.rs b/src/lib.rs index b7375c2..b8e84fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,6 @@ pub mod asynch; mod config; mod connection; mod network; -mod peer_builder; mod hex; @@ -29,6 +28,4 @@ pub use atat; pub mod command; pub mod error; -// pub mod wifi; pub use config::WifiConfig; -pub use peer_builder::SecurityCredentials; diff --git a/src/network.rs b/src/network.rs index e980dc9..eafa25d 100644 --- a/src/network.rs +++ b/src/network.rs @@ -6,7 +6,7 @@ use heapless::String; use core::convert::TryFrom; -#[derive(PartialEq, Debug)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum WifiMode { Station, AccessPoint, diff --git a/src/wifi/ap.rs b/src/wifi/ap.rs deleted file mode 100644 index 5995140..0000000 --- a/src/wifi/ap.rs +++ /dev/null @@ -1,227 +0,0 @@ -use crate::{ - blocking::UbloxClient, - command::{ - edm::EdmAtCmdWrapper, - wifi::{ - self, - types::{ - AccessPointAction, AccessPointConfig, AccessPointId, IPv4Mode, PasskeyR, - SecurityMode, SecurityModePSK, - }, - SetWifiAPConfig, WifiAPAction, - }, - }, - error::WifiHotspotError, - wifi::{ - network::{WifiMode, WifiNetwork}, - options::{ConnectionOptions, HotspotOptions}, - }, -}; -use atat::blocking::AtatClient; -use atat::heapless_bytes::Bytes; -use embedded_hal::digital::OutputPin; - -use super::connection::{WiFiState, WifiConnection}; - -impl UbloxClient -where - C: AtatClient, - RST: OutputPin, -{ - /// Creates wireless hotspot service for host machine. - pub fn create_hotspot( - &mut self, - options: ConnectionOptions, - configuration: HotspotOptions, - ) -> Result<(), WifiHotspotError> { - let ap_config_id = AccessPointId::Id0; - - // Network part - // Deactivate network id 0 - self.send_internal( - &EdmAtCmdWrapper(WifiAPAction { - ap_config_id, - ap_action: AccessPointAction::Deactivate, - }), - true, - )?; - - self.send_internal( - &EdmAtCmdWrapper(WifiAPAction { - ap_config_id, - ap_action: AccessPointAction::Reset, - }), - true, - )?; - - if let Some(ref con) = self.wifi_connection { - if con.activated { - return Err(WifiHotspotError::CreationFailed); - } - } - - // Disable DHCP Server (static IP address will be used) - if options.ip.is_some() || options.subnet.is_some() || options.gateway.is_some() { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::IPv4Mode(IPv4Mode::Static), - }), - true, - )?; - } - - // Network IP address - if let Some(ip) = options.ip { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::IPv4Address(ip), - }), - true, - )?; - } - // Network Subnet mask - if let Some(subnet) = options.subnet { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::SubnetMask(subnet), - }), - true, - )?; - } - // Network Default gateway - if let Some(gateway) = options.gateway { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::DefaultGateway(gateway), - }), - true, - )?; - } - - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::DHCPServer(true.into()), - }), - true, - )?; - - // Active on startup - // self.send_internal(&SetWifiAPConfig{ - // ap_config_id, - // ap_config_param: AccessPointConfig::ActiveOnStartup(true), - // }, true)?; - - // Wifi part - // Set the Network SSID to connect to - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::SSID(options.ssid.clone()), - }), - true, - )?; - - if let Some(pass) = options.password.clone() { - // Use WPA2 as authentication type - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::SecurityMode( - SecurityMode::Wpa2AesCcmp, - SecurityModePSK::PSK, - ), - }), - true, - )?; - - // Input passphrase - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::PSKPassphrase(PasskeyR::Passphrase(pass)), - }), - true, - )?; - } else { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::SecurityMode( - SecurityMode::Open, - SecurityModePSK::Open, - ), - }), - true, - )?; - } - - if let Some(channel) = configuration.channel { - self.send_internal( - &EdmAtCmdWrapper(SetWifiAPConfig { - ap_config_id, - ap_config_param: AccessPointConfig::Channel(channel as u8), - }), - true, - )?; - } - - self.send_internal( - &EdmAtCmdWrapper(WifiAPAction { - ap_config_id, - ap_action: AccessPointAction::Activate, - }), - true, - )?; - - self.wifi_connection.replace( - WifiConnection::new( - WifiNetwork { - bssid: Bytes::new(), - op_mode: wifi::types::OperationMode::AdHoc, - ssid: options.ssid, - channel: 0, - rssi: 1, - authentication_suites: 0, - unicast_ciphers: 0, - group_ciphers: 0, - mode: WifiMode::AccessPoint, - }, - WiFiState::NotConnected, - ap_config_id as u8, - ) - .activate(), - ); - Ok(()) - } - - /// Stop serving a wireless network. - /// - /// **NOTE: All users connected will automatically be disconnected.** - pub fn stop_hotspot(&mut self) -> Result<(), WifiHotspotError> { - let ap_config_id = AccessPointId::Id0; - - if let Some(ref con) = self.wifi_connection { - if con.activated { - self.send_internal( - &EdmAtCmdWrapper(WifiAPAction { - ap_config_id, - ap_action: AccessPointAction::Deactivate, - }), - true, - )?; - } - } else { - return Err(WifiHotspotError::FailedToStop); - } - if let Some(ref mut con) = self.wifi_connection { - con.deactivate() - } - - Ok(()) - } -} diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs deleted file mode 100644 index 15f6b48..0000000 --- a/src/wifi/mod.rs +++ /dev/null @@ -1,86 +0,0 @@ -pub use ublox_sockets::{PeerHandle, SocketHandle}; - -use crate::command::edm::types::ChannelId; - -pub mod ap; -pub mod connection; -pub mod network; -pub mod options; -pub mod supplicant; - -pub mod peer_builder; - -pub(crate) const EGRESS_CHUNK_SIZE: usize = 512; -/// The socket map, keeps mappings between `ublox::sockets`s `SocketHandle`, -/// and the modems `PeerHandle` and `ChannelId`. The peer handle is used -/// for controlling the connection, while the channel id is used for sending -/// data over the connection in EDM mode. -pub struct SocketMap { - channel_map: heapless::FnvIndexMap, - peer_map: heapless::FnvIndexMap, -} - -impl Default for SocketMap { - fn default() -> Self { - Self::new() - } -} - -impl SocketMap { - fn new() -> Self { - Self { - channel_map: heapless::FnvIndexMap::new(), - peer_map: heapless::FnvIndexMap::new(), - } - } - - pub fn insert_channel( - &mut self, - channel_id: ChannelId, - socket_handle: SocketHandle, - ) -> Result<(), ()> { - trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, channel_id); - self.channel_map - .insert(channel_id, socket_handle) - .map_err(drop)?; - Ok(()) - } - - pub fn remove_channel(&mut self, channel_id: &ChannelId) -> Result<(), ()> { - trace!("[SOCK_MAP] {:?} removed", channel_id); - self.channel_map.remove(channel_id).ok_or(())?; - Ok(()) - } - - pub fn channel_to_socket(&self, channel_id: &ChannelId) -> Option<&SocketHandle> { - self.channel_map.get(channel_id) - } - - pub fn socket_to_channel_id(&self, socket_handle: &SocketHandle) -> Option<&ChannelId> { - self.channel_map - .iter() - .find_map(|(c, s)| if s == socket_handle { Some(c) } else { None }) - } - - pub fn insert_peer(&mut self, peer: PeerHandle, socket_handle: SocketHandle) -> Result<(), ()> { - trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, peer); - self.peer_map.insert(peer, socket_handle).map_err(drop)?; - Ok(()) - } - - pub fn remove_peer(&mut self, peer: &PeerHandle) -> Result<(), ()> { - trace!("[SOCK_MAP] {:?} removed", peer); - self.peer_map.remove(peer).ok_or(())?; - Ok(()) - } - - pub fn peer_to_socket(&self, peer: &PeerHandle) -> Option<&SocketHandle> { - self.peer_map.get(peer) - } - - pub fn socket_to_peer(&self, socket_handle: &SocketHandle) -> Option<&PeerHandle> { - self.peer_map - .iter() - .find_map(|(c, s)| if s == socket_handle { Some(c) } else { None }) - } -} diff --git a/src/wifi/options.rs b/src/wifi/options.rs deleted file mode 100644 index aac9dd3..0000000 --- a/src/wifi/options.rs +++ /dev/null @@ -1,137 +0,0 @@ -use embedded_nal::Ipv4Addr; -use heapless::String; -use serde::{Deserialize, Serialize}; - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -/// Channel to broadcast wireless hotspot on. -pub enum Channel { - /// Channel 1 - One = 1, - /// Channel 2 - Two = 2, - /// Channel 3 - Three = 3, - /// Channel 4 - Four = 4, - /// Channel 5 - Five = 5, - /// Channel 6 - Six = 6, -} - -#[allow(dead_code)] -#[derive(Debug)] -/// Band type of wireless hotspot. -pub enum Band { - /// Band `A` - A, - /// Band `BG` - Bg, -} - -#[derive(Debug, Default)] -pub struct HotspotOptions { - pub(crate) channel: Option, - pub(crate) band: Option, -} - -impl HotspotOptions { - pub fn new() -> Self { - Self { - channel: Some(Channel::One), - band: Some(Band::Bg), - } - } - - pub fn channel(mut self, channel: Channel) -> Self { - self.channel = Some(channel); - self - } - - pub fn band(mut self, band: Band) -> Self { - self.band = Some(band); - self - } -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct ConnectionOptions { - pub ssid: String<64>, - pub password: Option>, - - #[defmt(Debug2Format)] - pub ip: Option, - #[defmt(Debug2Format)] - pub subnet: Option, - #[defmt(Debug2Format)] - pub gateway: Option, -} - -impl ConnectionOptions { - pub fn new() -> Self { - Self::default() - } - - pub fn ssid(mut self, ssid: String<64>) -> Self { - self.ssid = ssid; - self - } - - pub fn password(mut self, password: String<64>) -> Self { - self.password = Some(password); - self - } - - pub fn ip_address(mut self, ip_addr: Ipv4Addr) -> Self { - self.ip = Some(ip_addr); - self.subnet = if let Some(subnet) = self.subnet { - Some(subnet) - } else { - Some(Ipv4Addr::new(255, 255, 255, 0)) - }; - - self.gateway = if let Some(gateway) = self.gateway { - Some(gateway) - } else { - Some(Ipv4Addr::new(192, 168, 2, 1)) - }; - self - } - - pub fn subnet_address(mut self, subnet_addr: Ipv4Addr) -> Self { - self.subnet = Some(subnet_addr); - - self.ip = if let Some(ip) = self.ip { - Some(ip) - } else { - Some(Ipv4Addr::new(192, 168, 2, 1)) - }; - - self.gateway = if let Some(gateway) = self.gateway { - Some(gateway) - } else { - Some(Ipv4Addr::new(192, 168, 2, 1)) - }; - - self - } - - pub fn gateway_address(mut self, gateway_addr: Ipv4Addr) -> Self { - self.gateway = Some(gateway_addr); - - self.subnet = if let Some(subnet) = self.subnet { - Some(subnet) - } else { - Some(Ipv4Addr::new(255, 255, 255, 0)) - }; - - self.ip = if let Some(ip) = self.ip { - Some(ip) - } else { - Some(Ipv4Addr::new(192, 168, 2, 1)) - }; - self - } -} diff --git a/src/wifi/supplicant.rs b/src/wifi/supplicant.rs deleted file mode 100644 index dabd5bf..0000000 --- a/src/wifi/supplicant.rs +++ /dev/null @@ -1,603 +0,0 @@ -use heapless::Vec; - -use crate::{ - command::{ - edm::EdmAtCmdWrapper, - system::RebootDCE, - wifi::{ - responses::GetWifiStationConfigResponse, - types::{ - Authentication, IPv4Mode, WifiStationAction, WifiStationConfig, - WifiStationConfigParameter, WifiStationConfigR, - }, - ExecWifiStationAction, GetWifiStationConfig, SetWifiStationConfig, WifiScan, - }, - }, - error::{Error, WifiConnectionError, WifiError}, -}; - -use super::{ - connection::{WiFiState, WifiConnection}, - network::WifiNetwork, - options::ConnectionOptions, -}; - -use debug; - -/// Supplicant is used to -/// -/// -/// ``` -/// // Add, activate and remove network -/// let network = ConnectionOptions::new().ssid("my-ssid").password("hunter2"); -/// let config_id: u8 = 0; -/// let mut supplicant = ublox.supplicant::().unwrap(); -/// -/// supplicant.upsert_connection(config_id, network).unwrap(); -/// supplicant.activate(config_id).unwrap(); -/// while ublox.connected_to_network().is_err() { -/// ublox.spin().ok(); -/// } -/// // Now connected to a wifi network. -/// -/// let mut supplicant = ublox.supplicant::().unwrap(); -/// supplicant.deactivate(0).unwrap(); -/// // Connection has to be down before removal -/// while ublox.supplicant::().unwrap().get_active_config().is_some() { -/// ublox.spin().ok(); -/// } -/// let mut supplicant = ublox.supplicant::().unwrap(); -/// supplicant.remove_connection(0) -/// -/// -pub struct Supplicant<'a, C, const N: usize> { - pub(crate) client: &'a mut C, - pub(crate) wifi_connection: &'a mut Option, - pub(crate) active_on_startup: &'a mut Option, -} - -impl<'a, C, const N: usize> Supplicant<'a, C, N> -where - C: atat::blocking::AtatClient, -{ - fn send_at(&mut self, req: &A) -> Result { - self.client.send(req).map_err(|e| { - error!("{:?}: {=[u8]:a}", e, req.as_bytes()); - e.into() - }) - } - - // pub fn load(&mut self) { - // for config_id in 0..N as u8 { - // self.client - // .send(&EdmAtCmdWrapper(ExecWifiStationAction { - // config_id, - // action: WifiStationAction::Load, - // })) - // .ok(); - // } - // } - pub(crate) fn init(&mut self) -> Result<(), Error> { - debug!("[SUP] init"); - for config_id in 0..N as u8 { - let load = self.client.send(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Load, - })); - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::ActiveOnStartup), - }))?; - - if parameter == WifiStationConfigR::ActiveOnStartup(true.into()) { - debug!("[SUP] Config {:?} is active on startup", config_id); - if *self.active_on_startup == None || *self.active_on_startup == Some(config_id) { - *self.active_on_startup = Some(config_id); - // Update wifi connection - if self.wifi_connection.is_none() { - let con = self.get_connection(config_id)?.unwrap_or_default(); - - self.wifi_connection.replace( - WifiConnection::new( - WifiNetwork { - bssid: atat::heapless_bytes::Bytes::new(), - op_mode: - crate::command::wifi::types::OperationMode::Infrastructure, - ssid: con.ssid, - channel: 0, - rssi: 1, - authentication_suites: 0, - unicast_ciphers: 0, - group_ciphers: 0, - mode: super::network::WifiMode::Station, - }, - WiFiState::NotConnected, - config_id, - ) - .activate(), - ); - } else if let Some(ref mut con) = self.wifi_connection { - if con.config_id == 255 { - con.config_id = config_id; - } - } - // One could argue that an excisting connection should be verified, - // but should this be the case, the module is already having unexpected behaviour - } else { - // This causes unexpected behaviour - error!("Two configs are active on startup!"); - return Err(Error::Supplicant); - } - } else if load.is_err() { - //Handle shadow store bug - //TODO: Check if the ssid is set, if so the credential has to be cleared, as it is not there actually. - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::SSID), - }))?; - - if let WifiStationConfigR::SSID(ssid) = parameter { - if !ssid.is_empty() { - error!("Shadow store bug!"); - // This should fix the issue - self.remove_connection(config_id) - .map_err(|_| Error::Supplicant)?; - self.send_at(&EdmAtCmdWrapper(RebootDCE)).ok(); - return Err(Error::ShadowStoreBug); - } - } - } - } - Ok(()) - } - - pub fn get_connection(&mut self, config_id: u8) -> Result, Error> { - debug!("[SUP] Get connection: {:?}", config_id); - let GetWifiStationConfigResponse { - parameter: ip_mode, .. - } = self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::IPv4Mode), - }))?; - - let mut options = ConnectionOptions { - ssid: heapless::String::new(), - password: None, - ip: None, - subnet: None, - gateway: None, - }; - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::SSID), - }))?; - - if let WifiStationConfigR::SSID(ssid) = parameter { - if ssid.is_empty() { - return Ok(None); - } - options.ssid = ssid; - } - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::Authentication), - }))?; - - if let WifiStationConfigR::Authentication(auth) = parameter { - if !matches!(auth, Authentication::Open) { - options.password = Some(heapless::String::from("***")); - } - } - - if let WifiStationConfigR::IPv4Mode(IPv4Mode::Static) = ip_mode { - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::IPv4Address), - }))?; - - if let WifiStationConfigR::IPv4Address(ip) = parameter { - options.ip = Some(ip); - } - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::SubnetMask), - }))?; - - if let WifiStationConfigR::SubnetMask(subnet) = parameter { - options.subnet = Some(subnet); - } - - let GetWifiStationConfigResponse { parameter, .. } = - self.send_at(&EdmAtCmdWrapper(GetWifiStationConfig { - config_id, - parameter: Some(WifiStationConfigParameter::DefaultGateway), - }))?; - - if let WifiStationConfigR::DefaultGateway(gateway) = parameter { - options.gateway = Some(gateway); - } - } - - Ok(Some(options)) - } - - /// Get id of active config - pub fn get_active_config_id(&self) -> Option { - debug!("[SUP] Get active config id"); - if let Some(ref wifi) = self.wifi_connection { - if wifi.wifi_state != WiFiState::Inactive { - debug!("[SUP] Active: {:?}", wifi.config_id); - return Some(wifi.config_id); - } - } - None - } - - /// Get id of active config - pub fn has_active_config_id(&self) -> bool { - if let Some(ref wifi) = self.wifi_connection { - if wifi.wifi_state != WiFiState::Inactive { - return true; - } - } - false - } - - /// List connections stored in module - /// - /// Sorted by config ID - pub fn list_connections(&mut self) -> Result, Error> { - debug!("[SUP] list connections"); - Ok((0..N as u8) - .filter_map(|config_id| { - self.get_connection(config_id) - .unwrap() - .map(|c| (config_id, c)) - }) - .collect()) - } - - /// Attempts to remove a stored wireless network - /// - /// Removing the active connection is not possible. Deactivate the network first. - pub fn remove_connection(&mut self, config_id: u8) -> Result<(), WifiConnectionError> { - // self.deactivate(config_id)?; - debug!("[SUP] Remove connection: {:?}", config_id); - // check for active - if self.is_config_in_use(config_id) { - error!("Config id is active!"); - return Err(WifiConnectionError::Illegal); - } - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Reset, - }))?; - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Store, - }))?; - - if Some(config_id) == self.get_active_on_startup() { - self.unset_active_on_startup()?; - } - // debug!("[SUP] Remove config: {:?}", config_id); - - Ok(()) - } - - /// Attempts to store a wireless network with the given connection options. - /// - /// Replacing the currently active network is not possible. - pub fn insert_connection( - &mut self, - config_id: u8, - options: &ConnectionOptions, - ) -> Result<(), WifiConnectionError> { - debug!("[SUP] Insert config: {:?}", config_id); - // Network part - // Reset network config slot - - // check for active - if self.is_config_in_use(config_id) { - error!("Config id is active!"); - return Err(WifiConnectionError::Illegal); - } - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Reset, - }))?; - if Some(config_id) == self.get_active_on_startup() { - self.unset_active_on_startup()?; - } - - // Disable DHCP Client (static IP address will be used) - if options.ip.is_some() || options.subnet.is_some() || options.gateway.is_some() { - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::IPv4Mode(IPv4Mode::Static), - }))?; - } - - // Network IP address - if let Some(ip) = options.ip { - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::IPv4Address(ip), - }))?; - } - // Network Subnet mask - if let Some(subnet) = options.subnet { - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::SubnetMask(subnet), - }))?; - } - // Network Default gateway - if let Some(gateway) = options.gateway { - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::DefaultGateway(gateway), - }))?; - } - - // Wifi part - // Set the Network SSID to connect to - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::SSID(options.ssid.clone()), - }))?; - - if let Some(pass) = options.password.clone() { - // Use WPA2 as authentication type - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::Authentication(Authentication::WpaWpa2Psk), - }))?; - - // Input passphrase - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::WpaPskOrPassphrase(pass), - }))?; - } else { - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::Authentication(Authentication::Open), - }))?; - } - - // Store config - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Store, - }))?; - - Ok(()) - } - - /// Activate a given network config - /// Only one config can be active at any time. - /// - /// The driver has two modes of active for ID's. Active in driver and active on module. - /// These are differentiated by the driver mode being called activated and modules - /// mode called active. The driver activates a config, and then the driver reacts - /// asyncronous to the request and sets a config as active. - /// Driver activation is seen as `wificonnection.active()`. - /// Module is seen in `wificonnection.state`, where `inactive` is inactive and all others - /// are activated. - /// - /// The activation flow is as follows: - /// - /// driver.activate() driver.deactivate() - /// ┼─────────────────────────┼ - /// ┼─────────────────────────┼ - /// module is active module inactive - pub fn activate(&mut self, config_id: u8) -> Result<(), WifiConnectionError> { - debug!("[SUP] Activate connection: {:?}", config_id); - if let Some(w) = self.wifi_connection { - if w.activated { - return Err(WifiConnectionError::Illegal); - } - } - - let con = self.get_connection(config_id)?.unwrap_or_default(); - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Activate, - }))?; - - self.wifi_connection.replace( - WifiConnection::new( - WifiNetwork { - bssid: atat::heapless_bytes::Bytes::new(), - op_mode: crate::command::wifi::types::OperationMode::Infrastructure, - ssid: con.ssid, - channel: 0, - rssi: 1, - authentication_suites: 0, - unicast_ciphers: 0, - group_ciphers: 0, - mode: super::network::WifiMode::Station, - }, - WiFiState::Inactive, - config_id, - ) - .activate(), - ); - debug!("[SUP] Activated: {:?}", config_id); - - Ok(()) - } - - /// Deactivates a given network config - /// - /// Operation not done until network conneciton is lost - pub fn deactivate(&mut self, config_id: u8) -> Result<(), WifiConnectionError> { - debug!("[SUP] Deactivate connection: {:?}", config_id); - let mut active = false; - - if let Some(con) = self.wifi_connection { - if con.activated && con.config_id == config_id { - active = true; - } - } - - if active { - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Deactivate, - }))?; - - if let Some(ref mut con) = self.wifi_connection { - con.deactivate(); - } - debug!("[SUP] Deactivated: {:?}", config_id); - } - Ok(()) - } - - pub fn scan(&mut self) -> Result, WifiError> { - match self.send_at(&EdmAtCmdWrapper(WifiScan { ssid: None })) { - Ok(resp) => resp - .network_list - .into_iter() - .map(WifiNetwork::try_from) - .collect(), - Err(_) => Err(WifiError::UnexpectedResponse), - } - } - - pub fn is_connected(&self) -> bool { - self.wifi_connection - .as_ref() - .map(WifiConnection::is_connected) - .unwrap_or_default() - } - - pub fn flush(&mut self) -> Result<(), WifiConnectionError> { - todo!() - } - - /// Returns Active on startup config ID if any - pub fn get_active_on_startup(&self) -> Option { - debug!( - "[SUP] Get active on startup: {:?}", - self.active_on_startup.clone() - ); - return self.active_on_startup.clone(); - } - - /// Returns Active on startup config ID if any - pub fn has_active_on_startup(&self) -> bool { - return self.active_on_startup.is_some(); - } - - /// Sets a config as active on startup, replacing the current. - /// - /// This is not possible if any of the two are currently active. - pub fn set_active_on_startup(&mut self, config_id: u8) -> Result<(), WifiConnectionError> { - debug!("[SUP] Set active on startup connection: {:?}", config_id); - // check end condition true - if let Some(active_on_startup) = *self.active_on_startup { - if active_on_startup == config_id { - return Ok(()); - } - // check for active connection - if self.is_config_in_use(active_on_startup) { - error!("Active on startup is active!"); - return Err(WifiConnectionError::Illegal); - } - } - if self.is_config_in_use(config_id) { - error!("Config id is active!"); - return Err(WifiConnectionError::Illegal); - } - - // disable current active on startup - if let Some(active_on_startup) = *self.active_on_startup { - // if any active on startup remove this parameter. - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id: active_on_startup, - config_param: WifiStationConfig::ActiveOnStartup(false.into()), - }))?; - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id: active_on_startup, - action: WifiStationAction::Store, - }))?; - } - - // Insert the new one as active on startup. - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id, - config_param: WifiStationConfig::ActiveOnStartup(true.into()), - }))?; - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id, - action: WifiStationAction::Store, - }))?; - - *self.active_on_startup = Some(config_id); - - Ok(()) - } - - /// Unsets a config as active on startup, replacing the current. - /// - /// This is not possible if any of the two are currently active. - pub fn unset_active_on_startup(&mut self) -> Result<(), WifiConnectionError> { - debug!("[SUP] Unset active on startup connection"); - // check for any of them as active - if let Some(active_on_startup) = self.active_on_startup.clone() { - // check for active connection - if self.is_config_in_use(active_on_startup) { - error!("Active on startup is active!"); - return Err(WifiConnectionError::Illegal); - } - // if any active remove this asset. - self.send_at(&EdmAtCmdWrapper(SetWifiStationConfig { - config_id: active_on_startup, - config_param: WifiStationConfig::ActiveOnStartup(false.into()), - }))?; - - self.send_at(&EdmAtCmdWrapper(ExecWifiStationAction { - config_id: active_on_startup, - action: WifiStationAction::Store, - }))?; - *self.active_on_startup = None; - } - Ok(()) - } - - /// Checks for active and activated. - /// See self.activate for explanation. - fn is_config_in_use(&self, config_id: u8) -> bool { - if let Some(active_id) = self.get_active_config_id() { - if active_id == config_id { - return true; - } - } else if let Some(ref con) = self.wifi_connection { - if con.activated && con.config_id == config_id { - error!("One of the IDs being changed is activated!"); - return true; - } - } - false - } -}

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