xref: /aosp_15_r20/external/openthread/src/core/mac/sub_mac.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1 /*
2  *  Copyright (c) 2016-2018, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the IEEE 802.15.4 MAC layer (sub-MAC).
32  */
33 
34 #ifndef SUB_MAC_HPP_
35 #define SUB_MAC_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/link.h>
40 
41 #include <openthread/platform/crypto.h>
42 
43 #include "common/callback.hpp"
44 #include "common/locator.hpp"
45 #include "common/non_copyable.hpp"
46 #include "common/timer.hpp"
47 #include "mac/mac_frame.hpp"
48 #include "radio/radio.hpp"
49 
50 namespace ot {
51 
52 /**
53  * @addtogroup core-mac
54  *
55  * @brief
56  *   This module includes definitions for the IEEE 802.15.4 MAC (sub-MAC).
57  *
58  * @{
59  *
60  */
61 
62 namespace Mac {
63 
64 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
65 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE."
66 #endif
67 
68 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
69 
70 #if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
71 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE."
72 #endif
73 
74 #if !OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
75 #error "Microsecond timer OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE is required for "\
76     "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE"
77 #endif
78 
79 #endif
80 
81 #if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE && !OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
82 #error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE."
83 #endif
84 
85 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
86 class LinkRaw;
87 #endif
88 
89 /**
90  * Implements the IEEE 802.15.4 MAC (sub-MAC).
91  *
92  * Sub-MAC layer implements a subset of IEEE802.15.4 MAC primitives which are shared by both MAC layer (in FTD/MTD
93  * modes) and Raw Link (Radio only mode).
94 
95  * The sub-MAC layer handles the following (if not provided by radio platform):
96  *
97  *    - Ack timeout for frame transmission,
98  *    - CSMA backoff logic,
99  *    - Frame re-transmissions,
100  *    - Energy scan on a single channel and RSSI sampling.
101  *
102  * It also act as the interface (to radio platform) for setting/getting radio configurations such as short or extended
103  * addresses and PAN Id.
104  *
105  */
106 class SubMac : public InstanceLocator, private NonCopyable
107 {
108     friend class Radio::Callbacks;
109     friend class LinkRaw;
110 
111 public:
112     /**
113      * Defines the callbacks notifying `SubMac` user of changes and events.
114      *
115      */
116     class Callbacks : public InstanceLocator
117     {
118     public:
119         /**
120          * Initializes the `Callbacks` object.
121          *
122          * @param[in]  aInstance  A reference to the OpenThread instance.
123          *
124          */
125         explicit Callbacks(Instance &aInstance);
126 
127         /**
128          * Notifies user of `SubMac` of a received frame.
129          *
130          * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
131          * @param[in]  aError    kErrorNone when successfully received a frame,
132          *                       kErrorAbort when reception was aborted and a frame was not received,
133          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
134          *
135          */
136         void ReceiveDone(RxFrame *aFrame, Error aError);
137 
138         /**
139          * Notifies user of `SubMac` of CCA status (success/failure) for a frame transmission attempt.
140          *
141          * This is intended for updating counters, logging, and/or tracking CCA failure rate statistics.
142          *
143          * @param[in] aCcaSuccess   TRUE if the CCA succeeded, FALSE otherwise.
144          * @param[in] aChannel      The channel on which CCA was performed.
145          *
146          */
147         void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel);
148 
149         /**
150          * Notifies user of `SubMac` of the status of a frame transmission attempt.
151          *
152          * This is intended for updating counters, logging, and/or collecting statistics.
153          *
154          * @note Unlike `TransmitDone` which is invoked after all re-transmission attempts to indicate the final status
155          * of a frame transmission, this method is invoked on all frame transmission attempts.
156          *
157          * @param[in] aFrame      The transmitted frame.
158          * @param[in] aError      kErrorNone when the frame was transmitted successfully,
159          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
160          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
161          *                        kErrorAbort when transmission was aborted for other reasons.
162          * @param[in] aRetryCount Current retry count. This is valid only when sub-mac handles frame re-transmissions.
163          * @param[in] aWillRetx   Indicates whether frame will be retransmitted or not. This is applicable only
164          *                        when there was an error in current transmission attempt.
165          *
166          */
167         void RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx);
168 
169         /**
170          * The method notifies user of `SubMac` that the transmit operation has completed, providing, if applicable,
171          * the received ACK frame.
172          *
173          * @param[in]  aFrame     The transmitted frame.
174          * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
175          * @param[in]  aError     kErrorNone when the frame was transmitted,
176          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
177          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
178          *                        kErrorAbort when transmission was aborted for other reasons.
179          *
180          */
181         void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
182 
183         /**
184          * Notifies user of `SubMac` that energy scan is complete.
185          *
186          * @param[in]  aMaxRssi  Maximum RSSI seen on the channel, or `Radio::kInvalidRssi` if failed.
187          *
188          */
189         void EnergyScanDone(int8_t aMaxRssi);
190 
191         /**
192          * Notifies user of `SubMac` that a specific MAC frame counter is used for transmission.
193          *
194          * It is possible that this callback is invoked out of order in terms of counter values (i.e., called for a
195          * smaller counter value after a call for a larger counter value).
196          *
197          * @param[in]  aFrameCounter  The MAC frame counter value which was used.
198          *
199          */
200         void FrameCounterUsed(uint32_t aFrameCounter);
201     };
202 
203     /**
204      * Initializes the `SubMac` object.
205      *
206      * @param[in]  aInstance  A reference to the OpenThread instance.
207      *
208      */
209     explicit SubMac(Instance &aInstance);
210 
211     /**
212      * Gets the capabilities provided by platform radio.
213      *
214      * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
215      *
216      */
GetRadioCaps(void) const217     otRadioCaps GetRadioCaps(void) const { return mRadioCaps; }
218 
219     /**
220      * Gets the capabilities provided by `SubMac` layer.
221      *
222      * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
223      *
224      */
225     otRadioCaps GetCaps(void) const;
226 
227     /**
228      * Sets the PAN ID.
229      *
230      * @param[in] aPanId  The PAN ID.
231      *
232      */
233     void SetPanId(PanId aPanId);
234 
235     /**
236      * Gets the short address.
237      *
238      * @returns The short address.
239      *
240      */
GetShortAddress(void) const241     ShortAddress GetShortAddress(void) const { return mShortAddress; }
242 
243     /**
244      * Sets the short address.
245      *
246      * @param[in] aShortAddress   The short address.
247      *
248      */
249     void SetShortAddress(ShortAddress aShortAddress);
250 
251     /**
252      * Gets the extended address.
253      *
254      * @returns A reference to the extended address.
255      *
256      */
GetExtAddress(void) const257     const ExtAddress &GetExtAddress(void) const { return mExtAddress; }
258 
259     /**
260      * Sets extended address.
261      *
262      * @param[in] aExtAddress  The extended address.
263      *
264      */
265     void SetExtAddress(const ExtAddress &aExtAddress);
266 
267     /**
268      * Registers a callback to provide received packet capture for IEEE 802.15.4 frames.
269      *
270      * @param[in]  aPcapCallback     A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
271      *                               or `nullptr` to disable the callback.
272      * @param[in]  aCallbackContext  A pointer to application-specific context.
273      *
274      */
SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)275     void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext)
276     {
277         mPcapCallback.Set(aPcapCallback, aCallbackContext);
278     }
279 
280     /**
281      * Indicates whether radio should stay in Receive or Sleep during idle periods.
282      *
283      * @param[in]  aRxOnWhenIdle  TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods.
284      *
285      */
286     void SetRxOnWhenIdle(bool aRxOnWhenIdle);
287 
288     /**
289      * Enables the radio.
290      *
291      * @retval kErrorNone     Successfully enabled.
292      * @retval kErrorFailed   The radio could not be enabled.
293      *
294      */
295     Error Enable(void);
296 
297     /**
298      * Disables the radio.
299      *
300      * @retval kErrorNone     Successfully disabled the radio.
301      *
302      */
303     Error Disable(void);
304 
305     /**
306      * Transitions the radio to Sleep.
307      *
308      * @retval kErrorNone          Successfully transitioned to Sleep.
309      * @retval kErrorBusy          The radio was transmitting.
310      * @retval kErrorInvalidState  The radio was disabled.
311      *
312      */
313     Error Sleep(void);
314 
315     /**
316      * Indicates whether the sub-mac is busy transmitting or scanning.
317      *
318      * @retval TRUE if the sub-mac is busy transmitting or scanning.
319      * @retval FALSE if the sub-mac is not busy transmitting or scanning.
320      *
321      */
IsTransmittingOrScanning(void) const322     bool IsTransmittingOrScanning(void) const { return (mState == kStateTransmit) || (mState == kStateEnergyScan); }
323 
324     /**
325      * Transitions the radio to Receive.
326      *
327      * @param[in]  aChannel   The channel to use for receiving.
328      *
329      * @retval kErrorNone          Successfully transitioned to Receive.
330      * @retval kErrorInvalidState  The radio was disabled or transmitting.
331      *
332      */
333     Error Receive(uint8_t aChannel);
334 
335     /**
336      * Gets the radio transmit frame.
337      *
338      * @returns The transmit frame.
339      *
340      */
GetTransmitFrame(void)341     TxFrame &GetTransmitFrame(void) { return mTransmitFrame; }
342 
343     /**
344      * Sends a prepared frame.
345      *
346      * The frame should be placed in `GetTransmitFrame()` frame.
347      *
348      * The `SubMac` layer handles Ack timeout, CSMA backoff, and frame retransmission.
349      *
350      * @retval kErrorNone          Successfully started the frame transmission
351      * @retval kErrorInvalidState  The radio was disabled or transmitting.
352      *
353      */
354     Error Send(void);
355 
356     /**
357      * Gets the number of transmit retries of last transmitted frame.
358      *
359      * @returns Number of transmit retries.
360      *
361      */
GetTransmitRetries(void) const362     uint8_t GetTransmitRetries(void) const { return mTransmitRetries; }
363 
364     /**
365      * Gets the most recent RSSI measurement.
366      *
367      * @returns The RSSI in dBm when it is valid. `Radio::kInvalidRssi` when RSSI is invalid.
368      *
369      */
370     int8_t GetRssi(void) const;
371 
372     /**
373      * Begins energy scan.
374      *
375      * @param[in] aScanChannel   The channel to perform the energy scan on.
376      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
377      *
378      * @retval kErrorNone            Successfully started scanning the channel.
379      * @retval kErrorBusy            The radio is performing energy scanning.
380      * @retval kErrorInvalidState    The radio was disabled or transmitting.
381      * @retval kErrorNotImplemented  Energy scan is not supported (applicable in link-raw/radio mode only).
382      *
383      */
384     Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
385 
386     /**
387      * Returns the noise floor value (currently use the radio receive sensitivity value).
388      *
389      * @returns The noise floor value in dBm.
390      *
391      */
392     int8_t GetNoiseFloor(void) const;
393 
394 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
395     /**
396      * Configures CSL parameters in 'SubMac'.
397      *
398      * @param[in]  aPeriod    The CSL period (in unit of 10 symbols).
399      * @param[in]  aChannel   The CSL channel.
400      * @param[in]  aShortAddr The short source address of CSL receiver's peer.
401      * @param[in]  aExtAddr   The extended source address of CSL receiver's peer.
402      *
403      * @retval  TRUE if CSL Period or CSL Channel changed.
404      * @retval  FALSE if CSL Period and CSL Channel did not change.
405      *
406      */
407     bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr);
408 
409     /**
410      * Lets `SubMac` start CSL sample mode given a configured non-zero CSL period.
411      *
412      * `SubMac` would switch the radio state between `Receive` and `Sleep` according the CSL timer.
413      *
414      */
415     void CslSample(void);
416 
417     /**
418      * Returns parent CSL accuracy (clock accuracy and uncertainty).
419      *
420      * @returns The parent CSL accuracy.
421      *
422      */
GetCslParentAccuracy(void) const423     const CslAccuracy &GetCslParentAccuracy(void) const { return mCslParentAccuracy; }
424 
425     /**
426      * Sets parent CSL accuracy.
427      *
428      * @param[in] aCslAccuracy  The parent CSL accuracy.
429      *
430      */
SetCslParentAccuracy(const CslAccuracy & aCslAccuracy)431     void SetCslParentAccuracy(const CslAccuracy &aCslAccuracy) { mCslParentAccuracy = aCslAccuracy; }
432 
433 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
434 
435     /**
436      * Sets MAC keys and key index.
437      *
438      * @param[in] aKeyIdMode  MAC key ID mode.
439      * @param[in] aKeyId      The key ID.
440      * @param[in] aPrevKey    The previous MAC key.
441      * @param[in] aCurrKey    The current MAC key.
442      * @param[in] aNextKey    The next MAC key.
443      *
444      */
445     void SetMacKey(uint8_t            aKeyIdMode,
446                    uint8_t            aKeyId,
447                    const KeyMaterial &aPrevKey,
448                    const KeyMaterial &aCurrKey,
449                    const KeyMaterial &aNextKey);
450 
451     /**
452      * Returns a reference to the current MAC key.
453      *
454      * @returns A reference to the current MAC key.
455      *
456      */
GetCurrentMacKey(void) const457     const KeyMaterial &GetCurrentMacKey(void) const { return mCurrKey; }
458 
459     /**
460      * Returns a reference to the previous MAC key.
461      *
462      * @returns A reference to the previous MAC key.
463      *
464      */
GetPreviousMacKey(void) const465     const KeyMaterial &GetPreviousMacKey(void) const { return mPrevKey; }
466 
467     /**
468      * Returns a reference to the next MAC key.
469      *
470      * @returns A reference to the next MAC key.
471      *
472      */
GetNextMacKey(void) const473     const KeyMaterial &GetNextMacKey(void) const { return mNextKey; }
474 
475     /**
476      * Clears the stored MAC keys.
477      *
478      */
ClearMacKeys(void)479     void ClearMacKeys(void)
480     {
481         mPrevKey.Clear();
482         mCurrKey.Clear();
483         mNextKey.Clear();
484     }
485 
486     /**
487      * Returns the current MAC frame counter value.
488      *
489      * @returns The current MAC frame counter value.
490      *
491      */
GetFrameCounter(void) const492     uint32_t GetFrameCounter(void) const { return mFrameCounter; }
493 
494     /**
495      * Sets the current MAC Frame Counter value.
496      *
497      * @param[in] aFrameCounter  The MAC Frame Counter value.
498      * @param[in] aSetIfLarger   If `true`, set only if the new value @p aFrameCounter is larger than the current value.
499      *                           If `false`, set the new value independent of the current value.
500      *
501      */
502     void SetFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger);
503 
504 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
505     /**
506      * Enables/disables the radio filter.
507      *
508      * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
509      * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
510      * frame over the air (return "no ack" error if ack is requested, otherwise return success).
511      *
512      * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable.
513      *
514      */
SetRadioFilterEnabled(bool aFilterEnabled)515     void SetRadioFilterEnabled(bool aFilterEnabled) { mRadioFilterEnabled = aFilterEnabled; }
516 
517     /**
518      * Indicates whether the radio filter is enabled or not.
519      *
520      * @retval TRUE   If the radio filter is enabled.
521      * @retval FALSE  If the radio filter is disabled.
522      *
523      */
IsRadioFilterEnabled(void) const524     bool IsRadioFilterEnabled(void) const { return mRadioFilterEnabled; }
525 #endif
526 
527 private:
528 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
529     void        CslInit(void);
530     void        UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame);
531     void        UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError);
532     static void HandleCslTimer(Timer &aTimer);
533     void        HandleCslTimer(void);
534     void        GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter);
535     uint32_t    GetLocalTime(void);
536 #if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
537     void LogReceived(RxFrame *aFrame);
538 #endif
539 #endif
540 
541     static constexpr uint8_t  kCsmaMinBe         = 3;                  // macMinBE (IEEE 802.15.4-2006).
542     static constexpr uint8_t  kCsmaMaxBe         = 5;                  // macMaxBE (IEEE 802.15.4-2006).
543     static constexpr uint32_t kUnitBackoffPeriod = 20;                 // Number of symbols (IEEE 802.15.4-2006).
544     static constexpr uint32_t kAckTimeout = 16 * Time::kOneMsecInUsec; // Timeout for waiting on an ACK (in usec).
545     static constexpr uint32_t kCcaSampleInterval = 128;                // CCA sample interval, 128 usec.
546 
547 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
548     static constexpr uint8_t kRetxDelayMinBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT;
549     static constexpr uint8_t kRetxDelayMaxBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT;
550 #endif
551 
552 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
553     static constexpr uint32_t kEnergyScanRssiSampleInterval = 128; // RSSI sample interval for energy scan, in usec
554 #else
555     static constexpr uint32_t kEnergyScanRssiSampleInterval = 1000; // RSSI sample interval for energy scan, in usec
556 #endif
557 
558     enum State : uint8_t
559     {
560         kStateDisabled,    // Radio is disabled.
561         kStateSleep,       // Radio is in sleep.
562         kStateReceive,     // Radio in in receive.
563         kStateCsmaBackoff, // CSMA backoff before transmission.
564         kStateTransmit,    // Radio is transmitting.
565         kStateEnergyScan,  // Energy scan.
566 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
567         kStateDelayBeforeRetx, // Delay before retx
568 #endif
569 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
570         kStateCslTransmit, // CSL transmission.
571 #endif
572 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
573         kStateCslSample, // CSL receive.
574 #endif
575     };
576 
577 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
578     // Radio on times needed before and after MHR time for proper frame detection
579     static constexpr uint32_t kMinReceiveOnAhead = OPENTHREAD_CONFIG_MIN_RECEIVE_ON_AHEAD;
580     static constexpr uint32_t kMinReceiveOnAfter = OPENTHREAD_CONFIG_MIN_RECEIVE_ON_AFTER;
581 
582     // CSL receivers would wake up `kCslReceiveTimeAhead` earlier
583     // than expected sample window. The value is in usec.
584     static constexpr uint32_t kCslReceiveTimeAhead = OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD;
585 #endif
586 
587 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
588     // CSL transmitter would schedule delayed transmission `kCslTransmitTimeAhead` earlier
589     // than expected delayed transmit time. The value is in usec.
590     // Only for radios not supporting OT_RADIO_CAPS_TRANSMIT_TIMING.
591     static constexpr uint32_t kCslTransmitTimeAhead = OPENTHREAD_CONFIG_CSL_TRANSMIT_TIME_AHEAD;
592 #endif
593 
594     /**
595      * Initializes the states of the sub-MAC layer.
596      *
597      */
598     void Init(void);
599 
RadioSupportsCsmaBackoff(void) const600     bool RadioSupportsCsmaBackoff(void) const
601     {
602         return ((mRadioCaps & (OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES)) != 0);
603     }
604 
RadioSupportsTransmitSecurity(void) const605     bool RadioSupportsTransmitSecurity(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) != 0); }
RadioSupportsRetries(void) const606     bool RadioSupportsRetries(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) != 0); }
RadioSupportsAckTimeout(void) const607     bool RadioSupportsAckTimeout(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) != 0); }
RadioSupportsEnergyScan(void) const608     bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); }
RadioSupportsTransmitTiming(void) const609     bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); }
RadioSupportsReceiveTiming(void) const610     bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); }
RadioSupportsRxOnWhenIdle(void) const611     bool RadioSupportsRxOnWhenIdle(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0); }
612 
613     bool ShouldHandleTransmitSecurity(void) const;
614     bool ShouldHandleCsmaBackOff(void) const;
615     bool ShouldHandleAckTimeout(void) const;
616     bool ShouldHandleRetries(void) const;
617     bool ShouldHandleEnergyScan(void) const;
618     bool ShouldHandleTransmitTargetTime(void) const;
619     bool ShouldHandleTransitionToSleep(void) const;
620 
621     void ProcessTransmitSecurity(void);
622     void SignalFrameCounterUsed(uint32_t aFrameCounter, uint8_t aKeyId);
623     void StartCsmaBackoff(void);
624     void StartTimerForBackoff(uint8_t aBackoffExponent);
625     void BeginTransmit(void);
626     void SampleRssi(void);
627     void StartTimer(uint32_t aDelayUs);
628     void StartTimerAt(Time aStartTime, uint32_t aDelayUs);
629 
630     void HandleReceiveDone(RxFrame *aFrame, Error aError);
631     void HandleTransmitStarted(TxFrame &aFrame);
632     void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
633     void SignalFrameCounterUsedOnTxDone(const TxFrame &aFrame);
634     void HandleEnergyScanDone(int8_t aMaxRssi);
635     void HandleTimer(void);
636 
637     void               SetState(State aState);
638     static const char *StateToString(State aState);
639 
640     using SubMacTimer =
641 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
642         TimerMicroIn<SubMac, &SubMac::HandleTimer>;
643 #else
644         TimerMilliIn<SubMac, &SubMac::HandleTimer>;
645 #endif
646 
647     otRadioCaps  mRadioCaps;
648     State        mState;
649     uint8_t      mCsmaBackoffs;
650     uint8_t      mTransmitRetries;
651     ShortAddress mShortAddress;
652     ExtAddress   mExtAddress;
653     bool         mRxOnWhenIdle : 1;
654 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
655     bool mRadioFilterEnabled : 1;
656 #endif
657     int8_t                       mEnergyScanMaxRssi;
658     TimeMilli                    mEnergyScanEndTime;
659     TxFrame                     &mTransmitFrame;
660     Callbacks                    mCallbacks;
661     Callback<otLinkPcapCallback> mPcapCallback;
662     KeyMaterial                  mPrevKey;
663     KeyMaterial                  mCurrKey;
664     KeyMaterial                  mNextKey;
665     uint32_t                     mFrameCounter;
666     uint8_t                      mKeyId;
667 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
668     uint8_t mRetxDelayBackOffExponent;
669 #endif
670     SubMacTimer mTimer;
671 
672 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
673     uint16_t mCslPeriod;            // The CSL sample period, in units of 10 symbols (160 microseconds).
674     uint8_t  mCslChannel : 7;       // The CSL sample channel.
675     bool     mIsCslSampling : 1;    // Indicates that the radio is receiving in CSL state for platforms not supporting
676                                     // delayed reception.
677     uint16_t    mCslPeerShort;      // The CSL peer short address.
678     TimeMicro   mCslSampleTime;     // The CSL sample time of the current period relative to the local radio clock.
679     TimeMicro   mCslLastSync;       // The timestamp of the last successful CSL synchronization.
680     CslAccuracy mCslParentAccuracy; // The parent's CSL accuracy (clock accuracy and uncertainty).
681     TimerMicro  mCslTimer;
682 #endif
683 };
684 
685 /**
686  * @}
687  *
688  */
689 
690 } // namespace Mac
691 } // namespace ot
692 
693 #endif // SUB_MAC_HPP_
694