diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 83bc6eae5..8a5c40c9f 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 (262) +#define OPENTHREAD_API_VERSION (263) /** * @addtogroup api-instance diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 3ac715c6d..09e9aa7ee 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -1096,6 +1096,7 @@ otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aCh * * @retval OT_ERROR_FAILED Other platform specific errors. * @retval OT_ERROR_NONE Successfully set region code. + * @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented. * */ otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode); @@ -1112,6 +1113,7 @@ otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode); * @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr. * @retval OT_ERROR_FAILED Other platform specific errors. * @retval OT_ERROR_NONE Successfully got region code. + * @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented. * */ otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode); @@ -1134,6 +1136,7 @@ otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode); * @retval OT_ERROR_INVALID_ARGS @p aExtAddress is `NULL`. * @retval OT_ERROR_NOT_FOUND The Initiator indicated by @p aShortAddress is not found when trying to clear. * @retval OT_ERROR_NO_BUFS No more Initiator can be supported. + * @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented. * */ otError otPlatRadioConfigureEnhAckProbing(otInstance * aInstance, diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 414c04d94..6ab6d3c54 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -136,6 +136,9 @@ static inline otError SpinelStatusToOtError(spinel_status_t aError) break; case SPINEL_STATUS_PROP_NOT_FOUND: + ret = OT_ERROR_NOT_IMPLEMENTED; + break; + case SPINEL_STATUS_ITEM_NOT_FOUND: ret = OT_ERROR_NOT_FOUND; break; @@ -410,8 +413,6 @@ otError RadioSpinel::CheckRcpApiVersion(bool SuccessOrExit(error = Get(SPINEL_PROP_RCP_API_VERSION, SPINEL_DATATYPE_UINT_PACKED_S, &rcpApiVersion)); } - otLogNotePlat("RCP API Version: %u", rcpApiVersion); - static_assert(SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION <= SPINEL_RCP_API_VERSION, "MIN_HOST_SUPPORTED_RCP_API_VERSION must be smaller than or equal to RCP_API_VERSION"); diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 17e16d1be..2df6c157b 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -321,11 +321,51 @@ * * - SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION specifies the minimum spinel * RCP API Version which is supported by the host-side implementation. + * To reduce the backward compatibility issues, this number should be kept + * as constant as possible. * * - On start, host implementation queries the RCP API version and accepts * any version number from SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION up to * and including SPINEL_RCP_API_VERSION. * + * Host and RCP compatibility guideline: + * + * - New host spinel layer should work with an older RCP firmware, i.e., host + * implementation should remain backward compatible. + * + * - Existing fields in the format of an already implemented spinel + * property or command must not change. + * + * - New fields must be appended to the end of the existing spinel format. + * * New fields for new features: + * Adding a new capability flag to the otRadioCaps to indicate the new + * fields. The host parses the spinel format based on the pre-fetched + * otRadioCaps. The host should be able to enable/disable the feature + * in runtime based on the otRadioCaps. Refer to PR4919 and PR5139. + * * New fields for changing existing implementations: + * This case should be avoided as much as possible. It will cause the + * compatibility issue. + * + * - Deprecated fields must not be removed from the spinel format and they + * must be set to a suitable default value. + * + * - Adding new spinel properties. + * * If the old version RCP doesn't support the new spinel property, it + * must return the spinel error SPINEL_STATUS_PROP_NOT_FOUND. + * + * * If the host can handle the new spinel property by processing the error + * SPINEL_STATUS_PROP_NOT_FOUND, the API of the new spinel property must + * return OT_ERROR_NOT_IMPLEMENTED or default value. + * + * * If the host can't handle the new spinel property by processing the + * error SPINEL_STATUS_PROP_NOT_FOUND, a new capability flag must be + * added to the otRadioCaps to indicate whether RCP supports the new + * spinel property. The host must handle the new spinel property by + * processing the new capability flag. + * + * - If none of the above methods make the new functions work, increasing the + * SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION. This case should be avoided + * as much as possible. * --------------------------------------------------------------------------- */ diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp index 675738252..9114f1d06 100644 --- a/src/posix/platform/radio.cpp +++ b/src/posix/platform/radio.cpp @@ -35,6 +35,8 @@ #include +#include + #include "common/code_utils.hpp" #include "common/new.hpp" #include "lib/spinel/radio_spinel.hpp" @@ -151,10 +153,15 @@ void Radio::Init(void) { power = static_cast(strtol(str, nullptr, 0)); error = sRadioSpinel.SetChannelMaxTransmitPower(channel, power); - if (error != OT_ERROR_NONE && error != OT_ERROR_NOT_FOUND) + if (error != OT_ERROR_NONE && error != OT_ERROR_NOT_IMPLEMENTED) { DieNow(OT_ERROR_FAILED); } + else if (error == OT_ERROR_NOT_IMPLEMENTED) + { + otLogWarnPlat("The RCP doesn't support setting the max transmit power"); + } + ++channel; } @@ -162,10 +169,15 @@ void Radio::Init(void) while (channel <= ot::Radio::kChannelMax) { error = sRadioSpinel.SetChannelMaxTransmitPower(channel, power); - if (error != OT_ERROR_NONE && error != OT_ERROR_NOT_FOUND) + if (error != OT_ERROR_NONE && error != OT_ERROR_NOT_IMPLEMENTED) { DieNow(OT_ERROR_FAILED); } + else if (error == OT_ERROR_NOT_IMPLEMENTED) + { + otLogWarnPlat("The RCP doesn't support setting the max transmit power"); + } + ++channel; }