• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/locator.hpp"
44 #include "common/non_copyable.hpp"
45 #include "common/timer.hpp"
46 #include "mac/mac_frame.hpp"
47 #include "radio/radio.hpp"
48 
49 namespace ot {
50 
51 /**
52  * @addtogroup core-mac
53  *
54  * @brief
55  *   This module includes definitions for the IEEE 802.15.4 MAC (sub-MAC).
56  *
57  * @{
58  *
59  */
60 
61 namespace Mac {
62 
63 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
64 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE."
65 #endif
66 
67 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
68 
69 #if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
70 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE."
71 #endif
72 
73 #if !OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
74 #error "Microsecond timer OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE is required for "\
75     "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE"
76 #endif
77 
78 #endif
79 
80 #if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE && !OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
81 #error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE."
82 #endif
83 
84 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
85 class LinkRaw;
86 #endif
87 
88 /**
89  * This class implements the IEEE 802.15.4 MAC (sub-MAC).
90  *
91  * Sub-MAC layer implements a subset of IEEE802.15.4 MAC primitives which are shared by both MAC layer (in FTD/MTD
92  * modes) and Raw Link (Radio only mode).
93 
94  * The sub-MAC layer handles the following (if not provided by radio platform):
95  *
96  *    - Ack timeout for frame transmission,
97  *    - CSMA backoff logic,
98  *    - Frame re-transmissions,
99  *    - Energy scan on a single channel and RSSI sampling.
100  *
101  * It also act as the interface (to radio platform) for setting/getting radio configurations such as short or extended
102  * addresses and PAN Id.
103  *
104  */
105 class SubMac : public InstanceLocator, private NonCopyable
106 {
107     friend class Radio::Callbacks;
108     friend class LinkRaw;
109 
110 public:
111     static constexpr int8_t kInvalidRssiValue = 127; ///< Invalid Received Signal Strength Indicator (RSSI) value.
112 
113     /**
114      * This class defines the callbacks notifying `SubMac` user of changes and events.
115      *
116      */
117     class Callbacks : public InstanceLocator
118     {
119     public:
120         /**
121          * This constructor initializes the `Callbacks` object.
122          *
123          * @param[in]  aInstance  A reference to the OpenThread instance.
124          *
125          */
126         explicit Callbacks(Instance &aInstance);
127 
128         /**
129          * This method notifies user of `SubMac` of a received frame.
130          *
131          * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
132          * @param[in]  aError    kErrorNone when successfully received a frame,
133          *                       kErrorAbort when reception was aborted and a frame was not received,
134          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
135          *
136          */
137         void ReceiveDone(RxFrame *aFrame, Error aError);
138 
139         /**
140          * This method notifies user of `SubMac` of CCA status (success/failure) for a frame transmission attempt.
141          *
142          * This is intended for updating counters, logging, and/or tracking CCA failure rate statistics.
143          *
144          * @param[in] aCcaSuccess   TRUE if the CCA succeeded, FALSE otherwise.
145          * @param[in] aChannel      The channel on which CCA was performed.
146          *
147          */
148         void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel);
149 
150         /**
151          * This method notifies user of `SubMac` of the status of a frame transmission attempt.
152          *
153          * This is intended for updating counters, logging, and/or collecting statistics.
154          *
155          * @note Unlike `TransmitDone` which is invoked after all re-transmission attempts to indicate the final status
156          * of a frame transmission, this method is invoked on all frame transmission attempts.
157          *
158          * @param[in] aFrame      The transmitted frame.
159          * @param[in] aAckFrame   A pointer to the ACK frame, or `nullptr` if no ACK was received.
160          * @param[in] aError      kErrorNone when the frame was transmitted successfully,
161          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
162          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
163          *                        kErrorAbort when transmission was aborted for other reasons.
164          * @param[in] aRetryCount Current retry count. This is valid only when sub-mac handles frame re-transmissions.
165          * @param[in] aWillRetx   Indicates whether frame will be retransmitted or not. This is applicable only
166          *                        when there was an error in current transmission attempt.
167          *
168          */
169         void RecordFrameTransmitStatus(const TxFrame &aFrame,
170                                        const RxFrame *aAckFrame,
171                                        Error          aError,
172                                        uint8_t        aRetryCount,
173                                        bool           aWillRetx);
174 
175         /**
176          * The method notifies user of `SubMac` that the transmit operation has completed, providing, if applicable,
177          * the received ACK frame.
178          *
179          * @param[in]  aFrame     The transmitted frame.
180          * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
181          * @param[in]  aError     kErrorNone when the frame was transmitted,
182          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
183          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
184          *                        kErrorAbort when transmission was aborted for other reasons.
185          *
186          */
187         void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
188 
189         /**
190          * This method notifies user of `SubMac` that energy scan is complete.
191          *
192          * @param[in]  aMaxRssi  Maximum RSSI seen on the channel, or `SubMac::kInvalidRssiValue` if failed.
193          *
194          */
195         void EnergyScanDone(int8_t aMaxRssi);
196 
197         /**
198          * This method notifies user of `SubMac` that a specific MAC frame counter is used for transmission.
199          *
200          * It is possible that this callback is invoked out of order in terms of counter values (i.e., called for a
201          * smaller counter value after a call for a larger counter value).
202          *
203          * @param[in]  aFrameCounter  The MAC frame counter value which was used.
204          *
205          */
206         void FrameCounterUsed(uint32_t aFrameCounter);
207     };
208 
209     /**
210      * This constructor initializes the `SubMac` object.
211      *
212      * @param[in]  aInstance  A reference to the OpenThread instance.
213      *
214      */
215     explicit SubMac(Instance &aInstance);
216 
217     /**
218      * This method gets the capabilities provided by platform radio.
219      *
220      * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
221      *
222      */
GetRadioCaps(void) const223     otRadioCaps GetRadioCaps(void) const { return mRadioCaps; }
224 
225     /**
226      * This method gets the capabilities provided by `SubMac` layer.
227      *
228      * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions).
229      *
230      */
231     otRadioCaps GetCaps(void) const;
232 
233     /**
234      * This method sets the PAN ID.
235      *
236      * @param[in] aPanId  The PAN ID.
237      *
238      */
239     void SetPanId(PanId aPanId);
240 
241     /**
242      * This method gets the short address.
243      *
244      * @returns The short address.
245      *
246      */
GetShortAddress(void) const247     ShortAddress GetShortAddress(void) const { return mShortAddress; }
248 
249     /**
250      * This method sets the short address.
251      *
252      * @param[in] aShortAddress   The short address.
253      *
254      */
255     void SetShortAddress(ShortAddress aShortAddress);
256 
257     /**
258      * This function gets the extended address.
259      *
260      * @returns A reference to the extended address.
261      *
262      */
GetExtAddress(void) const263     const ExtAddress &GetExtAddress(void) const { return mExtAddress; }
264 
265     /**
266      * This method sets extended address.
267      *
268      * @param[in] aExtAddress  The extended address.
269      *
270      */
271     void SetExtAddress(const ExtAddress &aExtAddress);
272 
273     /**
274      * This method registers a callback to provide received packet capture for IEEE 802.15.4 frames.
275      *
276      * @param[in]  aPcapCallback     A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
277      *                               or `nullptr` to disable the callback.
278      * @param[in]  aCallbackContext  A pointer to application-specific context.
279      *
280      */
281     void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext);
282 
283     /**
284      * This method indicates whether radio should stay in Receive or Sleep during CSMA backoff.
285      *
286      * @param[in]  aRxOnWhenBackoff  TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff.
287      *
288      */
SetRxOnWhenBackoff(bool aRxOnWhenBackoff)289     void SetRxOnWhenBackoff(bool aRxOnWhenBackoff) { mRxOnWhenBackoff = aRxOnWhenBackoff; }
290 
291     /**
292      * This method enables the radio.
293      *
294      * @retval kErrorNone     Successfully enabled.
295      * @retval kErrorFailed   The radio could not be enabled.
296      *
297      */
298     Error Enable(void);
299 
300     /**
301      * This method disables the radio.
302      *
303      * @retval kErrorNone     Successfully disabled the radio.
304      *
305      */
306     Error Disable(void);
307 
308     /**
309      * This method transitions the radio to Sleep.
310      *
311      * @retval kErrorNone          Successfully transitioned to Sleep.
312      * @retval kErrorBusy          The radio was transmitting.
313      * @retval kErrorInvalidState  The radio was disabled.
314      *
315      */
316     Error Sleep(void);
317 
318     /**
319      * This method indicates whether the sub-mac is busy transmitting or scanning.
320      *
321      * @retval TRUE if the sub-mac is busy transmitting or scanning.
322      * @retval FALSE if the sub-mac is not busy transmitting or scanning.
323      *
324      */
IsTransmittingOrScanning(void) const325     bool IsTransmittingOrScanning(void) const { return (mState == kStateTransmit) || (mState == kStateEnergyScan); }
326 
327     /**
328      * This method transitions the radio to Receive.
329      *
330      * @param[in]  aChannel   The channel to use for receiving.
331      *
332      * @retval kErrorNone          Successfully transitioned to Receive.
333      * @retval kErrorInvalidState  The radio was disabled or transmitting.
334      *
335      */
336     Error Receive(uint8_t aChannel);
337 
338     /**
339      * This method gets the radio transmit frame.
340      *
341      * @returns The transmit frame.
342      *
343      */
GetTransmitFrame(void)344     TxFrame &GetTransmitFrame(void) { return mTransmitFrame; }
345 
346     /**
347      * This method sends a prepared frame.
348      *
349      * The frame should be placed in `GetTransmitFrame()` frame.
350      *
351      * The `SubMac` layer handles Ack timeout, CSMA backoff, and frame retransmission.
352      *
353      * @retval kErrorNone          Successfully started the frame transmission
354      * @retval kErrorInvalidState  The radio was disabled or transmitting.
355      *
356      */
357     Error Send(void);
358 
359     /**
360      * This method gets the number of transmit retries of last transmitted frame.
361      *
362      * @returns Number of transmit retries.
363      *
364      */
GetTransmitRetries(void) const365     uint8_t GetTransmitRetries(void) const { return mTransmitRetries; }
366 
367     /**
368      * This method gets the most recent RSSI measurement.
369      *
370      * @returns The RSSI in dBm when it is valid. `kInvalidRssiValue` when RSSI is invalid.
371      *
372      */
373     int8_t GetRssi(void) const;
374 
375     /**
376      * This method begins energy scan.
377      *
378      * @param[in] aScanChannel   The channel to perform the energy scan on.
379      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
380      *
381      * @retval kErrorNone            Successfully started scanning the channel.
382      * @retval kErrorBusy            The radio is performing energy scanning.
383      * @retval kErrorInvalidState    The radio was disabled or transmitting.
384      * @retval kErrorNotImplemented  Energy scan is not supported (applicable in link-raw/radio mode only).
385      *
386      */
387     Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
388 
389     /**
390      * This method returns the noise floor value (currently use the radio receive sensitivity value).
391      *
392      * @returns The noise floor value in dBm.
393      *
394      */
395     int8_t GetNoiseFloor(void);
396 
397 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
398     /**
399      * This method configures CSL parameters in 'SubMac'.
400      *
401      * @param[in]  aPeriod    The CSL period.
402      * @param[in]  aChannel   The CSL channel.
403      * @param[in]  aShortAddr The short source address of CSL receiver's peer.
404      * @param[in]  aExtAddr   The extended source address of CSL receiver's peer.
405      *
406      * @retval  TRUE if CSL Period or CSL Channel changed.
407      * @retval  FALSE if CSL Period and CSL Channel did not change.
408      *
409      */
410     bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr);
411 
412     /**
413      * This method lets `SubMac` start CSL sample mode given a configured non-zero CSL period.
414      *
415      * `SubMac` would switch the radio state between `Receive` and `Sleep` according the CSL timer.
416      *
417      */
418     void CslSample(void);
419 
420     /**
421      * This method returns CSL parent clock accuracy, in ± ppm.
422      *
423      * @retval CSL parent clock accuracy.
424      *
425      */
GetCslParentClockAccuracy(void) const426     uint8_t GetCslParentClockAccuracy(void) const { return mCslParentAccuracy; }
427 
428     /**
429      * This method sets CSL parent clock accuracy, in ± ppm.
430      *
431      * @param[in] aCslParentAccuracy CSL parent clock accuracy, in ± ppm.
432      *
433      */
SetCslParentClockAccuracy(uint8_t aCslParentAccuracy)434     void SetCslParentClockAccuracy(uint8_t aCslParentAccuracy) { mCslParentAccuracy = aCslParentAccuracy; }
435 
436     /**
437      * This method sets CSL parent uncertainty, in ±10 us units.
438      *
439      * @retval CSL parent uncertainty, in ±10 us units.
440      *
441      */
GetCslParentUncertainty(void) const442     uint8_t GetCslParentUncertainty(void) const { return mCslParentUncert; }
443 
444     /**
445      * This method returns CSL parent uncertainty, in ±10 us units.
446      *
447      * @param[in] aCslParentUncert  CSL parent uncertainty, in ±10 us units.
448      *
449      */
SetCslParentUncertainty(uint8_t aCslParentUncert)450     void SetCslParentUncertainty(uint8_t aCslParentUncert) { mCslParentUncert = aCslParentUncert; }
451 
452 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
453 
454     /**
455      * This method sets MAC keys and key index.
456      *
457      * @param[in] aKeyIdMode  MAC key ID mode.
458      * @param[in] aKeyId      The key ID.
459      * @param[in] aPrevKey    The previous MAC key.
460      * @param[in] aCurrKey    The current MAC key.
461      * @param[in] aNextKey    The next MAC key.
462      *
463      */
464     void SetMacKey(uint8_t            aKeyIdMode,
465                    uint8_t            aKeyId,
466                    const KeyMaterial &aPrevKey,
467                    const KeyMaterial &aCurrKey,
468                    const KeyMaterial &aNextKey);
469 
470     /**
471      * This method returns a reference to the current MAC key.
472      *
473      * @returns A reference to the current MAC key.
474      *
475      */
GetCurrentMacKey(void) const476     const KeyMaterial &GetCurrentMacKey(void) const { return mCurrKey; }
477 
478     /**
479      * This method returns a reference to the previous MAC key.
480      *
481      * @returns A reference to the previous MAC key.
482      *
483      */
GetPreviousMacKey(void) const484     const KeyMaterial &GetPreviousMacKey(void) const { return mPrevKey; }
485 
486     /**
487      * This method returns a reference to the next MAC key.
488      *
489      * @returns A reference to the next MAC key.
490      *
491      */
GetNextMacKey(void) const492     const KeyMaterial &GetNextMacKey(void) const { return mNextKey; }
493 
494     /**
495      * This method returns the current MAC frame counter value.
496      *
497      * @returns The current MAC frame counter value.
498      *
499      */
GetFrameCounter(void) const500     uint32_t GetFrameCounter(void) const { return mFrameCounter; }
501 
502     /**
503      * This method sets the current MAC Frame Counter value.
504      *
505      * @param[in] aFrameCounter  The MAC Frame Counter value.
506      *
507      */
508     void SetFrameCounter(uint32_t aFrameCounter);
509 
510 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
511     /**
512      * This method enables/disables the radio filter.
513      *
514      * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
515      * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
516      * frame over the air (return "no ack" error if ack is requested, otherwise return success).
517      *
518      * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable.
519      *
520      */
SetRadioFilterEnabled(bool aFilterEnabled)521     void SetRadioFilterEnabled(bool aFilterEnabled) { mRadioFilterEnabled = aFilterEnabled; }
522 
523     /**
524      * This method indicates whether the radio filter is enabled or not.
525      *
526      * @retval TRUE   If the radio filter is enabled.
527      * @retval FALSE  If the radio filter is disabled.
528      *
529      */
IsRadioFilterEnabled(void) const530     bool IsRadioFilterEnabled(void) const { return mRadioFilterEnabled; }
531 #endif
532 
533 private:
534 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
535     static void HandleCslTimer(Timer &aTimer);
536     void        HandleCslTimer(void);
537     void        GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter);
538 #endif
539 
540     static constexpr uint8_t  kCsmaMinBe         = 3;   // macMinBE (IEEE 802.15.4-2006).
541     static constexpr uint8_t  kCsmaMaxBe         = 5;   // macMaxBE (IEEE 802.15.4-2006).
542     static constexpr uint32_t kUnitBackoffPeriod = 20;  // Number of symbols (IEEE 802.15.4-2006).
543     static constexpr uint32_t kAckTimeout        = 16;  // Timeout for waiting on an ACK (in msec).
544     static constexpr uint32_t kCcaSampleInterval = 128; // CCA sample interval, 128 usec.
545 
546 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
547     static constexpr uint8_t kRetxDelayMinBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT;
548     static constexpr uint8_t kRetxDelayMaxBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT;
549 #endif
550 
551 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
552     static constexpr uint32_t kEnergyScanRssiSampleInterval = 128; // RSSI sample interval for energy scan, 128 usec
553 #else
554     static constexpr uint32_t kEnergyScanRssiSampleInterval = 1; // RSSI sample interval during energy scan, 1 msec
555 #endif
556 
557     enum State : uint8_t
558     {
559         kStateDisabled,    // Radio is disabled.
560         kStateSleep,       // Radio is in sleep.
561         kStateReceive,     // Radio in in receive.
562         kStateCsmaBackoff, // CSMA backoff before transmission.
563         kStateTransmit,    // Radio is transmitting.
564         kStateEnergyScan,  // Energy scan.
565 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
566         kStateDelayBeforeRetx, // Delay before retx
567 #endif
568 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
569         kStateCslTransmit, // CSL transmission.
570 #endif
571 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
572         kStateCslSample, // CSL receive.
573 #endif
574     };
575 
576 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
577     // CSL receive window for the longest possible frame and
578     // ack duration.
579     static constexpr uint32_t kMinCslWindow = OPENTHREAD_CONFIG_CSL_MIN_RECEIVE_ON;
580 
581     // CSL receivers would wake up `kCslReceiveTimeAhead` earlier
582     // than expected sample window. The value is in usec.
583     static constexpr uint32_t kCslReceiveTimeAhead = OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD;
584 #endif
585 
586     /**
587      * This method initializes the states of the sub-MAC layer.
588      *
589      */
590     void Init(void);
591 
RadioSupportsCsmaBackoff(void) const592     bool RadioSupportsCsmaBackoff(void) const
593     {
594         return ((mRadioCaps & (OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES)) != 0);
595     }
596 
RadioSupportsTransmitSecurity(void) const597     bool RadioSupportsTransmitSecurity(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) != 0); }
RadioSupportsRetries(void) const598     bool RadioSupportsRetries(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) != 0); }
RadioSupportsAckTimeout(void) const599     bool RadioSupportsAckTimeout(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) != 0); }
RadioSupportsEnergyScan(void) const600     bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); }
RadioSupportsTransmitTiming(void) const601     bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); }
RadioSupportsReceiveTiming(void) const602     bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); }
603 
604     bool ShouldHandleTransmitSecurity(void) const;
605     bool ShouldHandleCsmaBackOff(void) const;
606     bool ShouldHandleAckTimeout(void) const;
607     bool ShouldHandleRetries(void) const;
608     bool ShouldHandleEnergyScan(void) const;
609     bool ShouldHandleTransmitTargetTime(void) const;
610 
611     void ProcessTransmitSecurity(void);
612     void SignalFrameCounterUsed(uint32_t aFrameCounter);
613     void StartCsmaBackoff(void);
614     void StartTimerForBackoff(uint8_t aBackoffExponent);
615     void BeginTransmit(void);
616     void SampleRssi(void);
617 
618     void HandleReceiveDone(RxFrame *aFrame, Error aError);
619     void HandleTransmitStarted(TxFrame &aFrame);
620     void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
621     void SignalFrameCounterUsedOnTxDone(const TxFrame &aFrame);
622     void HandleEnergyScanDone(int8_t aMaxRssi);
623 
624     static void HandleTimer(Timer &aTimer);
625     void        HandleTimer(void);
626 
627     void               SetState(State aState);
628     static const char *StateToString(State aState);
629 
630     otRadioCaps  mRadioCaps;
631     State        mState;
632     uint8_t      mCsmaBackoffs;
633     uint8_t      mTransmitRetries;
634     ShortAddress mShortAddress;
635     ExtAddress   mExtAddress;
636     bool         mRxOnWhenBackoff : 1;
637 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
638     bool mRadioFilterEnabled : 1;
639 #endif
640     int8_t             mEnergyScanMaxRssi;
641     TimeMilli          mEnergyScanEndTime;
642     TxFrame &          mTransmitFrame;
643     Callbacks          mCallbacks;
644     otLinkPcapCallback mPcapCallback;
645     void *             mPcapCallbackContext;
646     KeyMaterial        mPrevKey;
647     KeyMaterial        mCurrKey;
648     KeyMaterial        mNextKey;
649     uint32_t           mFrameCounter;
650     uint8_t            mKeyId;
651 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
652     uint8_t mRetxDelayBackOffExponent;
653 #endif
654 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
655     TimerMicro mTimer;
656 #else
657     TimerMilli                mTimer;
658 #endif
659 
660 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
661     uint16_t mCslPeriod;      // The CSL sample period, in units of 10 symbols (160 microseconds).
662     uint8_t  mCslChannel : 7; // The CSL sample channel.
663     bool mIsCslSampling : 1;  // Indicates that the radio is receiving in CSL state for platforms not supporting delayed
664                               // reception.
665     uint16_t   mCslPeerShort; // The CSL peer short address.
666     TimeMicro  mCslSampleTime;     // The CSL sample time of the current period.
667     TimeMicro  mCslLastSync;       // The timestamp of the last successful CSL synchronization.
668     uint8_t    mCslParentAccuracy; // Drift of timer used for scheduling CSL tx by the parent, in ± ppm.
669     uint8_t    mCslParentUncert;   // Uncertainty of the scheduling CSL of tx by the parent, in ±10 us units.
670     TimerMicro mCslTimer;
671 #endif
672 };
673 
674 /**
675  * @}
676  *
677  */
678 
679 } // namespace Mac
680 } // namespace ot
681 
682 #endif // SUB_MAC_HPP_
683