use core::sync::atomic::Ordering;
use esp_radio_rtos_driver::semaphore::{SemaphoreHandle, SemaphoreKind};
use esp_sync::NonReentrantMutex;
use portable_atomic_enum::atomic_enum;
use super::event::WifiEvent;
#[atomic_enum]
#[derive(PartialEq, Debug, Clone, Copy, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub(crate) enum WifiStationState {
Starting,
Started,
Connecting,
Connected,
Disconnecting,
Disconnected,
Stopping,
Stopped,
Uninitialized,
}
#[atomic_enum]
#[derive(PartialEq, Debug, Clone, Copy, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub(crate) enum WifiAccessPointState {
Starting,
Started,
Stopping,
Stopped,
Uninitialized,
}
impl From<WifiEvent> for WifiStationState {
fn from(event: WifiEvent) -> WifiStationState {
match event {
WifiEvent::StationStart => WifiStationState::Started,
WifiEvent::StationConnected => WifiStationState::Connected,
WifiEvent::StationDisconnected => WifiStationState::Disconnected,
WifiEvent::StationStop => WifiStationState::Stopped,
_ => WifiStationState::Uninitialized,
}
}
}
impl From<WifiEvent> for WifiAccessPointState {
fn from(event: WifiEvent) -> WifiAccessPointState {
match event {
WifiEvent::AccessPointStart => WifiAccessPointState::Started,
WifiEvent::AccessPointStop => WifiAccessPointState::Stopped,
_ => WifiAccessPointState::Uninitialized,
}
}
}
static STATION_STATE: AtomicWifiStationState =
AtomicWifiStationState::new(WifiStationState::Uninitialized);
static ACCESS_POINT_STATE: AtomicWifiAccessPointState =
AtomicWifiAccessPointState::new(WifiAccessPointState::Uninitialized);
pub(crate) fn access_point_state() -> WifiAccessPointState {
ACCESS_POINT_STATE.load(Ordering::Relaxed)
}
pub(crate) fn station_state() -> WifiStationState {
STATION_STATE.load(Ordering::Relaxed)
}
pub(crate) fn update_state(event: WifiEvent) {
match event {
WifiEvent::StationConnected
| WifiEvent::StationDisconnected
| WifiEvent::StationStart
| WifiEvent::StationStop => {
STATION_STATE.store(WifiStationState::from(event), Ordering::Relaxed)
}
WifiEvent::AccessPointStart | WifiEvent::AccessPointStop => {
ACCESS_POINT_STATE.store(WifiAccessPointState::from(event), Ordering::Relaxed)
}
_ => (),
}
}
pub(crate) fn set_access_point_state(state: WifiAccessPointState) {
ACCESS_POINT_STATE.store(state, Ordering::Relaxed)
}
pub(crate) fn set_station_state(state: WifiStationState) {
STATION_STATE.store(state, Ordering::Relaxed)
}
pub(crate) fn locked<R>(f: impl FnOnce() -> R) -> R {
static LOCK: NonReentrantMutex<Option<SemaphoreHandle>> = NonReentrantMutex::new(None);
LOCK.with(|sem| {
sem.get_or_insert_with(|| SemaphoreHandle::new(SemaphoreKind::Mutex))
.take(None)
});
let res: R = f();
LOCK.with(|sem| {
sem.get_or_insert_with(|| SemaphoreHandle::new(SemaphoreKind::Mutex))
.give()
});
res
}