diff --git a/include/openthread/thread.h b/include/openthread/thread.h index 33e09bf88..eafb0720f 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -182,6 +182,22 @@ typedef struct otMleCounters uint16_t mParentChanges; } otMleCounters; +/** + * This structure represents the MLE Parent Response data. + * + */ +typedef struct otThreadParentResponseInfo +{ + otExtAddress mExtAddr; ///< IEEE 802.15.4 Extended Address of the Parent + uint16_t mRloc16; ///< Short address of the Parent + int8_t mRssi; ///< Rssi of the Parent + int8_t mPriority; ///< Parent priority + uint8_t mLinkQuality3; ///< Parent Link Quality 3 + uint8_t mLinkQuality2; ///< Parent Link Quality 2 + uint8_t mLinkQuality1; ///< Parent Link Quality 1 + bool mIsAttached; ///< Is the node receiving parent response attached +} otThreadParentResponseInfo; + /** * This function starts Thread protocol operation. * @@ -717,6 +733,30 @@ const otMleCounters *otThreadGetMleCounters(otInstance *aInstance); */ void otThreadResetMleCounters(otInstance *aInstance); +/** + * This function pointer is called every time an MLE Parent Response message is received. + * + * @param[in] aStats pointer to a location on stack holding the stats data. + * @param[in] aContext A pointer to callback client-specific context. + * + */ +typedef void(OTCALL *otThreadParentResponseCallback)(otThreadParentResponseInfo *aInfo, void *aContext); + +/** + * This function registers a callback to receive MLE Parent Response data. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aCallback A pointer to a function that is called upon receiving an MLE Parent Response message. + * @param[in] aContext A pointer to callback client-specific context. + * + * @retval OT_ERROR_NONE On successful registration + * @retval OT_ERROR_DISABLED_FEATURE If the feature is not supported + * + */ +OTAPI otError OTCALL otThreadRegisterParentResponseCallback(otInstance * aInstance, + otThreadParentResponseCallback aCallback, + void * aContext); + /** * @} * diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index 4eb346711..16ecc1324 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -538,3 +538,22 @@ void otThreadResetMleCounters(otInstance *aInstance) instance.GetThreadNetif().GetMle().ResetCounters(); } + +otError otThreadRegisterParentResponseCallback(otInstance * aInstance, + otThreadParentResponseCallback aCallback, + void * aContext) +{ +#if OPENTHREAD_FTD || OPENTHREAD_MTD + Instance &instance = *static_cast(aInstance); + + instance.GetThreadNetif().GetMle().RegisterParentResponseStatsCallback(aCallback, aContext); + + return OT_ERROR_NONE; +#else + (void)aInstance; + (void)aCallback; + (void)aContext; + + return OT_ERROR_DISABLED_FEATURE; +#endif +} diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 6f29ab462..3274e18ba 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -109,6 +109,8 @@ Mle::Mle(Instance &aInstance) , mAlternatePanId(Mac::kPanIdBroadcast) , mAlternateTimestamp(0) , mNotifierCallback(&Mle::HandleStateChanged, this) + , mParentResponseCb(NULL) + , mParentResponseCbContext(NULL) { otMeshLocalPrefix meshLocalPrefix; @@ -3126,6 +3128,23 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kConnectivity, sizeof(connectivity), connectivity)); VerifyOrExit(connectivity.IsValid(), error = OT_ERROR_PARSE); + // Share data with application, if requested. + if (mParentResponseCb) + { + otThreadParentResponseInfo parentinfo; + + parentinfo.mExtAddr = extAddress; + parentinfo.mRloc16 = sourceAddress.GetRloc16(); + parentinfo.mRssi = linkInfo->mRss; + parentinfo.mPriority = connectivity.GetParentPriority(); + parentinfo.mLinkQuality3 = connectivity.GetLinkQuality3(); + parentinfo.mLinkQuality2 = connectivity.GetLinkQuality2(); + parentinfo.mLinkQuality1 = connectivity.GetLinkQuality1(); + parentinfo.mIsAttached = IsAttached(); + + mParentResponseCb(&parentinfo, mParentResponseCbContext); + } + #if OPENTHREAD_FTD if (IsFullThreadDevice() && (mRole != OT_DEVICE_ROLE_DETACHED)) { @@ -4177,5 +4196,11 @@ const char *Mle::ReattachStateToString(ReattachState aState) #endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MLE == 1) +void Mle::RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext) +{ + mParentResponseCb = aCallback; + mParentResponseCbContext = aContext; +} + } // namespace Mle } // namespace ot diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 55c214ac8..f30dc1f2a 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1057,6 +1057,15 @@ public: */ void ResetCounters(void) { memset(&mCounters, 0, sizeof(mCounters)); } + /** + * This function registers the client callback that is called when processing an MLE Parent Response message. + * + * @param[in] aCallback A pointer to a function that is called to deliver MLE Parent Response data. + * @param[in] aContext A pointer to application-specific context. + * + */ + void RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext); + protected: /** * States during attach (when searching for a parent). @@ -1786,6 +1795,9 @@ private: Ip6::NetifMulticastAddress mRealmLocalAllThreadNodes; Notifier::Callback mNotifierCallback; + + otThreadParentResponseCallback mParentResponseCb; + void * mParentResponseCbContext; }; } // namespace Mle