aboutsummaryrefslogtreecommitdiff
path: root/cyw43/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-12-11 16:53:36 +0000
committerGitHub <[email protected]>2025-12-11 16:53:36 +0000
commit3588023e3e04b18cf98a2a0d10756e1f236ca351 (patch)
tree9c044943daa253e7e489ee5cc374b1de6de72b2f /cyw43/src
parent0301bdf2c09854f9f3bc864f666608cef295373b (diff)
parent31039201e7edcba6bbf6ba8679332cf98d6d7b1f (diff)
Merge pull request #5020 from simonborje/improve_cyw43_join_result
Improve cyw43 join handling
Diffstat (limited to 'cyw43/src')
-rw-r--r--cyw43/src/consts.rs4
-rw-r--r--cyw43/src/control.rs74
-rw-r--r--cyw43/src/lib.rs2
3 files changed, 51 insertions, 29 deletions
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 {
177} 177}
178 178
179#[allow(non_camel_case_types)] 179#[allow(non_camel_case_types)]
180#[derive(Copy, Clone)] 180#[derive(Copy, Clone, PartialEq, num_enum::FromPrimitive)]
181#[repr(u8)] 181#[repr(u8)]
182pub enum EStatus { 182pub enum EStatus {
183 #[num_enum(default)]
184 Unknown = 0xFF,
183 /// operation was successful 185 /// operation was successful
184 SUCCESS = 0, 186 SUCCESS = 0,
185 /// operation failed 187 /// operation failed
diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index 07fa1955e..240c0e728 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -12,11 +12,16 @@ use crate::ioctl::{IoctlState, IoctlType};
12use crate::structs::*; 12use crate::structs::*;
13use crate::{PowerManagementMode, countries, events}; 13use crate::{PowerManagementMode, countries, events};
14 14
15/// Control errors. 15/// Join errors.
16#[derive(Debug)] 16#[derive(Debug)]
17pub struct Error { 17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18 /// Status code. 18pub enum JoinError {
19 pub status: u32, 19 /// Network not found.
20 NetworkNotFound,
21 /// Failure to join network. Contains the status code from the SET_SSID event.
22 JoinFailure(u8),
23 /// Authentication failure for a secure network.
24 AuthenticationFailure,
20} 25}
21 26
22/// Multicast errors. 27/// Multicast errors.
@@ -296,7 +301,7 @@ impl<'a> Control<'a> {
296 } 301 }
297 302
298 /// Join a network with the provided SSID using the specified options. 303 /// Join a network with the provided SSID using the specified options.
299 pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), Error> { 304 pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), JoinError> {
300 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 305 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
301 306
302 if options.auth == JoinAuth::Open { 307 if options.auth == JoinAuth::Open {
@@ -367,40 +372,55 @@ impl<'a> Control<'a> {
367 }; 372 };
368 i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); 373 i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes());
369 374
370 self.wait_for_join(i).await 375 let secure_network = options.auth != JoinAuth::Open;
376 self.wait_for_join(i, secure_network).await
371 } 377 }
372 378
373 async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> { 379 async fn wait_for_join(&mut self, i: SsidInfo, secure_network: bool) -> Result<(), JoinError> {
374 self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]); 380 self.events.mask.enable(&[Event::SET_SSID, Event::AUTH, Event::PSK_SUP]);
375 let mut subscriber = self.events.queue.subscriber().unwrap(); 381 let mut subscriber = self.events.queue.subscriber().unwrap();
376 // the actual join operation starts here 382 // the actual join operation starts here
377 // we make sure to enable events before so we don't miss any 383 // we make sure to enable events before so we don't miss any
378 384
379 self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await; 385 self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await;
380 386
381 // to complete the join, we wait for a SET_SSID event 387 // To complete the join on an open network, we wait for a SET_SSID event with status SUCCESS
382 // we also save the AUTH status for the user, it may be interesting 388 // For secured networks, we wait for a PSK_SUP event with status 6 "UNSOLICITED"
383 let mut auth_status = 0; 389 let result = loop {
384 let status = loop {
385 let msg = subscriber.next_message_pure().await; 390 let msg = subscriber.next_message_pure().await;
386 if msg.header.event_type == Event::AUTH && msg.header.status != EStatus::SUCCESS { 391
387 auth_status = msg.header.status; 392 let status = EStatus::from(msg.header.status as u8);
388 } else if msg.header.event_type == Event::SET_SSID { 393 match (msg.header.event_type, status, secure_network) {
389 // join operation ends with SET_SSID event 394 // Join operation ends with SET_SSID event for open networks
390 break msg.header.status; 395 (Event::SET_SSID, EStatus::SUCCESS, false) => break Ok(()),
391 } 396 (Event::SET_SSID, EStatus::NO_NETWORKS, _) => break Err(JoinError::NetworkNotFound),
397 (Event::SET_SSID, status, _) if status != EStatus::SUCCESS => {
398 break Err(JoinError::JoinFailure(status as u8));
399 }
400 // Ignore PSK_SUP "ABORT" which is sometimes sent before successful join
401 (Event::PSK_SUP, EStatus::ABORT, true) => {}
402 // Event PSK_SUP with status 6 "UNSOLICITED" indicates success for secure networks
403 (Event::PSK_SUP, EStatus::UNSOLICITED, true) => break Ok(()),
404 // Events indicating authentication failure, possibly due to incorrect password
405 (Event::PSK_SUP, _, true) | (Event::AUTH, EStatus::FAIL, true) => {
406 break Err(JoinError::AuthenticationFailure);
407 }
408 _ => {}
409 };
392 }; 410 };
393 411
394 self.events.mask.disable_all(); 412 self.events.mask.disable_all();
395 if status == EStatus::SUCCESS { 413 match result {
396 // successful join 414 Ok(()) => {
397 self.state_ch.set_link_state(LinkState::Up); 415 self.state_ch.set_link_state(LinkState::Up);
398 debug!("JOINED"); 416 debug!("JOINED");
399 Ok(()) 417 }
400 } else { 418 Err(JoinError::JoinFailure(status)) => debug!("JOIN failed: status={}", status),
401 warn!("JOIN failed with status={} auth={}", status, auth_status); 419 Err(JoinError::NetworkNotFound) => debug!("JOIN failed: network not found"),
402 Err(Error { status }) 420 Err(JoinError::AuthenticationFailure) => debug!("JOIN failed: authentication failure"),
403 } 421 };
422
423 result
404 } 424 }
405 425
406 /// Set GPIO pin on WiFi chip. 426 /// Set GPIO pin on WiFi chip.
diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs
index 82c636346..73d2830ca 100644
--- a/cyw43/src/lib.rs
+++ b/cyw43/src/lib.rs
@@ -31,7 +31,7 @@ use ioctl::IoctlState;
31use crate::bus::Bus; 31use crate::bus::Bus;
32pub use crate::bus::SpiBusCyw43; 32pub use crate::bus::SpiBusCyw43;
33pub use crate::control::{ 33pub use crate::control::{
34 AddMulticastAddressError, Control, Error as ControlError, JoinAuth, JoinOptions, ScanOptions, ScanType, Scanner, 34 AddMulticastAddressError, Control, JoinAuth, JoinError, JoinOptions, ScanOptions, ScanType, Scanner,
35}; 35};
36pub use crate::runner::Runner; 36pub use crate::runner::Runner;
37pub use crate::structs::BssInfo; 37pub use crate::structs::BssInfo;