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 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 * 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 class SubMac : public InstanceLocator, private NonCopyable 105 { 106 friend class Radio::Callbacks; 107 friend class LinkRaw; 108 109 public: 110 /** 111 * Defines the callbacks notifying `SubMac` user of changes and events. 112 */ 113 class Callbacks : public InstanceLocator 114 { 115 public: 116 /** 117 * Initializes the `Callbacks` object. 118 * 119 * @param[in] aInstance A reference to the OpenThread instance. 120 */ 121 explicit Callbacks(Instance &aInstance); 122 123 /** 124 * Notifies user of `SubMac` of a received frame. 125 * 126 * @param[in] aFrame A pointer to the received frame or `nullptr` if the receive operation failed. 127 * @param[in] aError kErrorNone when successfully received a frame, 128 * kErrorAbort when reception was aborted and a frame was not received, 129 * kErrorNoBufs when a frame could not be received due to lack of rx buffer space. 130 */ 131 void ReceiveDone(RxFrame *aFrame, Error aError); 132 133 /** 134 * Notifies user of `SubMac` of CCA status (success/failure) for a frame transmission attempt. 135 * 136 * This is intended for updating counters, logging, and/or tracking CCA failure rate statistics. 137 * 138 * @param[in] aCcaSuccess TRUE if the CCA succeeded, FALSE otherwise. 139 * @param[in] aChannel The channel on which CCA was performed. 140 */ 141 void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel); 142 143 /** 144 * Notifies user of `SubMac` of the status of a frame transmission attempt. 145 * 146 * This is intended for updating counters, logging, and/or collecting statistics. 147 * 148 * @note Unlike `TransmitDone` which is invoked after all re-transmission attempts to indicate the final status 149 * of a frame transmission, this method is invoked on all frame transmission attempts. 150 * 151 * @param[in] aFrame The transmitted frame. 152 * @param[in] aError kErrorNone when the frame was transmitted successfully, 153 * kErrorNoAck when the frame was transmitted but no ACK was received, 154 * kErrorChannelAccessFailure tx failed due to activity on the channel, 155 * kErrorAbort when transmission was aborted for other reasons. 156 * @param[in] aRetryCount Current retry count. This is valid only when sub-mac handles frame re-transmissions. 157 * @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only 158 * when there was an error in current transmission attempt. 159 */ 160 void RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx); 161 162 /** 163 * The method notifies user of `SubMac` that the transmit operation has completed, providing, if applicable, 164 * the received ACK frame. 165 * 166 * @param[in] aFrame The transmitted frame. 167 * @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received. 168 * @param[in] aError kErrorNone when the frame was transmitted, 169 * kErrorNoAck when the frame was transmitted but no ACK was received, 170 * kErrorChannelAccessFailure tx failed due to activity on the channel, 171 * kErrorAbort when transmission was aborted for other reasons. 172 */ 173 void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError); 174 175 /** 176 * Notifies user of `SubMac` that energy scan is complete. 177 * 178 * @param[in] aMaxRssi Maximum RSSI seen on the channel, or `Radio::kInvalidRssi` if failed. 179 */ 180 void EnergyScanDone(int8_t aMaxRssi); 181 182 /** 183 * Notifies user of `SubMac` that a specific MAC frame counter is used for transmission. 184 * 185 * It is possible that this callback is invoked out of order in terms of counter values (i.e., called for a 186 * smaller counter value after a call for a larger counter value). 187 * 188 * @param[in] aFrameCounter The MAC frame counter value which was used. 189 */ 190 void FrameCounterUsed(uint32_t aFrameCounter); 191 }; 192 193 /** 194 * Initializes the `SubMac` object. 195 * 196 * @param[in] aInstance A reference to the OpenThread instance. 197 */ 198 explicit SubMac(Instance &aInstance); 199 200 /** 201 * Gets the capabilities provided by platform radio. 202 * 203 * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions). 204 */ GetRadioCaps(void) const205 otRadioCaps GetRadioCaps(void) const { return mRadioCaps; } 206 207 /** 208 * Gets the capabilities provided by `SubMac` layer. 209 * 210 * @returns The capability bit vector (see `OT_RADIO_CAP_*` definitions). 211 */ 212 otRadioCaps GetCaps(void) const; 213 214 /** 215 * Sets the PAN ID. 216 * 217 * @param[in] aPanId The PAN ID. 218 */ 219 void SetPanId(PanId aPanId); 220 221 /** 222 * Gets the short address. 223 * 224 * @returns The short address. 225 */ GetShortAddress(void) const226 ShortAddress GetShortAddress(void) const { return mShortAddress; } 227 228 /** 229 * Sets the short address. 230 * 231 * @param[in] aShortAddress The short address. 232 */ 233 void SetShortAddress(ShortAddress aShortAddress); 234 235 /** 236 * Gets the alternate short address. 237 * 238 * @returns The alternate short address, or `kShortAddrInvalid` if there is no alternate address. 239 */ GetAlternateShortAddress(void) const240 ShortAddress GetAlternateShortAddress(void) const { return mAlternateShortAddress; } 241 242 /** 243 * Sets the alternate short address. 244 * 245 * @param[in] aShortAddress The short address. Use `kShortAddrInvalid` to clear it. 246 */ 247 void SetAlternateShortAddress(ShortAddress aShortAddress); 248 249 /** 250 * Gets the extended address. 251 * 252 * @returns A reference to the extended address. 253 */ GetExtAddress(void) const254 const ExtAddress &GetExtAddress(void) const { return mExtAddress; } 255 256 /** 257 * Sets extended address. 258 * 259 * @param[in] aExtAddress The extended address. 260 */ 261 void SetExtAddress(const ExtAddress &aExtAddress); 262 263 /** 264 * Registers a callback to provide received packet capture for IEEE 802.15.4 frames. 265 * 266 * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame 267 * or `nullptr` to disable the callback. 268 * @param[in] aCallbackContext A pointer to application-specific context. 269 */ SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)270 void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext) 271 { 272 mPcapCallback.Set(aPcapCallback, aCallbackContext); 273 } 274 275 /** 276 * Indicates whether radio should stay in Receive or Sleep during idle periods. 277 * 278 * @param[in] aRxOnWhenIdle TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods. 279 */ 280 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 281 282 /** 283 * Enables the radio. 284 * 285 * @retval kErrorNone Successfully enabled. 286 * @retval kErrorFailed The radio could not be enabled. 287 */ 288 Error Enable(void); 289 290 /** 291 * Disables the radio. 292 * 293 * @retval kErrorNone Successfully disabled the radio. 294 */ 295 Error Disable(void); 296 297 /** 298 * Transitions the radio to Sleep. 299 * 300 * @retval kErrorNone Successfully transitioned to Sleep. 301 * @retval kErrorBusy The radio was transmitting. 302 * @retval kErrorInvalidState The radio was disabled. 303 */ 304 Error Sleep(void); 305 306 /** 307 * Indicates whether the sub-mac is busy transmitting or scanning. 308 * 309 * @retval TRUE if the sub-mac is busy transmitting or scanning. 310 * @retval FALSE if the sub-mac is not busy transmitting or scanning. 311 */ IsTransmittingOrScanning(void) const312 bool IsTransmittingOrScanning(void) const { return (mState == kStateTransmit) || (mState == kStateEnergyScan); } 313 314 /** 315 * Transitions the radio to Receive. 316 * 317 * @param[in] aChannel The channel to use for receiving. 318 * 319 * @retval kErrorNone Successfully transitioned to Receive. 320 * @retval kErrorInvalidState The radio was disabled or transmitting. 321 */ 322 Error Receive(uint8_t aChannel); 323 324 /** 325 * Gets the radio transmit frame. 326 * 327 * @returns The transmit frame. 328 */ GetTransmitFrame(void)329 TxFrame &GetTransmitFrame(void) { return mTransmitFrame; } 330 331 /** 332 * Sends a prepared frame. 333 * 334 * The frame should be placed in `GetTransmitFrame()` frame. 335 * 336 * The `SubMac` layer handles Ack timeout, CSMA backoff, and frame retransmission. 337 * 338 * @retval kErrorNone Successfully started the frame transmission 339 * @retval kErrorInvalidState The radio was disabled or transmitting. 340 */ 341 Error Send(void); 342 343 /** 344 * Gets the number of transmit retries of last transmitted frame. 345 * 346 * @returns Number of transmit retries. 347 */ GetTransmitRetries(void) const348 uint8_t GetTransmitRetries(void) const { return mTransmitRetries; } 349 350 /** 351 * Gets the most recent RSSI measurement. 352 * 353 * @returns The RSSI in dBm when it is valid. `Radio::kInvalidRssi` when RSSI is invalid. 354 */ 355 int8_t GetRssi(void) const; 356 357 /** 358 * Begins energy scan. 359 * 360 * @param[in] aScanChannel The channel to perform the energy scan on. 361 * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. 362 * 363 * @retval kErrorNone Successfully started scanning the channel. 364 * @retval kErrorBusy The radio is performing energy scanning. 365 * @retval kErrorInvalidState The radio was disabled or transmitting. 366 * @retval kErrorNotImplemented Energy scan is not supported (applicable in link-raw/radio mode only). 367 */ 368 Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration); 369 370 /** 371 * Returns the noise floor value (currently use the radio receive sensitivity value). 372 * 373 * @returns The noise floor value in dBm. 374 */ 375 int8_t GetNoiseFloor(void) const; 376 377 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 378 /** 379 * Configures CSL parameters in 'SubMac'. 380 * 381 * @param[in] aPeriod The CSL period (in unit of 10 symbols). 382 * @param[in] aChannel The CSL channel. 383 * @param[in] aShortAddr The short source address of CSL receiver's peer. 384 * @param[in] aExtAddr The extended source address of CSL receiver's peer. 385 * 386 * @retval TRUE if CSL Period or CSL Channel changed. 387 * @retval FALSE if CSL Period and CSL Channel did not change. 388 */ 389 bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr); 390 391 /** 392 * Returns parent CSL accuracy (clock accuracy and uncertainty). 393 * 394 * @returns The parent CSL accuracy. 395 */ GetCslParentAccuracy(void) const396 const CslAccuracy &GetCslParentAccuracy(void) const { return mCslParentAccuracy; } 397 398 /** 399 * Sets parent CSL accuracy. 400 * 401 * @param[in] aCslAccuracy The parent CSL accuracy. 402 */ SetCslParentAccuracy(const CslAccuracy & aCslAccuracy)403 void SetCslParentAccuracy(const CslAccuracy &aCslAccuracy) { mCslParentAccuracy = aCslAccuracy; } 404 405 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 406 407 /** 408 * Sets MAC keys and key index. 409 * 410 * @param[in] aKeyIdMode MAC key ID mode. 411 * @param[in] aKeyId The key ID. 412 * @param[in] aPrevKey The previous MAC key. 413 * @param[in] aCurrKey The current MAC key. 414 * @param[in] aNextKey The next MAC key. 415 */ 416 void SetMacKey(uint8_t aKeyIdMode, 417 uint8_t aKeyId, 418 const KeyMaterial &aPrevKey, 419 const KeyMaterial &aCurrKey, 420 const KeyMaterial &aNextKey); 421 422 /** 423 * Returns a reference to the current MAC key. 424 * 425 * @returns A reference to the current MAC key. 426 */ GetCurrentMacKey(void) const427 const KeyMaterial &GetCurrentMacKey(void) const { return mCurrKey; } 428 429 /** 430 * Returns a reference to the previous MAC key. 431 * 432 * @returns A reference to the previous MAC key. 433 */ GetPreviousMacKey(void) const434 const KeyMaterial &GetPreviousMacKey(void) const { return mPrevKey; } 435 436 /** 437 * Returns a reference to the next MAC key. 438 * 439 * @returns A reference to the next MAC key. 440 */ GetNextMacKey(void) const441 const KeyMaterial &GetNextMacKey(void) const { return mNextKey; } 442 443 /** 444 * Clears the stored MAC keys. 445 */ ClearMacKeys(void)446 void ClearMacKeys(void) 447 { 448 mPrevKey.Clear(); 449 mCurrKey.Clear(); 450 mNextKey.Clear(); 451 } 452 453 /** 454 * Returns the current MAC frame counter value. 455 * 456 * @returns The current MAC frame counter value. 457 */ GetFrameCounter(void) const458 uint32_t GetFrameCounter(void) const { return mFrameCounter; } 459 460 /** 461 * Sets the current MAC Frame Counter value. 462 * 463 * @param[in] aFrameCounter The MAC Frame Counter value. 464 * @param[in] aSetIfLarger If `true`, set only if the new value @p aFrameCounter is larger than the current value. 465 * If `false`, set the new value independent of the current value. 466 */ 467 void SetFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger); 468 469 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 470 /** 471 * Enables/disables the radio filter. 472 * 473 * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any 474 * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the 475 * frame over the air (return "no ack" error if ack is requested, otherwise return success). 476 * 477 * @param[in] aFilterEnabled TRUE to enable radio filter, FALSE to disable. 478 */ SetRadioFilterEnabled(bool aFilterEnabled)479 void SetRadioFilterEnabled(bool aFilterEnabled) { mRadioFilterEnabled = aFilterEnabled; } 480 481 /** 482 * Indicates whether the radio filter is enabled or not. 483 * 484 * @retval TRUE If the radio filter is enabled. 485 * @retval FALSE If the radio filter is disabled. 486 */ IsRadioFilterEnabled(void) const487 bool IsRadioFilterEnabled(void) const { return mRadioFilterEnabled; } 488 #endif 489 490 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 491 /** 492 * Configures wake-up listening parameters in all radios. 493 * 494 * @param[in] aEnable Whether to enable or disable wake-up listening. 495 * @param[in] aInterval The wake-up listen interval in microseconds. 496 * @param[in] aDuration The wake-up listen duration in microseconds. 497 * @param[in] aChannel The wake-up channel. 498 */ 499 void UpdateWakeupListening(bool aEnable, uint32_t aInterval, uint32_t aDuration, uint8_t aChannel); 500 #endif 501 502 private: 503 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 504 void CslInit(void); 505 void CslSample(void); 506 void UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame); 507 void UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError); 508 static void HandleCslTimer(Timer &aTimer); 509 void HandleCslTimer(void); 510 void GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter); 511 uint32_t GetLocalTime(void); IsCslEnabled(void) const512 bool IsCslEnabled(void) const { return mCslPeriod > 0; } 513 #if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE 514 void LogReceived(RxFrame *aFrame); 515 #endif 516 void HandleCslReceiveAt(uint32_t aTimeAhead, uint32_t aTimeAfter); 517 void HandleCslReceiveOrSleep(uint32_t aTimeAhead, uint32_t aTimeAfter); 518 void LogCslWindow(uint32_t aWinStart, uint32_t aWinDuration); 519 #endif 520 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 521 void WedInit(void); 522 static void HandleWedTimer(Timer &aTimer); 523 void HandleWedTimer(void); 524 #endif 525 526 static constexpr uint8_t kCsmaMinBe = 3; // macMinBE (IEEE 802.15.4-2006). 527 static constexpr uint8_t kCsmaMaxBe = 5; // macMaxBE (IEEE 802.15.4-2006). 528 static constexpr uint32_t kUnitBackoffPeriod = 20; // Number of symbols (IEEE 802.15.4-2006). 529 static constexpr uint32_t kAckTimeout = 16 * Time::kOneMsecInUsec; // Timeout for waiting on an ACK (in usec). 530 static constexpr uint32_t kCcaSampleInterval = 128; // CCA sample interval, 128 usec. 531 532 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY 533 static constexpr uint8_t kRetxDelayMinBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT; 534 static constexpr uint8_t kRetxDelayMaxBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT; 535 #endif 536 537 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 538 static constexpr uint32_t kEnergyScanRssiSampleInterval = 128; // RSSI sample interval for energy scan, in usec 539 #else 540 static constexpr uint32_t kEnergyScanRssiSampleInterval = 1000; // RSSI sample interval for energy scan, in usec 541 #endif 542 543 enum State : uint8_t 544 { 545 kStateDisabled, // Radio is disabled. 546 kStateSleep, // Radio is in sleep. 547 kStateReceive, // Radio in in receive. 548 kStateCsmaBackoff, // CSMA backoff before transmission. 549 kStateTransmit, // Radio is transmitting. 550 kStateEnergyScan, // Energy scan. 551 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY 552 kStateDelayBeforeRetx, // Delay before retx 553 #endif 554 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 555 kStateCslTransmit, // CSL transmission. 556 #endif 557 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 558 kStateCslSample, // CSL receive. 559 #endif 560 }; 561 562 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 563 // Radio on times needed before and after MHR time for proper frame detection 564 static constexpr uint32_t kMinReceiveOnAhead = OPENTHREAD_CONFIG_MIN_RECEIVE_ON_AHEAD; 565 static constexpr uint32_t kMinReceiveOnAfter = OPENTHREAD_CONFIG_MIN_RECEIVE_ON_AFTER; 566 567 // CSL/wake-up listening receivers would wake up `kCslReceiveTimeAhead` earlier 568 // than expected sample window. The value is in usec. 569 static constexpr uint32_t kCslReceiveTimeAhead = OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD; 570 #endif 571 572 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 573 // Margin to be applied after the end of a wake-up listen duration to schedule the next listen interval. 574 // The value is in usec. 575 static constexpr uint32_t kWedReceiveTimeAfter = OPENTHREAD_CONFIG_WED_RECEIVE_TIME_AFTER; 576 #endif 577 578 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 579 // CSL transmitter would schedule delayed transmission `kCslTransmitTimeAhead` earlier 580 // than expected delayed transmit time. The value is in usec. 581 // Only for radios not supporting OT_RADIO_CAPS_TRANSMIT_TIMING. 582 static constexpr uint32_t kCslTransmitTimeAhead = OPENTHREAD_CONFIG_CSL_TRANSMIT_TIME_AHEAD; 583 #endif 584 585 /** 586 * Initializes the states of the sub-MAC layer. 587 */ 588 void Init(void); 589 RadioSupportsCsmaBackoff(void) const590 bool RadioSupportsCsmaBackoff(void) const 591 { 592 return ((mRadioCaps & (OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES)) != 0); 593 } 594 RadioSupportsTransmitSecurity(void) const595 bool RadioSupportsTransmitSecurity(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) != 0); } RadioSupportsRetries(void) const596 bool RadioSupportsRetries(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) != 0); } RadioSupportsAckTimeout(void) const597 bool RadioSupportsAckTimeout(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) != 0); } RadioSupportsEnergyScan(void) const598 bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); } RadioSupportsTransmitTiming(void) const599 bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); } RadioSupportsReceiveTiming(void) const600 bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); } RadioSupportsRxOnWhenIdle(void) const601 bool RadioSupportsRxOnWhenIdle(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0); } 602 603 bool ShouldHandleTransmitSecurity(void) const; 604 bool ShouldHandleCsmaBackOff(void) const; 605 bool ShouldHandleAckTimeout(void) const; 606 bool ShouldHandleRetries(void) const; 607 bool ShouldHandleEnergyScan(void) const; 608 bool ShouldHandleTransmitTargetTime(void) const; 609 bool ShouldHandleTransitionToSleep(void) const; 610 611 void ProcessTransmitSecurity(void); 612 void SignalFrameCounterUsed(uint32_t aFrameCounter, uint8_t aKeyId); 613 void StartCsmaBackoff(void); 614 void StartTimerForBackoff(uint8_t aBackoffExponent); 615 void BeginTransmit(void); 616 void SampleRssi(void); 617 void StartTimer(uint32_t aDelayUs); 618 void StartTimerAt(Time aStartTime, uint32_t aDelayUs); 619 620 void HandleReceiveDone(RxFrame *aFrame, Error aError); 621 void HandleTransmitStarted(TxFrame &aFrame); 622 void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError); 623 void SignalFrameCounterUsedOnTxDone(const TxFrame &aFrame); 624 void HandleEnergyScanDone(int8_t aMaxRssi); 625 void HandleTimer(void); 626 627 Error RadioSleep(void); 628 629 void SetState(State aState); 630 static const char *StateToString(State aState); 631 632 using SubMacTimer = 633 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 634 TimerMicroIn<SubMac, &SubMac::HandleTimer>; 635 #else 636 TimerMilliIn<SubMac, &SubMac::HandleTimer>; 637 #endif 638 639 otRadioCaps mRadioCaps; 640 State mState; 641 uint8_t mCsmaBackoffs; 642 uint8_t mTransmitRetries; 643 ShortAddress mShortAddress; 644 ShortAddress mAlternateShortAddress; 645 ExtAddress mExtAddress; 646 bool mRxOnWhenIdle : 1; 647 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 648 bool mRadioFilterEnabled : 1; 649 #endif 650 int8_t mEnergyScanMaxRssi; 651 TimeMilli mEnergyScanEndTime; 652 TxFrame &mTransmitFrame; 653 Callbacks mCallbacks; 654 Callback<otLinkPcapCallback> mPcapCallback; 655 KeyMaterial mPrevKey; 656 KeyMaterial mCurrKey; 657 KeyMaterial mNextKey; 658 uint32_t mFrameCounter; 659 uint8_t mKeyId; 660 #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY 661 uint8_t mRetxDelayBackOffExponent; 662 #endif 663 SubMacTimer mTimer; 664 665 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 666 uint16_t mCslPeriod; // The CSL sample period, in units of 10 symbols (160 microseconds). 667 uint8_t mCslChannel : 7; // The CSL sample channel. 668 bool mIsCslSampling : 1; // Indicates that the radio is receiving in CSL state for platforms not supporting 669 // delayed reception. 670 uint16_t mCslPeerShort; // The CSL peer short address. 671 TimeMicro mCslSampleTime; // The CSL sample time of the current period relative to the local radio clock. 672 TimeMicro mCslLastSync; // The timestamp of the last successful CSL synchronization. 673 CslAccuracy mCslParentAccuracy; // The parent's CSL accuracy (clock accuracy and uncertainty). 674 TimerMicro mCslTimer; 675 #endif 676 677 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 678 uint32_t mWakeupListenInterval; // The wake-up listen interval, in microseconds. 679 uint32_t mWakeupListenDuration; // The wake-up listen duration, in microseconds. 680 uint8_t mWakeupChannel; // The wake-up sample channel. 681 TimeMicro mWedSampleTime; // The WED sample time of the current interval in local time. 682 uint64_t mWedSampleTimeRadio; // The WED sample time of the current interval in radio time. 683 TimerMicro mWedTimer; 684 #endif 685 }; 686 687 /** 688 * @} 689 */ 690 691 } // namespace Mac 692 } // namespace ot 693 694 #endif // SUB_MAC_HPP_ 695