Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions esp-radio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ fn is_interrupts_disabled() -> bool {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// Error which can be returned during radio initialization.
#[non_exhaustive]
#[instability::unstable]
pub enum InitializationError {
/// An error from the Wi-Fi driver.
#[cfg(feature = "wifi")]
Expand Down
40 changes: 36 additions & 4 deletions esp-radio/src/wifi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ pub(crate) use self::os_adapter::*;
use self::sniffer::Sniffer;
#[cfg(feature = "wifi-eap")]
use self::sta::eap::EapStationConfig;
pub use self::state::*;
use self::{
ap::{AccessPointConfig, AccessPointInfo, convert_ap_info},
private::PacketBuffer,
scan::{FreeApListOnDrop, ScanConfig, ScanResults, ScanTypeConfig},
sta::StationConfig,
state::*,
};
#[cfg(all(feature = "csi", feature = "unstable"))]
#[instability::unstable]
Expand All @@ -47,7 +47,15 @@ use crate::{
pub mod ap;
#[cfg(all(feature = "csi", feature = "unstable"))]
pub mod csi;

#[cfg(any(doc, feature = "unstable"))]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
#[cfg(feature = "unstable")]
pub mod event;
#[cfg(not(any(doc, feature = "unstable")))]
#[allow(dead_code)]
#[cfg(not(feature = "unstable"))]
pub(crate) mod event;
pub mod scan;
#[cfg(all(feature = "sniffer", feature = "unstable"))]
pub mod sniffer;
Expand Down Expand Up @@ -653,6 +661,7 @@ impl From<InitializationError> for WifiError {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
#[repr(i32)]
#[instability::unstable]
pub enum WifiEvent {
/// Wi-Fi is ready for operation.
WifiReady = 0,
Expand Down Expand Up @@ -1998,6 +2007,9 @@ impl Drop for WifiController<'_> {
warn!("Failed to cleanly deinit wifi: {:?}", e);
}

set_access_point_state(WifiAccessPointState::Uninitialized);
set_station_state(WifiStationState::Uninitialized);

esp_hal::rng::TrngSource::decrease_entropy_source_counter(unsafe {
esp_hal::Internal::conjure()
});
Expand Down Expand Up @@ -2119,6 +2131,9 @@ impl WifiController<'_> {
/// This method is not blocking. To check if the controller has started, use the
/// [`Self::is_started`] method.
pub fn start(&mut self) -> Result<(), WifiError> {
set_access_point_state(WifiAccessPointState::Starting);
set_station_state(WifiStationState::Starting);

unsafe {
esp_wifi_result!(esp_wifi_start())?;

Expand Down Expand Up @@ -2292,15 +2307,22 @@ impl WifiController<'_> {
}

fn stop_impl(&mut self) -> Result<(), WifiError> {
set_access_point_state(WifiAccessPointState::Stopping);
set_station_state(WifiStationState::Stopping);

esp_wifi_result!(unsafe { esp_wifi_stop() })
}

fn connect_impl(&mut self) -> Result<(), WifiError> {
set_station_state(WifiStationState::Connecting);

// TODO: implement ROAMING
esp_wifi_result!(unsafe { esp_wifi_connect_internal() })
}

fn disconnect_impl(&mut self) -> Result<(), WifiError> {
set_station_state(WifiStationState::Disconnecting);

// TODO: implement ROAMING
esp_wifi_result!(unsafe { esp_wifi_disconnect_internal() })
}
Expand Down Expand Up @@ -2413,9 +2435,6 @@ impl WifiController<'_> {

self.wait_for_all_events(events, false).await;

reset_access_point_state();
reset_station_state();

Ok(())
}

Expand Down Expand Up @@ -2460,13 +2479,15 @@ impl WifiController<'_> {
}

/// Wait for one [`WifiEvent`].
#[instability::unstable]
pub async fn wait_for_event(&mut self, event: WifiEvent) {
Self::clear_events(event);
WifiEventFuture::new(event).await
}

/// Wait for one of multiple [`WifiEvent`]s. Returns the events that
/// occurred while waiting.
#[instability::unstable]
pub async fn wait_for_events(
&mut self,
events: EnumSet<WifiEvent>,
Expand All @@ -2479,6 +2500,7 @@ impl WifiController<'_> {
}

/// Wait for multiple [`WifiEvent`]s.
#[instability::unstable]
pub async fn wait_for_all_events(
&mut self,
mut events: EnumSet<WifiEvent>,
Expand All @@ -2494,6 +2516,16 @@ impl WifiController<'_> {
}
}

/// Wait for the station to disconnect.
pub async fn wait_for_station_disconnect(&mut self) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the idea is in the proper impl this will have state checks to ensure we're connected or in a state that emit the disconnection event?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes - I was a bit too lazy in the first iteration 👍

but I admit if this is meant to demonstrate my idea I have to show that

self.wait_for_event(WifiEvent::StationDisconnected).await;
}

/// Wait for the access point to stop.
pub async fn wait_for_access_point_stopped(&mut self) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this might be for demonstrative purposes, but isn't this something the user will request to close, not wait for close?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit I just mechanically translated the usage in our examples ... thanks for bringing it up, I think at least the comment in the examples is questionable and confusing

self.wait_for_event(WifiEvent::AccessPointStop).await;
}

