From 57e572ca12182007d0dc421e4406a4a0a4695d99 Mon Sep 17 00:00:00 2001 From: Simon Börjesson Date: Mon, 8 Dec 2025 23:41:19 +0100 Subject: Improve cyw43 join handling --- cyw43/src/consts.rs | 4 ++- cyw43/src/control.rs | 73 +++++++++++++++++++++++++++++++++------------------- cyw43/src/lib.rs | 2 +- 3 files changed, 50 insertions(+), 29 deletions(-) (limited to 'cyw43/src') diff --git a/cyw43/src/consts.rs b/cyw43/src/consts.rs index c3f0dbfd8..e561d4794 100644 --- a/cyw43/src/consts.rs +++ b/cyw43/src/consts.rs @@ -177,9 +177,11 @@ pub(crate) enum Security { } #[allow(non_camel_case_types)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, num_enum::FromPrimitive)] #[repr(u8)] pub enum EStatus { + #[num_enum(default)] + Unknown = 0xFF, /// operation was successful SUCCESS = 0, /// operation failed diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 219198d1f..98f456ce4 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -12,11 +12,15 @@ use crate::ioctl::{IoctlState, IoctlType}; use crate::structs::*; use crate::{PowerManagementMode, countries, events}; -/// Control errors. +/// Join errors. #[derive(Debug)] -pub struct Error { - /// Status code. - pub status: u32, +pub enum JoinError { + /// Network not found. + NetworkNotFound, + /// Failure to join network. Contains the status code from the SET_SSID event. + JoinFailure(u8), + /// Authentication failure for a secure network. + AuthenticationFailure, } /// Multicast errors. @@ -296,7 +300,7 @@ impl<'a> Control<'a> { } /// Join a network with the provided SSID using the specified options. - pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), Error> { + pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), JoinError> { self.set_iovar_u32("ampdu_ba_wsize", 8).await; if options.auth == JoinAuth::Open { @@ -367,40 +371,55 @@ impl<'a> Control<'a> { }; i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); - self.wait_for_join(i).await + let secure_network = options.auth != JoinAuth::Open; + self.wait_for_join(i, secure_network).await } - async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> { - self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]); + async fn wait_for_join(&mut self, i: SsidInfo, secure_network: bool) -> Result<(), JoinError> { + self.events.mask.enable(&[Event::SET_SSID, Event::AUTH, Event::PSK_SUP]); let mut subscriber = self.events.queue.subscriber().unwrap(); // the actual join operation starts here // we make sure to enable events before so we don't miss any self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await; - // to complete the join, we wait for a SET_SSID event - // we also save the AUTH status for the user, it may be interesting - let mut auth_status = 0; - let status = loop { + // To complete the join on an open network, we wait for a SET_SSID event with status SUCCESS + // For secured networks, we wait for a PSK_SUP event with status 6 "UNSOLICITED" + let result = loop { let msg = subscriber.next_message_pure().await; - if msg.header.event_type == Event::AUTH && msg.header.status != EStatus::SUCCESS { - auth_status = msg.header.status; - } else if msg.header.event_type == Event::SET_SSID { - // join operation ends with SET_SSID event - break msg.header.status; - } + + let status = EStatus::from(msg.header.status as u8); + match (msg.header.event_type, status, secure_network) { + // Join operation ends with SET_SSID event for open networks + (Event::SET_SSID, EStatus::SUCCESS, false) => break Ok(()), + (Event::SET_SSID, EStatus::NO_NETWORKS, _) => break Err(JoinError::NetworkNotFound), + (Event::SET_SSID, status, _) if status != EStatus::SUCCESS => { + break Err(JoinError::JoinFailure(status as u8)); + } + // Ignore PSK_SUP "ABORT" which is sometimes sent before successful join + (Event::PSK_SUP, EStatus::ABORT, true) => {} + // Event PSK_SUP with status 6 "UNSOLICITED" indicates success for secure networks + (Event::PSK_SUP, EStatus::UNSOLICITED, true) => break Ok(()), + // Events indicating authentication failure, possibly due to incorrect password + (Event::PSK_SUP, _, true) | (Event::AUTH, EStatus::FAIL, true) => { + break Err(JoinError::AuthenticationFailure); + } + _ => {} + }; }; self.events.mask.disable_all(); - if status == EStatus::SUCCESS { - // successful join - self.state_ch.set_link_state(LinkState::Up); - debug!("JOINED"); - Ok(()) - } else { - warn!("JOIN failed with status={} auth={}", status, auth_status); - Err(Error { status }) - } + match result { + Ok(()) => { + self.state_ch.set_link_state(LinkState::Up); + debug!("JOINED"); + } + Err(JoinError::JoinFailure(status)) => debug!("JOIN failed: status={}", status), + Err(JoinError::NetworkNotFound) => debug!("JOIN failed: network not found"), + Err(JoinError::AuthenticationFailure) => debug!("JOIN failed: authentication failure"), + }; + + result } /// Set GPIO pin on WiFi chip. diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index 82c636346..d723037c7 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs @@ -31,7 +31,7 @@ use ioctl::IoctlState; use crate::bus::Bus; pub use crate::bus::SpiBusCyw43; pub use crate::control::{ - AddMulticastAddressError, Control, Error as ControlError, JoinAuth, JoinOptions, ScanOptions, ScanType, Scanner, + AddMulticastAddressError, Control, JoinError, JoinAuth, JoinOptions, ScanOptions, ScanType, Scanner, }; pub use crate::runner::Runner; pub use crate::structs::BssInfo; -- cgit From dfdd0432ef41de44a8598845822e74138479e40a Mon Sep 17 00:00:00 2001 From: Simon Börjesson Date: Tue, 9 Dec 2025 22:14:27 +0100 Subject: Fix formatting --- cyw43/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cyw43/src') diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index d723037c7..73d2830ca 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs @@ -31,7 +31,7 @@ use ioctl::IoctlState; use crate::bus::Bus; pub use crate::bus::SpiBusCyw43; pub use crate::control::{ - AddMulticastAddressError, Control, JoinError, JoinAuth, JoinOptions, ScanOptions, ScanType, Scanner, + AddMulticastAddressError, Control, JoinAuth, JoinError, JoinOptions, ScanOptions, ScanType, Scanner, }; pub use crate::runner::Runner; pub use crate::structs::BssInfo; -- cgit From 31039201e7edcba6bbf6ba8679332cf98d6d7b1f Mon Sep 17 00:00:00 2001 From: Simon Börjesson Date: Wed, 10 Dec 2025 02:39:48 +0100 Subject: Update examples and tests --- cyw43/src/control.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'cyw43/src') diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 98f456ce4..36d5ee7f8 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -14,6 +14,7 @@ use crate::{PowerManagementMode, countries, events}; /// Join errors. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum JoinError { /// Network not found. NetworkNotFound, -- cgit