diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c857f7378..64c38ea7a 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/cyw43" [features] -defmt = ["dep:defmt"] +defmt = ["dep:defmt", "heapless/defmt-03"] log = ["dep:log"] # Fetch console logs from the WiFi firmware and forward them to `log` or `defmt`. @@ -32,6 +32,8 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa embedded-hal-1 = { package = "embedded-hal", version = "1.0" } num_enum = { version = "0.5.7", default-features = false } +heapless = "0.8.0" + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43/src/" diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 311fcb08c..26d50d311 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -3,7 +3,7 @@ use core::iter::zip; use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; -use embassy_time::Timer; +use embassy_time::{Duration, Timer}; use crate::consts::*; use crate::events::{Event, EventSubscriber, Events}; @@ -35,6 +35,45 @@ pub struct Control<'a> { ioctl_state: &'a IoctlState, } +#[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ScanType { + Active { + /// Period of time to wait on each channel when active scanning. + dwell_time: Option, + }, + Passive { + /// Period of time to wait on each channel when passive scanning. + dwell_time: Option, + }, +} + +#[derive(Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct ScanOptions { + pub ssid: Option>, + /// If set to `None`, all APs will be returned. If set to `Some`, only APs + /// with the specified BSSID will be returned. + pub bssid: Option<[u8; 6]>, + /// Number of probes to send on each channel. + pub nprobes: Option, + /// Time to spend waiting on the home channel. + pub home_time: Option, + pub scan_type: ScanType, +} + +impl Default for ScanOptions { + fn default() -> Self { + Self { + ssid: None, + bssid: None, + nprobes: None, + home_time: None, + scan_type: ScanType::Passive { dwell_time: None }, + } + } +} + impl<'a> Control<'a> { pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a Events, ioctl_state: &'a IoctlState) -> Self { Self { @@ -471,22 +510,56 @@ impl<'a> Control<'a> { /// # Note /// Device events are currently implemented using a bounded queue. /// To not miss any events, you should make sure to always await the stream. - pub async fn scan(&mut self) -> Scanner<'_> { + pub async fn scan(&mut self, scan_opts: ScanOptions) -> Scanner<'_> { + const SCANTYPE_ACTIVE: u8 = 0; const SCANTYPE_PASSIVE: u8 = 1; + let mut active_time = !0; + let mut passive_time = !0; + + let scan_type = match scan_opts.scan_type { + ScanType::Active { dwell_time: None } => SCANTYPE_ACTIVE, + ScanType::Active { + dwell_time: Some(dwell_time), + } => { + active_time = dwell_time.as_millis() as u32; + if active_time == !0 { + active_time = !0 - 1; + } + SCANTYPE_ACTIVE + } + ScanType::Passive { dwell_time: None } => SCANTYPE_PASSIVE, + ScanType::Passive { + dwell_time: Some(dwell_time), + } => { + passive_time = dwell_time.as_millis() as u32; + if passive_time == !0 { + passive_time = !0 - 1; + } + SCANTYPE_PASSIVE + } + }; + let scan_params = ScanParams { version: 1, action: 1, sync_id: 1, - ssid_len: 0, - ssid: [0; 32], - bssid: [0xff; 6], + ssid_len: scan_opts.ssid.as_ref().map(|e| e.as_bytes().len() as u32).unwrap_or(0), + ssid: scan_opts + .ssid + .map(|e| { + let mut ssid = [0; 32]; + ssid[..e.as_bytes().len()].copy_from_slice(e.as_bytes()); + ssid + }) + .unwrap_or([0; 32]), + bssid: scan_opts.bssid.unwrap_or([0xff; 6]), bss_type: 2, - scan_type: SCANTYPE_PASSIVE, - nprobes: !0, - active_time: !0, - passive_time: !0, - home_time: !0, + scan_type, + nprobes: scan_opts.nprobes.unwrap_or(!0).into(), + active_time, + passive_time, + home_time: scan_opts.home_time.map(|e| e.as_millis() as u32).unwrap_or(!0), channel_num: 0, channel_list: [0; 1], }; diff --git a/cyw43/src/events.rs b/cyw43/src/events.rs index a94c49a0c..44bfa98e9 100644 --- a/cyw43/src/events.rs +++ b/cyw43/src/events.rs @@ -311,13 +311,13 @@ pub struct Status { pub status: u32, } -#[derive(Clone, Copy)] +#[derive(Copy, Clone)] pub enum Payload { None, BssInfo(BssInfo), } -#[derive(Clone, Copy)] +#[derive(Copy, Clone)] pub struct Message { pub header: Status, diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 45bb5b76c..e678209dd 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) { .set_power_management(cyw43::PowerManagementMode::PowerSave) .await; - let mut scanner = control.scan().await; + let mut scanner = control.scan(Default::default()).await; while let Some(bss) = scanner.next().await { if let Ok(ssid_str) = str::from_utf8(&bss.ssid) { info!("scanned {} == {:x}", ssid_str, bss.bssid);