aboutsummaryrefslogtreecommitdiff
path: root/cyw43
diff options
context:
space:
mode:
Diffstat (limited to 'cyw43')
-rw-r--r--cyw43/CHANGELOG.md4
-rw-r--r--cyw43/Cargo.toml4
-rw-r--r--cyw43/src/bluetooth.rs2
-rw-r--r--cyw43/src/bus.rs6
-rw-r--r--cyw43/src/consts.rs4
-rw-r--r--cyw43/src/control.rs89
-rw-r--r--cyw43/src/ioctl.rs2
-rw-r--r--cyw43/src/lib.rs3
-rw-r--r--cyw43/src/runner.rs6
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]
2name = "cyw43" 2name = "cyw43"
3version = "0.5.0" 3version = "0.6.0"
4edition = "2021" 4edition = "2024"
5description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." 5description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W."
6keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] 6keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"]
7categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] 7categories = ["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;
15pub use crate::bus::SpiBusCyw43; 15pub use crate::bus::SpiBusCyw43;
16use crate::consts::*; 16use crate::consts::*;
17use crate::util::round_up; 17use crate::util::round_up;
18use crate::{util, CHIP}; 18use crate::{CHIP, util};
19 19
20pub(crate) struct BtState { 20pub(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)]
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 fd0d4d532..240c0e728 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -10,13 +10,18 @@ use crate::events::{Event, EventSubscriber, Events};
10use crate::fmt::Bytes; 10use crate::fmt::Bytes;
11use crate::ioctl::{IoctlState, IoctlType}; 11use crate::ioctl::{IoctlState, IoctlType};
12use crate::structs::*; 12use crate::structs::*;
13use crate::{countries, events, PowerManagementMode}; 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.
@@ -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 @@
1use core::cell::{Cell, RefCell}; 1use core::cell::{Cell, RefCell};
2use core::future::{poll_fn, Future}; 2use core::future::{Future, poll_fn};
3use core::task::{Poll, Waker}; 3use core::task::{Poll, Waker};
4 4
5use embassy_sync::waitqueue::WakerRegistration; 5use 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;
30use crate::bus::Bus; 31use crate::bus::Bus;
31pub use crate::bus::SpiBusCyw43; 32pub use crate::bus::SpiBusCyw43;
32pub use crate::control::{ 33pub 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};
35pub use crate::runner::Runner; 36pub use crate::runner::Runner;
36pub use crate::structs::BssInfo; 37pub 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 @@
1use embassy_futures::select::{select4, Either4}; 1use embassy_futures::select::{Either4, select4};
2use embassy_net_driver_channel as ch; 2use embassy_net_driver_channel as ch;
3use embassy_time::{block_for, Duration, Timer}; 3use embassy_time::{Duration, Timer, block_for};
4use embedded_hal_1::digital::OutputPin; 4use embedded_hal_1::digital::OutputPin;
5 5
6use crate::bus::Bus; 6use crate::bus::Bus;
@@ -12,7 +12,7 @@ use crate::ioctl::{IoctlState, IoctlType, PendingIoctl};
12use crate::nvram::NVRAM; 12use crate::nvram::NVRAM;
13use crate::structs::*; 13use crate::structs::*;
14use crate::util::slice8_mut; 14use crate::util::slice8_mut;
15use crate::{events, Core, CHIP, MTU}; 15use crate::{CHIP, Core, MTU, events};
16 16
17#[cfg(feature = "firmware-logs")] 17#[cfg(feature = "firmware-logs")]
18struct LogState { 18struct LogState {