diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 705129173..c1bc7b144 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -379,13 +379,23 @@ otLogLevel otGetDynamicLogLevel(otInstance *aInstance); otError otSetDynamicLogLevel(otInstance *aInstance, otLogLevel aLogLevel); /** - * Get the OpenThread version string. + * This function gets the OpenThread version string. * * @returns A pointer to the OpenThread version. * */ OTAPI const char *OTCALL otGetVersionString(void); +/** + * This function gets the OpenThread radio version string. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns A pointer to the OpenThread radio version. + * + */ +const char *otGetRadioVersionString(otInstance *aInstance); + /** * @} * diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 5d9872383..b4921710a 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -634,6 +634,19 @@ int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance); */ extern void otPlatRadioFrameUpdated(otInstance *aInstance, otRadioFrame *aFrame); +/** + * Get the radio version string. + * + * This is an optional radio driver platform function. If not provided by platform radio driver, OpenThread uses + * the OpenThread version instead (@sa otGetVersionString()). + * + * @param[in] aInstance The OpenThread instance structure. + * + * @returns A pointer to the OpenThread radio version. + * + */ +const char *otPlatRadioGetVersionString(otInstance *aInstance); + /** * @} * diff --git a/src/core/api/instance_api.cpp b/src/core/api/instance_api.cpp index a85850bfe..7604371b2 100644 --- a/src/core/api/instance_api.cpp +++ b/src/core/api/instance_api.cpp @@ -37,6 +37,7 @@ #include #include +#include #include "common/instance.hpp" #include "common/logging.hpp" @@ -183,3 +184,14 @@ const char *otGetVersionString(void) return sVersion; } + +const char *otGetRadioVersionString(otInstance *aInstance) +{ + return otPlatRadioGetVersionString(aInstance); +} + +OT_TOOL_WEAK const char *otPlatRadioGetVersionString(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return otGetVersionString(); +} diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 34e6285c7..eca4da5ec 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -1774,6 +1774,10 @@ template <> otError NcpBase::HandlePropertyGet(void) SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_RAW)); #endif +#if OPENTHREAD_ENABLE_POSIX_APP + SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX_APP)); +#endif + #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL) SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_OPENTHREAD_LOG_METADATA)); #endif diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index d7e0e7d08..25bfdb77f 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -500,6 +500,11 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) handler = &NcpBase::HandlePropertyGet; break; #endif +#if OPENTHREAD_ENABLE_POSIX_APP + case SPINEL_PROP_RCP_VERSION: + handler = &NcpBase::HandlePropertyGet; + break; +#endif #endif // OPENTHREAD_MTD || OPENTHREAD_FTD // -------------------------------------------------------------------------- @@ -614,7 +619,7 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) #endif // OPENTHREAD_FTD // -------------------------------------------------------------------------- - // Raw Link API Properties (Get Handler) + // Raw Link or Radio Mode Properties (Get Handler) #if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API case SPINEL_PROP_RADIO_CAPS: diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index a5bb95fd4..54ebaa534 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2484,6 +2484,15 @@ exit: #endif // OPENTHREAD_ENABLE_MAC_FILTER +#if OPENTHREAD_ENABLE_POSIX_APP + +template <> otError NcpBase::HandlePropertyGet(void) +{ + return mEncoder.WriteUtf8(otGetRadioVersionString(mInstance)); +} + +#endif // OPENTHREAD_ENABLE_POSIX_APP + #if OPENTHREAD_ENABLE_LEGACY void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers) diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index 2a5479b65..507bbc418 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1838,6 +1838,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "CHILD_SUPERVISION_CHECK_TIMEOUT"; break; + case SPINEL_PROP_RCP_VERSION: + ret = "RCP_VERSION"; + break; + case SPINEL_PROP_UART_BITRATE: ret = "UART_BITRATE"; break; @@ -2443,6 +2447,10 @@ const char *spinel_capability_to_cstr(unsigned int capability) ret = "CHILD_SUPERVISION"; break; + case SPINEL_CAP_POSIX_APP: + ret = "POSIX_APP"; + break; + case SPINEL_CAP_ERROR_RATE_TRACKING: ret = "ERROR_RATE_TRACKING"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 790308941..a0add20a1 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -477,6 +477,7 @@ enum SPINEL_CAP_OPENTHREAD_LOG_METADATA = (SPINEL_CAP_OPENTHREAD__BEGIN + 6), SPINEL_CAP_TIME_SYNC = (SPINEL_CAP_OPENTHREAD__BEGIN + 7), SPINEL_CAP_CHILD_SUPERVISION = (SPINEL_CAP_OPENTHREAD__BEGIN + 8), + SPINEL_CAP_POSIX_APP = (SPINEL_CAP_OPENTHREAD__BEGIN + 9), SPINEL_CAP_OPENTHREAD__END = 640, SPINEL_CAP_THREAD__BEGIN = 1024, @@ -2003,6 +2004,18 @@ typedef enum { */ SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT = SPINEL_PROP_OPENTHREAD__BEGIN + 11, + // RCP (NCP in radio only mode) version + /** Format `U` - Read only + * + * Required capability: SPINEL_CAP_POSIX_APP + * + * This property gives the version string of RCP (NCP in radio mode) which is being controlled by the POSIX + * application. It is available only in "POSIX Application" configuration (i.e., `OPENTHREAD_ENABLE_POSIX_APP` is + * enabled). + * + */ + SPINEL_PROP_RCP_VERSION = SPINEL_PROP_OPENTHREAD__BEGIN + 12, + SPINEL_PROP_OPENTHREAD__END = 0x2000, SPINEL_PROP_INTERFACE__BEGIN = 0x100, diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index 2761c07db..630c4779c 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -506,6 +506,7 @@ RadioSpinel::RadioSpinel(void) , mDiagOutputMaxLen(0) #endif { + mVersion[0] = '\0'; } void RadioSpinel::Init(const char *aRadioFile, const char *aRadioConfig) @@ -535,6 +536,8 @@ void RadioSpinel::Init(const char *aRadioFile, const char *aRadioConfig) SuccessOrExit(error = WaitResponse()); VerifyOrExit(mIsReady, error = OT_ERROR_FAILED); + SuccessOrExit(error = Get(SPINEL_PROP_NCP_VERSION, SPINEL_DATATYPE_UTF8_S, mVersion, sizeof(mVersion))); + SuccessOrExit(error = Get(SPINEL_PROP_HWADDR, SPINEL_DATATYPE_UINT64_S, &gNodeId)); gNodeId = ot::Encoding::BigEndian::HostSwap64(gNodeId); @@ -1725,6 +1728,12 @@ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) return sRadioSpinel.GetRadioCaps(); } +const char *otPlatRadioGetVersionString(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetVersion(); +} + bool otPlatRadioGetPromiscuous(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); diff --git a/src/posix/platform/radio_spinel.hpp b/src/posix/platform/radio_spinel.hpp index 16218da59..570e30435 100644 --- a/src/posix/platform/radio_spinel.hpp +++ b/src/posix/platform/radio_spinel.hpp @@ -160,6 +160,14 @@ public: */ otError SetTransmitPower(int8_t aPower); + /** + * This method returns the radio sw version string. + * + * @returns A pointer to the radio version string. + * + */ + const char *GetVersion(void) const { return mVersion; } + /** * This method returns the radio capabilities. * @@ -434,8 +442,9 @@ public: private: enum { - kMaxSpinelFrame = 2048, ///< Max size in bytes for transferring spinel frames. - kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds. + kMaxSpinelFrame = 2048, ///< Max size in bytes for transferring spinel frames. + kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds. + kVersionStringSize = 128, ///< Max size of version string. }; void DecodeHdlc(const uint8_t *aData, uint16_t aLength); @@ -578,6 +587,7 @@ private: int8_t mRxSensitivity; uint8_t mTxState; otError mTxError; + char mVersion[kVersionStringSize]; int mSockFd; otRadioState mState; diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index dcabdaece..d21526297 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -40,7 +40,13 @@ * The platform-specific string to insert into the OpenThread version string. * */ +#if OPENTHREAD_RADIO +#define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX-RCP-toranj" +#elif OPENTHREAD_ENABLE_POSIX_APP +#define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX-App-toranj" +#else #define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX-toranj" +#endif /** * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS