From 90ee0a4d66e8afb799c61ad1824a88034bf3bdb9 Mon Sep 17 00:00:00 2001 From: rongli Date: Thu, 9 Aug 2018 02:18:53 +0800 Subject: [PATCH] [ncp] add joiner spinel support (#2877) --- src/ncp/changed_props_set.cpp | 6 ++++ src/ncp/ncp_base.cpp | 4 +++ src/ncp/ncp_base.hpp | 5 +++ src/ncp/ncp_base_dispatcher.cpp | 10 ++++++ src/ncp/ncp_base_mtd.cpp | 63 +++++++++++++++++++++++++++++++++ src/ncp/spinel.c | 20 +++++++++++ src/ncp/spinel.h | 55 ++++++++++++++++++++++++++++ 7 files changed, 163 insertions(+) diff --git a/src/ncp/changed_props_set.cpp b/src/ncp/changed_props_set.cpp index 623e94973..4191af14e 100644 --- a/src/ncp/changed_props_set.cpp +++ b/src/ncp/changed_props_set.cpp @@ -83,6 +83,12 @@ const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = { #if OPENTHREAD_ENABLE_CHANNEL_MANAGER {SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_STATUS_OK, true}, // 29 #endif +#if OPENTHREAD_ENABLE_JOINER + {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_NO_PEERS, false}, // 30 + {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_SECURITY, false}, // 31 + {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_RSP_TIMEOUT, false}, // 32 + {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_SUCCESS, false}, // 33 +#endif }; uint8_t ChangedPropsSet::GetNumEntries(void) const diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 6b21b9744..3f0e2ddc6 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -1651,6 +1651,10 @@ template <> otError NcpBase::HandlePropertyGet(void) SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_COMMISSIONER)); #endif +#if OPENTHREAD_ENABLE_JOINER + SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_JOINER)); +#endif + #if OPENTHREAD_ENABLE_UDP_PROXY SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_UDP_PROXY)); #endif diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 997d48c22..f28569989 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -292,6 +292,11 @@ protected: void HandleCommissionerPanIdConflict(uint16_t aPanId, uint32_t aChannelMask); #endif +#if OPENTHREAD_ENABLE_JOINER + static void HandleJoinerCallback_Jump(otError aError, void *aContext); + void HandleJoinerCallback(otError aError); +#endif + static void SendDoneTask(void *aContext); void SendDoneTask(void); diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index b33f55aa9..4546ffcc8 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -551,6 +551,11 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE: handler = &NcpBase::HandlePropertyGet; break; +#if OPENTHREAD_ENABLE_JOINER + case SPINEL_PROP_MESHCOP_JOINER_STATE: + handler = &NcpBase::HandlePropertyGet; + break; +#endif #if OPENTHREAD_ENABLE_COMMISSIONER case SPINEL_PROP_MESHCOP_COMMISSIONER_STATE: handler = &NcpBase::HandlePropertyGet; @@ -725,6 +730,11 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_THREAD_CHILD_TIMEOUT: handler = &NcpBase::HandlePropertySet; break; +#if OPENTHREAD_ENABLE_JOINER + case SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING: + handler = &NcpBase::HandlePropertySet; + break; +#endif case SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU: handler = &NcpBase::HandlePropertySet; break; diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 5003aed99..145357626 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -1013,6 +1013,38 @@ template <> otError NcpBase::HandlePropertyGet otError NcpBase::HandlePropertyGet(void) +{ + return mEncoder.WriteUint8(static_cast(otJoinerGetState(mInstance))); +} + +template <> otError NcpBase::HandlePropertySet(void) +{ + bool action = false; + const char *psk = NULL; + const char *provisioningUrl = NULL; + otError error = OT_ERROR_NONE; + + SuccessOrExit(error = mDecoder.ReadBool(action)); + SuccessOrExit(error = mDecoder.ReadUtf8(psk)); + SuccessOrExit(error = mDecoder.ReadUtf8(provisioningUrl)); + + if (action) + { + error = otJoinerStart(mInstance, psk, provisioningUrl, PACKAGE_NAME, OPENTHREAD_CONFIG_PLATFORM_INFO, + PACKAGE_VERSION, NULL, &NcpBase::HandleJoinerCallback_Jump, this); + } + else + { + error = otJoinerStop(mInstance); + } +exit: + return error; +} + +#endif + template <> otError NcpBase::HandlePropertyGet(void) { otError error = OT_ERROR_NONE; @@ -2877,6 +2909,37 @@ exit: } } +#if OPENTHREAD_ENABLE_JOINER +void NcpBase::HandleJoinerCallback_Jump(otError aError, void *aContext) +{ + static_cast(aContext)->HandleJoinerCallback(aError); +} + +void NcpBase::HandleJoinerCallback(otError aError) +{ + switch (aError) + { + case OT_ERROR_NONE: + mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SUCCESS); + break; + case OT_ERROR_SECURITY: + mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SECURITY); + break; + case OT_ERROR_NOT_FOUND: + mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_NO_PEERS); + break; + case OT_ERROR_RESPONSE_TIMEOUT: + mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_RSP_TIMEOUT); + break; + default: + mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE); + break; + } + + mUpdateChangedPropsTask.Post(); +} +#endif + // ---------------------------------------------------------------------------- // MARK: Outbound Datagram Handling // ---------------------------------------------------------------------------- diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index 09cd94b83..ece0bc544 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1577,6 +1577,14 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_DATASET_DEST_ADDRESS"; break; + case SPINEL_PROP_MESHCOP_JOINER_STATE: + ret = "PROP_MESHCOP_JOINER_STATE"; + break; + + case SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING: + ret = "PROP_MESHCOP_JOINER_COMMISSIONING"; + break; + case SPINEL_PROP_IPV6_LL_ADDR: ret = "PROP_IPV6_LL_ADDR"; break; @@ -2125,6 +2133,14 @@ const char *spinel_status_to_cstr(spinel_status_t status) ret = "STATUS_JOIN_INCOMPATIBLE"; break; + case SPINEL_STATUS_JOIN_RSP_TIMEOUT: + ret = "STATUS_JOIN_RSP_TIMEOUT"; + break; + + case SPINEL_STATUS_JOIN_SUCCESS: + ret = "STATUS_JOIN_SUCCESS"; + break; + case SPINEL_STATUS_RESET_POWER_ON: ret = "STATUS_RESET_POWER_ON"; break; @@ -2330,6 +2346,10 @@ const char *spinel_capability_to_cstr(unsigned int capability) ret = "CAP_THREAD_UDP_PROXY"; break; + case SPINEL_CAP_THREAD_JOINER: + ret = "CAP_THREAD_JOINER"; + break; + case SPINEL_CAP_NEST_LEGACY_INTERFACE: ret = "CAP_NEST_LEGACY_INTERFACE"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 5fedc47a8..02bd2a2ad 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -141,6 +141,7 @@ typedef enum { * later join failure status codes would be more accurate. * * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING + * \sa SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING */ SPINEL_STATUS_JOIN_FAILURE = SPINEL_STATUS_JOIN__BEGIN + 0, @@ -150,12 +151,14 @@ typedef enum { * key has been set incorrectly. * * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING + * \sa SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING */ SPINEL_STATUS_JOIN_SECURITY = SPINEL_STATUS_JOIN__BEGIN + 1, /// The node was unable to find any other peers on the network. /** * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING + * \sa SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING */ SPINEL_STATUS_JOIN_NO_PEERS = SPINEL_STATUS_JOIN__BEGIN + 2, @@ -165,6 +168,18 @@ typedef enum { */ SPINEL_STATUS_JOIN_INCOMPATIBLE = SPINEL_STATUS_JOIN__BEGIN + 3, + /// No response in expecting time. + /** + * \sa SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING + */ + SPINEL_STATUS_JOIN_RSP_TIMEOUT = SPINEL_STATUS_JOIN__BEGIN + 4, + + /// The node succeeds in commissioning and get the network credentials. + /** + * \sa SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING + */ + SPINEL_STATUS_JOIN_SUCCESS = SPINEL_STATUS_JOIN__BEGIN + 5, + SPINEL_STATUS_JOIN__END = 112, SPINEL_STATUS_RESET__BEGIN = 112, @@ -467,6 +482,7 @@ enum SPINEL_CAP_THREAD_COMMISSIONER = (SPINEL_CAP_THREAD__BEGIN + 0), SPINEL_CAP_THREAD_TMF_PROXY = (SPINEL_CAP_THREAD__BEGIN + 1), SPINEL_CAP_THREAD_UDP_PROXY = (SPINEL_CAP_THREAD__BEGIN + 2), + SPINEL_CAP_THREAD_JOINER = (SPINEL_CAP_THREAD__BEGIN + 3), SPINEL_CAP_THREAD__END = 1152, SPINEL_CAP_NEST__BEGIN = 15296, @@ -1604,6 +1620,45 @@ typedef enum { SPINEL_PROP_MESHCOP__BEGIN = 0x80, + // Thread Joiner State + /** Format `C` - Read Only + * + * Required capability: SPINEL_CAP_THREAD_JOINER + * + * The valid values are specified by SPINEL_MESHCOP_COMMISIONER_STATE_ enumeration. + * + */ + SPINEL_PROP_MESHCOP_JOINER_STATE = SPINEL_PROP_MESHCOP__BEGIN + 0, ///<[C] + + /// Thread Joiner Commissioning command and the parameters + /** Format `bUU` - Write Only + * + * This property starts or stops Joiner's commissioning process + * + * Required capability: SPINEL_CAP_THREAD_JOINER + * + * Writing to this property starts/stops the Joiner commissioning process. + * The immediate `VALUE_IS` response indicates success/failure of the starting/stopping + * the Joiner commissioning process. + * + * After a successful start operation, the join process outcome is reported through an + * asynchronous `VALUE_IS(LAST_STATUS)` update with one of the following error status values: + * + * - SPINEL_STATUS_JOIN_SUCCESS the join process succeeded. + * - SPINEL_STATUS_JOIN_SECURITY the join process failed due to security credentials. + * - SPINEL_STATUS_JOIN_NO_PEERS no joinable network was discovered. + * - SPINEL_STATUS_JOIN_RSP_TIMEOUT if a response timed out. + * - SPINEL_STATUS_JOIN_FAILURE join failure. + * + * Data per item is: + * + * `b` : Start or stop commissioning process + * `U` : Joiner's PSKd if start commissioning, empty string if stop commissioning + * `U` : Provisioning url if start commissioning, empty string if stop commissioning + * + */ + SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING = SPINEL_PROP_MESHCOP__BEGIN + 1, + // Thread Commissioner State /** Format `C` *