Split the wifi feature into wifi-ap, wifi-sta and wifi-eap (#3924)

* Split wifi feature into wifi-ap, wifi-sta and wifi-eap

* changelog

* Revert most of the changes, keep wifi and wifi-eap features only

* wifi-eap is unstable, include this feature into CI tests and documentation
This commit is contained in:
Juraj Sadel 2025-08-21 11:47:42 +02:00 committed by GitHub
parent 68345293ed
commit 0ce9a1c5e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 48 additions and 11 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `AccessPointInfo::country` to access the Country Code from the Wi-Fi scan results (#3837) - `AccessPointInfo::country` to access the Country Code from the Wi-Fi scan results (#3837)
- `unstable` feature to opt into `ble`, `esp-now`, `csi`, `sniffer`, `esp-ieee802154` and `smoltcp` APIs (#3865) - `unstable` feature to opt into `ble`, `esp-now`, `csi`, `sniffer`, `esp-ieee802154` and `smoltcp` APIs (#3865)
- Added unstable `wifi-eap` feature (#3924)
- Optional `max` field in `ScanConfig` to allow limiting the number of returned results (#3963) - Optional `max` field in `ScanConfig` to allow limiting the number of returned results (#3963)
### Changed ### Changed

View File

@ -129,6 +129,9 @@ sys-logs = ["esp-wifi-sys/sys-logs"]
## Enable WiFi support ## Enable WiFi support
wifi = ["dep:enumset", "dep:embassy-net-driver"] wifi = ["dep:enumset", "dep:embassy-net-driver"]
## Enable WiFi Enterprise Authentication Protocol (EAP) support
wifi-eap = ["wifi"]
## Enable esp-now support ## Enable esp-now support
esp-now = ["wifi"] esp-now = ["wifi"]
@ -141,7 +144,7 @@ ble = ["esp-hal/__bluetooth", "dep:bt-hci"]
## Enable WiFi-BLE coexistence support ## Enable WiFi-BLE coexistence support
coex = [] coex = []
## Enable WiFi channel state information. See [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv4N18wifi_init_config_t10csi_enableE)", ## Enable WiFi channel state information. See [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv4N18wifi_init_config_t10csi_enableE),
csi = [] csi = []
## Use IEEE 802.15.4 ## Use IEEE 802.15.4

View File

@ -45,12 +45,13 @@ fn main() -> Result<(), Box<dyn Error>> {
|| cfg!(feature = "esp-now") || cfg!(feature = "esp-now")
|| cfg!(feature = "ieee802154") || cfg!(feature = "ieee802154")
|| cfg!(feature = "smoltcp") || cfg!(feature = "smoltcp")
|| cfg!(feature = "sniffer")) || cfg!(feature = "sniffer")
|| cfg!(feature = "wifi-eap"))
&& !cfg!(feature = "unstable") && !cfg!(feature = "unstable")
&& !suppress_panics && !suppress_panics
{ {
panic!( panic!(
"\n\nThe `unstable` feature was not provided, but is required for the following features: `ble`, `coex`, `csi`, `esp-now`, `ieee802154`, `smoltcp`, `sniffer`.\n\n" "\n\nThe `unstable` feature was not provided, but is required for the following features: `ble`, `coex`, `csi`, `esp-now`, `ieee802154`, `smoltcp`, `sniffer`, `wifi-eap`.\n\n"
) )
} }

View File

@ -8,7 +8,8 @@ use alloc::{collections::vec_deque::VecDeque, string::String};
use core::{ use core::{
fmt::Debug, fmt::Debug,
marker::PhantomData, marker::PhantomData,
mem::{self, MaybeUninit}, mem,
mem::MaybeUninit,
ptr::addr_of, ptr::addr_of,
task::Poll, task::Poll,
time::Duration, time::Duration,
@ -22,6 +23,11 @@ use esp_wifi_sys::include::{
WIFI_PROTOCOL_11G, WIFI_PROTOCOL_11G,
WIFI_PROTOCOL_11N, WIFI_PROTOCOL_11N,
WIFI_PROTOCOL_LR, WIFI_PROTOCOL_LR,
wifi_pkt_rx_ctrl_t,
wifi_scan_channel_bitmap_t,
};
#[cfg(feature = "wifi-eap")]
use esp_wifi_sys::include::{
esp_eap_client_clear_ca_cert, esp_eap_client_clear_ca_cert,
esp_eap_client_clear_certificate_and_key, esp_eap_client_clear_certificate_and_key,
esp_eap_client_clear_identity, esp_eap_client_clear_identity,
@ -40,8 +46,6 @@ use esp_wifi_sys::include::{
esp_eap_client_set_username, esp_eap_client_set_username,
esp_eap_fast_config, esp_eap_fast_config,
esp_wifi_sta_enterprise_enable, esp_wifi_sta_enterprise_enable,
wifi_pkt_rx_ctrl_t,
wifi_scan_channel_bitmap_t,
}; };
#[cfg(all(feature = "sniffer", feature = "unstable"))] #[cfg(all(feature = "sniffer", feature = "unstable"))]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
@ -481,6 +485,8 @@ impl defmt::Format for ClientConfiguration {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg(feature = "wifi-eap")]
#[instability::unstable]
pub struct EapFastConfig { pub struct EapFastConfig {
/// Specifies the provisioning mode for EAP-FAST. /// Specifies the provisioning mode for EAP-FAST.
pub fast_provisioning: u8, pub fast_provisioning: u8,
@ -494,6 +500,8 @@ pub struct EapFastConfig {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg(feature = "wifi-eap")]
#[instability::unstable]
pub enum TtlsPhase2Method { pub enum TtlsPhase2Method {
/// EAP (Extensible Authentication Protocol). /// EAP (Extensible Authentication Protocol).
Eap, Eap,
@ -511,6 +519,7 @@ pub enum TtlsPhase2Method {
Chap, Chap,
} }
#[cfg(feature = "wifi-eap")]
impl TtlsPhase2Method { impl TtlsPhase2Method {
/// Maps the phase 2 method to a raw `u32` representation. /// Maps the phase 2 method to a raw `u32` representation.
fn to_raw(&self) -> u32 { fn to_raw(&self) -> u32 {
@ -537,6 +546,8 @@ impl TtlsPhase2Method {
/// Configuration for an EAP (Extensible Authentication Protocol) client. /// Configuration for an EAP (Extensible Authentication Protocol) client.
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg(feature = "wifi-eap")]
#[instability::unstable]
pub struct EapClientConfiguration { pub struct EapClientConfiguration {
/// The SSID of the network the client is connecting to. /// The SSID of the network the client is connecting to.
pub ssid: String, pub ssid: String,
@ -588,6 +599,7 @@ pub struct EapClientConfiguration {
pub channel: Option<u8>, pub channel: Option<u8>,
} }
#[cfg(feature = "wifi-eap")]
impl EapClientConfiguration { impl EapClientConfiguration {
fn validate(&self) -> Result<(), WifiError> { fn validate(&self) -> Result<(), WifiError> {
if self.ssid.len() > 32 { if self.ssid.len() > 32 {
@ -614,6 +626,7 @@ impl EapClientConfiguration {
} }
} }
#[cfg(feature = "wifi-eap")]
impl Debug for EapClientConfiguration { impl Debug for EapClientConfiguration {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("EapClientConfiguration") f.debug_struct("EapClientConfiguration")
@ -636,6 +649,7 @@ impl Debug for EapClientConfiguration {
} }
#[cfg(feature = "defmt")] #[cfg(feature = "defmt")]
#[cfg(feature = "wifi-eap")]
impl defmt::Format for EapClientConfiguration { impl defmt::Format for EapClientConfiguration {
fn format(&self, fmt: defmt::Formatter<'_>) { fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!( defmt::write!(
@ -671,6 +685,7 @@ impl defmt::Format for EapClientConfiguration {
} }
} }
#[cfg(feature = "wifi-eap")]
impl Default for EapClientConfiguration { impl Default for EapClientConfiguration {
fn default() -> Self { fn default() -> Self {
EapClientConfiguration { EapClientConfiguration {
@ -729,6 +744,7 @@ pub enum Configuration {
Mixed(ClientConfiguration, AccessPointConfiguration), Mixed(ClientConfiguration, AccessPointConfiguration),
/// EAP client configuration for enterprise Wi-Fi. /// EAP client configuration for enterprise Wi-Fi.
#[cfg(feature = "wifi-eap")]
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
EapClient(EapClientConfiguration), EapClient(EapClientConfiguration),
} }
@ -745,6 +761,7 @@ impl Configuration {
client_configuration.validate()?; client_configuration.validate()?;
access_point_configuration.validate() access_point_configuration.validate()
} }
#[cfg(feature = "wifi-eap")]
Configuration::EapClient(eap_client_configuration) => { Configuration::EapClient(eap_client_configuration) => {
eap_client_configuration.validate() eap_client_configuration.validate()
} }
@ -754,7 +771,8 @@ impl Configuration {
/// Returns a reference to the client configuration if available. /// Returns a reference to the client configuration if available.
pub fn as_client_conf_ref(&self) -> Option<&ClientConfiguration> { pub fn as_client_conf_ref(&self) -> Option<&ClientConfiguration> {
match self { match self {
Self::Client(client_conf) | Self::Mixed(client_conf, _) => Some(client_conf), Self::Client(client_conf) => Some(client_conf),
Self::Mixed(client_conf, _) => Some(client_conf),
_ => None, _ => None,
} }
} }
@ -762,7 +780,8 @@ impl Configuration {
/// Returns a reference to the access point configuration if available. /// Returns a reference to the access point configuration if available.
pub fn as_ap_conf_ref(&self) -> Option<&AccessPointConfiguration> { pub fn as_ap_conf_ref(&self) -> Option<&AccessPointConfiguration> {
match self { match self {
Self::AccessPoint(ap_conf) | Self::Mixed(_, ap_conf) => Some(ap_conf), Self::AccessPoint(ap_conf) => Some(ap_conf),
Self::Mixed(_, ap_conf) => Some(ap_conf),
_ => None, _ => None,
} }
} }
@ -930,6 +949,7 @@ impl TryFrom<&Configuration> for WifiMode {
Configuration::AccessPoint(_) => Self::Ap, Configuration::AccessPoint(_) => Self::Ap,
Configuration::Client(_) => Self::Sta, Configuration::Client(_) => Self::Sta,
Configuration::Mixed(_, _) => Self::ApSta, Configuration::Mixed(_, _) => Self::ApSta,
#[cfg(feature = "wifi-eap")]
Configuration::EapClient(_) => Self::Sta, Configuration::EapClient(_) => Self::Sta,
}; };
@ -2391,6 +2411,7 @@ fn apply_sta_config(config: &ClientConfiguration) -> Result<(), WifiError> {
} }
} }
#[cfg(feature = "wifi-eap")]
fn apply_sta_eap_config(config: &EapClientConfiguration) -> Result<(), WifiError> { fn apply_sta_eap_config(config: &EapClientConfiguration) -> Result<(), WifiError> {
let mut cfg = wifi_config_t { let mut cfg = wifi_config_t {
sta: wifi_sta_config_t { sta: wifi_sta_config_t {
@ -2894,6 +2915,7 @@ impl WifiController<'_> {
pub fn capabilities(&self) -> Result<EnumSet<crate::wifi::Capability>, WifiError> { pub fn capabilities(&self) -> Result<EnumSet<crate::wifi::Capability>, WifiError> {
let caps = let caps =
enumset::enum_set! { Capability::Client | Capability::AccessPoint | Capability::Mixed }; enumset::enum_set! { Capability::Client | Capability::AccessPoint | Capability::Mixed };
Ok(caps) Ok(caps)
} }
@ -2914,6 +2936,7 @@ impl WifiController<'_> {
Configuration::Client(_) => wifi_mode_t_WIFI_MODE_STA, Configuration::Client(_) => wifi_mode_t_WIFI_MODE_STA,
Configuration::AccessPoint(_) => wifi_mode_t_WIFI_MODE_AP, Configuration::AccessPoint(_) => wifi_mode_t_WIFI_MODE_AP,
Configuration::Mixed(_, _) => wifi_mode_t_WIFI_MODE_APSTA, Configuration::Mixed(_, _) => wifi_mode_t_WIFI_MODE_APSTA,
#[cfg(feature = "wifi-eap")]
Configuration::EapClient(_) => wifi_mode_t_WIFI_MODE_STA, Configuration::EapClient(_) => wifi_mode_t_WIFI_MODE_STA,
}; };
@ -2926,6 +2949,7 @@ impl WifiController<'_> {
Configuration::Mixed(sta_config, ap_config) => { Configuration::Mixed(sta_config, ap_config) => {
apply_ap_config(ap_config).and_then(|()| apply_sta_config(sta_config)) apply_ap_config(ap_config).and_then(|()| apply_sta_config(sta_config))
} }
#[cfg(feature = "wifi-eap")]
Configuration::EapClient(config) => apply_sta_eap_config(config), Configuration::EapClient(config) => apply_sta_eap_config(config),
} }
.inspect_err(|_| { .inspect_err(|_| {

View File

@ -22,7 +22,7 @@ esp-radio = { path = "../../../esp-radio", features = [
"log-04", "log-04",
"smoltcp", "smoltcp",
"unstable", "unstable",
"wifi", "wifi"
] } ] }
log = "0.4.27" log = "0.4.27"
smoltcp = { version = "0.12.0", default-features = false, features = [ smoltcp = { version = "0.12.0", default-features = false, features = [

View File

@ -31,7 +31,7 @@ esp-preempt = { path = "../../../esp-preempt", features = [
esp-radio = { path = "../../../esp-radio", features = [ esp-radio = { path = "../../../esp-radio", features = [
"log-04", "log-04",
"unstable", "unstable",
"wifi", "wifi"
] } ] }
static_cell = "2.1.0" static_cell = "2.1.0"

View File

@ -207,6 +207,7 @@ impl Package {
features.push("defmt".to_owned()); features.push("defmt".to_owned());
if config.contains("wifi") { if config.contains("wifi") {
features.push("wifi".to_owned()); features.push("wifi".to_owned());
features.push("wifi-eap".to_owned());
features.push("esp-now".to_owned()); features.push("esp-now".to_owned());
features.push("sniffer".to_owned()); features.push("sniffer".to_owned());
features.push("smoltcp/proto-ipv4".to_owned()); features.push("smoltcp/proto-ipv4".to_owned());
@ -277,13 +278,20 @@ impl Package {
Package::EspRadio => { Package::EspRadio => {
// Minimal set of features that when enabled _should_ still compile: // Minimal set of features that when enabled _should_ still compile:
cases.push(vec!["esp-hal/rt".to_owned(), "esp-hal/unstable".to_owned()]); cases.push(vec!["esp-hal/rt".to_owned(), "esp-hal/unstable".to_owned()]);
// This tests if `wifi` feature works without `unstable`
if config.contains("wifi") { if config.contains("wifi") {
// This tests if `wifi` feature works without `esp-radio/unstable`
cases.push(vec![ cases.push(vec![
"esp-hal/rt".to_owned(), "esp-hal/rt".to_owned(),
"esp-hal/unstable".to_owned(), "esp-hal/unstable".to_owned(),
"wifi".to_owned(), "wifi".to_owned(),
]); ]);
// This tests `wifi-eap` feature
cases.push(vec![
"esp-hal/rt".to_owned(),
"esp-hal/unstable".to_owned(),
"wifi-eap".to_owned(),
"unstable".to_owned(),
]);
} }
} }
Package::EspMetadataGenerated => { Package::EspMetadataGenerated => {