fn apply_ap_config(&mut self, config: &AccessPointConfig) -> Result<(), WifiError> {
self.ap_beacon_timeout = config.beacon_timeout;

Expand Down
42 changes: 27 additions & 15 deletions esp-radio/src/wifi/state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::sync::atomic::Ordering;

use private::{AtomicWifiAccessPointState, AtomicWifiStationState};
pub use private::{WifiAccessPointState, WifiStationState};
pub(crate) use private::{WifiAccessPointState, WifiStationState};

use super::WifiEvent;

Expand All @@ -14,16 +14,24 @@ mod private {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum WifiStationState {
/// Start initiated.
Starting,
/// Station started.
Started,
/// Connect initiated.
Connecting,
/// Station connected.
Connected,
/// Disconnect initiated.
Disconnecting,
/// Station disconnected.
Disconnected,
/// Stop initiated.
Stopping,
/// Station stopped
Stopped,
/// Invalid state.
Invalid,
/// Uninitialized state.
Uninitialized,
}

/// Wi-Fi interface for access point state.
Expand All @@ -32,12 +40,16 @@ mod private {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum WifiAccessPointState {
/// Start initiated.
Starting,
/// Access point started.
Started,
/// Stop initiated.
Stopping,
/// Access point stopped.
Stopped,
/// Invalid state.
Invalid,
/// Uninitialized state.
Uninitialized,
}
}

Expand All @@ -48,7 +60,7 @@ impl From<WifiEvent> for WifiStationState {
WifiEvent::StationConnected => WifiStationState::Connected,
WifiEvent::StationDisconnected => WifiStationState::Disconnected,
WifiEvent::StationStop => WifiStationState::Stopped,
_ => WifiStationState::Invalid,
_ => WifiStationState::Uninitialized,
}
}
}
Expand All @@ -58,23 +70,23 @@ impl From<WifiEvent> for WifiAccessPointState {
match event {
WifiEvent::AccessPointStart => WifiAccessPointState::Started,
WifiEvent::AccessPointStop => WifiAccessPointState::Stopped,
_ => WifiAccessPointState::Invalid,
_ => WifiAccessPointState::Uninitialized,
}
}
}

pub(crate) static STATION_STATE: AtomicWifiStationState =
AtomicWifiStationState::new(WifiStationState::Invalid);
AtomicWifiStationState::new(WifiStationState::Uninitialized);
pub(crate) static ACCESS_POINT_STATE: AtomicWifiAccessPointState =
AtomicWifiAccessPointState::new(WifiAccessPointState::Invalid);
AtomicWifiAccessPointState::new(WifiAccessPointState::Uninitialized);

