diff options
| author | Simon Börjesson <[email protected]> | 2025-12-08 23:41:19 +0100 |
|---|---|---|
| committer | Simon Börjesson <[email protected]> | 2025-12-08 23:41:19 +0100 |
| commit | 57e572ca12182007d0dc421e4406a4a0a4695d99 (patch) | |
| tree | 37bfee25078595bdac922d5f9ecb20d950e06e07 /cyw43/src/control.rs | |
| parent | 95fd1f46a2c44f961e27f48920d87468d39a3793 (diff) | |
Improve cyw43 join handling
Diffstat (limited to 'cyw43/src/control.rs')
| -rw-r--r-- | cyw43/src/control.rs | 73 |
1 files changed, 46 insertions, 27 deletions
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}; | |||
| 12 | use crate::structs::*; | 12 | use crate::structs::*; |
| 13 | use crate::{PowerManagementMode, countries, events}; | 13 | use crate::{PowerManagementMode, countries, events}; |
| 14 | 14 | ||
| 15 | /// Control errors. | 15 | /// Join errors. |
| 16 | #[derive(Debug)] | 16 | #[derive(Debug)] |
| 17 | pub struct Error { | 17 | pub enum JoinError { |
| 18 | /// Status code. | 18 | /// Network not found. |
| 19 | pub status: u32, | 19 | NetworkNotFound, |
| 20 | /// Failure to join network. Contains the status code from the SET_SSID event. | ||
| 21 | JoinFailure(u8), | ||
| 22 | /// Authentication failure for a secure network. | ||
| 23 | AuthenticationFailure, | ||
| 20 | } | 24 | } |
| 21 | 25 | ||
| 22 | /// Multicast errors. | 26 | /// Multicast errors. |
| @@ -296,7 +300,7 @@ impl<'a> Control<'a> { | |||
| 296 | } | 300 | } |
| 297 | 301 | ||
| 298 | /// Join a network with the provided SSID using the specified options. | 302 | /// Join a network with the provided SSID using the specified options. |
| 299 | pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), Error> { | 303 | pub async fn join(&mut self, ssid: &str, options: JoinOptions<'_>) -> Result<(), JoinError> { |
| 300 | self.set_iovar_u32("ampdu_ba_wsize", 8).await; | 304 | self.set_iovar_u32("ampdu_ba_wsize", 8).await; |
| 301 | 305 | ||
| 302 | if options.auth == JoinAuth::Open { | 306 | if options.auth == JoinAuth::Open { |
| @@ -367,40 +371,55 @@ impl<'a> Control<'a> { | |||
| 367 | }; | 371 | }; |
| 368 | i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); | 372 | i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); |
| 369 | 373 | ||
| 370 | self.wait_for_join(i).await | 374 | let secure_network = options.auth != JoinAuth::Open; |
| 375 | self.wait_for_join(i, secure_network).await | ||
| 371 | } | 376 | } |
| 372 | 377 | ||
| 373 | async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> { | 378 | async fn wait_for_join(&mut self, i: SsidInfo, secure_network: bool) -> Result<(), JoinError> { |
| 374 | self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]); | 379 | self.events.mask.enable(&[Event::SET_SSID, Event::AUTH, Event::PSK_SUP]); |
| 375 | let mut subscriber = self.events.queue.subscriber().unwrap(); | 380 | let mut subscriber = self.events.queue.subscriber().unwrap(); |
| 376 | // the actual join operation starts here | 381 | // the actual join operation starts here |
| 377 | // we make sure to enable events before so we don't miss any | 382 | // we make sure to enable events before so we don't miss any |
| 378 | 383 | ||
| 379 | self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await; | 384 | self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await; |
| 380 | 385 | ||
| 381 | // to complete the join, we wait for a SET_SSID event | 386 | // 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 | 387 | // For secured networks, we wait for a PSK_SUP event with status 6 "UNSOLICITED" |
| 383 | let mut auth_status = 0; | 388 | let result = loop { |
| 384 | let status = loop { | ||
| 385 | let msg = subscriber.next_message_pure().await; | 389 | let msg = subscriber.next_message_pure().await; |
| 386 | if msg.header.event_type == Event::AUTH && msg.header.status != EStatus::SUCCESS { | 390 | |
| 387 | auth_status = msg.header.status; | 391 | let status = EStatus::from(msg.header.status as u8); |
| 388 | } else if msg.header.event_type == Event::SET_SSID { | 392 | match (msg.header.event_type, status, secure_network) { |
| 389 | // join operation ends with SET_SSID event | 393 | // Join operation ends with SET_SSID event for open networks |
| 390 | break msg.header.status; | 394 | (Event::SET_SSID, EStatus::SUCCESS, false) => break Ok(()), |
| 391 | } | 395 | (Event::SET_SSID, EStatus::NO_NETWORKS, _) => break Err(JoinError::NetworkNotFound), |
| 396 | (Event::SET_SSID, status, _) if status != EStatus::SUCCESS => { | ||
| 397 | break Err(JoinError::JoinFailure(status as u8)); | ||
| 398 | } | ||
| 399 | // Ignore PSK_SUP "ABORT" which is sometimes sent before successful join | ||
| 400 | (Event::PSK_SUP, EStatus::ABORT, true) => {} | ||
| 401 | // Event PSK_SUP with status 6 "UNSOLICITED" indicates success for secure networks | ||
| 402 | (Event::PSK_SUP, EStatus::UNSOLICITED, true) => break Ok(()), | ||
| 403 | // Events indicating authentication failure, possibly due to incorrect password | ||
| 404 | (Event::PSK_SUP, _, true) | (Event::AUTH, EStatus::FAIL, true) => { | ||
| 405 | break Err(JoinError::AuthenticationFailure); | ||
| 406 | } | ||
| 407 | _ => {} | ||
| 408 | }; | ||
| 392 | }; | 409 | }; |
| 393 | 410 | ||
| 394 | self.events.mask.disable_all(); | 411 | self.events.mask.disable_all(); |
| 395 | if status == EStatus::SUCCESS { | 412 | match result { |
| 396 | // successful join | 413 | Ok(()) => { |
| 397 | self.state_ch.set_link_state(LinkState::Up); | 414 | self.state_ch.set_link_state(LinkState::Up); |
| 398 | debug!("JOINED"); | 415 | debug!("JOINED"); |
| 399 | Ok(()) | 416 | } |
| 400 | } else { | 417 | Err(JoinError::JoinFailure(status)) => debug!("JOIN failed: status={}", status), |
| 401 | warn!("JOIN failed with status={} auth={}", status, auth_status); | 418 | Err(JoinError::NetworkNotFound) => debug!("JOIN failed: network not found"), |
| 402 | Err(Error { status }) | 419 | Err(JoinError::AuthenticationFailure) => debug!("JOIN failed: authentication failure"), |
| 403 | } | 420 | }; |
| 421 | |||
| 422 | result | ||
| 404 | } | 423 | } |
| 405 | 424 | ||
| 406 | /// Set GPIO pin on WiFi chip. | 425 | /// Set GPIO pin on WiFi chip. |
