diff options
Diffstat (limited to 'cyw43')
| -rw-r--r-- | cyw43/CHANGELOG.md | 4 | ||||
| -rw-r--r-- | cyw43/Cargo.toml | 4 | ||||
| -rw-r--r-- | cyw43/src/bluetooth.rs | 2 | ||||
| -rw-r--r-- | cyw43/src/bus.rs | 6 | ||||
| -rw-r--r-- | cyw43/src/consts.rs | 4 | ||||
| -rw-r--r-- | cyw43/src/control.rs | 89 | ||||
| -rw-r--r-- | cyw43/src/ioctl.rs | 2 | ||||
| -rw-r--r-- | cyw43/src/lib.rs | 3 | ||||
| -rw-r--r-- | cyw43/src/runner.rs | 6 |
9 files changed, 76 insertions, 44 deletions
diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index 1045fd30b..4f0dc896b 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md | |||
| @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 8 | <!-- next-header --> | 8 | <!-- next-header --> |
| 9 | ## Unreleased - ReleaseDate | 9 | ## Unreleased - ReleaseDate |
| 10 | 10 | ||
| 11 | - Reset WPA security before creating secure AP | ||
| 12 | |||
| 13 | ## 0.6.0 - 2025-11-27 | ||
| 14 | |||
| 11 | - Updated documentation for Control::join() #4678 | 15 | - Updated documentation for Control::join() #4678 |
| 12 | - Bump bt-hci to 0.6.0. | 16 | - Bump bt-hci to 0.6.0. |
| 13 | - Add error handling to HCI transport implementation. | 17 | - Add error handling to HCI transport implementation. |
diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c59c15a71..6d7647697 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "cyw43" | 2 | name = "cyw43" |
| 3 | version = "0.5.0" | 3 | version = "0.6.0" |
| 4 | edition = "2021" | 4 | edition = "2024" |
| 5 | description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." | 5 | description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." |
| 6 | keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] | 6 | keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] |
| 7 | categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] | 7 | categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] |
diff --git a/cyw43/src/bluetooth.rs b/cyw43/src/bluetooth.rs index d176c4b09..332b7048d 100644 --- a/cyw43/src/bluetooth.rs +++ b/cyw43/src/bluetooth.rs | |||
| @@ -15,7 +15,7 @@ use crate::bus::Bus; | |||
| 15 | pub use crate::bus::SpiBusCyw43; | 15 | pub use crate::bus::SpiBusCyw43; |
| 16 | use crate::consts::*; | 16 | use crate::consts::*; |
| 17 | use crate::util::round_up; | 17 | use crate::util::round_up; |
| 18 | use crate::{util, CHIP}; | 18 | use crate::{CHIP, util}; |
| 19 | 19 | ||
| 20 | pub(crate) struct BtState { | 20 | pub(crate) struct BtState { |
| 21 | rx: [BtPacketBuf; 4], | 21 | rx: [BtPacketBuf; 4], |
diff --git a/cyw43/src/bus.rs b/cyw43/src/bus.rs index 8a53484d5..aa2b66a40 100644 --- a/cyw43/src/bus.rs +++ b/cyw43/src/bus.rs | |||
| @@ -340,11 +340,7 @@ where | |||
| 340 | self.status = self.spi.cmd_read(cmd, &mut buf[..len]).await; | 340 | self.status = self.spi.cmd_read(cmd, &mut buf[..len]).await; |
| 341 | 341 | ||
| 342 | // if we read from the backplane, the result is in the second word, after the response delay | 342 | // if we read from the backplane, the result is in the second word, after the response delay |
| 343 | if func == FUNC_BACKPLANE { | 343 | if func == FUNC_BACKPLANE { buf[1] } else { buf[0] } |
| 344 | buf[1] | ||
| 345 | } else { | ||
| 346 | buf[0] | ||
| 347 | } | ||
| 348 | } | 344 | } |
| 349 | 345 | ||
| 350 | async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { | 346 | async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { |
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)] |
| 182 | pub enum EStatus { | 182 | pub 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 fd0d4d532..240c0e728 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs | |||
| @@ -10,13 +10,18 @@ use crate::events::{Event, EventSubscriber, Events}; | |||
| 10 | use crate::fmt::Bytes; | 10 | use crate::fmt::Bytes; |
| 11 | use crate::ioctl::{IoctlState, IoctlType}; | 11 | use crate::ioctl::{IoctlState, IoctlType}; |
| 12 | use crate::structs::*; | 12 | use crate::structs::*; |
| 13 | use crate::{countries, events, PowerManagementMode}; | 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 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 18 | /// Status code. | 18 | pub 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. |
| @@ -436,6 +456,9 @@ impl<'a> Control<'a> { | |||
| 436 | // Set wifi up again | 456 | // Set wifi up again |
| 437 | self.up().await; | 457 | self.up().await; |
| 438 | 458 | ||
| 459 | // Disable authentication | ||
| 460 | self.ioctl_set_u32(Ioctl::SetAuth, 0, AUTH_OPEN).await; | ||
| 461 | |||
| 439 | // Turn on AP mode | 462 | // Turn on AP mode |
| 440 | self.ioctl_set_u32(Ioctl::SetAp, 0, 1).await; | 463 | self.ioctl_set_u32(Ioctl::SetAp, 0, 1).await; |
| 441 | 464 | ||
| @@ -470,8 +493,6 @@ impl<'a> Control<'a> { | |||
| 470 | pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); | 493 | pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); |
| 471 | self.ioctl(IoctlType::Set, Ioctl::SetWsecPmk, 0, &mut pfi.to_bytes()) | 494 | self.ioctl(IoctlType::Set, Ioctl::SetWsecPmk, 0, &mut pfi.to_bytes()) |
| 472 | .await; | 495 | .await; |
| 473 | } else { | ||
| 474 | self.ioctl_set_u32(Ioctl::SetAuth, 0, 0).await; | ||
| 475 | } | 496 | } |
| 476 | 497 | ||
| 477 | // Change mutlicast rate from 1 Mbps to 11 Mbps | 498 | // Change mutlicast rate from 1 Mbps to 11 Mbps |
| @@ -547,6 +568,14 @@ impl<'a> Control<'a> { | |||
| 547 | n | 568 | n |
| 548 | } | 569 | } |
| 549 | 570 | ||
| 571 | /// Retrieve the latest RSSI value | ||
| 572 | pub async fn get_rssi(&mut self) -> i32 { | ||
| 573 | let mut rssi_buf = [0u8; 4]; | ||
| 574 | let n = self.ioctl(IoctlType::Get, Ioctl::GetRssi, 0, &mut rssi_buf).await; | ||
| 575 | assert_eq!(n, 4); | ||
| 576 | i32::from_ne_bytes(rssi_buf) | ||
| 577 | } | ||
| 578 | |||
| 550 | async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) { | 579 | async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) { |
| 551 | let mut buf = [0; 8]; | 580 | let mut buf = [0; 8]; |
| 552 | buf[0..4].copy_from_slice(&val1.to_le_bytes()); | 581 | buf[0..4].copy_from_slice(&val1.to_le_bytes()); |
diff --git a/cyw43/src/ioctl.rs b/cyw43/src/ioctl.rs index 35135e296..deccc945d 100644 --- a/cyw43/src/ioctl.rs +++ b/cyw43/src/ioctl.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use core::cell::{Cell, RefCell}; | 1 | use core::cell::{Cell, RefCell}; |
| 2 | use core::future::{poll_fn, Future}; | 2 | use core::future::{Future, poll_fn}; |
| 3 | use core::task::{Poll, Waker}; | 3 | use core::task::{Poll, Waker}; |
| 4 | 4 | ||
| 5 | use embassy_sync::waitqueue::WakerRegistration; | 5 | use embassy_sync::waitqueue::WakerRegistration; |
diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index 16b436e66..73d2830ca 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![allow(async_fn_in_trait)] | 3 | #![allow(async_fn_in_trait)] |
| 4 | #![allow(unsafe_op_in_unsafe_fn)] | ||
| 4 | #![deny(unused_must_use)] | 5 | #![deny(unused_must_use)] |
| 5 | #![doc = include_str!("../README.md")] | 6 | #![doc = include_str!("../README.md")] |
| 6 | #![warn(missing_docs)] | 7 | #![warn(missing_docs)] |
| @@ -30,7 +31,7 @@ use ioctl::IoctlState; | |||
| 30 | use crate::bus::Bus; | 31 | use crate::bus::Bus; |
| 31 | pub use crate::bus::SpiBusCyw43; | 32 | pub use crate::bus::SpiBusCyw43; |
| 32 | pub use crate::control::{ | 33 | pub use crate::control::{ |
| 33 | AddMulticastAddressError, Control, Error as ControlError, JoinAuth, JoinOptions, ScanOptions, ScanType, Scanner, | 34 | AddMulticastAddressError, Control, JoinAuth, JoinError, JoinOptions, ScanOptions, ScanType, Scanner, |
| 34 | }; | 35 | }; |
| 35 | pub use crate::runner::Runner; | 36 | pub use crate::runner::Runner; |
| 36 | pub use crate::structs::BssInfo; | 37 | pub use crate::structs::BssInfo; |
diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs index 77910b281..7c38be24a 100644 --- a/cyw43/src/runner.rs +++ b/cyw43/src/runner.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use embassy_futures::select::{select4, Either4}; | 1 | use embassy_futures::select::{Either4, select4}; |
| 2 | use embassy_net_driver_channel as ch; | 2 | use embassy_net_driver_channel as ch; |
| 3 | use embassy_time::{block_for, Duration, Timer}; | 3 | use embassy_time::{Duration, Timer, block_for}; |
| 4 | use embedded_hal_1::digital::OutputPin; | 4 | use embedded_hal_1::digital::OutputPin; |
| 5 | 5 | ||
| 6 | use crate::bus::Bus; | 6 | use crate::bus::Bus; |
| @@ -12,7 +12,7 @@ use crate::ioctl::{IoctlState, IoctlType, PendingIoctl}; | |||
| 12 | use crate::nvram::NVRAM; | 12 | use crate::nvram::NVRAM; |
| 13 | use crate::structs::*; | 13 | use crate::structs::*; |
| 14 | use crate::util::slice8_mut; | 14 | use crate::util::slice8_mut; |
| 15 | use crate::{events, Core, CHIP, MTU}; | 15 | use crate::{CHIP, Core, MTU, events}; |
| 16 | 16 | ||
| 17 | #[cfg(feature = "firmware-logs")] | 17 | #[cfg(feature = "firmware-logs")] |
| 18 | struct LogState { | 18 | struct LogState { |
