1use alloc::string::String;
4use core::fmt;
5
6use procmacros::BuilderLite;
7
8use super::ScanMethod;
9use crate::{
10 WifiError,
11 wifi::{AuthenticationMethod, Protocols, Ssid},
12};
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17#[instability::unstable]
18pub struct EapFastConfig {
19 pub fast_provisioning: u8,
21 pub fast_max_pac_list_len: u8,
23 pub fast_pac_format_binary: bool,
25}
26
27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30#[instability::unstable]
31pub enum TtlsPhase2Method {
32 Eap,
34 Mschapv2,
36 Mschap,
38 Pap,
40 Chap,
42}
43
44impl TtlsPhase2Method {
45 pub(crate) fn to_raw(self) -> u32 {
47 match self {
48 TtlsPhase2Method::Eap => {
49 crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_EAP
50 }
51 TtlsPhase2Method::Mschapv2 => {
52 crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAPV2
53 }
54 TtlsPhase2Method::Mschap => {
55 crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAP
56 }
57 TtlsPhase2Method::Pap => {
58 crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_PAP
59 }
60 TtlsPhase2Method::Chap => {
61 crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_CHAP
62 }
63 }
64 }
65}
66
67type CertificateAndKey = (&'static [u8], &'static [u8], Option<&'static [u8]>);
68
69#[derive(BuilderLite, Clone, PartialEq, Eq, Hash)]
71#[instability::unstable]
72pub struct EapStationConfig {
73 #[builder_lite(skip_setter)]
75 pub(crate) ssid: Ssid,
76 pub(crate) bssid: Option<[u8; 6]>,
78 pub(crate) auth_method: AuthenticationMethod,
80 #[builder_lite(reference)]
82 pub(crate) identity: Option<String>,
83 #[builder_lite(reference)]
86 pub(crate) username: Option<String>,
87 #[builder_lite(reference)]
89 pub(crate) password: Option<String>,
90 #[builder_lite(reference)]
93 pub(crate) new_password: Option<String>,
94 #[builder_lite(reference)]
96 pub(crate) eap_fast_config: Option<EapFastConfig>,
97 pub(crate) pac_file: Option<&'static [u8]>,
99 pub(crate) time_check: bool,
102 pub(crate) ca_cert: Option<&'static [u8]>,
105 pub(crate) certificate_and_key: Option<CertificateAndKey>,
108 #[builder_lite(reference)]
110 pub(crate) ttls_phase2_method: Option<TtlsPhase2Method>,
111 pub(crate) channel: Option<u8>,
113 pub(crate) protocols: Protocols,
115 #[builder_lite(unstable)]
121 pub(crate) listen_interval: u16,
122 #[builder_lite(unstable)]
126 pub(crate) beacon_timeout: u16,
127 #[builder_lite(unstable)]
134 pub(crate) failure_retry_cnt: u8,
135 #[builder_lite(unstable)]
137 pub(crate) scan_method: ScanMethod,
138}
139
140impl EapStationConfig {
141 #[instability::unstable]
143 pub fn with_ssid(mut self, ssid: impl Into<Ssid>) -> Self {
144 self.ssid = ssid.into();
145 self
146 }
147
148 pub(crate) fn validate(&self) -> Result<(), WifiError> {
149 if self.ssid.len() > 32 {
150 return Err(WifiError::InvalidArguments);
151 }
152
153 if self.identity.as_ref().unwrap_or(&String::new()).len() > 128 {
154 return Err(WifiError::InvalidArguments);
155 }
156
157 if self.username.as_ref().unwrap_or(&String::new()).len() > 128 {
158 return Err(WifiError::InvalidArguments);
159 }
160
161 if self.password.as_ref().unwrap_or(&String::new()).len() > 64 {
162 return Err(WifiError::InvalidArguments);
163 }
164
165 if self.new_password.as_ref().unwrap_or(&String::new()).len() > 64 {
166 return Err(WifiError::InvalidArguments);
167 }
168
169 if !(6..=31).contains(&self.beacon_timeout) {
170 return Err(WifiError::InvalidArguments);
171 }
172
173 Ok(())
174 }
175}
176
177impl Default for EapStationConfig {
178 fn default() -> Self {
179 EapStationConfig {
180 ssid: Ssid::default(),
181 bssid: None,
182 auth_method: AuthenticationMethod::Wpa2Enterprise,
183 identity: None,
184 username: None,
185 password: None,
186 channel: None,
187 eap_fast_config: None,
188 time_check: false,
189 new_password: None,
190 pac_file: None,
191 ca_cert: None,
192 certificate_and_key: None,
193 ttls_phase2_method: None,
194 protocols: Protocols::default(),
195 listen_interval: 3,
196 beacon_timeout: 6,
197 failure_retry_cnt: 1,
198 scan_method: ScanMethod::Fast,
199 }
200 }
201}
202
203impl fmt::Debug for EapStationConfig {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 f.debug_struct("EapStationConfig")
206 .field("ssid", &self.ssid)
207 .field("bssid", &self.bssid)
208 .field("auth_method", &self.auth_method)
209 .field("channel", &self.channel)
210 .field("identity", &self.identity)
211 .field("username", &self.username)
212 .field("password", &"**REDACTED**")
213 .field("new_password", &"**REDACTED**")
214 .field("eap_fast_config", &self.eap_fast_config)
215 .field("time_check", &self.time_check)
216 .field("pac_file set", &self.pac_file.is_some())
217 .field("ca_cert set", &self.ca_cert.is_some())
218 .field("certificate_and_key set", &"**REDACTED**")
219 .field("ttls_phase2_method", &self.ttls_phase2_method)
220 .field("protocols", &self.protocols)
221 .field("listen_interval", &self.listen_interval)
222 .field("beacon_timeout", &self.beacon_timeout)
223 .field("failure_retry_cnt", &self.failure_retry_cnt)
224 .field("scan_method", &self.scan_method)
225 .finish()
226 }
227}
228
229#[cfg(feature = "defmt")]
230impl defmt::Format for EapStationConfig {
231 fn format(&self, fmt: defmt::Formatter<'_>) {
232 defmt::write!(
233 fmt,
234 "EapStationConfig {{\
235 ssid: {}, \
236 bssid: {:?}, \
237 auth_method: {:?}, \
238 channel: {:?}, \
239 identity: {:?}, \
240 username: {:?}, \
241 password: **REDACTED**, \
242 new_password: **REDACTED**, \
243 eap_fast_config: {:?}, \
244 time_check: {}, \
245 pac_file: {}, \
246 ca_cert: {}, \
247 certificate_and_key: **REDACTED**, \
248 ttls_phase2_method: {:?}, \
249 protocols: {}, \
250 listen_interval: {}, \
251 beacon_timeout: {}, \
252 failure_retry_cnt: {}, \
253 scan_method: {},
254 }}",
255 self.ssid.as_str(),
256 self.bssid,
257 self.auth_method,
258 self.channel,
259 &self.identity.as_ref().map_or("", |v| v.as_str()),
260 &self.username.as_ref().map_or("", |v| v.as_str()),
261 self.eap_fast_config,
262 self.time_check,
263 self.pac_file,
264 self.ca_cert,
265 self.ttls_phase2_method,
266 self.protocols,
267 self.listen_interval,
268 self.beacon_timeout,
269 self.failure_retry_cnt,
270 self.scan_method
271 )
272 }
273}