aboutsummaryrefslogtreecommitdiff
path: root/cyw43/src/structs.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-30 22:42:49 +0200
committerDario Nieuwenhuis <[email protected]>2023-05-30 22:42:49 +0200
commitc327c6cd6fc3c11cfaf83cf64591940d401c5f6b (patch)
tree1e9f693a74b01ae930caa145ae282c24276510e3 /cyw43/src/structs.rs
parent3cc0ec654a1e46fe7b8fa168942452303343cd84 (diff)
cyw43: move crate to subdir.
Diffstat (limited to 'cyw43/src/structs.rs')
-rw-r--r--cyw43/src/structs.rs496
1 files changed, 496 insertions, 0 deletions
diff --git a/cyw43/src/structs.rs b/cyw43/src/structs.rs
new file mode 100644
index 000000000..5ba633c74
--- /dev/null
+++ b/cyw43/src/structs.rs
@@ -0,0 +1,496 @@
1use crate::events::Event;
2use crate::fmt::Bytes;
3
4macro_rules! impl_bytes {
5 ($t:ident) => {
6 impl $t {
7 pub const SIZE: usize = core::mem::size_of::<Self>();
8
9 #[allow(unused)]
10 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
11 unsafe { core::mem::transmute(*self) }
12 }
13
14 #[allow(unused)]
15 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self {
16 let alignment = core::mem::align_of::<Self>();
17 assert_eq!(
18 bytes.as_ptr().align_offset(alignment),
19 0,
20 "{} is not aligned",
21 core::any::type_name::<Self>()
22 );
23 unsafe { core::mem::transmute(bytes) }
24 }
25
26 #[allow(unused)]
27 pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self {
28 let alignment = core::mem::align_of::<Self>();
29 assert_eq!(
30 bytes.as_ptr().align_offset(alignment),
31 0,
32 "{} is not aligned",
33 core::any::type_name::<Self>()
34 );
35
36 unsafe { core::mem::transmute(bytes) }
37 }
38 }
39 };
40}
41
42#[derive(Clone, Copy)]
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44#[repr(C)]
45pub struct SharedMemData {
46 pub flags: u32,
47 pub trap_addr: u32,
48 pub assert_exp_addr: u32,
49 pub assert_file_addr: u32,
50 pub assert_line: u32,
51 pub console_addr: u32,
52 pub msgtrace_addr: u32,
53 pub fwid: u32,
54}
55impl_bytes!(SharedMemData);
56
57#[derive(Clone, Copy)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59#[repr(C)]
60pub struct SharedMemLog {
61 pub buf: u32,
62 pub buf_size: u32,
63 pub idx: u32,
64 pub out_idx: u32,
65}
66impl_bytes!(SharedMemLog);
67
68#[derive(Debug, Clone, Copy)]
69#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70#[repr(C)]
71pub struct SdpcmHeader {
72 pub len: u16,
73 pub len_inv: u16,
74 /// Rx/Tx sequence number
75 pub sequence: u8,
76 /// 4 MSB Channel number, 4 LSB arbitrary flag
77 pub channel_and_flags: u8,
78 /// Length of next data frame, reserved for Tx
79 pub next_length: u8,
80 /// Data offset
81 pub header_length: u8,
82 /// Flow control bits, reserved for Tx
83 pub wireless_flow_control: u8,
84 /// Maximum Sequence number allowed by firmware for Tx
85 pub bus_data_credit: u8,
86 /// Reserved
87 pub reserved: [u8; 2],
88}
89impl_bytes!(SdpcmHeader);
90
91impl SdpcmHeader {
92 pub fn parse(packet: &mut [u8]) -> Option<(&mut Self, &mut [u8])> {
93 let packet_len = packet.len();
94 if packet_len < Self::SIZE {
95 warn!("packet too short, len={}", packet.len());
96 return None;
97 }
98 let (sdpcm_header, sdpcm_packet) = packet.split_at_mut(Self::SIZE);
99 let sdpcm_header = Self::from_bytes_mut(sdpcm_header.try_into().unwrap());
100 trace!("rx {:?}", sdpcm_header);
101
102 if sdpcm_header.len != !sdpcm_header.len_inv {
103 warn!("len inv mismatch");
104 return None;
105 }
106
107 if sdpcm_header.len as usize != packet_len {
108 warn!("len from header doesn't match len from spi");
109 return None;
110 }
111
112 let sdpcm_packet = &mut sdpcm_packet[(sdpcm_header.header_length as usize - Self::SIZE)..];
113 Some((sdpcm_header, sdpcm_packet))
114 }
115}
116
117#[derive(Debug, Clone, Copy)]
118#[repr(C, packed(2))]
119pub struct CdcHeader {
120 pub cmd: u32,
121 pub len: u32,
122 pub flags: u16,
123 pub id: u16,
124 pub status: u32,
125}
126impl_bytes!(CdcHeader);
127
128#[cfg(feature = "defmt")]
129impl defmt::Format for CdcHeader {
130 fn format(&self, fmt: defmt::Formatter) {
131 fn copy<T: Copy>(t: T) -> T {
132 t
133 }
134
135 defmt::write!(
136 fmt,
137 "CdcHeader{{cmd: {=u32:08x}, len: {=u32:08x}, flags: {=u16:04x}, id: {=u16:04x}, status: {=u32:08x}}}",
138 copy(self.cmd),
139 copy(self.len),
140 copy(self.flags),
141 copy(self.id),
142 copy(self.status),
143 )
144 }
145}
146
147impl CdcHeader {
148 pub fn parse(packet: &mut [u8]) -> Option<(&mut Self, &mut [u8])> {
149 if packet.len() < Self::SIZE {
150 warn!("payload too short, len={}", packet.len());
151 return None;
152 }
153
154 let (cdc_header, payload) = packet.split_at_mut(Self::SIZE);
155 let cdc_header = Self::from_bytes_mut(cdc_header.try_into().unwrap());
156
157 let payload = &mut payload[..cdc_header.len as usize];
158 Some((cdc_header, payload))
159 }
160}
161
162pub const BDC_VERSION: u8 = 2;
163pub const BDC_VERSION_SHIFT: u8 = 4;
164
165#[derive(Debug, Clone, Copy)]
166#[cfg_attr(feature = "defmt", derive(defmt::Format))]
167#[repr(C)]
168pub struct BdcHeader {
169 pub flags: u8,
170 /// 802.1d Priority (low 3 bits)
171 pub priority: u8,
172 pub flags2: u8,
173 /// Offset from end of BDC header to packet data, in 4-uint8_t words. Leaves room for optional headers.
174 pub data_offset: u8,
175}
176impl_bytes!(BdcHeader);
177
178impl BdcHeader {
179 pub fn parse(packet: &mut [u8]) -> Option<(&mut Self, &mut [u8])> {
180 if packet.len() < Self::SIZE {
181 return None;
182 }
183
184 let (bdc_header, bdc_packet) = packet.split_at_mut(Self::SIZE);
185 let bdc_header = Self::from_bytes_mut(bdc_header.try_into().unwrap());
186 trace!(" {:?}", bdc_header);
187
188 let packet_start = 4 * bdc_header.data_offset as usize;
189
190 let bdc_packet = bdc_packet.get_mut(packet_start..)?;
191 trace!(" {:02x}", Bytes(&bdc_packet[..bdc_packet.len().min(36)]));
192
193 Some((bdc_header, bdc_packet))
194 }
195}
196
197#[derive(Clone, Copy)]
198#[cfg_attr(feature = "defmt", derive(defmt::Format))]
199#[repr(C)]
200pub struct EthernetHeader {
201 pub destination_mac: [u8; 6],
202 pub source_mac: [u8; 6],
203 pub ether_type: u16,
204}
205
206impl EthernetHeader {
207 pub fn byteswap(&mut self) {
208 self.ether_type = self.ether_type.to_be();
209 }
210}
211
212#[derive(Clone, Copy)]
213#[cfg_attr(feature = "defmt", derive(defmt::Format))]
214#[repr(C)]
215pub struct EventHeader {
216 pub subtype: u16,
217 pub length: u16,
218 pub version: u8,
219 pub oui: [u8; 3],
220 pub user_subtype: u16,
221}
222
223impl EventHeader {
224 pub fn byteswap(&mut self) {
225 self.subtype = self.subtype.to_be();
226 self.length = self.length.to_be();
227 self.user_subtype = self.user_subtype.to_be();
228 }
229}
230
231#[derive(Debug, Clone, Copy)]
232// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
233#[repr(C, packed(2))]
234pub struct EventMessage {
235 /// version
236 pub version: u16,
237 /// see flags below
238 pub flags: u16,
239 /// Message (see below)
240 pub event_type: u32,
241 /// Status code (see below)
242 pub status: u32,
243 /// Reason code (if applicable)
244 pub reason: u32,
245 /// WLC_E_AUTH
246 pub auth_type: u32,
247 /// data buf
248 pub datalen: u32,
249 /// Station address (if applicable)
250 pub addr: [u8; 6],
251 /// name of the incoming packet interface
252 pub ifname: [u8; 16],
253 /// destination OS i/f index
254 pub ifidx: u8,
255 /// source bsscfg index
256 pub bsscfgidx: u8,
257}
258impl_bytes!(EventMessage);
259
260#[cfg(feature = "defmt")]
261impl defmt::Format for EventMessage {
262 fn format(&self, fmt: defmt::Formatter) {
263 let event_type = self.event_type;
264 let status = self.status;
265 let reason = self.reason;
266 let auth_type = self.auth_type;
267 let datalen = self.datalen;
268
269 defmt::write!(
270 fmt,
271 "EventMessage {{ \
272 version: {=u16}, \
273 flags: {=u16}, \
274 event_type: {=u32}, \
275 status: {=u32}, \
276 reason: {=u32}, \
277 auth_type: {=u32}, \
278 datalen: {=u32}, \
279 addr: {=[u8; 6]:x}, \
280 ifname: {=[u8; 16]:x}, \
281 ifidx: {=u8}, \
282 bsscfgidx: {=u8}, \
283 }} ",
284 self.version,
285 self.flags,
286 event_type,
287 status,
288 reason,
289 auth_type,
290 datalen,
291 self.addr,
292 self.ifname,
293 self.ifidx,
294 self.bsscfgidx
295 );
296 }
297}
298
299impl EventMessage {
300 pub fn byteswap(&mut self) {
301 self.version = self.version.to_be();
302 self.flags = self.flags.to_be();
303 self.event_type = self.event_type.to_be();
304 self.status = self.status.to_be();
305 self.reason = self.reason.to_be();
306 self.auth_type = self.auth_type.to_be();
307 self.datalen = self.datalen.to_be();
308 }
309}
310
311#[derive(Clone, Copy)]
312#[cfg_attr(feature = "defmt", derive(defmt::Format))]
313#[repr(C, packed(2))]
314pub struct EventPacket {
315 pub eth: EthernetHeader,
316 pub hdr: EventHeader,
317 pub msg: EventMessage,
318}
319impl_bytes!(EventPacket);
320
321impl EventPacket {
322 pub fn parse(packet: &mut [u8]) -> Option<(&mut Self, &mut [u8])> {
323 if packet.len() < Self::SIZE {
324 return None;
325 }
326
327 let (event_header, event_packet) = packet.split_at_mut(Self::SIZE);
328 let event_header = Self::from_bytes_mut(event_header.try_into().unwrap());
329 // warn!("event_header {:x}", event_header as *const _);
330 event_header.byteswap();
331
332 let event_packet = event_packet.get_mut(..event_header.msg.datalen as usize)?;
333
334 Some((event_header, event_packet))
335 }
336
337 pub fn byteswap(&mut self) {
338 self.eth.byteswap();
339 self.hdr.byteswap();
340 self.msg.byteswap();
341 }
342}
343
344#[derive(Clone, Copy)]
345#[repr(C)]
346pub struct DownloadHeader {
347 pub flag: u16, //
348 pub dload_type: u16,
349 pub len: u32,
350 pub crc: u32,
351}
352impl_bytes!(DownloadHeader);
353
354#[allow(unused)]
355pub const DOWNLOAD_FLAG_NO_CRC: u16 = 0x0001;
356pub const DOWNLOAD_FLAG_BEGIN: u16 = 0x0002;
357pub const DOWNLOAD_FLAG_END: u16 = 0x0004;
358pub const DOWNLOAD_FLAG_HANDLER_VER: u16 = 0x1000;
359
360// Country Locale Matrix (CLM)
361pub const DOWNLOAD_TYPE_CLM: u16 = 2;
362
363#[derive(Clone, Copy)]
364#[cfg_attr(feature = "defmt", derive(defmt::Format))]
365#[repr(C)]
366pub struct CountryInfo {
367 pub country_abbrev: [u8; 4],
368 pub rev: i32,
369 pub country_code: [u8; 4],
370}
371impl_bytes!(CountryInfo);
372
373#[derive(Clone, Copy)]
374#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375#[repr(C)]
376pub struct SsidInfo {
377 pub len: u32,
378 pub ssid: [u8; 32],
379}
380impl_bytes!(SsidInfo);
381
382#[derive(Clone, Copy)]
383#[cfg_attr(feature = "defmt", derive(defmt::Format))]
384#[repr(C)]
385pub struct PassphraseInfo {
386 pub len: u16,
387 pub flags: u16,
388 pub passphrase: [u8; 64],
389}
390impl_bytes!(PassphraseInfo);
391
392#[derive(Clone, Copy)]
393#[cfg_attr(feature = "defmt", derive(defmt::Format))]
394#[repr(C)]
395pub struct SsidInfoWithIndex {
396 pub index: u32,
397 pub ssid_info: SsidInfo,
398}
399impl_bytes!(SsidInfoWithIndex);
400
401#[derive(Clone, Copy)]
402#[cfg_attr(feature = "defmt", derive(defmt::Format))]
403#[repr(C)]
404pub struct EventMask {
405 pub iface: u32,
406 pub events: [u8; 24],
407}
408impl_bytes!(EventMask);
409
410impl EventMask {
411 pub fn unset(&mut self, evt: Event) {
412 let evt = evt as u8 as usize;
413 self.events[evt / 8] &= !(1 << (evt % 8));
414 }
415}
416
417/// Parameters for a wifi scan
418#[derive(Clone, Copy)]
419#[cfg_attr(feature = "defmt", derive(defmt::Format))]
420#[repr(C)]
421pub struct ScanParams {
422 pub version: u32,
423 pub action: u16,
424 pub sync_id: u16,
425 pub ssid_len: u32,
426 pub ssid: [u8; 32],
427 pub bssid: [u8; 6],
428 pub bss_type: u8,
429 pub scan_type: u8,
430 pub nprobes: u32,
431 pub active_time: u32,
432 pub passive_time: u32,
433 pub home_time: u32,
434 pub channel_num: u32,
435 pub channel_list: [u16; 1],
436}
437impl_bytes!(ScanParams);
438
439/// Wifi Scan Results Header, followed by `bss_count` `BssInfo`
440#[derive(Clone, Copy)]
441// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
442#[repr(C, packed(2))]
443pub struct ScanResults {
444 pub buflen: u32,
445 pub version: u32,
446 pub sync_id: u16,
447 pub bss_count: u16,
448}
449impl_bytes!(ScanResults);
450
451impl ScanResults {
452 pub fn parse(packet: &mut [u8]) -> Option<(&mut ScanResults, &mut [u8])> {
453 if packet.len() < ScanResults::SIZE {
454 return None;
455 }
456
457 let (scan_results, bssinfo) = packet.split_at_mut(ScanResults::SIZE);
458 let scan_results = ScanResults::from_bytes_mut(scan_results.try_into().unwrap());
459
460 if scan_results.bss_count > 0 && bssinfo.len() < BssInfo::SIZE {
461 warn!("Scan result, incomplete BssInfo");
462 return None;
463 }
464
465 Some((scan_results, bssinfo))
466 }
467}
468
469/// Wifi Scan Result
470#[derive(Clone, Copy)]
471// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
472#[repr(C, packed(2))]
473#[non_exhaustive]
474pub struct BssInfo {
475 pub version: u32,
476 pub length: u32,
477 pub bssid: [u8; 6],
478 pub beacon_period: u16,
479 pub capability: u16,
480 pub ssid_len: u8,
481 pub ssid: [u8; 32],
482 // there will be more stuff here
483}
484impl_bytes!(BssInfo);
485
486impl BssInfo {
487 pub fn parse(packet: &mut [u8]) -> Option<&mut Self> {
488 if packet.len() < BssInfo::SIZE {
489 return None;
490 }
491
492 Some(BssInfo::from_bytes_mut(
493 packet[..BssInfo::SIZE].as_mut().try_into().unwrap(),
494 ))
495 }
496}