From 17f065afa4d0eace086126d3dd12f187d47ddfaf Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Tue, 31 Oct 2023 13:45:31 +0100 Subject: [PATCH] [radio] add `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` capability (#9554) Add a new `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` radio capability which lets OpenThread know what the radio idle state operation will be: receive or sleep. This allows to save power on sleepy devices since the active --> idle transition is much faster, specially for the cases in which there is some kind of serialization between OpenThread core and the radio driver. --- .../openthread-core-simulation-config.h | 4 ++ include/openthread/instance.h | 2 +- include/openthread/platform/radio.h | 35 +++++++++++++++- src/core/config/mac.h | 10 +++++ src/core/mac/mac.cpp | 4 +- src/core/mac/mac_links.hpp | 10 ++--- src/core/mac/sub_mac.cpp | 41 +++++++++++++++---- src/core/mac/sub_mac.hpp | 10 +++-- src/core/radio/radio.cpp | 1 + src/core/radio/radio.hpp | 12 ++++++ src/core/radio/radio_platform.cpp | 6 +++ src/lib/spinel/radio_spinel.cpp | 18 ++++++++ src/lib/spinel/radio_spinel.hpp | 13 ++++++ src/lib/spinel/spinel.c | 1 + src/lib/spinel/spinel.h | 13 +++++- src/ncp/ncp_base.cpp | 12 ++++++ src/ncp/ncp_base_dispatcher.cpp | 1 + tests/fuzz/fuzzer_platform.cpp | 6 +++ tests/unit/test_platform.cpp | 2 + 19 files changed, 179 insertions(+), 22 deletions(-) diff --git a/examples/platforms/simulation/openthread-core-simulation-config.h b/examples/platforms/simulation/openthread-core-simulation-config.h index 517b5b5b2579..8cae8aaf6e0c 100644 --- a/examples/platforms/simulation/openthread-core-simulation-config.h +++ b/examples/platforms/simulation/openthread-core-simulation-config.h @@ -77,6 +77,10 @@ #define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 1 #endif +#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE 1 +#endif + #endif // OPENTHREAD_RADIO #ifndef OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 03f5c623ad6e..1ff946b0dc13 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (370) +#define OPENTHREAD_API_VERSION (371) /** * @addtogroup api-instance diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 7f39d9832a6f..ffd268e2c3ab 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -119,7 +119,7 @@ enum * The value is a bit-field indicating the capabilities supported by the radio. See `OT_RADIO_CAPS_*` definitions. * */ -typedef uint8_t otRadioCaps; +typedef uint16_t otRadioCaps; /** * Defines constants that are used to indicate different radio capabilities. See `otRadioCaps`. @@ -136,6 +136,7 @@ enum OT_RADIO_CAPS_TRANSMIT_SEC = 1 << 5, ///< Radio supports tx security. OT_RADIO_CAPS_TRANSMIT_TIMING = 1 << 6, ///< Radio supports tx at specific time. OT_RADIO_CAPS_RECEIVE_TIMING = 1 << 7, ///< Radio supports rx at specific time. + OT_RADIO_CAPS_RX_ON_WHEN_IDLE = 1 << 8, ///< Radio supports RxOnWhenIdle handling. }; #define OT_PANID_BROADCAST 0xffff ///< IEEE 802.15.4 Broadcast PAN ID @@ -621,6 +622,38 @@ bool otPlatRadioGetPromiscuous(otInstance *aInstance); */ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable); +/** + * Sets the rx-on-when-idle state to the radio platform. + * + * Radio driver implementations supporting OT_RADIO_CAPS_RX_ON_WHEN_IDLE capability should consider idle periods the + * following situations: + * + * - Finalization of a regular frame reception task, provided that: + * - The frame is received without errors and passes the filtering and it's not an spurious ACK. + * - ACK is not requested or transmission of ACK is not possible due to internal conditions. + * - Finalization of a frame transmission or transmission of an ACK frame, when ACK is not requested in the transmitted + * frame. + * - Finalization of the reception operation of a requested ACK due to: + * - ACK timeout expiration. + * - Reception of an invalid ACK or not an ACK frame. + * - Reception of the proper ACK, unless the transmitted frame was a Data Request Command and the frame pending bit + * on the received ACK is set to true. In this case the radio platform implementation SHOULD keep the receiver on + * until a determined timeout which triggers an idle period start.`OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT` can be + * taken as a reference for this. + * - Finalization of a stand alone CCA task. + * - Finalization of a CCA operation with busy result during CSMA/CA procedure. + * - Finalization of an Energy Detection task. + * - Finalization of a radio reception window scheduled with `otPlatRadioReceiveAt`. + * + * If a platform supports `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` it must also support `OT_RADIO_CAPS_CSMA_BACKOFF` and handle + * idle periods after CCA as described above. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[in] aEnable TRUE to keep radio in Receive state, FALSE to put to Sleep state during idle periods. + * + */ +void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnable); + /** * Update MAC keys and key index * diff --git a/src/core/config/mac.h b/src/core/config/mac.h index 2694e0dc84a4..c9ae99131bcd 100644 --- a/src/core/config/mac.h +++ b/src/core/config/mac.h @@ -395,6 +395,16 @@ #define OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE + * + * Define to 1 to enable software rx off when idle switching. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE 0 +#endif + /** * @def OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE * diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index fe41b62b9dae..75162181b1bf 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -414,7 +414,7 @@ void Mac::SetRxOnWhenIdle(bool aRxOnWhenIdle) #endif } - mLinks.SetRxOnWhenBackoff(mRxOnWhenIdle || mPromiscuous); + mLinks.SetRxOnWhenIdle(mRxOnWhenIdle || mPromiscuous); UpdateIdleMode(); exit: @@ -2101,7 +2101,7 @@ void Mac::SetPromiscuous(bool aPromiscuous) mShouldDelaySleep = false; #endif - mLinks.SetRxOnWhenBackoff(mRxOnWhenIdle || mPromiscuous); + mLinks.SetRxOnWhenIdle(mRxOnWhenIdle || mPromiscuous); UpdateIdleMode(); } diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp index 605866d1831d..5d9a8f09a3f8 100644 --- a/src/core/mac/mac_links.hpp +++ b/src/core/mac/mac_links.hpp @@ -402,17 +402,17 @@ class Links : public InstanceLocator } /** - * Indicates whether radio should stay in Receive or Sleep during CSMA backoff. + * Indicates whether radio should stay in Receive or Sleep during idle periods. * - * @param[in] aRxOnWhenBackoff TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff. + * @param[in] aRxOnWhenIdle TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods. * */ - void SetRxOnWhenBackoff(bool aRxOnWhenBackoff) + void SetRxOnWhenIdle(bool aRxOnWhenIdle) { #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE - mSubMac.SetRxOnWhenBackoff(aRxOnWhenBackoff); + mSubMac.SetRxOnWhenIdle(aRxOnWhenIdle); #endif - OT_UNUSED_VARIABLE(aRxOnWhenBackoff); + OT_UNUSED_VARIABLE(aRxOnWhenIdle); } /** diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp index 86e58c276599..cbff1b279c51 100644 --- a/src/core/mac/sub_mac.cpp +++ b/src/core/mac/sub_mac.cpp @@ -76,7 +76,7 @@ void SubMac::Init(void) mTransmitRetries = 0; mShortAddress = kShortAddrInvalid; mExtAddress.Clear(); - mRxOnWhenBackoff = true; + mRxOnWhenIdle = true; mEnergyScanMaxRssi = Radio::kInvalidRssi; mEnergyScanEndTime = Time{0}; #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY @@ -141,10 +141,14 @@ otRadioCaps SubMac::GetCaps(void) const caps |= OT_RADIO_CAPS_RECEIVE_TIMING; #endif +#if OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE + caps |= OT_RADIO_CAPS_RX_ON_WHEN_IDLE; +#endif + #else caps = OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES | OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_TRANSMIT_SEC | OT_RADIO_CAPS_TRANSMIT_TIMING | - OT_RADIO_CAPS_RECEIVE_TIMING; + OT_RADIO_CAPS_RECEIVE_TIMING | OT_RADIO_CAPS_RX_ON_WHEN_IDLE; #endif return caps; @@ -176,6 +180,20 @@ void SubMac::SetExtAddress(const ExtAddress &aExtAddress) LogDebg("RadioExtAddress: %s", mExtAddress.ToString().AsCString()); } +void SubMac::SetRxOnWhenIdle(bool aRxOnWhenIdle) +{ + mRxOnWhenIdle = aRxOnWhenIdle; + + if (RadioSupportsRxOnWhenIdle()) + { +#if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE + Get().SetRxOnWhenIdle(mRxOnWhenIdle); +#endif + } + + LogDebg("RxOnWhenIdle: %d", mRxOnWhenIdle); +} + Error SubMac::Enable(void) { Error error = kErrorNone; @@ -211,17 +229,22 @@ Error SubMac::Disable(void) Error SubMac::Sleep(void) { - Error error = Get().Sleep(); + Error error = kErrorNone; + VerifyOrExit(ShouldHandleTransitionToSleep()); + + error = Get().Sleep(); + +exit: if (error != kErrorNone) { LogWarn("RadioSleep() failed, error: %s", ErrorToString(error)); - ExitNow(); + } + else + { + SetState(kStateSleep); } - SetState(kStateSleep); - -exit: return error; } @@ -507,7 +530,7 @@ void SubMac::StartTimerForBackoff(uint8_t aBackoffExponent) backoff = Random::NonCrypto::GetUint32InRange(0, static_cast(1UL << aBackoffExponent)); backoff *= (kUnitBackoffPeriod * Radio::kSymbolTime); - if (mRxOnWhenBackoff) + if (mRxOnWhenIdle) { IgnoreError(Get().Receive(mTransmitFrame.GetChannel())); } @@ -970,6 +993,8 @@ bool SubMac::ShouldHandleTransmitTargetTime(void) const return swTxDelay; } +bool SubMac::ShouldHandleTransitionToSleep(void) const { return !(!mRxOnWhenIdle && RadioSupportsRxOnWhenIdle()); } + void SubMac::SetState(State aState) { if (mState != aState) diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index 96af313035eb..211babd0b286 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -278,12 +278,12 @@ class SubMac : public InstanceLocator, private NonCopyable } /** - * Indicates whether radio should stay in Receive or Sleep during CSMA backoff. + * Indicates whether radio should stay in Receive or Sleep during idle periods. * - * @param[in] aRxOnWhenBackoff TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff. + * @param[in] aRxOnWhenIdle TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods. * */ - void SetRxOnWhenBackoff(bool aRxOnWhenBackoff) { mRxOnWhenBackoff = aRxOnWhenBackoff; } + void SetRxOnWhenIdle(bool aRxOnWhenIdle); /** * Enables the radio. @@ -604,6 +604,7 @@ class SubMac : public InstanceLocator, private NonCopyable bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); } bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); } bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); } + bool RadioSupportsRxOnWhenIdle(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0); } bool ShouldHandleTransmitSecurity(void) const; bool ShouldHandleCsmaBackOff(void) const; @@ -611,6 +612,7 @@ class SubMac : public InstanceLocator, private NonCopyable bool ShouldHandleRetries(void) const; bool ShouldHandleEnergyScan(void) const; bool ShouldHandleTransmitTargetTime(void) const; + bool ShouldHandleTransitionToSleep(void) const; void ProcessTransmitSecurity(void); void SignalFrameCounterUsed(uint32_t aFrameCounter, uint8_t aKeyId); @@ -642,7 +644,7 @@ class SubMac : public InstanceLocator, private NonCopyable uint8_t mTransmitRetries; ShortAddress mShortAddress; ExtAddress mExtAddress; - bool mRxOnWhenBackoff : 1; + bool mRxOnWhenIdle : 1; #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE bool mRadioFilterEnabled : 1; #endif diff --git a/src/core/radio/radio.cpp b/src/core/radio/radio.cpp index 9b3eb695e77d..bdc46bed339e 100644 --- a/src/core/radio/radio.cpp +++ b/src/core/radio/radio.cpp @@ -61,6 +61,7 @@ void Radio::Init(void) SetMacFrameCounter(0); SetPromiscuous(false); + SetRxOnWhenIdle(true); #endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE } #endif // OPENTHREAD_RADIO diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp index 892e579193fb..3321abea47ad 100644 --- a/src/core/radio/radio.hpp +++ b/src/core/radio/radio.hpp @@ -434,6 +434,14 @@ class Radio : public InstanceLocator, private NonCopyable */ void SetPromiscuous(bool aEnable); + /** + * Indicates whether radio should stay in Receive or Sleep during idle periods. + * + * @param[in] aEnable TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods. + * + */ + void SetRxOnWhenIdle(bool aEnable); + /** * Returns the current state of the radio. * @@ -833,6 +841,8 @@ inline bool Radio::GetPromiscuous(void) { return otPlatRadioGetPromiscuous(GetIn inline void Radio::SetPromiscuous(bool aEnable) { otPlatRadioSetPromiscuous(GetInstancePtr(), aEnable); } +inline void Radio::SetRxOnWhenIdle(bool aEnable) { otPlatRadioSetRxOnWhenIdle(GetInstancePtr(), aEnable); } + inline otRadioState Radio::GetState(void) { return otPlatRadioGetState(GetInstancePtr()); } inline Error Radio::Enable(void) @@ -974,6 +984,8 @@ inline bool Radio::GetPromiscuous(void) { return false; } inline void Radio::SetPromiscuous(bool) {} +inline void Radio::SetRxOnWhenIdle(bool) {} + inline otRadioState Radio::GetState(void) { return OT_RADIO_STATE_DISABLED; } inline Error Radio::Enable(void) { return kErrorNone; } diff --git a/src/core/radio/radio_platform.cpp b/src/core/radio/radio_platform.cpp index d1f6866ed86a..b71a0fb0e317 100644 --- a/src/core/radio/radio_platform.cpp +++ b/src/core/radio/radio_platform.cpp @@ -314,3 +314,9 @@ OT_TOOL_WEAK otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChanne return kErrorNotImplemented; } + +OT_TOOL_WEAK void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnable) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aEnable); +} diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index ab031ae66d5f..ffca5b277ee7 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -70,6 +70,7 @@ RadioSpinel::RadioSpinel(void) , mRxSensitivity(0) , mState(kStateDisabled) , mIsPromiscuous(false) + , mRxOnWhenIdle(true) , mIsReady(false) , mSupportsLogStream(false) , mSupportsResetToBootloader(false) @@ -872,6 +873,18 @@ otError RadioSpinel::SetPromiscuous(bool aEnable) return error; } +otError RadioSpinel::SetRxOnWhenIdle(bool aEnable) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(mRxOnWhenIdle != aEnable); + SuccessOrExit(error = Set(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, SPINEL_DATATYPE_BOOL_S, aEnable)); + mRxOnWhenIdle = aEnable; + +exit: + return error; +} + otError RadioSpinel::SetShortAddress(uint16_t aAddress) { otError error = OT_ERROR_NONE; @@ -2135,6 +2148,11 @@ void RadioSpinel::RestoreProperties(void) } #endif // OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE + if ((mRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0) + { + SuccessOrDie(Set(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, SPINEL_DATATYPE_BOOL_S, mRxOnWhenIdle)); + } + CalcRcpTimeOffset(); } #endif // OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index a1249854507d..f102b8fbcfea 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -103,6 +103,18 @@ class RadioSpinel */ otError SetPromiscuous(bool aEnable); + /** + * Sets the status of RxOnWhenIdle mode. + * + * @param[in] aEnable Whether to enable or disable RxOnWhenIdle mode. + * + * @retval OT_ERROR_NONE Succeeded. + * @retval OT_ERROR_BUSY Failed due to another operation is on going. + * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. + * + */ + otError SetRxOnWhenIdle(bool aEnable); + /** * Sets the Short Address for address filtering. * @@ -1067,6 +1079,7 @@ class RadioSpinel State mState; bool mIsPromiscuous : 1; ///< Promiscuous mode. + bool mRxOnWhenIdle : 1; ///< RxOnWhenIdle mode. bool mIsReady : 1; ///< NCP ready. bool mSupportsLogStream : 1; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format. bool mSupportsResetToBootloader : 1; ///< RCP supports resetting into bootloader mode. diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index af95176dd5f6..ab82faceddce 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -1263,6 +1263,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_MAC_PROMISCUOUS_MODE, "MAC_PROMISCUOUS_MODE"}, {SPINEL_PROP_MAC_ENERGY_SCAN_RESULT, "MAC_ENERGY_SCAN_RESULT"}, {SPINEL_PROP_MAC_DATA_POLL_PERIOD, "MAC_DATA_POLL_PERIOD"}, + {SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, "MAC_RX_ON_WHEN_IDLE_MODE"}, {SPINEL_PROP_MAC_ALLOWLIST, "MAC_ALLOWLIST"}, {SPINEL_PROP_MAC_ALLOWLIST_ENABLED, "MAC_ALLOWLIST_ENABLED"}, {SPINEL_PROP_MAC_EXTENDED_ADDR, "MAC_EXTENDED_ADDR"}, diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 770cc96e1c93..3d6ceda660de 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -420,7 +420,7 @@ * Please see section "Spinel definition compatibility guideline" for more details. * */ -#define SPINEL_RCP_API_VERSION 9 +#define SPINEL_RCP_API_VERSION 10 /** * @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION @@ -2128,6 +2128,17 @@ enum */ SPINEL_PROP_MAC_DATA_POLL_PERIOD = SPINEL_PROP_MAC__BEGIN + 10, + /// MAC RxOnWhenIdle mode + /** Format: `b` + * + * Set to true to enable RxOnWhenIdle or false to disable it. + * When True, the radio is expected to stay in receive state during + * idle periods. When False, the radio is expected to switch to sleep + * state during idle periods. + * + */ + SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE = SPINEL_PROP_MAC__BEGIN + 11, + SPINEL_PROP_MAC__END = 0x40, SPINEL_PROP_MAC_EXT__BEGIN = 0x1300, diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index acff7845e22d..288373fc7729 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -1460,6 +1460,18 @@ template <> otError NcpBase::HandlePropertySet return error; } +template <> otError NcpBase::HandlePropertySet(void) +{ + bool enabled; + otError error = OT_ERROR_NONE; + + SuccessOrExit(error = mDecoder.ReadBool(enabled)); + otPlatRadioSetRxOnWhenIdle(mInstance, enabled); + +exit: + return error; +} + template <> otError NcpBase::HandlePropertyGet(void) { return mEncoder.WriteUint16(otLinkGetPanId(mInstance)); diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 6fc42678531d..568b95964ad1 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -430,6 +430,7 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_PROMISCUOUS_MODE), #if OPENTHREAD_MTD || OPENTHREAD_FTD OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_DATA_POLL_PERIOD), + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_IF_UP), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_STACK_UP), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_ROLE), diff --git a/tests/fuzz/fuzzer_platform.cpp b/tests/fuzz/fuzzer_platform.cpp index 012cee49b8b2..8a64cc8b8a12 100644 --- a/tests/fuzz/fuzzer_platform.cpp +++ b/tests/fuzz/fuzzer_platform.cpp @@ -260,6 +260,12 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnabled) OT_UNUSED_VARIABLE(aEnabled); } +void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnabled) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aEnabled); +} + bool otPlatRadioIsEnabled(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index 237c5eb01370..6980666cbb80 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -126,6 +126,8 @@ OT_TOOL_WEAK void otPlatRadioSetShortAddress(otInstance *, uint16_t) {} OT_TOOL_WEAK void otPlatRadioSetPromiscuous(otInstance *, bool) {} +OT_TOOL_WEAK void otPlatRadioSetRxOnWhenIdle(otInstance *, bool) {} + OT_TOOL_WEAK bool otPlatRadioIsEnabled(otInstance *) { return true; } OT_TOOL_WEAK otError otPlatRadioEnable(otInstance *) { return OT_ERROR_NONE; }