1use alloc::string::String;
4use core::fmt;
5
6use procmacros::BuilderLite;
7
8#[cfg(feature = "unstable")]
9use super::CountryInfo;
10use super::{AuthenticationMethod, Protocols, SecondaryChannel, Ssid};
11use crate::{WifiError, sys::include::wifi_ap_record_t};
12
13#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16#[non_exhaustive]
17pub struct AccessPointInfo {
18 pub ssid: Ssid,
20 pub bssid: [u8; 6],
22 pub channel: u8,
24 pub secondary_channel: SecondaryChannel,
26 pub signal_strength: i8,
28 pub auth_method: Option<AuthenticationMethod>,
30 #[cfg(feature = "unstable")]
31 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
32 pub country: Option<CountryInfo>,
34}
35
36#[derive(Clone, PartialEq, Eq, BuilderLite, Hash)]
38pub struct AccessPointConfig {
39 #[builder_lite(skip_setter)]
41 pub(crate) ssid: Ssid,
42 pub(crate) ssid_hidden: bool,
44 pub(crate) channel: u8,
46 pub(crate) secondary_channel: Option<SecondaryChannel>,
48 pub(crate) protocols: Protocols,
50 pub(crate) auth_method: AuthenticationMethod,
52 #[builder_lite(reference)]
54 pub(crate) password: String,
55 pub(crate) max_connections: u16,
57 pub(crate) dtim_period: u8,
59 #[builder_lite(unstable)]
61 pub(crate) beacon_timeout: u16,
62}
63
64impl AccessPointConfig {
65 pub fn with_ssid(mut self, ssid: impl Into<Ssid>) -> Self {
67 self.ssid = ssid.into();
68 self
69 }
70
71 pub(crate) fn validate(&self) -> Result<(), WifiError> {
72 if self.ssid.len() > 32 {
73 return Err(WifiError::InvalidArguments);
74 }
75
76 if self.password.len() > 64 {
77 return Err(WifiError::InvalidArguments);
78 }
79
80 if !(1..=10).contains(&self.dtim_period) {
81 return Err(WifiError::InvalidArguments);
82 }
83
84 Ok(())
85 }
86}
87
88impl Default for AccessPointConfig {
89 fn default() -> Self {
90 Self {
91 ssid: "iot-device".into(),
92 ssid_hidden: false,
93 channel: 1,
94 secondary_channel: None,
95 protocols: Protocols::default(),
96 auth_method: AuthenticationMethod::None,
97 password: String::new(),
98 max_connections: 255,
99 dtim_period: 2,
100 beacon_timeout: 300,
101 }
102 }
103}
104
105impl fmt::Debug for AccessPointConfig {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.debug_struct("AccessPointConfig")
108 .field("ssid", &self.ssid)
109 .field("ssid_hidden", &self.ssid_hidden)
110 .field("channel", &self.channel)
111 .field("secondary_channel", &self.secondary_channel)
112 .field("protocols", &self.protocols)
113 .field("auth_method", &self.auth_method)
114 .field("password", &"**REDACTED**")
115 .field("max_connections", &self.max_connections)
116 .field("dtim_period", &self.dtim_period)
117 .field("beacon_timeout", &self.beacon_timeout)
118 .finish()
119 }
120}
121
122#[cfg(feature = "defmt")]
123impl defmt::Format for AccessPointConfig {
124 fn format(&self, fmt: defmt::Formatter<'_>) {
125 defmt::write!(
126 fmt,
127 "AccessPointConfig {{\
128 ssid: {}, \
129 ssid_hidden: {}, \
130 channel: {}, \
131 secondary_channel: {}, \
132 protocols: {}, \
133 auth_method: {}, \
134 password: **REDACTED**, \
135 max_connections: {}, \
136 dtim_period: {}, \
137 beacon_timeout: {} \
138 }}",
139 self.ssid.as_str(),
140 self.ssid_hidden,
141 self.channel,
142 self.secondary_channel,
143 self.protocols,
144 self.auth_method,
145 self.max_connections,
146 self.dtim_period,
147 self.beacon_timeout
148 );
149 }
150}
151
152#[allow(non_upper_case_globals)]
153pub(crate) fn convert_ap_info(record: &wifi_ap_record_t) -> AccessPointInfo {
154 let str_len = record
155 .ssid
156 .iter()
157 .position(|&c| c == 0)
158 .unwrap_or(record.ssid.len());
159 let ssid = Ssid::from(&record.ssid[..str_len]);
160
161 AccessPointInfo {
162 ssid,
163 bssid: record.bssid,
164 channel: record.primary,
165 secondary_channel: SecondaryChannel::from_raw(record.second),
166 signal_strength: record.rssi,
167 auth_method: Some(AuthenticationMethod::from_raw(record.authmode)),
168 #[cfg(feature = "unstable")]
169 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
170 country: CountryInfo::try_from_c(&record.country),
171 }
172}