/// Get the current state of the access point.
pub fn access_point_state() -> WifiAccessPointState {
pub(crate) fn access_point_state() -> WifiAccessPointState {
ACCESS_POINT_STATE.load(Ordering::Relaxed)
}

/// Get the current state of the Station.
pub fn station_state() -> WifiStationState {
pub(crate) fn station_state() -> WifiStationState {
STATION_STATE.load(Ordering::Relaxed)
}

Expand All @@ -99,10 +111,10 @@ pub(crate) fn update_state(event: WifiEvent, handled: bool) {
}
}

pub(crate) fn reset_access_point_state() {
ACCESS_POINT_STATE.store(WifiAccessPointState::Invalid, Ordering::Relaxed)
pub(crate) fn set_access_point_state(state: WifiAccessPointState) {
ACCESS_POINT_STATE.store(state, Ordering::Relaxed)
}

pub(crate) fn reset_station_state() {
STATION_STATE.store(WifiStationState::Invalid, Ordering::Relaxed)
pub(crate) fn set_station_state(state: WifiStationState) {
STATION_STATE.store(state, Ordering::Relaxed)
}
21 changes: 5 additions & 16 deletions examples/wifi/embassy_access_point/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,7 @@ use esp_hal::{
timer::timg::TimerGroup,
};
use esp_println::{print, println};
use esp_radio::wifi::{
ModeConfig,
WifiAccessPointState,
WifiController,
WifiDevice,
WifiEvent,
ap::AccessPointConfig,
};
use esp_radio::wifi::{ModeConfig, WifiController, WifiDevice, ap::AccessPointConfig};

esp_bootloader_esp_idf::esp_app_desc!();

Expand Down Expand Up @@ -238,21 +231,17 @@ async fn connection(mut controller: WifiController<'static>) {
println!("start connection task");
println!("Device capabilities: {:?}", controller.capabilities());
loop {
match esp_radio::wifi::access_point_state() {
WifiAccessPointState::Started => {
// wait until we're no longer connected
controller.wait_for_event(WifiEvent::AccessPointStop).await;
Timer::after(Duration::from_millis(5000)).await
}
_ => {}
}
if !matches!(controller.is_started(), Ok(true)) {
let station_config =
ModeConfig::AccessPoint(AccessPointConfig::default().with_ssid("esp-radio".into()));
controller.set_config(&station_config).unwrap();
println!("Starting wifi");
controller.start_async().await.unwrap();
println!("Wifi started!");
} else {
// wait until we're no longer connected
controller.wait_for_access_point_stopped().await;
Timer::after(Duration::from_millis(5000)).await
}
}
}
Expand Down
33 changes: 14 additions & 19 deletions examples/wifi/embassy_access_point_with_sta/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ use esp_hal::{
use esp_println::{print, println};
use esp_radio::wifi::{
ModeConfig,
WifiAccessPointState,
WifiController,
WifiDevice,
WifiEvent,
ap::AccessPointConfig,
sta::StationConfig,
};
Expand Down Expand Up @@ -315,25 +313,22 @@ async fn connection(mut controller: WifiController<'static>) {
println!("Wifi started!");

loop {
match esp_radio::wifi::access_point_state() {
WifiAccessPointState::Started => {
println!("About to connect...");

match controller.connect_async().await {
Ok(_) => {
// wait until we're no longer connected
controller
.wait_for_event(WifiEvent::StationDisconnected)
.await;
println!("Station disconnected");
}
Err(e) => {
println!("Failed to connect to wifi: {e:?}");
Timer::after(Duration::from_millis(5000)).await
}
if matches!(controller.is_started(), Ok(true)) {
println!("About to connect...");

match controller.connect_async().await {
Ok(_) => {
// wait until we're no longer connected
controller.wait_for_station_disconnect().await;
println!("Station disconnected");
}
Err(e) => {
println!("Failed to connect to wifi: {e:?}");
Timer::after(Duration::from_millis(5000)).await
}
}
_ => return,
} else {
return;
}
}
}
Expand Down
Loading
Loading