aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/mac
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/mac')
-rw-r--r--embassy-stm32-wpan/src/mac/commands.rs478
-rw-r--r--embassy-stm32-wpan/src/mac/consts.rs4
-rw-r--r--embassy-stm32-wpan/src/mac/control.rs95
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs120
-rw-r--r--embassy-stm32-wpan/src/mac/event.rs153
-rw-r--r--embassy-stm32-wpan/src/mac/indications.rs265
-rw-r--r--embassy-stm32-wpan/src/mac/macros.rs32
-rw-r--r--embassy-stm32-wpan/src/mac/mod.rs21
-rw-r--r--embassy-stm32-wpan/src/mac/opcodes.rs92
-rw-r--r--embassy-stm32-wpan/src/mac/responses.rs273
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs109
-rw-r--r--embassy-stm32-wpan/src/mac/typedefs.rs381
12 files changed, 0 insertions, 2023 deletions
diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs
deleted file mode 100644
index 82b9d2772..000000000
--- a/embassy-stm32-wpan/src/mac/commands.rs
+++ /dev/null
@@ -1,478 +0,0 @@
1#![allow(unused)]
2
3use core::{mem, slice};
4
5use super::opcodes::OpcodeM4ToM0;
6use super::typedefs::{
7 AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus,
8 PanId, PibId, ScanType, SecurityLevel,
9};
10
11pub trait MacCommand: Sized {
12 const OPCODE: OpcodeM4ToM0;
13
14 fn payload<'a>(&'a self) -> &'a [u8] {
15 unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::<Self>()) }
16 }
17}
18
19/// MLME ASSOCIATE Request used to request an association
20#[repr(C)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct AssociateRequest {
23 /// the logical channel on which to attempt association
24 pub channel_number: MacChannel,
25 /// the channel page on which to attempt association
26 pub channel_page: u8,
27 /// coordinator addressing mode
28 pub coord_addr_mode: AddressMode,
29 /// operational capabilities of the associating device
30 pub capability_information: Capabilities,
31 /// the identifier of the PAN with which to associate
32 pub coord_pan_id: PanId,
33 /// the security level to be used
34 pub security_level: SecurityLevel,
35 /// the mode used to identify the key to be used
36 pub key_id_mode: KeyIdMode,
37 /// the originator of the key to be used
38 pub key_source: [u8; 8],
39 /// Coordinator address
40 pub coord_address: MacAddress,
41 /// the index of the key to be used
42 pub key_index: u8,
43}
44
45impl MacCommand for AssociateRequest {
46 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq;
47}
48
49/// MLME DISASSOCIATE Request sed to request a disassociation
50#[repr(C)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub struct DisassociateRequest {
53 /// device addressing mode used
54 pub device_addr_mode: AddressMode,
55 /// the identifier of the PAN of the device
56 pub device_pan_id: PanId,
57 /// the reason for the disassociation
58 pub disassociation_reason: DisassociationReason,
59 /// device address
60 pub device_address: MacAddress,
61 /// `true` if the disassociation notification command is to be sent indirectly
62 pub tx_indirect: bool,
63 /// the security level to be used
64 pub security_level: SecurityLevel,
65 /// the mode to be used to indetify the key to be used
66 pub key_id_mode: KeyIdMode,
67 /// the index of the key to be used
68 pub key_index: u8,
69 /// the originator of the key to be used
70 pub key_source: [u8; 8],
71}
72
73impl MacCommand for DisassociateRequest {
74 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq;
75}
76
77/// MLME GET Request used to request a PIB value
78#[repr(C)]
79#[derive(Default)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct GetRequest {
82 /// the name of the PIB attribute to read
83 pub pib_attribute: PibId,
84
85 /// byte stuffing to keep 32 bit alignment
86 pub a_stuffing: [u8; 3],
87}
88
89impl MacCommand for GetRequest {
90 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
91}
92
93/// MLME GTS Request used to request and maintain GTSs
94#[repr(C)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub struct GtsRequest {
97 /// the characteristics of the GTS
98 pub characteristics: GtsCharacteristics,
99 /// the security level to be used
100 pub security_level: SecurityLevel,
101 /// the mode used to identify the key to be used
102 pub key_id_mode: KeyIdMode,
103 /// the index of the key to be used
104 pub key_index: u8,
105 /// the originator of the key to be used
106 pub key_source: [u8; 8],
107}
108
109impl MacCommand for GtsRequest {
110 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
111}
112
113#[repr(C)]
114#[derive(Default)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116pub struct ResetRequest {
117 /// MAC PIB attributes are set to their default values or not during reset
118 pub set_default_pib: bool,
119 /// byte stuffing to keep 32 bit alignment
120 pub a_stuffing: [u8; 3],
121}
122
123impl MacCommand for ResetRequest {
124 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq;
125}
126
127/// MLME RX ENABLE Request used to request that the receiver is either enabled
128/// for a finite period of time or disabled
129#[repr(C)]
130#[cfg_attr(feature = "defmt", derive(defmt::Format))]
131pub struct RxEnableRequest {
132 /// the request operation can be deferred or not
133 pub defer_permit: bool,
134 /// configure the transceiver to RX with ranging for a value of
135 /// RANGING_ON or to not enable ranging for RANGING_OFF
136 pub ranging_rx_control: u8,
137 /// byte stuffing to keep 32 bit alignment
138 pub a_stuffing: [u8; 2],
139 /// number of symbols measured before the receiver is to be enabled or disabled
140 pub rx_on_time: [u8; 4],
141 /// number of symbols for which the receiver is to be enabled
142 pub rx_on_duration: [u8; 4],
143}
144
145impl MacCommand for RxEnableRequest {
146 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq;
147}
148
149/// MLME SCAN Request used to initiate a channel scan over a given list of channels
150#[repr(C)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152pub struct ScanRequest {
153 /// the type of scan to be performed
154 pub scan_type: ScanType,
155 /// the time spent on scanning each channel
156 pub scan_duration: u8,
157 /// channel page on which to perform the scan
158 pub channel_page: u8,
159 /// security level to be used
160 pub security_level: SecurityLevel,
161 /// indicate which channels are to be scanned
162 pub scan_channels: [u8; 4],
163 /// originator the key to be used
164 pub key_source: [u8; 8],
165 /// mode used to identify the key to be used
166 pub key_id_mode: KeyIdMode,
167 /// index of the key to be used
168 pub key_index: u8,
169 /// byte stuffing to keep 32 bit alignment
170 pub a_stuffing: [u8; 2],
171}
172
173impl MacCommand for ScanRequest {
174 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq;
175}
176
177/// MLME SET Request used to attempt to write the given value to the indicated PIB attribute
178#[repr(C)]
179#[cfg_attr(feature = "defmt", derive(defmt::Format))]
180pub struct SetRequest {
181 /// the pointer to the value of the PIB attribute to set
182 pub pib_attribute_ptr: *const u8,
183 /// the name of the PIB attribute to set
184 pub pib_attribute: PibId,
185}
186
187impl MacCommand for SetRequest {
188 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq;
189}
190
191/// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe
192/// configuration
193#[repr(C)]
194#[derive(Default)]
195#[cfg_attr(feature = "defmt", derive(defmt::Format))]
196pub struct StartRequest {
197 /// PAN indentifier to used by the device
198 pub pan_id: PanId,
199 /// logical channel on which to begin
200 pub channel_number: MacChannel,
201 /// channel page on which to begin
202 pub channel_page: u8,
203 /// time at which to begin transmitting beacons
204 pub start_time: [u8; 4],
205 /// indicated how often the beacon is to be transmitted
206 pub beacon_order: u8,
207 /// length of the active portion of the superframe
208 pub superframe_order: u8,
209 /// indicated wheter the device is a PAN coordinator or not
210 pub pan_coordinator: bool,
211 /// indicates if the receiver of the beaconing device is disabled or not
212 pub battery_life_extension: bool,
213 /// indicated if the coordinator realignment command is to be trasmitted
214 pub coord_realignment: u8,
215 /// indicated if the coordinator realignment command is to be trasmitted
216 pub coord_realign_security_level: SecurityLevel,
217 /// index of the key to be used
218 pub coord_realign_key_id_index: u8,
219 /// originator of the key to be used
220 pub coord_realign_key_source: [u8; 8],
221 /// security level to be used for beacon frames
222 pub beacon_security_level: SecurityLevel,
223 /// mode used to identify the key to be used
224 pub beacon_key_id_mode: KeyIdMode,
225 /// index of the key to be used
226 pub beacon_key_index: u8,
227 /// originator of the key to be used
228 pub beacon_key_source: [u8; 8],
229}
230
231impl MacCommand for StartRequest {
232 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq;
233}
234
235/// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if
236/// specified, tracking its beacons
237#[repr(C)]
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239pub struct SyncRequest {
240 /// the channel number on which to attempt coordinator synchronization
241 pub channel_number: MacChannel,
242 /// the channel page on which to attempt coordinator synchronization
243 pub channel_page: u8,
244 /// `true` if the MLME is to synchronize with the next beacon and attempts
245 /// to track all future beacons.
246 ///
247 /// `false` if the MLME is to synchronize with only the next beacon
248 pub track_beacon: bool,
249 /// byte stuffing to keep 32 bit alignment
250 pub a_stuffing: [u8; 1],
251}
252
253impl MacCommand for SyncRequest {
254 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq;
255}
256
257/// MLME POLL Request propmts the device to request data from the coordinator
258#[repr(C)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260pub struct PollRequest {
261 /// addressing mode of the coordinator
262 pub coord_addr_mode: AddressMode,
263 /// security level to be used
264 pub security_level: SecurityLevel,
265 /// mode used to identify the key to be used
266 pub key_id_mode: KeyIdMode,
267 /// index of the key to be used
268 pub key_index: u8,
269 /// coordinator address
270 pub coord_address: MacAddress,
271 /// originator of the key to be used
272 pub key_source: [u8; 8],
273 /// PAN identifier of the coordinator
274 pub coord_pan_id: PanId,
275 /// byte stuffing to keep 32 bit alignment
276 pub a_stuffing: [u8; 2],
277}
278
279impl MacCommand for PollRequest {
280 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq;
281}
282
283/// MLME DPS Request allows the next higher layer to request that the PHY utilize a
284/// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration
285#[repr(C)]
286#[cfg_attr(feature = "defmt", derive(defmt::Format))]
287pub struct DpsRequest {
288 /// the index value for the transmitter
289 tx_dps_index: u8,
290 /// the index value of the receiver
291 rx_dps_index: u8,
292 /// the number of symbols for which the transmitter and receiver will utilize the
293 /// respective DPS indices
294 dps_index_duration: u8,
295 /// byte stuffing to keep 32 bit alignment
296 pub a_stuffing: [u8; 1],
297}
298
299impl MacCommand for DpsRequest {
300 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq;
301}
302
303/// MLME SOUNDING request primitive which is used by the next higher layer to request that
304/// the PHY respond with channel sounding information
305#[repr(C)]
306#[cfg_attr(feature = "defmt", derive(defmt::Format))]
307pub struct SoundingRequest {
308 /// byte stuffing to keep 32 bit alignment
309 pub a_stuffing: [u8; 4],
310}
311
312impl MacCommand for SoundingRequest {
313 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq;
314}
315
316/// MLME CALIBRATE request primitive which used to obtain the results of a ranging
317/// calibration request from an RDEV
318#[repr(C)]
319#[cfg_attr(feature = "defmt", derive(defmt::Format))]
320pub struct CalibrateRequest {
321 /// byte stuffing to keep 32 bit alignment
322 pub a_stuffing: [u8; 4],
323}
324
325impl MacCommand for CalibrateRequest {
326 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq;
327}
328
329/// MCPS DATA Request used for MAC data related requests from the application
330#[repr(C)]
331#[cfg_attr(feature = "defmt", derive(defmt::Format))]
332pub struct DataRequest {
333 /// the handle assocated with the MSDU to be transmitted
334 pub msdu_ptr: *const u8,
335 /// source addressing mode used
336 pub src_addr_mode: AddressMode,
337 /// destination addressing mode used
338 pub dst_addr_mode: AddressMode,
339 /// destination PAN Id
340 pub dst_pan_id: PanId,
341 /// destination address
342 pub dst_address: MacAddress,
343 /// the number of octets contained in the MSDU
344 pub msdu_length: u8,
345 /// the handle assocated with the MSDU to be transmitted
346 pub msdu_handle: u8,
347 /// the ACK transmittion options for the MSDU
348 pub ack_tx: u8,
349 /// `true` if a GTS is to be used for transmission
350 ///
351 /// `false` indicates that the CAP will be used
352 pub gts_tx: bool,
353 /// the pending bit transmission options for the MSDU
354 pub indirect_tx: u8,
355 /// the security level to be used
356 pub security_level: SecurityLevel,
357 /// the mode used to indentify the key to be used
358 pub key_id_mode: KeyIdMode,
359 /// the index of the key to be used
360 pub key_index: u8,
361 /// the originator of the key to be used
362 pub key_source: [u8; 8],
363 /// 2011 - the pulse repitition value
364 pub uwbprf: u8,
365 /// 2011 - the ranging configuration
366 pub ranging: u8,
367 /// 2011 - the preamble symbol repititions
368 pub uwb_preamble_symbol_repetitions: u8,
369 /// 2011 - indicates the data rate
370 pub datrate: u8,
371}
372
373impl DataRequest {
374 pub fn set_buffer<'a>(&'a mut self, buf: &'a [u8]) -> &'a mut Self {
375 self.msdu_ptr = buf as *const _ as *const u8;
376 self.msdu_length = buf.len() as u8;
377
378 self
379 }
380}
381
382impl Default for DataRequest {
383 fn default() -> Self {
384 Self {
385 msdu_ptr: 0 as *const u8,
386 src_addr_mode: AddressMode::NoAddress,
387 dst_addr_mode: AddressMode::NoAddress,
388 dst_pan_id: PanId([0, 0]),
389 dst_address: MacAddress { short: [0, 0] },
390 msdu_length: 0,
391 msdu_handle: 0,
392 ack_tx: 0,
393 gts_tx: false,
394 indirect_tx: 0,
395 security_level: SecurityLevel::Unsecure,
396 key_id_mode: KeyIdMode::Implicite,
397 key_index: 0,
398 key_source: [0u8; 8],
399 uwbprf: 0,
400 ranging: 0,
401 uwb_preamble_symbol_repetitions: 0,
402 datrate: 0,
403 }
404 }
405}
406
407impl MacCommand for DataRequest {
408 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq;
409}
410
411/// for MCPS PURGE Request used to purge an MSDU from the transaction queue
412#[repr(C)]
413#[cfg_attr(feature = "defmt", derive(defmt::Format))]
414pub struct PurgeRequest {
415 /// the handle associated with the MSDU to be purged from the transaction
416 /// queue
417 pub msdu_handle: u8,
418 /// byte stuffing to keep 32 bit alignment
419 pub a_stuffing: [u8; 3],
420}
421
422impl MacCommand for PurgeRequest {
423 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq;
424}
425
426/// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication
427#[repr(C)]
428#[derive(Default)]
429#[cfg_attr(feature = "defmt", derive(defmt::Format))]
430pub struct AssociateResponse {
431 /// extended address of the device requesting association
432 pub device_address: [u8; 8],
433 /// 16-bitshort device address allocated by the coordinator on successful
434 /// association
435 pub assoc_short_address: [u8; 2],
436 /// status of the association attempt
437 pub status: MacStatus,
438 /// security level to be used
439 pub security_level: SecurityLevel,
440 /// the originator of the key to be used
441 pub key_source: [u8; 8],
442 /// the mode used to identify the key to be used
443 pub key_id_mode: KeyIdMode,
444 /// the index of the key to be used
445 pub key_index: u8,
446 /// byte stuffing to keep 32 bit alignment
447 pub a_stuffing: [u8; 2],
448}
449
450impl MacCommand for AssociateResponse {
451 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes;
452}
453
454/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication
455#[repr(C)]
456#[cfg_attr(feature = "defmt", derive(defmt::Format))]
457pub struct OrphanResponse {
458 /// extended address of the orphaned device
459 pub orphan_address: [u8; 8],
460 /// short address allocated to the orphaned device
461 pub short_address: [u8; 2],
462 /// if the orphaned device is associated with coordinator or not
463 pub associated_member: bool,
464 /// security level to be used
465 pub security_level: SecurityLevel,
466 /// the originator of the key to be used
467 pub key_source: [u8; 8],
468 /// the mode used to identify the key to be used
469 pub key_id_mode: KeyIdMode,
470 /// the index of the key to be used
471 pub key_index: u8,
472 /// byte stuffing to keep 32 bit alignment
473 pub a_stuffing: [u8; 2],
474}
475
476impl MacCommand for OrphanResponse {
477 const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes;
478}
diff --git a/embassy-stm32-wpan/src/mac/consts.rs b/embassy-stm32-wpan/src/mac/consts.rs
deleted file mode 100644
index 56903d980..000000000
--- a/embassy-stm32-wpan/src/mac/consts.rs
+++ /dev/null
@@ -1,4 +0,0 @@
1pub const MAX_PAN_DESC_SUPPORTED: usize = 6;
2pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6;
3pub const MAX_PENDING_ADDRESS: usize = 7;
4pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16;
diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs
deleted file mode 100644
index e8d2f9f7b..000000000
--- a/embassy-stm32-wpan/src/mac/control.rs
+++ /dev/null
@@ -1,95 +0,0 @@
1use core::future::Future;
2use core::task;
3use core::task::Poll;
4
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::mutex::MutexGuard;
7use embassy_sync::signal::Signal;
8use futures_util::FutureExt;
9
10use super::commands::MacCommand;
11use super::event::MacEvent;
12use super::typedefs::MacError;
13use crate::mac::runner::Runner;
14
15pub struct Control<'a> {
16 runner: &'a Runner<'a>,
17}
18
19impl<'a> Control<'a> {
20 pub(crate) fn new(runner: &'a Runner<'a>) -> Self {
21 Self { runner: runner }
22 }
23
24 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
25 where
26 T: MacCommand,
27 {
28 let _wm = self.runner.write_mutex.lock().await;
29
30 self.runner.mac_subsystem.send_command(cmd).await
31 }
32
33 pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
34 where
35 T: MacCommand,
36 {
37 let rm = self.runner.read_mutex.lock().await;
38 let _wm = self.runner.write_mutex.lock().await;
39 let token = EventToken::new(self.runner, rm);
40
41 self.runner.mac_subsystem.send_command(cmd).await?;
42
43 Ok(token)
44 }
45}
46
47pub struct EventToken<'a> {
48 runner: &'a Runner<'a>,
49 _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>,
50}
51
52impl<'a> EventToken<'a> {
53 pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self {
54 // Enable event receiving
55 runner.rx_event_channel.lock(|s| {
56 *s.borrow_mut() = Some(Signal::new());
57 });
58
59 Self {
60 runner: runner,
61 _mutex_guard: mutex_guard,
62 }
63 }
64}
65
66impl<'a> Future for EventToken<'a> {
67 type Output = MacEvent<'a>;
68
69 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
70 self.get_mut().runner.rx_event_channel.lock(|s| {
71 let signal = s.borrow_mut();
72 let signal = match &*signal {
73 Some(s) => s,
74 _ => unreachable!(),
75 };
76
77 let result = match signal.wait().poll_unpin(cx) {
78 Poll::Ready(mac_event) => Poll::Ready(mac_event),
79 Poll::Pending => Poll::Pending,
80 };
81
82 result
83 })
84 }
85}
86
87impl<'a> Drop for EventToken<'a> {
88 fn drop(&mut self) {
89 // Disable event receiving
90 // This will also drop the contained event, if it exists, and will free up receiving the next event
91 self.runner.rx_event_channel.lock(|s| {
92 *s.borrow_mut() = None;
93 });
94 }
95}
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs
deleted file mode 100644
index 41cca09e3..000000000
--- a/embassy-stm32-wpan/src/mac/driver.rs
+++ /dev/null
@@ -1,120 +0,0 @@
1#![deny(unused_must_use)]
2
3use core::task::Context;
4
5use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::channel::Channel;
8
9use crate::mac::event::MacEvent;
10use crate::mac::runner::Runner;
11use crate::mac::MTU;
12
13pub struct Driver<'d> {
14 runner: &'d Runner<'d>,
15}
16
17impl<'d> Driver<'d> {
18 pub(crate) fn new(runner: &'d Runner<'d>) -> Self {
19 Self { runner: runner }
20 }
21}
22
23impl<'d> embassy_net_driver::Driver for Driver<'d> {
24 // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a;
25 // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a;
26 type RxToken<'a>
27 = RxToken<'d>
28 where
29 Self: 'a;
30 type TxToken<'a>
31 = TxToken<'d>
32 where
33 Self: 'a;
34
35 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
36 if self.runner.rx_channel.poll_ready_to_receive(cx).is_ready()
37 && self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready()
38 {
39 Some((
40 RxToken {
41 rx: &self.runner.rx_channel,
42 },
43 TxToken {
44 tx: &self.runner.tx_channel,
45 tx_buf: &self.runner.tx_buf_channel,
46 },
47 ))
48 } else {
49 None
50 }
51 }
52
53 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
54 if self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() {
55 Some(TxToken {
56 tx: &self.runner.tx_channel,
57 tx_buf: &self.runner.tx_buf_channel,
58 })
59 } else {
60 None
61 }
62 }
63
64 fn capabilities(&self) -> Capabilities {
65 let mut caps = Capabilities::default();
66 caps.max_transmission_unit = MTU;
67 // caps.max_burst_size = Some(self.tx.len());
68 caps
69 }
70
71 fn link_state(&mut self, _cx: &mut Context) -> LinkState {
72 LinkState::Down
73 }
74
75 fn hardware_address(&self) -> HardwareAddress {
76 // self.mac_addr
77 HardwareAddress::Ieee802154([0; 8])
78 }
79}
80
81pub struct RxToken<'d> {
82 rx: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
83}
84
85impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
86 fn consume<R, F>(self, f: F) -> R
87 where
88 F: FnOnce(&mut [u8]) -> R,
89 {
90 // Only valid data events should be put into the queue
91
92 let data_event = match self.rx.try_receive().unwrap() {
93 MacEvent::McpsDataInd(data_event) => data_event,
94 _ => unreachable!(),
95 };
96
97 f(&mut data_event.payload())
98 }
99}
100
101pub struct TxToken<'d> {
102 tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>,
103 tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>,
104}
105
106impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
107 fn consume<R, F>(self, len: usize, f: F) -> R
108 where
109 F: FnOnce(&mut [u8]) -> R,
110 {
111 // Only valid tx buffers should be put into the queue
112 let buf = self.tx_buf.try_receive().unwrap();
113 let r = f(&mut buf[..len]);
114
115 // The tx channel should always be of equal capacity to the tx_buf channel
116 self.tx.try_send((buf, len)).unwrap();
117
118 r
119 }
120}
diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs
deleted file mode 100644
index 9ca4f5a2a..000000000
--- a/embassy-stm32-wpan/src/mac/event.rs
+++ /dev/null
@@ -1,153 +0,0 @@
1use core::{mem, ptr};
2
3use super::indications::{
4 AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
5 DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication,
6};
7use super::responses::{
8 AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
9 PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
10};
11use crate::evt::{EvtBox, MemoryManager};
12use crate::mac::opcodes::OpcodeM0ToM4;
13use crate::sub::mac::{self, Mac};
14
15pub(crate) trait ParseableMacEvent: Sized {
16 fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
17 if buf.len() < mem::size_of::<Self>() {
18 Err(())
19 } else {
20 Ok(unsafe { &*(buf as *const _ as *const Self) })
21 }
22 }
23}
24
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[derive(Debug)]
27pub enum MacEvent<'a> {
28 MlmeAssociateCnf(&'a AssociateConfirm),
29 MlmeDisassociateCnf(&'a DisassociateConfirm),
30 MlmeGetCnf(&'a GetConfirm),
31 MlmeGtsCnf(&'a GtsConfirm),
32 MlmeResetCnf(&'a ResetConfirm),
33 MlmeRxEnableCnf(&'a RxEnableConfirm),
34 MlmeScanCnf(&'a ScanConfirm),
35 MlmeSetCnf(&'a SetConfirm),
36 MlmeStartCnf(&'a StartConfirm),
37 MlmePollCnf(&'a PollConfirm),
38 MlmeDpsCnf(&'a DpsConfirm),
39 MlmeSoundingCnf(&'a SoundingConfirm),
40 MlmeCalibrateCnf(&'a CalibrateConfirm),
41 McpsDataCnf(&'a DataConfirm),
42 McpsPurgeCnf(&'a PurgeConfirm),
43 MlmeAssociateInd(&'a AssociateIndication),
44 MlmeDisassociateInd(&'a DisassociateIndication),
45 MlmeBeaconNotifyInd(&'a BeaconNotifyIndication),
46 MlmeCommStatusInd(&'a CommStatusIndication),
47 MlmeGtsInd(&'a GtsIndication),
48 MlmeOrphanInd(&'a OrphanIndication),
49 MlmeSyncLossInd(&'a SyncLossIndication),
50 MlmeDpsInd(&'a DpsIndication),
51 McpsDataInd(&'a DataIndication),
52 MlmePollInd(&'a PollIndication),
53}
54
55impl<'a> MacEvent<'a> {
56 pub(crate) fn new(event_box: EvtBox<Mac>) -> Result<Self, ()> {
57 let payload = event_box.payload();
58 let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
59
60 let opcode = OpcodeM0ToM4::try_from(opcode)?;
61 let buf = &payload[2..];
62
63 // To avoid re-parsing the opcode, we store the result of the parse
64 // this requires use of unsafe because rust cannot assume that a reference will become
65 // invalid when the underlying result is moved. However, because we refer to a "heap"
66 // allocation, the underlying reference will not move until the struct is dropped.
67
68 let mac_event = match opcode {
69 OpcodeM0ToM4::MlmeAssociateCnf => {
70 MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) })
71 }
72 OpcodeM0ToM4::MlmeDisassociateCnf => {
73 MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) })
74 }
75 OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }),
76 OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }),
77 OpcodeM0ToM4::MlmeResetCnf => {
78 MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) })
79 }
80 OpcodeM0ToM4::MlmeRxEnableCnf => {
81 MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) })
82 }
83 OpcodeM0ToM4::MlmeScanCnf => {
84 MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) })
85 }
86 OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }),
87 OpcodeM0ToM4::MlmeStartCnf => {
88 MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) })
89 }
90 OpcodeM0ToM4::MlmePollCnf => {
91 MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) })
92 }
93 OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }),
94 OpcodeM0ToM4::MlmeSoundingCnf => {
95 MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) })
96 }
97 OpcodeM0ToM4::MlmeCalibrateCnf => {
98 MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) })
99 }
100 OpcodeM0ToM4::McpsDataCnf => {
101 MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) })
102 }
103 OpcodeM0ToM4::McpsPurgeCnf => {
104 MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) })
105 }
106 OpcodeM0ToM4::MlmeAssociateInd => {
107 MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) })
108 }
109 OpcodeM0ToM4::MlmeDisassociateInd => {
110 MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) })
111 }
112 OpcodeM0ToM4::MlmeBeaconNotifyInd => {
113 MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) })
114 }
115 OpcodeM0ToM4::MlmeCommStatusInd => {
116 MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) })
117 }
118 OpcodeM0ToM4::MlmeGtsInd => {
119 MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) })
120 }
121 OpcodeM0ToM4::MlmeOrphanInd => {
122 MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) })
123 }
124 OpcodeM0ToM4::MlmeSyncLossInd => {
125 MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) })
126 }
127 OpcodeM0ToM4::MlmeDpsInd => {
128 MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) })
129 }
130 OpcodeM0ToM4::McpsDataInd => {
131 MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) })
132 }
133 OpcodeM0ToM4::MlmePollInd => {
134 MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) })
135 }
136 };
137
138 // Forget the event box so that drop isn't called
139 // We want to handle the lifetime ourselves
140
141 mem::forget(event_box);
142
143 Ok(mac_event)
144 }
145}
146
147unsafe impl<'a> Send for MacEvent<'a> {}
148
149impl<'a> Drop for MacEvent<'a> {
150 fn drop(&mut self) {
151 unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) };
152 }
153}
diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs
deleted file mode 100644
index c0b86d745..000000000
--- a/embassy-stm32-wpan/src/mac/indications.rs
+++ /dev/null
@@ -1,265 +0,0 @@
1use core::slice;
2
3use super::consts::MAX_PENDING_ADDRESS;
4use super::event::ParseableMacEvent;
5use super::typedefs::{
6 AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor,
7 PanId, SecurityLevel,
8};
9
10/// MLME ASSOCIATE Indication which will be used by the MAC
11/// to indicate the reception of an association request command
12#[repr(C)]
13#[derive(Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct AssociateIndication {
16 /// Extended address of the device requesting association
17 pub device_address: [u8; 8],
18 /// Operational capabilities of the device requesting association
19 pub capability_information: Capabilities,
20 /// Security level purportedly used by the received MAC command frame
21 pub security_level: SecurityLevel,
22 /// The mode used to identify the key used by the originator of frame
23 pub key_id_mode: KeyIdMode,
24 /// Index of the key used by the originator of the received frame
25 pub key_index: u8,
26 /// The originator of the key used by the originator of the received frame
27 pub key_source: [u8; 8],
28}
29
30impl ParseableMacEvent for AssociateIndication {}
31
32/// MLME DISASSOCIATE indication which will be used to send
33/// disassociation indication to the application.
34#[repr(C)]
35#[derive(Debug)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub struct DisassociateIndication {
38 /// Extended address of the device requesting association
39 pub device_address: [u8; 8],
40 /// The reason for the disassociation
41 pub disassociation_reason: DisassociationReason,
42 /// The security level to be used
43 pub security_level: SecurityLevel,
44 /// The mode used to identify the key to be used
45 pub key_id_mode: KeyIdMode,
46 /// The index of the key to be used
47 pub key_index: u8,
48 /// The originator of the key to be used
49 pub key_source: [u8; 8],
50}
51
52impl ParseableMacEvent for DisassociateIndication {}
53
54/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
55/// within a beacon frame received by the MAC to the application
56#[repr(C)]
57#[derive(Debug)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59pub struct BeaconNotifyIndication {
60 /// he set of octets comprising the beacon payload to be transferred
61 /// from the MAC sublayer entity to the next higher layer
62 pub sdu_ptr: *const u8,
63 /// The PAN Descriptor for the received beacon
64 pub pan_descriptor: PanDescriptor,
65 /// The list of addresses of the devices
66 pub addr_list: [MacAddress; MAX_PENDING_ADDRESS],
67 /// Beacon Sequence Number
68 pub bsn: u8,
69 /// The beacon pending address specification
70 pub pend_addr_spec: u8,
71 /// Number of octets contained in the beacon payload of the beacon frame
72 pub sdu_length: u8,
73}
74
75impl ParseableMacEvent for BeaconNotifyIndication {}
76
77/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
78#[repr(C)]
79#[derive(Debug)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct CommStatusIndication {
82 /// The 16-bit PAN identifier of the device from which the frame
83 /// was received or to which the frame was being sent
84 pub pan_id: PanId,
85 /// Source addressing mode
86 pub src_addr_mode: AddressMode,
87 /// Destination addressing mode
88 pub dst_addr_mode: AddressMode,
89 /// Source address
90 pub src_address: MacAddress,
91 /// Destination address
92 pub dst_address: MacAddress,
93 /// The communications status
94 pub status: MacStatus,
95 /// Security level to be used
96 pub security_level: SecurityLevel,
97 /// Mode used to identify the key to be used
98 pub key_id_mode: KeyIdMode,
99 /// Index of the key to be used
100 pub key_index: u8,
101 /// Originator of the key to be used
102 pub key_source: [u8; 8],
103}
104
105impl ParseableMacEvent for CommStatusIndication {}
106
107/// MLME GTS Indication indicates that a GTS has been allocated or that a
108/// previously allocated GTS has been deallocated
109#[repr(C)]
110#[derive(Debug)]
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
112pub struct GtsIndication {
113 /// The short address of the device that has been allocated or deallocated a GTS
114 pub device_address: [u8; 2],
115 /// The characteristics of the GTS
116 pub gts_characteristics: u8,
117 /// Security level to be used
118 pub security_level: SecurityLevel,
119 /// Mode used to identify the key to be used
120 pub key_id_mode: KeyIdMode,
121 /// Index of the key to be used
122 pub key_index: u8,
123 /// byte stuffing to keep 32 bit alignment
124 a_stuffing: [u8; 2],
125 /// Originator of the key to be used
126 pub key_source: [u8; 8],
127}
128
129impl ParseableMacEvent for GtsIndication {}
130
131/// MLME ORPHAN Indication which is used by the coordinator to notify the
132/// application of the presence of an orphaned device
133#[repr(C)]
134#[derive(Debug)]
135#[cfg_attr(feature = "defmt", derive(defmt::Format))]
136pub struct OrphanIndication {
137 /// Extended address of the orphaned device
138 pub orphan_address: [u8; 8],
139 /// Originator of the key used by the originator of the received frame
140 pub key_source: [u8; 8],
141 /// Security level purportedly used by the received MAC command frame
142 pub security_level: SecurityLevel,
143 /// Mode used to identify the key used by originator of received frame
144 pub key_id_mode: KeyIdMode,
145 /// Index of the key used by the originator of the received frame
146 pub key_index: u8,
147 /// byte stuffing to keep 32 bit alignment
148 a_stuffing: [u8; 1],
149}
150
151impl ParseableMacEvent for OrphanIndication {}
152
153/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
154/// of synchronization with the coordinator
155#[repr(C)]
156#[derive(Debug)]
157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
158pub struct SyncLossIndication {
159 /// The PAN identifier with which the device lost synchronization or to which it was realigned
160 pub pan_id: PanId,
161 /// The reason that synchronization was lost
162 pub loss_reason: u8,
163 /// The logical channel on which the device lost synchronization or to whi
164 pub channel_number: MacChannel,
165 /// The channel page on which the device lost synchronization or to which
166 pub channel_page: u8,
167 /// The security level used by the received MAC frame
168 pub security_level: SecurityLevel,
169 /// Mode used to identify the key used by originator of received frame
170 pub key_id_mode: KeyIdMode,
171 /// Index of the key used by the originator of the received frame
172 pub key_index: u8,
173 /// Originator of the key used by the originator of the received frame
174 pub key_source: [u8; 8],
175}
176
177impl ParseableMacEvent for SyncLossIndication {}
178
179/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
180/// and the resetting of the DPS values in the PHY
181#[repr(C)]
182#[derive(Debug)]
183#[cfg_attr(feature = "defmt", derive(defmt::Format))]
184pub struct DpsIndication {
185 /// byte stuffing to keep 32 bit alignment
186 a_stuffing: [u8; 4],
187}
188
189impl ParseableMacEvent for DpsIndication {}
190
191#[repr(C)]
192#[derive(Debug)]
193#[cfg_attr(feature = "defmt", derive(defmt::Format))]
194pub struct DataIndication {
195 /// Pointer to the set of octets forming the MSDU being indicated
196 pub msdu_ptr: *const u8,
197 /// Source addressing mode used
198 pub src_addr_mode: AddressMode,
199 /// Source PAN ID
200 pub src_pan_id: PanId,
201 /// Source address
202 pub src_address: MacAddress,
203 /// Destination addressing mode used
204 pub dst_addr_mode: AddressMode,
205 /// Destination PAN ID
206 pub dst_pan_id: PanId,
207 /// Destination address
208 pub dst_address: MacAddress,
209 /// The number of octets contained in the MSDU being indicated
210 pub msdu_length: u8,
211 /// QI value measured during reception of the MPDU
212 pub mpdu_link_quality: u8,
213 /// The data sequence number of the received data frame
214 pub dsn: u8,
215 /// The time, in symbols, at which the data were received
216 pub time_stamp: [u8; 4],
217 /// The security level purportedly used by the received data frame
218 security_level: SecurityLevel,
219 /// Mode used to identify the key used by originator of received frame
220 key_id_mode: KeyIdMode,
221 /// The originator of the key
222 pub key_source: [u8; 8],
223 /// The index of the key
224 pub key_index: u8,
225 /// he pulse repetition value of the received PPDU
226 pub uwbprf: u8,
227 /// The preamble symbol repetitions of the UWB PHY frame
228 pub uwn_preamble_symbol_repetitions: u8,
229 /// Indicates the data rate
230 pub datrate: u8,
231 /// time units corresponding to an RMARKER at the antenna at the end of a ranging exchange,
232 pub ranging_received: u8,
233 pub ranging_counter_start: u32,
234 pub ranging_counter_stop: u32,
235 /// ime units in a message exchange over which the tracking offset was measured
236 pub ranging_tracking_interval: u32,
237 /// time units slipped or advanced by the radio tracking system
238 pub ranging_offset: u32,
239 /// The FoM characterizing the ranging measurement
240 pub ranging_fom: u8,
241 /// The Received Signal Strength Indicator measured
242 pub rssi: u8,
243}
244
245impl ParseableMacEvent for DataIndication {}
246
247impl DataIndication {
248 pub fn payload<'a>(&'a self) -> &'a mut [u8] {
249 unsafe { slice::from_raw_parts_mut(self.msdu_ptr as *mut _, self.msdu_length as usize) }
250 }
251}
252
253/// MLME POLL Indication which will be used for indicating the Data Request
254/// reception to upper layer as defined in Zigbee r22 - D.8.2
255#[repr(C)]
256#[derive(Debug)]
257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
258pub struct PollIndication {
259 /// addressing mode used
260 pub addr_mode: AddressMode,
261 /// Poll requester address
262 pub request_address: MacAddress,
263}
264
265impl ParseableMacEvent for PollIndication {}
diff --git a/embassy-stm32-wpan/src/mac/macros.rs b/embassy-stm32-wpan/src/mac/macros.rs
deleted file mode 100644
index 1a988a779..000000000
--- a/embassy-stm32-wpan/src/mac/macros.rs
+++ /dev/null
@@ -1,32 +0,0 @@
1#[macro_export]
2macro_rules! numeric_enum {
3 (#[repr($repr:ident)]
4 $(#$attrs:tt)* $vis:vis enum $name:ident {
5 $($(#$enum_attrs:tt)* $enum:ident = $constant:expr),* $(,)?
6 } ) => {
7 #[repr($repr)]
8 $(#$attrs)*
9 $vis enum $name {
10 $($(#$enum_attrs)* $enum = $constant),*
11 }
12
13 impl ::core::convert::TryFrom<$repr> for $name {
14 type Error = ();
15
16 fn try_from(value: $repr) -> ::core::result::Result<Self, ()> {
17 match value {
18 $($constant => Ok( $name :: $enum ),)*
19 _ => Err(())
20 }
21 }
22 }
23
24 impl ::core::convert::From<$name> for $repr {
25 fn from(value: $name) -> $repr {
26 match value {
27 $($name :: $enum => $constant,)*
28 }
29 }
30 }
31 }
32}
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs
deleted file mode 100644
index c847a5cca..000000000
--- a/embassy-stm32-wpan/src/mac/mod.rs
+++ /dev/null
@@ -1,21 +0,0 @@
1pub mod commands;
2mod consts;
3pub mod control;
4mod driver;
5pub mod event;
6pub mod indications;
7mod macros;
8mod opcodes;
9pub mod responses;
10pub mod runner;
11pub mod typedefs;
12
13pub use crate::mac::control::Control;
14use crate::mac::driver::Driver;
15pub use crate::mac::runner::Runner;
16
17const MTU: usize = 127;
18
19pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) {
20 (Control::new(runner), Driver::new(runner))
21}
diff --git a/embassy-stm32-wpan/src/mac/opcodes.rs b/embassy-stm32-wpan/src/mac/opcodes.rs
deleted file mode 100644
index fd7011873..000000000
--- a/embassy-stm32-wpan/src/mac/opcodes.rs
+++ /dev/null
@@ -1,92 +0,0 @@
1const ST_VENDOR_OGF: u16 = 0x3F;
2const MAC_802_15_4_CMD_OPCODE_OFFSET: u16 = 0x280;
3
4const fn opcode(ocf: u16) -> isize {
5 ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize
6}
7
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub enum OpcodeM4ToM0 {
10 MlmeAssociateReq = opcode(0x00),
11 MlmeAssociateRes = opcode(0x01),
12 MlmeDisassociateReq = opcode(0x02),
13 MlmeGetReq = opcode(0x03),
14 MlmeGtsReq = opcode(0x04),
15 MlmeOrphanRes = opcode(0x05),
16 MlmeResetReq = opcode(0x06),
17 MlmeRxEnableReq = opcode(0x07),
18 MlmeScanReq = opcode(0x08),
19 MlmeSetReq = opcode(0x09),
20 MlmeStartReq = opcode(0x0A),
21 MlmeSyncReq = opcode(0x0B),
22 MlmePollReq = opcode(0x0C),
23 MlmeDpsReq = opcode(0x0D),
24 MlmeSoundingReq = opcode(0x0E),
25 MlmeCalibrateReq = opcode(0x0F),
26 McpsDataReq = opcode(0x10),
27 McpsPurgeReq = opcode(0x11),
28}
29
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31pub enum OpcodeM0ToM4 {
32 MlmeAssociateCnf = 0x00,
33 MlmeDisassociateCnf,
34 MlmeGetCnf,
35 MlmeGtsCnf,
36 MlmeResetCnf,
37 MlmeRxEnableCnf,
38 MlmeScanCnf,
39 MlmeSetCnf,
40 MlmeStartCnf,
41 MlmePollCnf,
42 MlmeDpsCnf,
43 MlmeSoundingCnf,
44 MlmeCalibrateCnf,
45 McpsDataCnf,
46 McpsPurgeCnf,
47 MlmeAssociateInd,
48 MlmeDisassociateInd,
49 MlmeBeaconNotifyInd,
50 MlmeCommStatusInd,
51 MlmeGtsInd,
52 MlmeOrphanInd,
53 MlmeSyncLossInd,
54 MlmeDpsInd,
55 McpsDataInd,
56 MlmePollInd,
57}
58
59impl TryFrom<u16> for OpcodeM0ToM4 {
60 type Error = ();
61
62 fn try_from(value: u16) -> Result<Self, Self::Error> {
63 match value {
64 0 => Ok(Self::MlmeAssociateCnf),
65 1 => Ok(Self::MlmeDisassociateCnf),
66 2 => Ok(Self::MlmeGetCnf),
67 3 => Ok(Self::MlmeGtsCnf),
68 4 => Ok(Self::MlmeResetCnf),
69 5 => Ok(Self::MlmeRxEnableCnf),
70 6 => Ok(Self::MlmeScanCnf),
71 7 => Ok(Self::MlmeSetCnf),
72 8 => Ok(Self::MlmeStartCnf),
73 9 => Ok(Self::MlmePollCnf),
74 10 => Ok(Self::MlmeDpsCnf),
75 11 => Ok(Self::MlmeSoundingCnf),
76 12 => Ok(Self::MlmeCalibrateCnf),
77 13 => Ok(Self::McpsDataCnf),
78 14 => Ok(Self::McpsPurgeCnf),
79 15 => Ok(Self::MlmeAssociateInd),
80 16 => Ok(Self::MlmeDisassociateInd),
81 17 => Ok(Self::MlmeBeaconNotifyInd),
82 18 => Ok(Self::MlmeCommStatusInd),
83 19 => Ok(Self::MlmeGtsInd),
84 20 => Ok(Self::MlmeOrphanInd),
85 21 => Ok(Self::MlmeSyncLossInd),
86 22 => Ok(Self::MlmeDpsInd),
87 23 => Ok(Self::McpsDataInd),
88 24 => Ok(Self::MlmePollInd),
89 _ => Err(()),
90 }
91 }
92}
diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs
deleted file mode 100644
index 544fdaae8..000000000
--- a/embassy-stm32-wpan/src/mac/responses.rs
+++ /dev/null
@@ -1,273 +0,0 @@
1use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED};
2use super::event::ParseableMacEvent;
3use super::typedefs::{
4 AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType,
5 SecurityLevel,
6};
7
8/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
9/// its request to associate was successful or unsuccessful
10#[repr(C)]
11#[derive(Debug)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct AssociateConfirm {
14 /// short address allocated by the coordinator on successful association
15 pub assoc_short_address: [u8; 2],
16 /// status of the association request
17 pub status: AssociationStatus,
18 /// security level to be used
19 pub security_level: SecurityLevel,
20 /// the originator of the key to be used
21 pub key_source: [u8; 8],
22 /// the mode used to identify the key to be used
23 pub key_id_mode: KeyIdMode,
24 /// the index of the key to be used
25 pub key_index: u8,
26 /// byte stuffing to keep 32 bit alignment
27 a_stuffing: [u8; 2],
28}
29
30impl ParseableMacEvent for AssociateConfirm {}
31
32/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
33#[repr(C)]
34#[derive(Debug)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub struct DisassociateConfirm {
37 /// status of the disassociation attempt
38 pub status: MacStatus,
39 /// device addressing mode used
40 pub device_addr_mode: AddressMode,
41 /// the identifier of the PAN of the device
42 pub device_pan_id: PanId,
43 /// device address
44 pub device_address: MacAddress,
45}
46
47impl ParseableMacEvent for DisassociateConfirm {}
48
49/// MLME GET Confirm which requests information about a given PIB attribute
50#[repr(C)]
51#[derive(Debug)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53pub struct GetConfirm {
54 /// The pointer to the value of the PIB attribute attempted to read
55 pub pib_attribute_value_ptr: *const u8,
56 /// Status of the GET attempt
57 pub status: MacStatus,
58 /// The name of the PIB attribute attempted to read
59 pub pib_attribute: PibId,
60 /// The lenght of the PIB attribute Value return
61 pub pib_attribute_value_len: u8,
62 /// byte stuffing to keep 32 bit alignment
63 a_stuffing: [u8; 1],
64}
65
66impl ParseableMacEvent for GetConfirm {}
67
68/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
69/// or to deallocate an existing GTS
70#[repr(C)]
71#[derive(Debug)]
72#[cfg_attr(feature = "defmt", derive(defmt::Format))]
73pub struct GtsConfirm {
74 /// The characteristics of the GTS
75 pub gts_characteristics: u8,
76 /// The status of the GTS reques
77 pub status: MacStatus,
78 /// byte stuffing to keep 32 bit alignment
79 a_stuffing: [u8; 2],
80}
81
82impl ParseableMacEvent for GtsConfirm {}
83
84/// MLME RESET Confirm which is used to report the results of the reset operation
85#[repr(C)]
86#[derive(Debug)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub struct ResetConfirm {
89 /// The result of the reset operation
90 pub status: MacStatus,
91 /// byte stuffing to keep 32 bit alignment
92 a_stuffing: [u8; 3],
93}
94
95impl ParseableMacEvent for ResetConfirm {}
96
97/// MLME RX ENABLE Confirm which is used to report the results of the attempt
98/// to enable or disable the receiver
99#[repr(C)]
100#[derive(Debug)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102pub struct RxEnableConfirm {
103 /// Result of the request to enable or disable the receiver
104 pub status: MacStatus,
105 /// byte stuffing to keep 32 bit alignment
106 a_stuffing: [u8; 3],
107}
108
109impl ParseableMacEvent for RxEnableConfirm {}
110
111/// MLME SCAN Confirm which is used to report the result of the channel scan request
112#[repr(C)]
113#[derive(Debug)]
114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
115pub struct ScanConfirm {
116 /// Status of the scan request
117 pub status: MacStatus,
118 /// The type of scan performed
119 pub scan_type: ScanType,
120 /// Channel page on which the scan was performed
121 pub channel_page: u8,
122 /// Channels given in the request which were not scanned
123 pub unscanned_channels: [u8; 4],
124 /// Number of elements returned in the appropriate result lists
125 pub result_list_size: u8,
126 /// List of energy measurements
127 pub energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED],
128 /// List of PAN descriptors
129 pub pan_descriptor_list: [PanDescriptor; MAX_PAN_DESC_SUPPORTED],
130 /// Categorization of energy detected in channel
131 pub detected_category: u8,
132 /// For UWB PHYs, the list of energy measurements taken
133 pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED],
134}
135
136impl ParseableMacEvent for ScanConfirm {}
137
138/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
139#[repr(C)]
140#[derive(Debug)]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142pub struct SetConfirm {
143 /// The result of the set operation
144 pub status: MacStatus,
145 /// The name of the PIB attribute that was written
146 pub pin_attribute: PibId,
147 /// byte stuffing to keep 32 bit alignment
148 a_stuffing: [u8; 2],
149}
150
151impl ParseableMacEvent for SetConfirm {}
152
153/// MLME START Confirm which is used to report the results of the attempt to
154/// start using a new superframe configuration
155#[repr(C)]
156#[derive(Debug)]
157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
158pub struct StartConfirm {
159 /// Result of the attempt to start using an updated superframe configuration
160 pub status: MacStatus,
161 /// byte stuffing to keep 32 bit alignment
162 a_stuffing: [u8; 3],
163}
164
165impl ParseableMacEvent for StartConfirm {}
166
167/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
168#[repr(C)]
169#[derive(Debug)]
170#[cfg_attr(feature = "defmt", derive(defmt::Format))]
171pub struct PollConfirm {
172 /// The status of the data request
173 pub status: MacStatus,
174 /// byte stuffing to keep 32 bit alignment
175 a_stuffing: [u8; 3],
176}
177
178impl ParseableMacEvent for PollConfirm {}
179
180/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS
181#[repr(C)]
182#[derive(Debug)]
183#[cfg_attr(feature = "defmt", derive(defmt::Format))]
184pub struct DpsConfirm {
185 /// The status of the DPS request
186 pub status: MacStatus,
187 /// byte stuffing to keep 32 bit alignment
188 a_stuffing: [u8; 3],
189}
190
191impl ParseableMacEvent for DpsConfirm {}
192
193/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
194/// channel sounding information
195#[repr(C)]
196#[derive(Debug)]
197#[cfg_attr(feature = "defmt", derive(defmt::Format))]
198pub struct SoundingConfirm {
199 /// Results of the sounding measurement
200 pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
201
202 status: u8,
203}
204
205impl ParseableMacEvent for SoundingConfirm {}
206
207/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
208/// to provide internal propagation path information
209#[repr(C)]
210#[derive(Debug)]
211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
212pub struct CalibrateConfirm {
213 /// The status of the attempt to return sounding data
214 pub status: MacStatus,
215 /// byte stuffing to keep 32 bit alignment
216 a_stuffing: [u8; 3],
217 /// A count of the propagation time from the ranging counter
218 /// to the transmit antenna
219 pub cal_tx_rmaker_offset: u32,
220 /// A count of the propagation time from the receive antenna
221 /// to the ranging counter
222 pub cal_rx_rmaker_offset: u32,
223}
224
225impl ParseableMacEvent for CalibrateConfirm {}
226
227/// MCPS DATA Confirm which will be used for reporting the results of
228/// MAC data related requests from the application
229#[repr(C)]
230#[derive(Debug)]
231#[cfg_attr(feature = "defmt", derive(defmt::Format))]
232pub struct DataConfirm {
233 /// The handle associated with the MSDU being confirmed
234 pub msdu_handle: u8,
235 /// The time, in symbols, at which the data were transmitted
236 pub time_stamp: [u8; 4],
237 /// ranging status
238 pub ranging_received: u8,
239 /// The status of the last MSDU transmission
240 pub status: MacStatus,
241 /// time units corresponding to an RMARKER at the antenna at
242 /// the beginning of a ranging exchange
243 pub ranging_counter_start: u32,
244 /// time units corresponding to an RMARKER at the antenna
245 /// at the end of a ranging exchange
246 pub ranging_counter_stop: u32,
247 /// time units in a message exchange over which the tracking offset was measured
248 pub ranging_tracking_interval: u32,
249 /// time units slipped or advanced by the radio tracking system
250 pub ranging_offset: u32,
251 /// The FoM characterizing the ranging measurement
252 pub ranging_fom: u8,
253 /// byte stuffing to keep 32 bit alignment
254 a_stuffing: [u8; 3],
255}
256
257impl ParseableMacEvent for DataConfirm {}
258
259/// MCPS PURGE Confirm which will be used by the MAC to notify the application of
260/// the status of its request to purge an MSDU from the transaction queue
261#[repr(C)]
262#[derive(Debug)]
263#[cfg_attr(feature = "defmt", derive(defmt::Format))]
264pub struct PurgeConfirm {
265 /// Handle associated with the MSDU requested to be purged from the transaction queue
266 pub msdu_handle: u8,
267 /// The status of the request
268 pub status: MacStatus,
269 /// byte stuffing to keep 32 bit alignment
270 a_stuffing: [u8; 2],
271}
272
273impl ParseableMacEvent for PurgeConfirm {}
diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs
deleted file mode 100644
index d3099b6b7..000000000
--- a/embassy-stm32-wpan/src/mac/runner.rs
+++ /dev/null
@@ -1,109 +0,0 @@
1use core::cell::RefCell;
2
3use embassy_futures::join;
4use embassy_sync::blocking_mutex;
5use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
6use embassy_sync::channel::Channel;
7use embassy_sync::mutex::Mutex;
8use embassy_sync::signal::Signal;
9
10use crate::mac::commands::DataRequest;
11use crate::mac::event::MacEvent;
12use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel};
13use crate::mac::MTU;
14use crate::sub::mac::Mac;
15
16type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>;
17
18pub struct Runner<'a> {
19 pub(crate) mac_subsystem: Mac,
20 // rx event backpressure is already provided through the MacEvent drop mechanism
21 // therefore, we don't need to worry about overwriting events
22 pub(crate) rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
23 pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>,
24 pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>,
25 pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
26 pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>,
27 pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>,
28}
29
30impl<'a> Runner<'a> {
31 pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self {
32 let this = Self {
33 mac_subsystem: mac,
34 rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)),
35 read_mutex: Mutex::new(()),
36 write_mutex: Mutex::new(()),
37 rx_channel: Channel::new(),
38 tx_channel: Channel::new(),
39 tx_buf_channel: Channel::new(),
40 };
41
42 for buf in tx_buf_queue {
43 this.tx_buf_channel.try_send(buf).unwrap();
44 }
45
46 this
47 }
48
49 pub async fn run(&'a self) -> ! {
50 join::join(
51 async {
52 loop {
53 if let Ok(mac_event) = self.mac_subsystem.read().await {
54 match mac_event {
55 MacEvent::McpsDataInd(_) => {
56 self.rx_channel.send(mac_event).await;
57 }
58 _ => {
59 self.rx_event_channel.lock(|s| {
60 match &*s.borrow() {
61 Some(signal) => {
62 signal.signal(mac_event);
63 }
64 None => {}
65 };
66 });
67 }
68 }
69 }
70 }
71 },
72 async {
73 let mut msdu_handle = 0x02;
74
75 loop {
76 let (buf, len) = self.tx_channel.receive().await;
77 let _wm = self.write_mutex.lock().await;
78
79 // The mutex should be dropped on the next loop iteration
80 self.mac_subsystem
81 .send_command(
82 DataRequest {
83 src_addr_mode: AddressMode::Short,
84 dst_addr_mode: AddressMode::Short,
85 dst_pan_id: PanId([0x1A, 0xAA]),
86 dst_address: MacAddress::BROADCAST,
87 msdu_handle: msdu_handle,
88 ack_tx: 0x00,
89 gts_tx: false,
90 security_level: SecurityLevel::Unsecure,
91 ..Default::default()
92 }
93 .set_buffer(&buf[..len]),
94 )
95 .await
96 .unwrap();
97
98 msdu_handle = msdu_handle.wrapping_add(1);
99
100 // The tx channel should always be of equal capacity to the tx_buf channel
101 self.tx_buf_channel.try_send(buf).unwrap();
102 }
103 },
104 )
105 .await;
106
107 loop {}
108 }
109}
diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs
deleted file mode 100644
index 0552b8ea1..000000000
--- a/embassy-stm32-wpan/src/mac/typedefs.rs
+++ /dev/null
@@ -1,381 +0,0 @@
1use core::fmt::Debug;
2
3use crate::numeric_enum;
4
5#[derive(Debug)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub enum MacError {
8 Error = 0x01,
9 NotImplemented = 0x02,
10 NotSupported = 0x03,
11 HardwareNotSupported = 0x04,
12 Undefined = 0x05,
13}
14
15impl From<u8> for MacError {
16 fn from(value: u8) -> Self {
17 match value {
18 0x01 => Self::Error,
19 0x02 => Self::NotImplemented,
20 0x03 => Self::NotSupported,
21 0x04 => Self::HardwareNotSupported,
22 0x05 => Self::Undefined,
23 _ => Self::Undefined,
24 }
25 }
26}
27
28numeric_enum! {
29 #[repr(u8)]
30 #[derive(Debug, Default)]
31 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
32 pub enum MacStatus {
33 #[default]
34 Success = 0x00,
35 Failure = 0xFF
36 }
37}
38
39numeric_enum! {
40 #[repr(u8)]
41 /// this enum contains all the MAC PIB Ids
42 #[derive(Default, Debug)]
43 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
44 pub enum PibId {
45 // PHY
46 #[default]
47 CurrentChannel = 0x00,
48 ChannelsSupported = 0x01,
49 TransmitPower = 0x02,
50 CCAMode = 0x03,
51 CurrentPage = 0x04,
52 MaxFrameDuration = 0x05,
53 SHRDuration = 0x06,
54 SymbolsPerOctet = 0x07,
55
56 // MAC
57 AckWaitDuration = 0x40,
58 AssociationPermit = 0x41,
59 AutoRequest = 0x42,
60 BeaconPayload = 0x45,
61 BeaconPayloadLength = 0x46,
62 BeaconOrder = 0x47,
63 Bsn = 0x49,
64 CoordExtendedAdddress = 0x4A,
65 CoordShortAddress = 0x4B,
66 Dsn = 0x4C,
67 MaxFrameTotalWaitTime = 0x58,
68 MaxFrameRetries = 0x59,
69 PanId = 0x50,
70 ResponseWaitTime = 0x5A,
71 RxOnWhenIdle = 0x52,
72 SecurityEnabled = 0x5D,
73 ShortAddress = 0x53,
74 SuperframeOrder = 0x54,
75 TimestampSupported = 0x5C,
76 TransactionPersistenceTime = 0x55,
77 MaxBe = 0x57,
78 LifsPeriod = 0x5E,
79 SifsPeriod = 0x5F,
80 MaxCsmaBackoffs = 0x4E,
81 MinBe = 0x4F,
82 PanCoordinator = 0x10,
83 AssocPanCoordinator = 0x11,
84 ExtendedAddress = 0x6F,
85 AclEntryDescriptor = 0x70,
86 AclEntryDescriptorSize = 0x71,
87 DefaultSecurity = 0x72,
88 DefaultSecurityMaterialLength = 0x73,
89 DefaultSecurityMaterial = 0x74,
90 DefaultSecuritySuite = 0x75,
91 SecurityMode = 0x76,
92 CurrentAclEntries = 0x80,
93 DefaultSecurityExtendedAddress = 0x81,
94 AssociatedPanCoordinator = 0x56,
95 PromiscuousMode = 0x51,
96 }
97}
98
99numeric_enum! {
100 #[repr(u8)]
101 #[derive(Default, Clone, Copy, Debug)]
102 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
103 pub enum AddressMode {
104 #[default]
105 NoAddress = 0x00,
106 Reserved = 0x01,
107 Short = 0x02,
108 Extended = 0x03,
109}
110}
111
112#[derive(Clone, Copy)]
113pub union MacAddress {
114 pub short: [u8; 2],
115 pub extended: [u8; 8],
116}
117
118impl Debug for MacAddress {
119 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 unsafe {
121 write!(
122 fmt,
123 "MacAddress {{ short: {:?}, extended: {:?} }}",
124 self.short, self.extended
125 )
126 }
127 }
128}
129
130#[cfg(feature = "defmt")]
131impl defmt::Format for MacAddress {
132 fn format(&self, fmt: defmt::Formatter) {
133 unsafe {
134 defmt::write!(
135 fmt,
136 "MacAddress {{ short: {}, extended: {} }}",
137 self.short,
138 self.extended
139 )
140 }
141 }
142}
143
144impl Default for MacAddress {
145 fn default() -> Self {
146 Self { short: [0, 0] }
147 }
148}
149
150impl MacAddress {
151 pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] };
152}
153
154impl TryFrom<&[u8]> for MacAddress {
155 type Error = ();
156
157 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
158 const SIZE: usize = 8;
159 if buf.len() < SIZE {
160 return Err(());
161 }
162
163 Ok(Self {
164 extended: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]],
165 })
166 }
167}
168
169#[cfg_attr(feature = "defmt", derive(defmt::Format))]
170pub struct GtsCharacteristics {
171 pub fields: u8,
172}
173
174/// MAC PAN Descriptor which contains the network details of the device from
175/// which the beacon is received
176#[derive(Default, Clone, Copy, Debug)]
177#[cfg_attr(feature = "defmt", derive(defmt::Format))]
178pub struct PanDescriptor {
179 /// PAN identifier of the coordinator
180 pub coord_pan_id: PanId,
181 /// Coordinator addressing mode
182 pub coord_addr_mode: AddressMode,
183 /// The current logical channel occupied by the network
184 pub logical_channel: MacChannel,
185 /// Coordinator address
186 pub coord_addr: MacAddress,
187 /// The current channel page occupied by the network
188 pub channel_page: u8,
189 /// PAN coordinator is accepting GTS requests or not
190 pub gts_permit: bool,
191 /// Superframe specification as specified in the received beacon frame
192 pub superframe_spec: [u8; 2],
193 /// The time at which the beacon frame was received, in symbols
194 pub time_stamp: [u8; 4],
195 /// The LQI at which the network beacon was received
196 pub link_quality: u8,
197 /// Security level purportedly used by the received beacon frame
198 pub security_level: u8,
199}
200
201impl TryFrom<&[u8]> for PanDescriptor {
202 type Error = ();
203
204 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
205 const SIZE: usize = 22;
206 if buf.len() < SIZE {
207 return Err(());
208 }
209
210 let coord_addr_mode = AddressMode::try_from(buf[2])?;
211 let coord_addr = match coord_addr_mode {
212 AddressMode::NoAddress => MacAddress { short: [0, 0] },
213 AddressMode::Reserved => MacAddress { short: [0, 0] },
214 AddressMode::Short => MacAddress {
215 short: [buf[4], buf[5]],
216 },
217 AddressMode::Extended => MacAddress {
218 extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]],
219 },
220 };
221
222 Ok(Self {
223 coord_pan_id: PanId([buf[0], buf[1]]),
224 coord_addr_mode,
225 logical_channel: MacChannel::try_from(buf[3])?,
226 coord_addr,
227 channel_page: buf[12],
228 gts_permit: buf[13] != 0,
229 superframe_spec: [buf[14], buf[15]],
230 time_stamp: [buf[16], buf[17], buf[18], buf[19]],
231 link_quality: buf[20],
232 security_level: buf[21],
233 // 2 byte stuffing
234 })
235 }
236}
237
238numeric_enum! {
239 #[repr(u8)]
240 #[derive(Default, Clone, Copy, Debug)]
241 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
242 /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3
243 pub enum MacChannel {
244 Channel11 = 0x0B,
245 Channel12 = 0x0C,
246 Channel13 = 0x0D,
247 Channel14 = 0x0E,
248 Channel15 = 0x0F,
249 #[default]
250 Channel16 = 0x10,
251 Channel17 = 0x11,
252 Channel18 = 0x12,
253 Channel19 = 0x13,
254 Channel20 = 0x14,
255 Channel21 = 0x15,
256 Channel22 = 0x16,
257 Channel23 = 0x17,
258 Channel24 = 0x18,
259 Channel25 = 0x19,
260 Channel26 = 0x1A,
261 }
262}
263
264#[cfg(not(feature = "defmt"))]
265bitflags::bitflags! {
266 pub struct Capabilities: u8 {
267 /// 1 if the device is capabaleof becoming a PAN coordinator
268 const IS_COORDINATOR_CAPABLE = 0b00000001;
269 /// 1 if the device is an FFD, 0 if it is an RFD
270 const IS_FFD = 0b00000010;
271 /// 1 if the device is receiving power from mains, 0 if it is battery-powered
272 const IS_MAINS_POWERED = 0b00000100;
273 /// 1 if the device does not disable its receiver to conserver power during idle periods
274 const RECEIVER_ON_WHEN_IDLE = 0b00001000;
275 // 0b00010000 reserved
276 // 0b00100000 reserved
277 /// 1 if the device is capable of sending and receiving secured MAC frames
278 const IS_SECURE = 0b01000000;
279 /// 1 if the device wishes the coordinator to allocate a short address as a result of the association
280 const ALLOCATE_ADDRESS = 0b10000000;
281 }
282}
283
284#[cfg(feature = "defmt")]
285defmt::bitflags! {
286 pub struct Capabilities: u8 {
287 /// 1 if the device is capabaleof becoming a PAN coordinator
288 const IS_COORDINATOR_CAPABLE = 0b00000001;
289 /// 1 if the device is an FFD, 0 if it is an RFD
290 const IS_FFD = 0b00000010;
291 /// 1 if the device is receiving power from mains, 0 if it is battery-powered
292 const IS_MAINS_POWERED = 0b00000100;
293 /// 1 if the device does not disable its receiver to conserver power during idle periods
294 const RECEIVER_ON_WHEN_IDLE = 0b00001000;
295 // 0b00010000 reserved
296 // 0b00100000 reserved
297 /// 1 if the device is capable of sending and receiving secured MAC frames
298 const IS_SECURE = 0b01000000;
299 /// 1 if the device wishes the coordinator to allocate a short address as a result of the association
300 const ALLOCATE_ADDRESS = 0b10000000;
301 }
302}
303
304numeric_enum! {
305 #[repr(u8)]
306 #[derive(Default, Clone, Copy, Debug)]
307 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
308 pub enum KeyIdMode {
309 #[default]
310 /// the key is determined implicitly from the originator and recipient(s) of the frame
311 Implicite = 0x00,
312 /// the key is determined explicitly using a 1 bytes key source and a 1 byte key index
313 Explicite1Byte = 0x01,
314 /// the key is determined explicitly using a 4 bytes key source and a 1 byte key index
315 Explicite4Byte = 0x02,
316 /// the key is determined explicitly using a 8 bytes key source and a 1 byte key index
317 Explicite8Byte = 0x03,
318 }
319}
320
321numeric_enum! {
322 #[repr(u8)]
323 #[derive(Debug)]
324 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
325 pub enum AssociationStatus {
326 /// Association successful
327 Success = 0x00,
328 /// PAN at capacity
329 PanAtCapacity = 0x01,
330 /// PAN access denied
331 PanAccessDenied = 0x02
332 }
333}
334
335numeric_enum! {
336 #[repr(u8)]
337 #[derive(Clone, Copy, Debug)]
338 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
339 pub enum DisassociationReason {
340 /// The coordinator wishes the device to leave the PAN.
341 CoordRequested = 0x01,
342 /// The device wishes to leave the PAN.
343 DeviceRequested = 0x02,
344 }
345}
346
347numeric_enum! {
348 #[repr(u8)]
349 #[derive(Default, Clone, Copy, Debug)]
350 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
351 pub enum SecurityLevel {
352 /// MAC Unsecured Mode Security
353 #[default]
354 Unsecure = 0x00,
355 /// MAC ACL Mode Security
356 AclMode = 0x01,
357 /// MAC Secured Mode Security
358 Secured = 0x02,
359 }
360}
361
362numeric_enum! {
363 #[repr(u8)]
364 #[derive(Debug)]
365 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
366 pub enum ScanType {
367 EdScan = 0x00,
368 Active = 0x01,
369 Passive = 0x02,
370 Orphan = 0x03
371 }
372}
373
374/// newtype for Pan Id
375#[derive(Default, Clone, Copy, Debug)]
376#[cfg_attr(feature = "defmt", derive(defmt::Format))]
377pub struct PanId(pub [u8; 2]);
378
379impl PanId {
380 pub const BROADCAST: Self = Self([0xFF, 0xFF]);
381}