1#![no_std]
2#![no_main]
3#![allow(async_fn_in_trait)]
4#![allow(unsafe_op_in_unsafe_fn)]
5#![deny(unused_must_use)]
6#![doc = include_str!("../README.md")]
7#![warn(missing_docs)]
8
9pub(crate) mod fmt;
11
12#[cfg(feature = "bluetooth")]
13pub mod bluetooth;
15mod consts;
16mod control;
17mod countries;
18mod events;
19mod ioctl;
20mod runner;
21mod sdio;
22mod spi;
23mod structs;
24mod util;
25
26use core::sync::atomic::AtomicBool;
27
28pub use aligned::{A4, Aligned};
29use embassy_net_driver_channel as ch;
30use embedded_hal_1::digital::OutputPin;
31use events::Events;
32use ioctl::IoctlState;
33
34pub use crate::control::{
35 AddMulticastAddressError, Control, JoinAuth, JoinError, JoinOptions, ScanOptions, ScanType, Scanner,
36};
37pub use crate::runner::Runner;
38pub use crate::sdio::{SdioBus, SdioBusCyw43};
39pub use crate::spi::{SpiBus, SpiBusCyw43};
40pub use crate::structs::BssInfo;
41
42const MTU: usize = 1514;
43
44#[allow(unused)]
45#[derive(Clone, Copy, PartialEq, Eq)]
46enum Core {
47 WLAN = 0,
48 SOCSRAM = 1,
49 SDIOD = 2,
50}
51
52impl Core {
53 fn base_addr(&self) -> u32 {
54 match self {
55 Self::WLAN => CHIP.arm_core_base_address,
56 Self::SOCSRAM => CHIP.socsram_wrapper_base_address,
57 Self::SDIOD => CHIP.sdiod_core_base_address,
58 }
59 }
60}
61
62#[allow(unused)]
63struct Chip {
64 arm_core_base_address: u32,
65 socsram_base_address: u32,
66 bluetooth_base_address: u32,
67 socsram_wrapper_base_address: u32,
68 sdiod_core_base_address: u32,
69 pmu_base_address: u32,
70 chip_ram_size: u32,
71 atcm_ram_base_address: u32,
72 socram_srmem_size: u32,
73 chanspec_band_mask: u32,
74 chanspec_band_2g: u32,
75 chanspec_band_5g: u32,
76 chanspec_band_shift: u32,
77 chanspec_bw_10: u32,
78 chanspec_bw_20: u32,
79 chanspec_bw_40: u32,
80 chanspec_bw_mask: u32,
81 chanspec_bw_shift: u32,
82 chanspec_ctl_sb_lower: u32,
83 chanspec_ctl_sb_upper: u32,
84 chanspec_ctl_sb_none: u32,
85 chanspec_ctl_sb_mask: u32,
86}
87
88const WRAPPER_REGISTER_OFFSET: u32 = 0x100000;
89
90const CHIP: Chip = Chip {
92 arm_core_base_address: 0x18003000 + WRAPPER_REGISTER_OFFSET,
93 socsram_base_address: 0x18004000,
94 bluetooth_base_address: 0x19000000,
95 socsram_wrapper_base_address: 0x18004000 + WRAPPER_REGISTER_OFFSET,
96 sdiod_core_base_address: 0x18002000,
97 pmu_base_address: 0x18000000,
98 chip_ram_size: 512 * 1024,
99 atcm_ram_base_address: 0,
100 socram_srmem_size: 64 * 1024,
101 chanspec_band_mask: 0xc000,
102 chanspec_band_2g: 0x0000,
103 chanspec_band_5g: 0xc000,
104 chanspec_band_shift: 14,
105 chanspec_bw_10: 0x0800,
106 chanspec_bw_20: 0x1000,
107 chanspec_bw_40: 0x1800,
108 chanspec_bw_mask: 0x3800,
109 chanspec_bw_shift: 11,
110 chanspec_ctl_sb_lower: 0x0000,
111 chanspec_ctl_sb_upper: 0x0100,
112 chanspec_ctl_sb_none: 0x0000,
113 chanspec_ctl_sb_mask: 0x0700,
114};
115
116pub struct State {
118 ioctl_state: IoctlState,
119 net: NetState,
120 #[cfg(feature = "bluetooth")]
121 bt: bluetooth::BtState,
122}
123
124struct NetState {
125 ch: ch::State<MTU, 4, 4>,
126 events: Events,
127 secure_network: AtomicBool,
128}
129
130impl State {
131 pub const fn new() -> Self {
133 Self {
134 ioctl_state: IoctlState::new(),
135 net: NetState {
136 ch: ch::State::new(),
137 events: Events::new(),
138 secure_network: AtomicBool::new(false),
139 },
140 #[cfg(feature = "bluetooth")]
141 bt: bluetooth::BtState::new(),
142 }
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
148pub enum PowerManagementMode {
149 SuperSave,
153
154 Aggressive,
156
157 PowerSave,
159
160 Performance,
163
164 ThroughputThrottling,
167
168 None,
170}
171
172impl Default for PowerManagementMode {
173 fn default() -> Self {
174 Self::PowerSave
175 }
176}
177
178impl PowerManagementMode {
179 fn sleep_ret_ms(&self) -> u16 {
180 match self {
181 PowerManagementMode::SuperSave => 2000,
182 PowerManagementMode::Aggressive => 2000,
183 PowerManagementMode::PowerSave => 200,
184 PowerManagementMode::Performance => 20,
185 PowerManagementMode::ThroughputThrottling => 0, PowerManagementMode::None => 0, }
188 }
189
190 fn beacon_period(&self) -> u8 {
191 match self {
192 PowerManagementMode::SuperSave => 255,
193 PowerManagementMode::Aggressive => 1,
194 PowerManagementMode::PowerSave => 1,
195 PowerManagementMode::Performance => 1,
196 PowerManagementMode::ThroughputThrottling => 0, PowerManagementMode::None => 0, }
199 }
200
201 fn dtim_period(&self) -> u8 {
202 match self {
203 PowerManagementMode::SuperSave => 255,
204 PowerManagementMode::Aggressive => 1,
205 PowerManagementMode::PowerSave => 1,
206 PowerManagementMode::Performance => 1,
207 PowerManagementMode::ThroughputThrottling => 0, PowerManagementMode::None => 0, }
210 }
211
212 fn assoc(&self) -> u8 {
213 match self {
214 PowerManagementMode::SuperSave => 255,
215 PowerManagementMode::Aggressive => 10,
216 PowerManagementMode::PowerSave => 10,
217 PowerManagementMode::Performance => 1,
218 PowerManagementMode::ThroughputThrottling => 0, PowerManagementMode::None => 0, }
221 }
222
223 fn mode(&self) -> u32 {
224 match self {
225 PowerManagementMode::ThroughputThrottling => 1,
226 PowerManagementMode::None => 0,
227 _ => 2,
228 }
229 }
230}
231
232pub type NetDriver<'a> = ch::Device<'a, MTU>;
234
235pub async fn new<'a, PWR, SPI>(
240 state: &'a mut State,
241 pwr: PWR,
242 spi: SPI,
243 firmware: &Aligned<A4, [u8]>,
244 nvram: &Aligned<A4, [u8]>,
245) -> (NetDriver<'a>, Control<'a>, Runner<'a, SpiBus<PWR, SPI>>)
246where
247 PWR: OutputPin,
248 SPI: SpiBusCyw43,
249{
250 let (ch_runner, device) = ch::new(&mut state.net.ch, ch::driver::HardwareAddress::Ethernet([0; 6]));
251 let state_ch = ch_runner.state_runner();
252
253 let mut runner = Runner::new(
254 ch_runner,
255 SpiBus::new(pwr, spi),
256 &state.ioctl_state,
257 &state.net.events,
258 &state.net.secure_network,
259 #[cfg(feature = "bluetooth")]
260 None,
261 );
262
263 runner.init(firmware, nvram, None).await.unwrap();
264 let control = Control::new(
265 state_ch,
266 &state.net.events,
267 &state.ioctl_state,
268 &state.net.secure_network,
269 );
270
271 (device, control, runner)
272}
273
274pub async fn new_sdio<'a, SDIO>(
279 state: &'a mut State,
280 sdio: SDIO,
281 firmware: &Aligned<A4, [u8]>,
282 nvram: &Aligned<A4, [u8]>,
283) -> (NetDriver<'a>, Control<'a>, Runner<'a, SdioBus<SDIO>>)
284where
285 SDIO: SdioBusCyw43<64>,
286{
287 let (ch_runner, device) = ch::new(&mut state.net.ch, ch::driver::HardwareAddress::Ethernet([0; 6]));
288 let state_ch = ch_runner.state_runner();
289
290 let mut runner = Runner::new(
291 ch_runner,
292 SdioBus::new(sdio),
293 &state.ioctl_state,
294 &state.net.events,
295 &state.net.secure_network,
296 #[cfg(feature = "bluetooth")]
297 None,
298 );
299
300 runner.init(firmware, nvram, None).await.unwrap();
301 let control = Control::new(
302 state_ch,
303 &state.net.events,
304 &state.ioctl_state,
305 &state.net.secure_network,
306 );
307
308 (device, control, runner)
309}
310
311#[cfg(feature = "bluetooth")]
316pub async fn new_with_bluetooth<'a, PWR, SPI>(
317 state: &'a mut State,
318 pwr: PWR,
319 spi: SPI,
320 wifi_firmware: &Aligned<A4, [u8]>,
321 bluetooth_firmware: &Aligned<A4, [u8]>,
322 nvram: &Aligned<A4, [u8]>,
323) -> (
324 NetDriver<'a>,
325 bluetooth::BtDriver<'a>,
326 Control<'a>,
327 Runner<'a, SpiBus<PWR, SPI>>,
328)
329where
330 PWR: OutputPin,
331 SPI: SpiBusCyw43,
332{
333 let (ch_runner, device) = ch::new(&mut state.net.ch, ch::driver::HardwareAddress::Ethernet([0; 6]));
334 let state_ch = ch_runner.state_runner();
335
336 let (bt_runner, bt_driver) = bluetooth::new(&mut state.bt);
337 let mut runner = Runner::new(
338 ch_runner,
339 SpiBus::new(pwr, spi),
340 &state.ioctl_state,
341 &state.net.events,
342 &state.net.secure_network,
343 #[cfg(feature = "bluetooth")]
344 Some(bt_runner),
345 );
346
347 runner
348 .init(wifi_firmware, nvram, Some(bluetooth_firmware))
349 .await
350 .unwrap();
351 let control = Control::new(
352 state_ch,
353 &state.net.events,
354 &state.ioctl_state,
355 &state.net.secure_network,
356 );
357
358 (device, bt_driver, control, runner)
359}
360
361#[macro_export]
363macro_rules! aligned_bytes {
364 ($path:expr) => {{
365 {
366 static BYTES: &cyw43::Aligned<cyw43::A4, [u8]> = &cyw43::Aligned(*include_bytes!($path));
367
368 BYTES
369 }
370 }};
371}