blob: 65767b1d1d210a6b5b1135ba3b426b1b645a5e29 [file] [log] [blame]
Buke Po818998e2017-08-04 01:19:07 +08001/*
2 * Copyright (c) 2016-2017, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/**
29 * @file
30 * This file implements minimal thread device required Spinel interface to the OpenThread stack.
31 */
32
Yakun Xu96ed7cc2018-04-17 00:28:00 +080033#include <openthread/config.h>
34
Buke Po818998e2017-08-04 01:19:07 +080035#include "ncp_base.hpp"
36
37#if OPENTHREAD_ENABLE_BORDER_ROUTER
38#include <openthread/border_router.h>
39#endif
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -080040#if OPENTHREAD_ENABLE_CHANNEL_MONITOR
41#include <openthread/channel_monitor.h>
42#endif
Buke Po818998e2017-08-04 01:19:07 +080043#include <openthread/diag.h>
44#include <openthread/icmp6.h>
45#if OPENTHREAD_ENABLE_JAM_DETECTION
46#include <openthread/jam_detection.h>
47#endif
48#include <openthread/ncp.h>
49#include <openthread/openthread.h>
50#include <openthread/platform/misc.h>
51#include <openthread/platform/radio.h>
52#if OPENTHREAD_FTD
53#include <openthread/thread_ftd.h>
54#endif
55
Buke Po818998e2017-08-04 01:19:07 +080056#include "common/code_utils.hpp"
57#include "common/debug.hpp"
Abtin Keshavarzian02c876e2017-11-13 08:27:57 -080058#include "common/instance.hpp"
Buke Po818998e2017-08-04 01:19:07 +080059#include "net/ip6.hpp"
60
61#if OPENTHREAD_MTD || OPENTHREAD_FTD
62
63namespace ot {
64namespace Ncp {
65
Abtin Keshavarzian5c8a1052017-08-10 21:32:52 -070066#if OPENTHREAD_ENABLE_RAW_LINK_API
67
Buke Po818998e2017-08-04 01:19:07 +080068static bool HasOnly1BitSet(uint32_t aValue)
69{
70 return aValue != 0 && ((aValue & (aValue - 1)) == 0);
71}
72
73static uint8_t IndexOfMSB(uint32_t aValue)
74{
75 uint8_t index = 0;
76
77 while (aValue >>= 1)
78 {
79 index++;
80 }
81
82 return index;
83}
84
Abtin Keshavarzian5c8a1052017-08-10 21:32:52 -070085#endif // OPENTHREAD_ENABLE_RAW_LINK_API
86
Buke Po818998e2017-08-04 01:19:07 +080087static uint8_t BorderRouterConfigToFlagByte(const otBorderRouterConfig &aConfig)
88{
89 uint8_t flags(0);
90
91 if (aConfig.mPreferred)
92 {
93 flags |= SPINEL_NET_FLAG_PREFERRED;
94 }
95
96 if (aConfig.mSlaac)
97 {
98 flags |= SPINEL_NET_FLAG_SLAAC;
99 }
100
101 if (aConfig.mDhcp)
102 {
103 flags |= SPINEL_NET_FLAG_DHCP;
104 }
105
106 if (aConfig.mDefaultRoute)
107 {
108 flags |= SPINEL_NET_FLAG_DEFAULT_ROUTE;
109 }
110
111 if (aConfig.mConfigure)
112 {
113 flags |= SPINEL_NET_FLAG_CONFIGURE;
114 }
115
116 if (aConfig.mOnMesh)
117 {
118 flags |= SPINEL_NET_FLAG_ON_MESH;
119 }
120
121 flags |= (aConfig.mPreference << SPINEL_NET_FLAG_PREFERENCE_OFFSET);
122
123 return flags;
124}
125
126static uint8_t ExternalRoutePreferenceToFlagByte(int aPreference)
127{
128 uint8_t flags;
129
130 switch (aPreference)
131 {
132 case OT_ROUTE_PREFERENCE_LOW:
133 flags = SPINEL_ROUTE_PREFERENCE_LOW;
134 break;
135
136 case OT_ROUTE_PREFERENCE_MED:
137 flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
138 break;
139
140 case OT_ROUTE_PREFERENCE_HIGH:
141 flags = SPINEL_ROUTE_PREFERENCE_HIGH;
142 break;
143
144 default:
145 flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
146 break;
147 }
148
149 return flags;
150}
151
152uint8_t NcpBase::LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequests, bool aDeviceType, bool aNetworkData)
153{
154 uint8_t flags(0);
155
156 if (aRxOnWhenIdle)
157 {
158 flags |= SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE;
159 }
160
161 if (aSecureDataRequests)
162 {
163 flags |= SPINEL_THREAD_MODE_SECURE_DATA_REQUEST;
164 }
165
166 if (aDeviceType)
167 {
168 flags |= SPINEL_THREAD_MODE_FULL_FUNCTION_DEV;
169 }
170
171 if (aNetworkData)
172 {
173 flags |= SPINEL_THREAD_MODE_FULL_NETWORK_DATA;
174 }
175
176 return flags;
177}
178
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700179otError NcpBase::GetPropertyHandler_MAC_DATA_POLL_PERIOD(void)
Buke Po818998e2017-08-04 01:19:07 +0800180{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700181 return mEncoder.WriteUint32(otLinkGetPollPeriod(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800182}
183
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700184otError NcpBase::SetPropertyHandler_MAC_DATA_POLL_PERIOD(void)
Buke Po818998e2017-08-04 01:19:07 +0800185{
186 uint32_t pollPeriod;
Buke Po818998e2017-08-04 01:19:07 +0800187 otError error = OT_ERROR_NONE;
188
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700189 SuccessOrExit(error = mDecoder.ReadUint32(pollPeriod));
Buke Po818998e2017-08-04 01:19:07 +0800190
191 otLinkSetPollPeriod(mInstance, pollPeriod);
192
193exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700194 return error;
Buke Po818998e2017-08-04 01:19:07 +0800195}
196
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700197otError NcpBase::GetPropertyHandler_MAC_EXTENDED_ADDR(void)
Buke Po818998e2017-08-04 01:19:07 +0800198{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700199 return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800200}
201
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700202otError NcpBase::GetPropertyHandler_PHY_FREQ(void)
Buke Po818998e2017-08-04 01:19:07 +0800203{
204 uint32_t freq_khz(0);
205 const uint8_t chan(otLinkGetChannel(mInstance));
206
207 if (chan == 0)
208 {
209 freq_khz = 868300;
210 }
211 else if (chan < 11)
212 {
213 freq_khz = 906000 - (2000 * 1) + 2000 * (chan);
214 }
215 else if (chan < 26)
216 {
217 freq_khz = 2405000 - (5000 * 11) + 5000 * (chan);
218 }
219
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700220 return mEncoder.WriteUint32(freq_khz);
Buke Po818998e2017-08-04 01:19:07 +0800221}
222
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700223otError NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(void)
Buke Po818998e2017-08-04 01:19:07 +0800224{
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800225 return EncodeChannelMask(mSupportedChannelMask);
Buke Po818998e2017-08-04 01:19:07 +0800226}
227
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700228otError NcpBase::GetPropertyHandler_PHY_RSSI(void)
Buke Po818998e2017-08-04 01:19:07 +0800229{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700230 return mEncoder.WriteInt8(otPlatRadioGetRssi(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800231}
232
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700233otError NcpBase::CommandHandler_NET_SAVE(uint8_t aHeader)
Buke Po818998e2017-08-04 01:19:07 +0800234{
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800235 return PrepareLastStatusResponse(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
Buke Po818998e2017-08-04 01:19:07 +0800236}
237
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700238otError NcpBase::CommandHandler_NET_CLEAR(uint8_t aHeader)
Buke Po818998e2017-08-04 01:19:07 +0800239{
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800240 return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(otInstanceErasePersistentInfo(mInstance)));
Buke Po818998e2017-08-04 01:19:07 +0800241}
242
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700243otError NcpBase::CommandHandler_NET_RECALL(uint8_t aHeader)
Buke Po818998e2017-08-04 01:19:07 +0800244{
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800245 return PrepareLastStatusResponse(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
Buke Po818998e2017-08-04 01:19:07 +0800246}
247
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700248otError NcpBase::GetPropertyHandler_NET_SAVED(void)
Buke Po818998e2017-08-04 01:19:07 +0800249{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700250 return mEncoder.WriteBool(otDatasetIsCommissioned(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800251}
252
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700253otError NcpBase::GetPropertyHandler_NET_IF_UP(void)
Buke Po818998e2017-08-04 01:19:07 +0800254{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700255 return mEncoder.WriteBool(otIp6IsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800256}
257
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700258otError NcpBase::SetPropertyHandler_NET_IF_UP(void)
Buke Po818998e2017-08-04 01:19:07 +0800259{
260 bool enabled = false;
Buke Po818998e2017-08-04 01:19:07 +0800261 otError error = OT_ERROR_NONE;
262
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700263 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800264
265 error = otIp6SetEnabled(mInstance, enabled);
266
267exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700268 return error;
Buke Po818998e2017-08-04 01:19:07 +0800269}
270
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700271otError NcpBase::GetPropertyHandler_NET_STACK_UP(void)
Buke Po818998e2017-08-04 01:19:07 +0800272{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700273 return mEncoder.WriteBool(otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +0800274}
275
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700276otError NcpBase::SetPropertyHandler_NET_STACK_UP(void)
Buke Po818998e2017-08-04 01:19:07 +0800277{
278 bool enabled = false;
Buke Po818998e2017-08-04 01:19:07 +0800279 otError error = OT_ERROR_NONE;
280
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700281 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800282
283 // If the value has changed...
284 if ((enabled != false) != (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED))
285 {
286 if (enabled != false)
287 {
288 error = otThreadSetEnabled(mInstance, true);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700289 StartLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800290 }
291 else
292 {
293 error = otThreadSetEnabled(mInstance, false);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700294 StopLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800295 }
296 }
297
298exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700299 return error;
Buke Po818998e2017-08-04 01:19:07 +0800300}
301
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700302otError NcpBase::GetPropertyHandler_NET_ROLE(void)
Buke Po818998e2017-08-04 01:19:07 +0800303{
304 spinel_net_role_t role(SPINEL_NET_ROLE_DETACHED);
305
306 switch (otThreadGetDeviceRole(mInstance))
307 {
308 case OT_DEVICE_ROLE_DISABLED:
309 case OT_DEVICE_ROLE_DETACHED:
310 role = SPINEL_NET_ROLE_DETACHED;
311 break;
312
313 case OT_DEVICE_ROLE_CHILD:
314 role = SPINEL_NET_ROLE_CHILD;
315 break;
316
317 case OT_DEVICE_ROLE_ROUTER:
318 role = SPINEL_NET_ROLE_ROUTER;
319 break;
320
321 case OT_DEVICE_ROLE_LEADER:
322 role = SPINEL_NET_ROLE_LEADER;
323 break;
324 }
325
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700326 return mEncoder.WriteUint8(role);
Buke Po818998e2017-08-04 01:19:07 +0800327}
328
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700329otError NcpBase::SetPropertyHandler_NET_ROLE(void)
Buke Po818998e2017-08-04 01:19:07 +0800330{
331 unsigned int role = 0;
Buke Po818998e2017-08-04 01:19:07 +0800332 otError error = OT_ERROR_NONE;
333
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700334 SuccessOrExit(error = mDecoder.ReadUintPacked(role));
Buke Po818998e2017-08-04 01:19:07 +0800335
336 switch (role)
337 {
338 case SPINEL_NET_ROLE_DETACHED:
339 error = otThreadBecomeDetached(mInstance);
340 break;
341
342#if OPENTHREAD_FTD
343 case SPINEL_NET_ROLE_ROUTER:
344 error = otThreadBecomeRouter(mInstance);
345 break;
346
347 case SPINEL_NET_ROLE_LEADER:
348 error = otThreadBecomeLeader(mInstance);
349 break;
350#endif // OPENTHREAD_FTD
351
352 case SPINEL_NET_ROLE_CHILD:
353 error = otThreadBecomeChild(mInstance);
354 break;
355 }
356
357exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700358 return error;
Buke Po818998e2017-08-04 01:19:07 +0800359}
360
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700361otError NcpBase::GetPropertyHandler_NET_NETWORK_NAME(void)
Buke Po818998e2017-08-04 01:19:07 +0800362{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700363 return mEncoder.WriteUtf8(otThreadGetNetworkName(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800364}
365
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700366otError NcpBase::SetPropertyHandler_NET_NETWORK_NAME(void)
Buke Po818998e2017-08-04 01:19:07 +0800367{
368 const char *string = NULL;
Buke Po818998e2017-08-04 01:19:07 +0800369 otError error = OT_ERROR_NONE;
370
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700371 SuccessOrExit(mDecoder.ReadUtf8(string));
Buke Po818998e2017-08-04 01:19:07 +0800372
373 error = otThreadSetNetworkName(mInstance, string);
374
375exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700376 return error;
Buke Po818998e2017-08-04 01:19:07 +0800377}
378
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700379otError NcpBase::GetPropertyHandler_NET_XPANID(void)
Buke Po818998e2017-08-04 01:19:07 +0800380{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700381 return mEncoder.WriteData(otThreadGetExtendedPanId(mInstance), sizeof(spinel_net_xpanid_t));
Buke Po818998e2017-08-04 01:19:07 +0800382}
383
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700384otError NcpBase::SetPropertyHandler_NET_XPANID(void)
Buke Po818998e2017-08-04 01:19:07 +0800385{
386 const uint8_t *ptr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700387 uint16_t len;
Buke Po818998e2017-08-04 01:19:07 +0800388 otError error = OT_ERROR_NONE;
389
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700390 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800391
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700392 VerifyOrExit(len == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800393
394 error = otThreadSetExtendedPanId(mInstance, ptr);
395
396exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700397 return error;
Buke Po818998e2017-08-04 01:19:07 +0800398}
399
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700400otError NcpBase::GetPropertyHandler_NET_MASTER_KEY(void)
Buke Po818998e2017-08-04 01:19:07 +0800401{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700402 return mEncoder.WriteData(otThreadGetMasterKey(mInstance)->m8, OT_MASTER_KEY_SIZE);
Buke Po818998e2017-08-04 01:19:07 +0800403}
404
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700405otError NcpBase::SetPropertyHandler_NET_MASTER_KEY(void)
Buke Po818998e2017-08-04 01:19:07 +0800406{
407 const uint8_t *ptr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700408 uint16_t len;
Buke Po818998e2017-08-04 01:19:07 +0800409 otError error = OT_ERROR_NONE;
410
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700411 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800412
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700413 VerifyOrExit(len == OT_MASTER_KEY_SIZE, error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800414
415 error = otThreadSetMasterKey(mInstance, reinterpret_cast<const otMasterKey *>(ptr));
416
417exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700418 return error;
Buke Po818998e2017-08-04 01:19:07 +0800419}
420
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700421otError NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE_COUNTER(void)
Buke Po818998e2017-08-04 01:19:07 +0800422{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700423 return mEncoder.WriteUint32(otThreadGetKeySequenceCounter(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800424}
425
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700426otError NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE_COUNTER(void)
Buke Po818998e2017-08-04 01:19:07 +0800427{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700428 uint32_t keySeqCounter;
Buke Po818998e2017-08-04 01:19:07 +0800429 otError error = OT_ERROR_NONE;
430
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700431 SuccessOrExit(error = mDecoder.ReadUint32(keySeqCounter));
Buke Po818998e2017-08-04 01:19:07 +0800432
433 otThreadSetKeySequenceCounter(mInstance, keySeqCounter);
434
435exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700436 return error;
Buke Po818998e2017-08-04 01:19:07 +0800437}
438
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700439otError NcpBase::GetPropertyHandler_NET_PARTITION_ID(void)
Buke Po818998e2017-08-04 01:19:07 +0800440{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700441 return mEncoder.WriteUint32(otThreadGetPartitionId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800442}
443
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700444otError NcpBase::GetPropertyHandler_NET_KEY_SWITCH_GUARDTIME(void)
Buke Po818998e2017-08-04 01:19:07 +0800445{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700446 return mEncoder.WriteUint32(otThreadGetKeySwitchGuardTime(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800447}
448
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700449otError NcpBase::SetPropertyHandler_NET_KEY_SWITCH_GUARDTIME(void)
Buke Po818998e2017-08-04 01:19:07 +0800450{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700451 uint32_t keyGuardTime;
Buke Po818998e2017-08-04 01:19:07 +0800452 otError error = OT_ERROR_NONE;
453
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700454 SuccessOrExit(error = mDecoder.ReadUint32(keyGuardTime));
Buke Po818998e2017-08-04 01:19:07 +0800455
456 otThreadSetKeySwitchGuardTime(mInstance, keyGuardTime);
457
458exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700459 return error;
Buke Po818998e2017-08-04 01:19:07 +0800460}
461
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700462otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(void)
Buke Po818998e2017-08-04 01:19:07 +0800463{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700464 return mEncoder.WriteUint8(otNetDataGetVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800465}
466
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700467otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(void)
Buke Po818998e2017-08-04 01:19:07 +0800468{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700469 return mEncoder.WriteUint8(otNetDataGetStableVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800470}
471
472#if OPENTHREAD_ENABLE_BORDER_ROUTER
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700473otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(void)
Buke Po818998e2017-08-04 01:19:07 +0800474{
Buke Po818998e2017-08-04 01:19:07 +0800475 uint8_t networkData[255];
476 uint8_t networkDataLen = 255;
477
478 otBorderRouterGetNetData(
479 mInstance,
480 false, // Stable?
481 networkData,
482 &networkDataLen
483 );
484
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700485 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800486}
487
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700488otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(void)
Buke Po818998e2017-08-04 01:19:07 +0800489{
Buke Po818998e2017-08-04 01:19:07 +0800490 uint8_t networkData[255];
491 uint8_t networkDataLen = 255;
492
493 otBorderRouterGetNetData(
494 mInstance,
495 true, // Stable?
496 networkData,
497 &networkDataLen
498 );
499
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700500 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800501}
502#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
503
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700504otError NcpBase::GetPropertyHandler_THREAD_LEADER_NETWORK_DATA(void)
Buke Po818998e2017-08-04 01:19:07 +0800505{
Buke Po818998e2017-08-04 01:19:07 +0800506 uint8_t networkData[255];
507 uint8_t networkDataLen = 255;
508
509 otNetDataGet(
510 mInstance,
511 false, // Stable?
512 networkData,
513 &networkDataLen
514 );
515
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700516 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800517}
518
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700519otError NcpBase::GetPropertyHandler_THREAD_STABLE_LEADER_NETWORK_DATA(void)
Buke Po818998e2017-08-04 01:19:07 +0800520{
Buke Po818998e2017-08-04 01:19:07 +0800521 uint8_t networkData[255];
522 uint8_t networkDataLen = 255;
523
524 otNetDataGet(
525 mInstance,
526 true, // Stable?
527 networkData,
528 &networkDataLen
529 );
530
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700531 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800532}
533
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700534otError NcpBase::GetPropertyHandler_THREAD_LEADER_RID(void)
Buke Po818998e2017-08-04 01:19:07 +0800535{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700536 return mEncoder.WriteUint8(otThreadGetLeaderRouterId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800537}
538
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700539otError NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(void)
Buke Po818998e2017-08-04 01:19:07 +0800540{
541 otError error = OT_ERROR_NONE;
542 otIp6Address address;
543
544 error = otThreadGetLeaderRloc(mInstance, &address);
545
546 if (error == OT_ERROR_NONE)
547 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700548 error = mEncoder.WriteIp6Address(address);
Buke Po818998e2017-08-04 01:19:07 +0800549 }
550 else
551 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700552 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800553 }
554
555 return error;
556}
557
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700558otError NcpBase::GetPropertyHandler_THREAD_PARENT(void)
Buke Po818998e2017-08-04 01:19:07 +0800559{
560 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700561
Buke Po818998e2017-08-04 01:19:07 +0800562 otRouterInfo parentInfo;
563
564 error = otThreadGetParentInfo(mInstance, &parentInfo);
565
566 if (error == OT_ERROR_NONE)
567 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700568 SuccessOrExit(error = mEncoder.WriteEui64(parentInfo.mExtAddress)); // Parent's extended address
569 SuccessOrExit(error = mEncoder.WriteUint16(parentInfo.mRloc16));
Buke Po818998e2017-08-04 01:19:07 +0800570 }
571 else
572 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700573 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800574 }
575
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700576exit:
Buke Po818998e2017-08-04 01:19:07 +0800577 return error;
578}
579
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700580otError NcpBase::GetPropertyHandler_THREAD_NEIGHBOR_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +0800581{
582 otError error = OT_ERROR_NONE;
583 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
584 otNeighborInfo neighInfo;
585 uint8_t modeFlags;
586
Buke Po818998e2017-08-04 01:19:07 +0800587 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
588 {
589 modeFlags = LinkFlagsToFlagByte(
590 neighInfo.mRxOnWhenIdle,
591 neighInfo.mSecureDataRequest,
592 neighInfo.mFullFunction,
593 neighInfo.mFullNetworkData
594 );
595
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700596 SuccessOrExit(error = mEncoder.OpenStruct());
597
598 SuccessOrExit(error = mEncoder.WriteEui64(neighInfo.mExtAddress));
599 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mRloc16));
600 SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mAge));
601 SuccessOrExit(error = mEncoder.WriteUint8(neighInfo.mLinkQualityIn));
602 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mAverageRssi));
603 SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
604 SuccessOrExit(error = mEncoder.WriteBool(neighInfo.mIsChild));
605 SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mLinkFrameCounter));
606 SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mMleFrameCounter));
607 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mLastRssi));
608
609 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800610 }
611
Buke Po818998e2017-08-04 01:19:07 +0800612exit:
Buke Po818998e2017-08-04 01:19:07 +0800613 return error;
614}
615
Abtin Keshavarzian10f6c4f2018-02-02 10:29:52 -0800616#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
617
618otError NcpBase::GetPropertyHandler_THREAD_NEIGHBOR_TABLE_ERROR_RATES(void)
619{
620 otError error = OT_ERROR_NONE;
621 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
622 otNeighborInfo neighInfo;
623
624 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
625 {
626 SuccessOrExit(error = mEncoder.OpenStruct());
627
628 SuccessOrExit(error = mEncoder.WriteEui64(neighInfo.mExtAddress));
629 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mRloc16));
630 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mFrameErrorRate));
631 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mMessageErrorRate));
632 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mAverageRssi));
633 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mLastRssi));
634
635 SuccessOrExit(error = mEncoder.CloseStruct());
636 }
637
638exit:
639 return error;
640}
641
642#endif // OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
643
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700644otError NcpBase::GetPropertyHandler_THREAD_ASSISTING_PORTS(void)
Buke Po818998e2017-08-04 01:19:07 +0800645{
646 otError error = OT_ERROR_NONE;
647 uint8_t numEntries = 0;
648 const uint16_t *ports = otIp6GetUnsecurePorts(mInstance, &numEntries);
649
Buke Po818998e2017-08-04 01:19:07 +0800650 for (; numEntries != 0; ports++, numEntries--)
651 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700652 SuccessOrExit(error = mEncoder.WriteUint16(*ports));
Buke Po818998e2017-08-04 01:19:07 +0800653 }
654
Buke Po818998e2017-08-04 01:19:07 +0800655exit:
656 return error;
657}
658
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700659otError NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(void)
Buke Po818998e2017-08-04 01:19:07 +0800660{
661 uint8_t numEntries = 0;
662 const uint16_t *ports = otIp6GetUnsecurePorts(mInstance, &numEntries);
Buke Po818998e2017-08-04 01:19:07 +0800663 otError error = OT_ERROR_NONE;
664
665 // First, we need to remove all of the current assisting ports.
666 for (; numEntries != 0; ports++, numEntries--)
667 {
668 SuccessOrExit(error = otIp6RemoveUnsecurePort(mInstance, *ports));
Buke Po818998e2017-08-04 01:19:07 +0800669 }
670
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700671 while (mDecoder.GetRemainingLengthInStruct() >= sizeof(uint16_t))
Buke Po818998e2017-08-04 01:19:07 +0800672 {
673 uint16_t port;
674
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700675 SuccessOrExit(mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +0800676
677 SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, port));
Buke Po818998e2017-08-04 01:19:07 +0800678 }
679
Buke Po818998e2017-08-04 01:19:07 +0800680exit:
Buke Po818998e2017-08-04 01:19:07 +0800681
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700682 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800683 {
684 // We had an error, but we've actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700685 // the state of these ports, so we need to report
Buke Po818998e2017-08-04 01:19:07 +0800686 // those incomplete changes via an asynchronous
687 // change event.
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800688 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_THREAD_ASSISTING_PORTS);
Buke Po818998e2017-08-04 01:19:07 +0800689 }
690
691 return error;
692}
693
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700694otError NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(void)
Buke Po818998e2017-08-04 01:19:07 +0800695{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700696 return mEncoder.WriteBool(mAllowLocalNetworkDataChange);
Buke Po818998e2017-08-04 01:19:07 +0800697}
698
699#if OPENTHREAD_ENABLE_BORDER_ROUTER
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700700otError NcpBase::SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(void)
Buke Po818998e2017-08-04 01:19:07 +0800701{
702 bool value = false;
Buke Po818998e2017-08-04 01:19:07 +0800703 otError error = OT_ERROR_NONE;
704 bool shouldRegisterWithLeader = false;
705
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700706 SuccessOrExit(error = mDecoder.ReadBool(value));
Buke Po818998e2017-08-04 01:19:07 +0800707
708 // Register any net data changes on transition from `true` to `false`.
709 shouldRegisterWithLeader = (mAllowLocalNetworkDataChange == true) && (value == false);
710
711 mAllowLocalNetworkDataChange = value;
712
713exit:
Buke Po818998e2017-08-04 01:19:07 +0800714
715 if (shouldRegisterWithLeader)
716 {
717 otBorderRouterRegister(mInstance);
718 }
719
720 return error;
721}
722#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
723
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700724otError NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS(void)
Buke Po818998e2017-08-04 01:19:07 +0800725{
726 otError error = OT_ERROR_NONE;
727 otBorderRouterConfig borderRouterConfig;
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700728 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
Buke Po818998e2017-08-04 01:19:07 +0800729
730 // Fill from non-local network data first
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700731 while (otNetDataGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800732 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700733 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800734
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700735 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
736 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
737 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
738 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
739 SuccessOrExit(error = mEncoder.WriteBool(false)); // isLocal
740 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
741
742 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800743 }
744
745#if OPENTHREAD_ENABLE_BORDER_ROUTER
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700746
747 iter = OT_NETWORK_DATA_ITERATOR_INIT;
748
Buke Po818998e2017-08-04 01:19:07 +0800749 // Fill from local network data last
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700750 while (otBorderRouterGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800751 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700752 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800753
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700754 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
755 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
756 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
757 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
758 SuccessOrExit(error = mEncoder.WriteBool(true)); // isLocal
759 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
760
761 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800762 }
763#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
764
Buke Po818998e2017-08-04 01:19:07 +0800765exit:
Buke Po818998e2017-08-04 01:19:07 +0800766 return error;
767}
768
769#if OPENTHREAD_ENABLE_BORDER_ROUTER
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700770otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(void)
Buke Po818998e2017-08-04 01:19:07 +0800771{
Buke Po818998e2017-08-04 01:19:07 +0800772 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800773 otBorderRouterConfig borderRouterConfig;
Buke Po818998e2017-08-04 01:19:07 +0800774 bool stable = false;
775 uint8_t flags = 0;
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200776 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800777
778 memset(&borderRouterConfig, 0, sizeof(otBorderRouterConfig));
779
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700780 VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800781
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700782 SuccessOrExit(error = mDecoder.ReadIp6Address(borderRouterConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200783 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700784 SuccessOrExit(error = mDecoder.ReadBool(stable));
785 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +0800786
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200787 borderRouterConfig.mPrefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800788 borderRouterConfig.mStable = stable;
789 borderRouterConfig.mPreference =
790 ((flags & SPINEL_NET_FLAG_PREFERENCE_MASK) >> SPINEL_NET_FLAG_PREFERENCE_OFFSET);
791 borderRouterConfig.mPreferred = ((flags & SPINEL_NET_FLAG_PREFERRED) != 0);
792 borderRouterConfig.mSlaac = ((flags & SPINEL_NET_FLAG_SLAAC) != 0);
793 borderRouterConfig.mDhcp = ((flags & SPINEL_NET_FLAG_DHCP) != 0);
794 borderRouterConfig.mConfigure = ((flags & SPINEL_NET_FLAG_CONFIGURE) != 0);
795 borderRouterConfig.mDefaultRoute = ((flags & SPINEL_NET_FLAG_DEFAULT_ROUTE) != 0);
796 borderRouterConfig.mOnMesh = ((flags & SPINEL_NET_FLAG_ON_MESH) != 0);
797
798 error = otBorderRouterAddOnMeshPrefix(mInstance, &borderRouterConfig);
Buke Po818998e2017-08-04 01:19:07 +0800799
800exit:
Buke Po818998e2017-08-04 01:19:07 +0800801 return error;
802}
803
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700804otError NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(void)
Buke Po818998e2017-08-04 01:19:07 +0800805{
Buke Po818998e2017-08-04 01:19:07 +0800806 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800807 otIp6Prefix ip6Prefix;
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200808 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800809
810 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
811
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700812 VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800813
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700814 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200815 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
816
817 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800818
819 error = otBorderRouterRemoveOnMeshPrefix(mInstance, &ip6Prefix);
820
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700821 // If prefix was not on the list, "remove" command can be considred
822 // successful.
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -0700823
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700824 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +0800825 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700826 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800827 }
828
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700829exit:
Buke Po818998e2017-08-04 01:19:07 +0800830 return error;
831}
832#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
833
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700834otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_JOINER_FLAG(void)
Buke Po818998e2017-08-04 01:19:07 +0800835{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700836 return mEncoder.WriteBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800837}
838
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700839otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_JOINER_FLAG(void)
Buke Po818998e2017-08-04 01:19:07 +0800840{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700841 return mDecoder.ReadBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800842}
843
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700844otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING(void)
Buke Po818998e2017-08-04 01:19:07 +0800845{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700846 return mEncoder.WriteBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800847}
848
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700849otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING(void)
Buke Po818998e2017-08-04 01:19:07 +0800850{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700851 return mDecoder.ReadBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800852}
853
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700854otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_PANID(void)
Buke Po818998e2017-08-04 01:19:07 +0800855{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700856 return mEncoder.WriteUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800857}
858
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700859otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_PANID(void)
Buke Po818998e2017-08-04 01:19:07 +0800860{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700861 return mDecoder.ReadUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800862}
863
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800864otError NcpBase::EncodeOperationalDataset(const otOperationalDataset &aDataset)
865{
866 otError error = OT_ERROR_NONE;
867
868 if (aDataset.mIsActiveTimestampSet)
869 {
870 SuccessOrExit(mEncoder.OpenStruct());
871 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP));
872 SuccessOrExit(mEncoder.WriteUint64(aDataset.mActiveTimestamp));
873 SuccessOrExit(mEncoder.CloseStruct());
874 }
875
876 if (aDataset.mIsPendingTimestampSet)
877 {
878 SuccessOrExit(mEncoder.OpenStruct());
879 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_PENDING_TIMESTAMP));
880 SuccessOrExit(mEncoder.WriteUint64(aDataset.mPendingTimestamp));
881 SuccessOrExit(mEncoder.CloseStruct());
882 }
883
884 if (aDataset.mIsMasterKeySet)
885 {
886 SuccessOrExit(mEncoder.OpenStruct());
887 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_MASTER_KEY));
888 SuccessOrExit(mEncoder.WriteData(aDataset.mMasterKey.m8, OT_MASTER_KEY_SIZE));
889 SuccessOrExit(mEncoder.CloseStruct());
890 }
891
892 if (aDataset.mIsNetworkNameSet)
893 {
894 SuccessOrExit(mEncoder.OpenStruct());
895 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_NETWORK_NAME));
896 SuccessOrExit(mEncoder.WriteUtf8(aDataset.mNetworkName.m8));
897 SuccessOrExit(mEncoder.CloseStruct());
898 }
899
900 if (aDataset.mIsExtendedPanIdSet)
901 {
902 SuccessOrExit(mEncoder.OpenStruct());
903 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_XPANID));
904 SuccessOrExit(mEncoder.WriteData(aDataset.mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
905 SuccessOrExit(mEncoder.CloseStruct());
906 }
907
908 if (aDataset.mIsMeshLocalPrefixSet)
909 {
910 otIp6Address addr;
911
912 memcpy(addr.mFields.m8, aDataset.mMeshLocalPrefix.m8, 8);
913 memset(addr.mFields.m8 + 8, 0, 8); // Zero out the last 8 bytes.
914
915 SuccessOrExit(mEncoder.OpenStruct());
916 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_IPV6_ML_PREFIX));
917 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
918 SuccessOrExit(error = mEncoder.WriteUint8(64)); // Prefix length (in bits)
919 SuccessOrExit(mEncoder.CloseStruct());
920 }
921
922 if (aDataset.mIsDelaySet)
923 {
924 SuccessOrExit(mEncoder.OpenStruct());
925 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_DELAY_TIMER));
926 SuccessOrExit(mEncoder.WriteUint32(aDataset.mDelay));
927 SuccessOrExit(mEncoder.CloseStruct());
928 }
929
930 if (aDataset.mIsPanIdSet)
931 {
932 SuccessOrExit(mEncoder.OpenStruct());
933 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_MAC_15_4_PANID));
934 SuccessOrExit(mEncoder.WriteUint16(aDataset.mPanId));
935 SuccessOrExit(mEncoder.CloseStruct());
936 }
937
938 if (aDataset.mIsChannelSet)
939 {
940 SuccessOrExit(mEncoder.OpenStruct());
941 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN));
942
943 // The channel is stored in Dataset as `uint16_t` (to accommodate
944 // larger number of channels in sub-GHz band), however the current
945 // definition of `SPINEL_PROP_PHY_CHAN` property limits the channel
946 // to a `uint8_t`.
947
948 SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(aDataset.mChannel)));
949 SuccessOrExit(mEncoder.CloseStruct());
950 }
951
952 if (aDataset.mIsPSKcSet)
953 {
954 SuccessOrExit(mEncoder.OpenStruct());
955 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_PSKC));
956 SuccessOrExit(mEncoder.WriteData(aDataset.mPSKc.m8, sizeof(spinel_net_pskc_t)));
957 SuccessOrExit(mEncoder.CloseStruct());
958 }
959
960 if (aDataset.mIsSecurityPolicySet)
961 {
962 SuccessOrExit(mEncoder.OpenStruct());
963 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_SECURITY_POLICY));
964 SuccessOrExit(mEncoder.WriteUint16(aDataset.mSecurityPolicy.mRotationTime));
965 SuccessOrExit(mEncoder.WriteUint8(aDataset.mSecurityPolicy.mFlags));
966 SuccessOrExit(mEncoder.CloseStruct());
967 }
968
969 if (aDataset.mIsChannelMaskPage0Set)
970 {
971 SuccessOrExit(mEncoder.OpenStruct());
972 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN_SUPPORTED));
973 SuccessOrExit(EncodeChannelMask(aDataset.mChannelMaskPage0));
974 SuccessOrExit(mEncoder.CloseStruct());
975 }
976
977exit:
978 return error;
979}
980
981otError NcpBase::GetPropertyHandler_THREAD_ACTIVE_DATASET(void)
982{
983 otOperationalDataset dataset;
984
985 IgnoreReturnValue(otDatasetGetActive(mInstance, &dataset));
986 return EncodeOperationalDataset(dataset);
987}
988
989otError NcpBase::GetPropertyHandler_THREAD_PENDING_DATASET(void)
990{
991 otOperationalDataset dataset;
992
993 IgnoreReturnValue(otDatasetGetPending(mInstance, &dataset));
994 return EncodeOperationalDataset(dataset);
995}
996
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700997otError NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(void)
Buke Po818998e2017-08-04 01:19:07 +0800998{
999 otError error = OT_ERROR_NONE;
1000 const uint8_t *mlPrefix = otThreadGetMeshLocalPrefix(mInstance);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001001 otIp6Address addr;
Buke Po818998e2017-08-04 01:19:07 +08001002
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001003 VerifyOrExit(mlPrefix != NULL); // If `mlPrefix` is NULL send empty response.
Buke Po818998e2017-08-04 01:19:07 +08001004
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001005 memcpy(addr.mFields.m8, mlPrefix, 8);
Buke Po818998e2017-08-04 01:19:07 +08001006
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001007 // Zero out the last 8 bytes.
1008 memset(addr.mFields.m8 + 8, 0, 8);
Buke Po818998e2017-08-04 01:19:07 +08001009
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001010 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
1011 SuccessOrExit(error = mEncoder.WriteUint8(64)); // Prefix length (in bits)
Buke Po818998e2017-08-04 01:19:07 +08001012
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001013exit:
Buke Po818998e2017-08-04 01:19:07 +08001014 return error;
1015}
1016
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001017otError NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(void)
Buke Po818998e2017-08-04 01:19:07 +08001018{
1019 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001020 const uint8_t *meshLocalPrefix;
rongli11f32602018-03-20 23:55:41 +08001021 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001022
rongli11f32602018-03-20 23:55:41 +08001023 SuccessOrExit(error = mDecoder.ReadIp6Address(meshLocalPrefix));
1024 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
1025 VerifyOrExit(prefixLength == 64, error = OT_ERROR_INVALID_ARGS);
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001026
1027 error = otThreadSetMeshLocalPrefix(mInstance, meshLocalPrefix);
Buke Po818998e2017-08-04 01:19:07 +08001028
1029exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001030 return error;
Buke Po818998e2017-08-04 01:19:07 +08001031}
1032
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001033otError NcpBase::GetPropertyHandler_IPV6_ML_ADDR(void)
Buke Po818998e2017-08-04 01:19:07 +08001034{
1035 otError error = OT_ERROR_NONE;
1036 const otIp6Address *ml64 = otThreadGetMeshLocalEid(mInstance);
1037
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001038 VerifyOrExit(ml64 != NULL);
1039 SuccessOrExit(error = mEncoder.WriteIp6Address(*ml64));
Buke Po818998e2017-08-04 01:19:07 +08001040
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001041exit:
Buke Po818998e2017-08-04 01:19:07 +08001042 return error;
1043}
1044
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001045otError NcpBase::GetPropertyHandler_IPV6_LL_ADDR(void)
Buke Po818998e2017-08-04 01:19:07 +08001046{
1047 otError error = OT_ERROR_NONE;
1048 const otIp6Address *address = otThreadGetLinkLocalIp6Address(mInstance);
1049
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001050 VerifyOrExit(address != NULL);
1051 SuccessOrExit(error = mEncoder.WriteIp6Address(*address));
Buke Po818998e2017-08-04 01:19:07 +08001052
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001053exit:
Buke Po818998e2017-08-04 01:19:07 +08001054 return error;
1055}
1056
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001057otError NcpBase::GetPropertyHandler_IPV6_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001058{
1059 otError error = OT_ERROR_NONE;
1060
Buke Po818998e2017-08-04 01:19:07 +08001061 for (const otNetifAddress *address = otIp6GetUnicastAddresses(mInstance); address; address = address->mNext)
1062 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001063 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08001064
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001065 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1066 SuccessOrExit(error = mEncoder.WriteUint8(address->mPrefixLength));
1067 SuccessOrExit(error = mEncoder.WriteUint32(address->mPreferred ? 0xffffffff : 0));
1068 SuccessOrExit(error = mEncoder.WriteUint32(address->mValid ? 0xffffffff : 0));
1069
1070 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001071 }
1072
Buke Po818998e2017-08-04 01:19:07 +08001073exit:
Buke Po818998e2017-08-04 01:19:07 +08001074 return error;
1075}
1076
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001077otError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001078{
Buke Po818998e2017-08-04 01:19:07 +08001079 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001080 otNetifAddress netifAddr;
Buke Po818998e2017-08-04 01:19:07 +08001081 uint32_t preferredLifetime;
1082 uint32_t validLifetime;
Buke Po818998e2017-08-04 01:19:07 +08001083
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001084 SuccessOrExit(error = mDecoder.ReadIp6Address(netifAddr.mAddress));
1085 SuccessOrExit(error = mDecoder.ReadUint8(netifAddr.mPrefixLength));
1086 SuccessOrExit(error = mDecoder.ReadUint32(preferredLifetime));
1087 SuccessOrExit(error = mDecoder.ReadUint32(validLifetime));
Buke Po818998e2017-08-04 01:19:07 +08001088
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001089 netifAddr.mPreferred = (preferredLifetime != 0);
1090 netifAddr.mValid = (validLifetime != 0);
Buke Po818998e2017-08-04 01:19:07 +08001091
1092 error = otIp6AddUnicastAddress(mInstance, &netifAddr);
1093
Buke Po818998e2017-08-04 01:19:07 +08001094exit:
Buke Po818998e2017-08-04 01:19:07 +08001095 return error;
1096}
1097
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001098otError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001099{
Buke Po818998e2017-08-04 01:19:07 +08001100 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001101 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001102
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001103 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001104
1105 error = otIp6RemoveUnicastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001106
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001107 // If address was not on the list, "remove" command is successful.
1108 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001109 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001110 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001111 }
1112
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001113exit:
Buke Po818998e2017-08-04 01:19:07 +08001114 return error;
1115}
1116
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001117otError NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001118{
1119 // TODO: Implement get route table
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001120 return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
Buke Po818998e2017-08-04 01:19:07 +08001121}
1122
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001123otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
Buke Po818998e2017-08-04 01:19:07 +08001124{
Jonathan Huif602dcd2018-03-13 18:10:28 +00001125 return mEncoder.WriteBool(otIcmp6GetEchoMode(mInstance) != OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001126}
1127
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001128otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
Buke Po818998e2017-08-04 01:19:07 +08001129{
1130 bool enabled = false;
Buke Po818998e2017-08-04 01:19:07 +08001131 otError error = OT_ERROR_NONE;
1132
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001133 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001134
Jonathan Huif602dcd2018-03-13 18:10:28 +00001135 otIcmp6SetEchoMode(mInstance, enabled ? OT_ICMP6_ECHO_HANDLER_ALL : OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001136
1137exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001138 return error;
Buke Po818998e2017-08-04 01:19:07 +08001139}
1140
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001141otError NcpBase::GetPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001142{
1143 otError error = OT_ERROR_NONE;
1144 const otNetifMulticastAddress *address;
1145
Buke Po818998e2017-08-04 01:19:07 +08001146 for (address = otIp6GetMulticastAddresses(mInstance); address; address = address->mNext)
1147 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001148 SuccessOrExit(error = mEncoder.OpenStruct());
1149 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1150 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001151 }
1152
Buke Po818998e2017-08-04 01:19:07 +08001153exit:
Buke Po818998e2017-08-04 01:19:07 +08001154 return error;
1155}
1156
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001157otError NcpBase::InsertPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001158{
Buke Po818998e2017-08-04 01:19:07 +08001159 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001160 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001161
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001162 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001163
1164 error = otIp6SubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001165
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001166 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08001167 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001168 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001169 }
1170
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001171exit:
Buke Po818998e2017-08-04 01:19:07 +08001172 return error;
1173}
1174
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001175otError NcpBase::RemovePropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001176{
Buke Po818998e2017-08-04 01:19:07 +08001177 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001178 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001179
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001180 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001181
1182 error = otIp6UnsubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001183
1184 // If the address was not on the list, "remove" command is successful,
1185 // and we respond with a `SPINEL_STATUS_OK` status.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001186 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001187 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001188 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001189 }
1190
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001191exit:
Buke Po818998e2017-08-04 01:19:07 +08001192 return error;
1193}
1194
Jonathan Huif602dcd2018-03-13 18:10:28 +00001195otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD_MODE(void)
1196{
1197 spinel_ipv6_icmp_ping_offload_mode_t mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1198
1199 switch (otIcmp6GetEchoMode(mInstance))
1200 {
1201 case OT_ICMP6_ECHO_HANDLER_DISABLED:
1202 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1203 break;
1204 case OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY:
1205 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY;
1206 break;
1207 case OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY:
1208 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY;
1209 break;
1210 case OT_ICMP6_ECHO_HANDLER_ALL:
1211 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL;
1212 break;
1213 };
1214
1215 return mEncoder.WriteUint8(mode);
1216}
1217
1218otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD_MODE(void)
1219{
1220 otError error = OT_ERROR_NONE;
1221 otIcmp6EchoMode mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1222 uint8_t spinelMode;
1223
1224 SuccessOrExit(error = mDecoder.ReadUint8(spinelMode));
1225
1226 switch (spinelMode)
1227 {
1228 case SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED:
1229 mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1230 break;
1231 case SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY:
1232 mode = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY;
1233 break;
1234 case SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY:
1235 mode = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY;
1236 break;
1237 case SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL:
1238 mode = OT_ICMP6_ECHO_HANDLER_ALL;
1239 break;
1240 };
1241
1242 otIcmp6SetEchoMode(mInstance, mode);
1243
1244exit:
1245 return error;
1246}
1247
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001248otError NcpBase::GetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(void)
Buke Po818998e2017-08-04 01:19:07 +08001249{
1250 // Note reverse logic: passthru enabled = filter disabled
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001251 return mEncoder.WriteBool(!otIp6IsReceiveFilterEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001252}
1253
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001254otError NcpBase::SetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(void)
Buke Po818998e2017-08-04 01:19:07 +08001255{
1256 bool enabled = false;
Buke Po818998e2017-08-04 01:19:07 +08001257 otError error = OT_ERROR_NONE;
1258
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001259 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001260
1261 // Note reverse logic: passthru enabled = filter disabled
1262 otIp6SetReceiveFilterEnabled(mInstance, !enabled);
1263
1264exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001265 return error;
Buke Po818998e2017-08-04 01:19:07 +08001266}
1267
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001268otError NcpBase::GetPropertyHandler_THREAD_OFF_MESH_ROUTES(void)
Buke Po818998e2017-08-04 01:19:07 +08001269{
1270 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001271 otExternalRouteConfig routeConfig;
Buke Po818998e2017-08-04 01:19:07 +08001272 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
1273
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001274 while (otNetDataGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001275 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001276 SuccessOrExit(error = mEncoder.OpenStruct());
1277
1278 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1279 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1280 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1281 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
1282 SuccessOrExit(error = mEncoder.WriteBool(false)); // IsLocal
1283 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1284 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1285
1286 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001287 }
1288
1289#if OPENTHREAD_ENABLE_BORDER_ROUTER
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -07001290
1291 iter = OT_NETWORK_DATA_ITERATOR_INIT;
1292
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001293 while (otBorderRouterGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001294 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001295 SuccessOrExit(error = mEncoder.OpenStruct());
1296
1297 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1298 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1299 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1300 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
1301 SuccessOrExit(error = mEncoder.WriteBool(true)); // IsLocal
1302 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1303 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1304
1305 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001306 }
1307#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
1308
Buke Po818998e2017-08-04 01:19:07 +08001309exit:
Buke Po818998e2017-08-04 01:19:07 +08001310 return error;
1311}
1312
1313#if OPENTHREAD_ENABLE_BORDER_ROUTER
1314static int FlagByteToExternalRoutePreference(uint8_t aFlags)
1315{
1316 int route_preference = 0;
1317
1318 switch (aFlags & SPINEL_NET_FLAG_PREFERENCE_MASK)
1319 {
1320 case SPINEL_ROUTE_PREFERENCE_HIGH:
1321 route_preference = OT_ROUTE_PREFERENCE_HIGH;
1322 break;
1323
1324 case SPINEL_ROUTE_PREFERENCE_MEDIUM:
1325 route_preference = OT_ROUTE_PREFERENCE_MED;
1326 break;
1327
1328 case SPINEL_ROUTE_PREFERENCE_LOW:
1329 route_preference = OT_ROUTE_PREFERENCE_LOW;
1330 break;
1331 }
1332
1333 return route_preference;
1334}
1335
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001336otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(void)
Buke Po818998e2017-08-04 01:19:07 +08001337{
Buke Po818998e2017-08-04 01:19:07 +08001338 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001339 otExternalRouteConfig routeConfig;
Buke Po818998e2017-08-04 01:19:07 +08001340 bool stable = false;
1341 uint8_t flags = 0;
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001342 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001343
1344 memset(&routeConfig, 0, sizeof(otExternalRouteConfig));
1345
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001346 VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001347
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001348 SuccessOrExit(error = mDecoder.ReadIp6Address(routeConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001349 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001350 SuccessOrExit(error = mDecoder.ReadBool(stable));
1351 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +08001352
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001353 routeConfig.mPrefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001354 routeConfig.mStable = stable;
1355 routeConfig.mPreference = FlagByteToExternalRoutePreference(flags);
1356
1357 error = otBorderRouterAddRoute(mInstance, &routeConfig);
Buke Po818998e2017-08-04 01:19:07 +08001358
1359exit:
Buke Po818998e2017-08-04 01:19:07 +08001360 return error;
1361}
1362
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001363otError NcpBase::RemovePropertyHandler_THREAD_OFF_MESH_ROUTES(void)
Buke Po818998e2017-08-04 01:19:07 +08001364{
Buke Po818998e2017-08-04 01:19:07 +08001365 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001366 otIp6Prefix ip6Prefix;
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001367 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001368
1369 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
1370
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001371 VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001372
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001373 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001374 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
1375
1376 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001377
1378 error = otBorderRouterRemoveRoute(mInstance, &ip6Prefix);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001379
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001380 // If the route prefix was not on the list, "remove" command is successful.
1381 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001382 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001383 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001384 }
1385
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001386exit:
Buke Po818998e2017-08-04 01:19:07 +08001387 return error;
1388}
1389#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
1390
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001391otError NcpBase::SetPropertyHandler_STREAM_NET(void)
Buke Po818998e2017-08-04 01:19:07 +08001392{
1393 const uint8_t *framePtr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001394 uint16_t frameLen = 0;
Buke Po818998e2017-08-04 01:19:07 +08001395 const uint8_t *metaPtr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001396 uint16_t metaLen = 0;
1397 otMessage *message = NULL;
Buke Po818998e2017-08-04 01:19:07 +08001398 otError error = OT_ERROR_NONE;
1399
1400 // STREAM_NET requires layer 2 security.
1401 message = otIp6NewMessage(mInstance, true);
1402 VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
1403
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001404 SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
1405 SuccessOrExit(error = mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08001406
1407 // We ignore metadata for now.
1408 // May later include TX power, allow retransmits, etc...
1409 OT_UNUSED_VARIABLE(metaPtr);
1410 OT_UNUSED_VARIABLE(metaLen);
Buke Po818998e2017-08-04 01:19:07 +08001411
Abtin Keshavarzian6f584b22017-12-07 10:19:52 -08001412 SuccessOrExit(error = otMessageAppend(message, framePtr, frameLen));
Buke Po818998e2017-08-04 01:19:07 +08001413
1414 error = otIp6Send(mInstance, message);
1415
1416 // `otIp6Send()` takes ownership of `message` (in both success or
1417 // failure cases). `message` is set to NULL so it is not freed at
1418 // exit.
1419 message = NULL;
1420
1421exit:
1422
1423 if (message != NULL)
1424 {
1425 otMessageFree(message);
1426 }
1427
1428 if (error == OT_ERROR_NONE)
1429 {
1430 mInboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08001431 }
1432 else
1433 {
1434 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08001435 }
1436
Buke Po818998e2017-08-04 01:19:07 +08001437 return error;
1438}
1439
1440#if OPENTHREAD_ENABLE_JAM_DETECTION
1441
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001442otError NcpBase::GetPropertyHandler_JAM_DETECT_ENABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001443{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001444 return mEncoder.WriteBool(otJamDetectionIsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001445}
1446
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001447otError NcpBase::GetPropertyHandler_JAM_DETECTED(void)
Buke Po818998e2017-08-04 01:19:07 +08001448{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001449 return mEncoder.WriteBool(otJamDetectionGetState(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001450}
1451
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001452otError NcpBase::GetPropertyHandler_JAM_DETECT_RSSI_THRESHOLD(void)
Buke Po818998e2017-08-04 01:19:07 +08001453{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001454 return mEncoder.WriteInt8(otJamDetectionGetRssiThreshold(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001455}
1456
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001457otError NcpBase::GetPropertyHandler_JAM_DETECT_WINDOW(void)
Buke Po818998e2017-08-04 01:19:07 +08001458{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001459 return mEncoder.WriteUint8(otJamDetectionGetWindow(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001460}
1461
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001462otError NcpBase::GetPropertyHandler_JAM_DETECT_BUSY(void)
Buke Po818998e2017-08-04 01:19:07 +08001463{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001464 return mEncoder.WriteUint8(otJamDetectionGetBusyPeriod(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001465}
1466
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001467otError NcpBase::GetPropertyHandler_JAM_DETECT_HISTORY_BITMAP(void)
Buke Po818998e2017-08-04 01:19:07 +08001468{
Abtin Keshavarzian07f4ae12017-12-07 10:22:24 -08001469 return mEncoder.WriteUint64(otJamDetectionGetHistoryBitmap(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001470}
1471
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001472otError NcpBase::SetPropertyHandler_JAM_DETECT_ENABLE(void)
Buke Po818998e2017-08-04 01:19:07 +08001473{
1474 bool enabled;
Buke Po818998e2017-08-04 01:19:07 +08001475 otError error = OT_ERROR_NONE;
1476
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001477 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001478
1479 if (enabled)
1480 {
1481 otJamDetectionStart(mInstance, &NcpBase::HandleJamStateChange_Jump, this);
1482 }
1483 else
1484 {
1485 otJamDetectionStop(mInstance);
1486 }
1487
1488exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001489 return error;
Buke Po818998e2017-08-04 01:19:07 +08001490}
1491
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001492otError NcpBase::SetPropertyHandler_JAM_DETECT_RSSI_THRESHOLD(void)
Buke Po818998e2017-08-04 01:19:07 +08001493{
1494 int8_t threshold = 0;
Buke Po818998e2017-08-04 01:19:07 +08001495 otError error = OT_ERROR_NONE;
1496
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001497 SuccessOrExit(error = mDecoder.ReadInt8(threshold));
Buke Po818998e2017-08-04 01:19:07 +08001498
1499 error = otJamDetectionSetRssiThreshold(mInstance, threshold);
1500
1501exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001502 return error;
Buke Po818998e2017-08-04 01:19:07 +08001503}
1504
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001505otError NcpBase::SetPropertyHandler_JAM_DETECT_WINDOW(void)
Buke Po818998e2017-08-04 01:19:07 +08001506{
1507 uint8_t window = 0;
Buke Po818998e2017-08-04 01:19:07 +08001508 otError error = OT_ERROR_NONE;
1509
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001510 SuccessOrExit(error = mDecoder.ReadUint8(window));
Buke Po818998e2017-08-04 01:19:07 +08001511
1512 error = otJamDetectionSetWindow(mInstance, window);
1513
1514exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001515 return error;
Buke Po818998e2017-08-04 01:19:07 +08001516}
1517
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001518otError NcpBase::SetPropertyHandler_JAM_DETECT_BUSY(void)
Buke Po818998e2017-08-04 01:19:07 +08001519{
1520 uint8_t busy = 0;
Buke Po818998e2017-08-04 01:19:07 +08001521 otError error = OT_ERROR_NONE;
1522
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001523 SuccessOrExit(error = mDecoder.ReadUint8(busy));
Buke Po818998e2017-08-04 01:19:07 +08001524
1525 error = otJamDetectionSetBusyPeriod(mInstance, busy);
1526
1527exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001528 return error;
Buke Po818998e2017-08-04 01:19:07 +08001529}
1530
1531void NcpBase::HandleJamStateChange_Jump(bool aJamState, void *aContext)
1532{
1533 static_cast<NcpBase *>(aContext)->HandleJamStateChange(aJamState);
1534}
1535
1536void NcpBase::HandleJamStateChange(bool aJamState)
1537{
1538 OT_UNUSED_VARIABLE(aJamState);
1539
1540 mChangedPropsSet.AddProperty(SPINEL_PROP_JAM_DETECTED);
1541 mUpdateChangedPropsTask.Post();
1542}
1543
1544#endif // OPENTHREAD_ENABLE_JAM_DETECTION
1545
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08001546#if OPENTHREAD_ENABLE_CHANNEL_MONITOR
1547
1548otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_SAMPLE_INTERVAL(void)
1549{
1550 return mEncoder.WriteUint32(otChannelMonitorGetSampleInterval(mInstance));
1551}
1552
1553otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_RSSI_THRESHOLD(void)
1554{
1555 return mEncoder.WriteInt8(otChannelMonitorGetRssiThreshold(mInstance));
1556}
1557
1558otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_SAMPLE_WINDOW(void)
1559{
1560 return mEncoder.WriteUint32(otChannelMonitorGetSampleWindow(mInstance));
1561}
1562
1563otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_SAMPLE_COUNT(void)
1564{
1565 return mEncoder.WriteUint32(otChannelMonitorGetSampleCount(mInstance));
1566}
1567
1568otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_CHANNEL_QUALITY(void)
1569{
1570 otError error = OT_ERROR_NONE;
1571
1572 for (uint8_t channel = OT_RADIO_CHANNEL_MIN; channel <= OT_RADIO_CHANNEL_MAX; channel++)
1573 {
1574 SuccessOrExit(error = mEncoder.OpenStruct());
1575
1576 SuccessOrExit(error = mEncoder.WriteUint8(channel));
1577 SuccessOrExit(error = mEncoder.WriteUint16(otChannelMonitorGetChannelQuality(mInstance, channel)));
1578
1579 SuccessOrExit(error = mEncoder.CloseStruct());
1580 }
1581
1582exit:
1583 return error;
1584}
1585
1586#endif // OPENTHREAD_ENABLE_CHANNEL_MONITOR
1587
Abtin Keshavarzian171c9512018-01-23 09:10:13 -08001588otError NcpBase::GetPropertyHandler_MAC_CCA_FAILURE_RATE(void)
1589{
1590 return mEncoder.WriteUint16(otLinkGetCcaFailureRate(mInstance));
1591}
1592
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001593otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_TOTAL(void)
Buke Po818998e2017-08-04 01:19:07 +08001594{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001595 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxTotal);
Buke Po818998e2017-08-04 01:19:07 +08001596}
1597
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001598otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_ACK_REQ(void)
Buke Po818998e2017-08-04 01:19:07 +08001599{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001600 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAckRequested);
Buke Po818998e2017-08-04 01:19:07 +08001601}
1602
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001603otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_ACKED(void)
Buke Po818998e2017-08-04 01:19:07 +08001604{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001605 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAcked);
Buke Po818998e2017-08-04 01:19:07 +08001606}
1607
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001608otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_NO_ACK_REQ(void)
1609{
1610 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxNoAckRequested);
1611}
1612
1613otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_DATA(void)
1614{
1615 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxData);
1616}
1617
1618otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_DATA_POLL(void)
1619{
1620 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxDataPoll);
1621}
1622
1623otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BEACON(void)
1624{
1625 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeacon);
1626}
1627
1628otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BEACON_REQ(void)
1629{
1630 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeaconRequest);
1631}
1632
1633otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_OTHER(void)
1634{
1635 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxOther);
1636}
1637
1638otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_RETRY(void)
1639{
1640 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxRetry);
1641}
1642
1643otError NcpBase::GetPropertyHandler_CNTR_TX_ERR_CCA(void)
1644{
1645 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrCca);
1646}
1647
1648otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_UNICAST(void)
1649{
1650 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxUnicast);
1651}
1652
1653otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BROADCAST(void)
1654{
1655 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBroadcast);
1656}
1657
1658otError NcpBase::GetPropertyHandler_CNTR_TX_ERR_ABORT(void)
1659{
1660 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrAbort);
1661}
1662
1663otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_TOTAL(void)
1664{
1665 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxTotal);
1666}
1667
1668otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DATA(void)
1669{
1670 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxData);
1671}
1672
1673otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DATA_POLL(void)
1674{
1675 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDataPoll);
1676}
1677
1678otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BEACON(void)
1679{
1680 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeacon);
1681}
1682
1683otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BEACON_REQ(void)
1684{
1685 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeaconRequest);
1686}
1687
1688otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_OTHER(void)
1689{
1690 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxOther);
1691}
1692
1693otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_FILT_WL(void)
1694{
ronglib1baa7d2017-10-14 00:33:23 +08001695 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxAddressFiltered);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001696}
1697
1698otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_FILT_DA(void)
1699{
1700 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDestAddrFiltered);
1701}
1702
1703otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DUP(void)
1704{
1705 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDuplicated);
1706}
1707
1708otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_UNICAST(void)
1709{
1710 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxUnicast);
1711}
1712
1713otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BROADCAST(void)
1714{
1715 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBroadcast);
1716}
1717
1718otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_EMPTY(void)
1719{
1720 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrNoFrame);
1721}
1722
1723otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_UKWN_NBR(void)
1724{
1725 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrUnknownNeighbor);
1726}
1727
1728otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_NVLD_SADDR(void)
1729{
1730 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrInvalidSrcAddr);
1731}
1732
1733otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_SECURITY(void)
1734{
1735 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrSec);
1736}
1737
1738otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_BAD_FCS(void)
1739{
1740 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrFcs);
1741}
1742
1743otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_OTHER(void)
1744{
1745 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrOther);
1746}
1747
1748otError NcpBase::GetPropertyHandler_CNTR_TX_IP_SEC_TOTAL(void)
1749{
1750 return mEncoder.WriteUint32(mInboundSecureIpFrameCounter);
1751}
1752
1753otError NcpBase::GetPropertyHandler_CNTR_TX_IP_INSEC_TOTAL(void)
1754{
1755 return mEncoder.WriteUint32(mInboundInsecureIpFrameCounter);
1756}
1757
1758otError NcpBase::GetPropertyHandler_CNTR_TX_IP_DROPPED(void)
1759{
1760 return mEncoder.WriteUint32(mDroppedInboundIpFrameCounter);
1761}
1762
1763otError NcpBase::GetPropertyHandler_CNTR_RX_IP_SEC_TOTAL(void)
1764{
1765 return mEncoder.WriteUint32(mOutboundSecureIpFrameCounter);
1766}
1767
1768otError NcpBase::GetPropertyHandler_CNTR_RX_IP_INSEC_TOTAL(void)
1769{
1770 return mEncoder.WriteUint32(mOutboundInsecureIpFrameCounter);
1771}
1772
1773otError NcpBase::GetPropertyHandler_CNTR_RX_IP_DROPPED(void)
1774{
1775 return mEncoder.WriteUint32(mDroppedOutboundIpFrameCounter);
1776}
1777
1778otError NcpBase::GetPropertyHandler_CNTR_TX_SPINEL_TOTAL(void)
1779{
1780 return mEncoder.WriteUint32(mTxSpinelFrameCounter);
1781}
1782
1783otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_TOTAL(void)
1784{
1785 return mEncoder.WriteUint32(mRxSpinelFrameCounter);
1786}
1787
1788otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_OUT_OF_ORDER_TID(void)
1789{
1790 return mEncoder.WriteUint32(mRxSpinelOutOfOrderTidCounter);
1791}
1792
1793otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_ERR(void)
1794{
1795 return mEncoder.WriteUint32(mFramingErrorCounter);
1796}
1797
1798otError NcpBase::GetPropertyHandler_CNTR_IP_TX_SUCCESS(void)
1799{
1800 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxSuccess);
1801}
1802
1803otError NcpBase::GetPropertyHandler_CNTR_IP_RX_SUCCESS(void)
1804{
1805 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxSuccess);
1806}
1807
1808otError NcpBase::GetPropertyHandler_CNTR_IP_TX_FAILURE(void)
1809{
1810 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxFailure);
1811}
1812
1813otError NcpBase::GetPropertyHandler_CNTR_IP_RX_FAILURE(void)
1814{
1815 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxFailure);
1816}
1817
1818otError NcpBase::GetPropertyHandler_MSG_BUFFER_COUNTERS(void)
Buke Po818998e2017-08-04 01:19:07 +08001819{
1820 otError error = OT_ERROR_NONE;
1821 otBufferInfo bufferInfo;
1822
1823 otMessageGetBufferInfo(mInstance, &bufferInfo);
1824
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001825 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mTotalBuffers));
1826 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mFreeBuffers));
1827 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendMessages));
1828 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendBuffers));
1829 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyMessages));
1830 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyBuffers));
1831 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Messages));
1832 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Buffers));
1833 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplMessages));
1834 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplBuffers));
1835 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleMessages));
1836 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleBuffers));
1837 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpMessages));
1838 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpBuffers));
1839 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapMessages));
1840 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapBuffers));
Buke Po818998e2017-08-04 01:19:07 +08001841
1842exit:
1843 return error;
1844}
1845
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08001846otError NcpBase::GetPropertyHandler_CNTR_ALL_MAC_COUNTERS(void)
1847{
1848 otError error = OT_ERROR_NONE;
1849 const otMacCounters *counters = otLinkGetCounters(mInstance);
1850
1851 if (counters == NULL)
1852 {
1853 error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_INVALID_COMMAND_FOR_PROP);
1854 ExitNow();
1855 }
1856
1857 // Encode Tx related counters
1858 SuccessOrExit(error = mEncoder.OpenStruct());
1859 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxTotal));
1860 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxUnicast));
1861 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBroadcast));
1862 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAckRequested));
1863 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAcked));
1864 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxNoAckRequested));
1865 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxData));
1866 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxDataPoll));
1867 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeacon));
1868 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeaconRequest));
1869 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxOther));
1870 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxRetry));
1871 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrCca));
1872 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrAbort));
1873 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrBusyChannel));
1874 SuccessOrExit(error = mEncoder.CloseStruct());
1875
1876 // Encode Rx related counters
1877 SuccessOrExit(error = mEncoder.OpenStruct());
1878 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxTotal));
1879 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxUnicast));
1880 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBroadcast));
1881 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxData));
1882 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDataPoll));
1883 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeacon));
1884 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeaconRequest));
1885 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxOther));
1886 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxAddressFiltered));
1887 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDestAddrFiltered));
1888 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDuplicated));
1889 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrNoFrame));
1890 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrUnknownNeighbor));
1891 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrInvalidSrcAddr));
1892 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrSec));
1893 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrFcs));
1894 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrOther));
1895 SuccessOrExit(error = mEncoder.CloseStruct());
1896
1897exit:
1898 return error;
1899}
1900
Buke Po818998e2017-08-04 01:19:07 +08001901#if OPENTHREAD_ENABLE_MAC_FILTER
1902
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001903otError NcpBase::GetPropertyHandler_MAC_WHITELIST(void)
Buke Po818998e2017-08-04 01:19:07 +08001904{
1905 otMacFilterEntry entry;
1906 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
1907 otError error = OT_ERROR_NONE;
1908
Buke Po818998e2017-08-04 01:19:07 +08001909 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
1910 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001911 SuccessOrExit(error = mEncoder.OpenStruct());
1912
1913 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
1914 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
1915
1916 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001917 }
1918
Buke Po818998e2017-08-04 01:19:07 +08001919exit:
Buke Po818998e2017-08-04 01:19:07 +08001920 return error;
1921}
1922
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001923otError NcpBase::GetPropertyHandler_MAC_WHITELIST_ENABLED(void)
Buke Po818998e2017-08-04 01:19:07 +08001924{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001925 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_WHITELIST);
Buke Po818998e2017-08-04 01:19:07 +08001926}
1927
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001928otError NcpBase::GetPropertyHandler_MAC_BLACKLIST(void)
Buke Po818998e2017-08-04 01:19:07 +08001929{
1930 otMacFilterEntry entry;
1931 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
1932 otError error = OT_ERROR_NONE;
1933
Buke Po818998e2017-08-04 01:19:07 +08001934 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
1935 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001936 SuccessOrExit(error = mEncoder.OpenStruct());
1937 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
1938 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001939 }
1940
Buke Po818998e2017-08-04 01:19:07 +08001941exit:
Buke Po818998e2017-08-04 01:19:07 +08001942 return error;
1943}
1944
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001945otError NcpBase::GetPropertyHandler_MAC_BLACKLIST_ENABLED(void)
Buke Po818998e2017-08-04 01:19:07 +08001946{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001947 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST);
Buke Po818998e2017-08-04 01:19:07 +08001948}
1949
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001950otError NcpBase::GetPropertyHandler_MAC_FIXED_RSS(void)
Buke Po818998e2017-08-04 01:19:07 +08001951{
1952 otMacFilterEntry entry;
1953 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
1954 otError error = OT_ERROR_NONE;
1955
Buke Po818998e2017-08-04 01:19:07 +08001956 while (otLinkFilterGetNextRssIn(mInstance, &iterator, &entry) == OT_ERROR_NONE)
1957 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001958 SuccessOrExit(error = mEncoder.OpenStruct());
1959
1960 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
1961 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
1962
1963 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001964 }
1965
Buke Po818998e2017-08-04 01:19:07 +08001966exit:
Buke Po818998e2017-08-04 01:19:07 +08001967 return error;
1968}
1969
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001970otError NcpBase::SetPropertyHandler_MAC_WHITELIST(void)
Buke Po818998e2017-08-04 01:19:07 +08001971{
Buke Po818998e2017-08-04 01:19:07 +08001972 otError error = OT_ERROR_NONE;
1973
1974 // First, clear the address filter entries.
1975 otLinkFilterClearAddresses(mInstance);
1976
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001977 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08001978 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001979 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08001980 int8_t rss;
1981
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001982 SuccessOrExit(error = mDecoder.OpenStruct());
1983 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08001984
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001985 if (!mDecoder.IsAllReadInStruct())
1986 {
1987 SuccessOrExit(error = mDecoder.ReadInt8(rss));
1988 }
1989 else
Buke Po818998e2017-08-04 01:19:07 +08001990 {
1991 rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08001992 }
1993
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001994 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001995
1996 error = otLinkFilterAddAddress(mInstance, extAddress);
1997
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001998 if (error == OT_ERROR_ALREADY)
1999 {
2000 error = OT_ERROR_NONE;
2001 }
2002
2003 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002004
2005 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
2006 {
2007 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
2008 }
Buke Po818998e2017-08-04 01:19:07 +08002009 }
2010
2011exit:
2012 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002013 // the state of the whitelist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002014 // those incomplete changes via an asynchronous
2015 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002016
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002017 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002018 {
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08002019 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_WHITELIST);
Buke Po818998e2017-08-04 01:19:07 +08002020 }
2021
2022 return error;
2023}
2024
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002025otError NcpBase::SetPropertyHandler_MAC_WHITELIST_ENABLED(void)
Buke Po818998e2017-08-04 01:19:07 +08002026{
2027 bool enabled;
Buke Po818998e2017-08-04 01:19:07 +08002028 otError error = OT_ERROR_NONE;
2029 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
2030
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002031 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002032
2033 if (enabled)
2034 {
2035 mode = OT_MAC_FILTER_ADDRESS_MODE_WHITELIST;
2036 }
2037
2038 error = otLinkFilterSetAddressMode(mInstance, mode);
2039
2040exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002041 return error;
Buke Po818998e2017-08-04 01:19:07 +08002042}
2043
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002044otError NcpBase::SetPropertyHandler_MAC_BLACKLIST(void)
Buke Po818998e2017-08-04 01:19:07 +08002045{
Buke Po818998e2017-08-04 01:19:07 +08002046 otError error = OT_ERROR_NONE;
2047
2048 // First, clear the address filter entries.
2049 otLinkFilterClearAddresses(mInstance);
2050
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002051 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002052 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002053 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002054
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002055 SuccessOrExit(error = mDecoder.OpenStruct());
2056 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2057 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002058
2059 error = otLinkFilterRemoveAddress(mInstance, extAddress);
2060
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002061 if (error == OT_ERROR_ALREADY)
2062 {
2063 error = OT_ERROR_NONE;
2064 }
Buke Po818998e2017-08-04 01:19:07 +08002065
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002066 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002067 }
2068
2069exit:
2070 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002071 // the state of the blacklist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002072 // those incomplete changes via an asynchronous
2073 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002074
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002075 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002076 {
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08002077 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_BLACKLIST);
Buke Po818998e2017-08-04 01:19:07 +08002078 }
2079
2080 return error;
2081}
2082
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002083otError NcpBase::SetPropertyHandler_MAC_BLACKLIST_ENABLED(void)
Buke Po818998e2017-08-04 01:19:07 +08002084{
2085 bool enabled;
Buke Po818998e2017-08-04 01:19:07 +08002086 otError error = OT_ERROR_NONE;
2087 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
2088
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002089 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002090
2091 if (enabled)
2092 {
2093 mode = OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST;
2094 }
2095
2096 error = otLinkFilterSetAddressMode(mInstance, mode);
2097
2098exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002099 return error;
Buke Po818998e2017-08-04 01:19:07 +08002100}
2101
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002102otError NcpBase::SetPropertyHandler_MAC_FIXED_RSS(void)
Buke Po818998e2017-08-04 01:19:07 +08002103{
Buke Po818998e2017-08-04 01:19:07 +08002104 otError error = OT_ERROR_NONE;
2105
2106 // First, clear the address filter entries.
2107 otLinkFilterClearRssIn(mInstance);
2108
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002109 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002110 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002111 const otExtAddress *extAddress;
Buke Po818998e2017-08-04 01:19:07 +08002112 int8_t rss;
2113
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002114 SuccessOrExit(error = mDecoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08002115
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002116 if (mDecoder.GetRemainingLengthInStruct() > sizeof(otExtAddress))
2117 {
2118 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2119 }
2120 else
Buke Po818998e2017-08-04 01:19:07 +08002121 {
2122 extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002123 }
2124
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002125 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2126
2127 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002128
2129 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
Buke Po818998e2017-08-04 01:19:07 +08002130 }
2131
2132exit:
2133 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002134 // the state of the RssIn filter, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002135 // those incomplete changes via an asynchronous
2136 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002137
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002138 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002139 {
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08002140 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_FIXED_RSS);
Buke Po818998e2017-08-04 01:19:07 +08002141 }
2142
2143 return error;
2144}
2145#endif // OPENTHREAD_ENABLE_MAC_FILTER
2146
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002147otError NcpBase::GetPropertyHandler_THREAD_MODE(void)
Buke Po818998e2017-08-04 01:19:07 +08002148{
2149 uint8_t numericMode;
2150 otLinkModeConfig modeConfig = otThreadGetLinkMode(mInstance);
2151
2152 numericMode = LinkFlagsToFlagByte(
2153 modeConfig.mRxOnWhenIdle,
2154 modeConfig.mSecureDataRequests,
2155 modeConfig.mDeviceType,
2156 modeConfig.mNetworkData
2157 );
2158
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002159 return mEncoder.WriteUint8(numericMode);
Buke Po818998e2017-08-04 01:19:07 +08002160}
2161
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002162otError NcpBase::SetPropertyHandler_THREAD_MODE(void)
Buke Po818998e2017-08-04 01:19:07 +08002163{
2164 uint8_t numericMode = 0;
2165 otLinkModeConfig modeConfig;
Buke Po818998e2017-08-04 01:19:07 +08002166 otError error = OT_ERROR_NONE;
2167
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002168 SuccessOrExit(mDecoder.ReadUint8(numericMode));
Buke Po818998e2017-08-04 01:19:07 +08002169
2170 modeConfig.mRxOnWhenIdle = ((numericMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) == SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE);
2171 modeConfig.mSecureDataRequests =
2172 ((numericMode & SPINEL_THREAD_MODE_SECURE_DATA_REQUEST) == SPINEL_THREAD_MODE_SECURE_DATA_REQUEST);
2173 modeConfig.mDeviceType = ((numericMode & SPINEL_THREAD_MODE_FULL_FUNCTION_DEV) == SPINEL_THREAD_MODE_FULL_FUNCTION_DEV);
2174 modeConfig.mNetworkData = ((numericMode & SPINEL_THREAD_MODE_FULL_NETWORK_DATA) == SPINEL_THREAD_MODE_FULL_NETWORK_DATA);
2175
2176 error = otThreadSetLinkMode(mInstance, modeConfig);
2177
2178exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002179 return error;
Buke Po818998e2017-08-04 01:19:07 +08002180}
2181
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002182otError NcpBase::GetPropertyHandler_THREAD_CHILD_TIMEOUT(void)
Buke Po818998e2017-08-04 01:19:07 +08002183{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002184 return mEncoder.WriteUint32(otThreadGetChildTimeout(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002185}
2186
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002187otError NcpBase::GetPropertyHandler_THREAD_RLOC16(void)
Buke Po818998e2017-08-04 01:19:07 +08002188{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002189 return mEncoder.WriteUint16(otThreadGetRloc16(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002190}
2191
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002192otError NcpBase::GetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(void)
Buke Po818998e2017-08-04 01:19:07 +08002193{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002194 return mEncoder.WriteBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002195}
2196
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002197otError NcpBase::SetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(void)
Buke Po818998e2017-08-04 01:19:07 +08002198{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002199 return mDecoder.ReadBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002200}
2201
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002202otError NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(void)
Buke Po818998e2017-08-04 01:19:07 +08002203{
2204 const uint8_t *framePtr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002205 uint16_t frameLen = 0;
Buke Po818998e2017-08-04 01:19:07 +08002206 const uint8_t *metaPtr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002207 uint16_t metaLen = 0;
2208 otMessage *message = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002209 otError error = OT_ERROR_NONE;
2210
2211 // STREAM_NET_INSECURE packets are not secured at layer 2.
2212 message = otIp6NewMessage(mInstance, false);
2213 VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
2214
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002215 SuccessOrExit(mDecoder.ReadDataWithLen(framePtr, frameLen));
2216 SuccessOrExit(mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08002217
2218 // We ignore metadata for now.
2219 // May later include TX power, allow retransmits, etc...
2220 OT_UNUSED_VARIABLE(metaPtr);
2221 OT_UNUSED_VARIABLE(metaLen);
Buke Po818998e2017-08-04 01:19:07 +08002222
Abtin Keshavarzian6f584b22017-12-07 10:19:52 -08002223 SuccessOrExit(error = otMessageAppend(message, framePtr, frameLen));
Buke Po818998e2017-08-04 01:19:07 +08002224
2225 // Ensure the insecure message is forwarded using direct transmission.
2226 otMessageSetDirectTransmission(message, true);
2227
2228 error = otIp6Send(mInstance, message);
2229
2230 // `otIp6Send()` takes ownership of `message` (in both success or
2231 // failure cases). `message` is set to NULL so it is not freed at
2232 // exit.
2233 message = NULL;
2234
2235exit:
2236 if (message != NULL)
2237 {
2238 otMessageFree(message);
2239 }
2240
2241 if (error == OT_ERROR_NONE)
2242 {
2243 mInboundInsecureIpFrameCounter++;
2244
Buke Po818998e2017-08-04 01:19:07 +08002245 }
2246 else
2247 {
2248 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002249 }
2250
Buke Po818998e2017-08-04 01:19:07 +08002251 return error;
2252}
2253
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002254otError NcpBase::SetPropertyHandler_CNTR_RESET(void)
Buke Po818998e2017-08-04 01:19:07 +08002255{
2256 uint8_t value = 0;
Buke Po818998e2017-08-04 01:19:07 +08002257 otError error = OT_ERROR_NONE;
2258
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002259 SuccessOrExit(error = mDecoder.ReadUint8(value));
Buke Po818998e2017-08-04 01:19:07 +08002260
2261 VerifyOrExit(value == 1, error = OT_ERROR_INVALID_ARGS);
2262
2263 // TODO: Implement counter reset!
2264 error = OT_ERROR_NOT_IMPLEMENTED;
2265
2266exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002267 return error;
Buke Po818998e2017-08-04 01:19:07 +08002268}
2269
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002270otError NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(void)
Buke Po818998e2017-08-04 01:19:07 +08002271{
Buke Po818998e2017-08-04 01:19:07 +08002272 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002273 uint16_t port;
2274
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002275 SuccessOrExit(error = mDecoder.ReadUint16(port));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002276
2277 error = otIp6AddUnsecurePort(mInstance, port);
2278exit:
2279 return error;
2280}
2281
2282#if OPENTHREAD_ENABLE_MAC_FILTER
2283
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002284otError NcpBase::InsertPropertyHandler_MAC_WHITELIST(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002285{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002286 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002287 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002288 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
2289
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002290 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002291
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002292 if (!mDecoder.IsAllRead())
2293 {
2294 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2295 }
Buke Po818998e2017-08-04 01:19:07 +08002296
2297 error = otLinkFilterAddAddress(mInstance, extAddress);
2298
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002299 if (error == OT_ERROR_ALREADY)
2300 {
2301 error = OT_ERROR_NONE;
2302 }
2303
2304 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002305
2306 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
2307 {
2308 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
Buke Po818998e2017-08-04 01:19:07 +08002309 }
2310
Buke Po818998e2017-08-04 01:19:07 +08002311exit:
Buke Po818998e2017-08-04 01:19:07 +08002312 return error;
2313}
2314
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002315otError NcpBase::InsertPropertyHandler_MAC_BLACKLIST(void)
Buke Po818998e2017-08-04 01:19:07 +08002316{
Buke Po818998e2017-08-04 01:19:07 +08002317 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002318 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002319
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002320 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002321
2322 error = otLinkFilterAddAddress(mInstance, extAddress);
2323
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002324 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08002325 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002326 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002327 }
2328
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002329exit:
Buke Po818998e2017-08-04 01:19:07 +08002330 return error;
2331}
2332
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002333otError NcpBase::InsertPropertyHandler_MAC_FIXED_RSS(void)
Buke Po818998e2017-08-04 01:19:07 +08002334{
Buke Po818998e2017-08-04 01:19:07 +08002335 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002336 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002337 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
2338
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002339 if (mDecoder.GetRemainingLength() > sizeof(int8_t))
Buke Po818998e2017-08-04 01:19:07 +08002340 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002341 SuccessOrExit(mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002342 }
2343
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002344 SuccessOrExit(mDecoder.ReadInt8(rss));
Buke Po818998e2017-08-04 01:19:07 +08002345
2346 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
2347
Buke Po818998e2017-08-04 01:19:07 +08002348exit:
Buke Po818998e2017-08-04 01:19:07 +08002349 return error;
2350}
2351
2352#endif // OPENTHREAD_ENABLE_MAC_FILTER
2353
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002354otError NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(void)
Buke Po818998e2017-08-04 01:19:07 +08002355{
Buke Po818998e2017-08-04 01:19:07 +08002356 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002357 uint16_t port;
2358
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002359 SuccessOrExit(error = mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +08002360
2361 error = otIp6RemoveUnsecurePort(mInstance, port);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07002362
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002363 // If unsecure port was not on the list, "remove" command is successful.
2364 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08002365 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002366 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002367 }
2368
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002369exit:
Buke Po818998e2017-08-04 01:19:07 +08002370 return error;
2371}
2372
2373#if OPENTHREAD_ENABLE_MAC_FILTER
2374
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002375otError NcpBase::RemovePropertyHandler_MAC_WHITELIST(void)
Buke Po818998e2017-08-04 01:19:07 +08002376{
Buke Po818998e2017-08-04 01:19:07 +08002377 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002378 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002379
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002380 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002381
2382 error = otLinkFilterRemoveAddress(mInstance, extAddress);
2383
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002384 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08002385 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002386 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002387 }
2388
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002389exit:
Buke Po818998e2017-08-04 01:19:07 +08002390 return error;
2391}
2392
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002393otError NcpBase::RemovePropertyHandler_MAC_BLACKLIST(void)
Buke Po818998e2017-08-04 01:19:07 +08002394{
Buke Po818998e2017-08-04 01:19:07 +08002395 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002396 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002397
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002398 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002399
2400 error = otLinkFilterRemoveAddress(mInstance, extAddress);
2401
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002402 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08002403 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002404 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002405 }
2406
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002407exit:
Buke Po818998e2017-08-04 01:19:07 +08002408 return error;
2409}
2410
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002411otError NcpBase::RemovePropertyHandler_MAC_FIXED_RSS(void)
Buke Po818998e2017-08-04 01:19:07 +08002412{
Buke Po818998e2017-08-04 01:19:07 +08002413 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002414 const otExtAddress *extAddress = NULL;
Buke Po818998e2017-08-04 01:19:07 +08002415
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002416 if (mDecoder.GetRemainingLength() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002417 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002418 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002419 }
2420
2421 error = otLinkFilterRemoveRssIn(mInstance, extAddress);
2422
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002423 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08002424 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002425 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002426 }
2427
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002428exit:
Buke Po818998e2017-08-04 01:19:07 +08002429 return error;
2430}
2431
2432#endif // OPENTHREAD_ENABLE_MAC_FILTER
2433
2434#if OPENTHREAD_ENABLE_LEGACY
2435
2436void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
2437{
2438 mLegacyHandlers = aHandlers;
2439 bool isEnabled;
2440
2441 VerifyOrExit(mLegacyHandlers != NULL);
2442
2443 isEnabled = (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
2444
2445 if (isEnabled)
2446 {
2447 if (mLegacyHandlers->mStartLegacy)
2448 {
2449 mLegacyHandlers->mStartLegacy();
2450 }
2451 }
2452 else
2453 {
2454 if (mLegacyHandlers->mStopLegacy)
2455 {
2456 mLegacyHandlers->mStopLegacy();
2457 }
2458 }
2459
2460 if (mLegacyHandlers->mSetLegacyUlaPrefix)
2461 {
2462 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
2463 }
2464
2465exit:
2466 return;
2467}
2468
2469void NcpBase::HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
2470{
2471 memcpy(mLegacyUlaPrefix, aUlaPrefix, OT_NCP_LEGACY_ULA_PREFIX_LENGTH);
2472 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX);
2473 mUpdateChangedPropsTask.Post();
2474}
2475
2476void NcpBase::HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
2477{
2478 mLegacyNodeDidJoin = true;
2479 mLegacyLastJoinedNode = *aExtAddr;
2480 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED);
2481 mUpdateChangedPropsTask.Post();
2482}
2483
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002484otError NcpBase::GetPropertyHandler_NEST_LEGACY_ULA_PREFIX(void)
Buke Po818998e2017-08-04 01:19:07 +08002485{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002486 return mEncoder.WriteData(mLegacyUlaPrefix, sizeof(mLegacyUlaPrefix));
Buke Po818998e2017-08-04 01:19:07 +08002487}
2488
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002489otError NcpBase::SetPropertyHandler_NEST_LEGACY_ULA_PREFIX(void)
Buke Po818998e2017-08-04 01:19:07 +08002490{
2491 const uint8_t *ptr = NULL;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002492 uint16_t len;
Buke Po818998e2017-08-04 01:19:07 +08002493 otError error = OT_ERROR_NONE;
2494
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002495 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +08002496
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002497 VerifyOrExit(len <= sizeof(mLegacyUlaPrefix), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +08002498
2499 memset(mLegacyUlaPrefix, 0, sizeof(mLegacyUlaPrefix));
2500 memcpy(mLegacyUlaPrefix, ptr, len);
2501
2502 if ((mLegacyHandlers != NULL) && (mLegacyHandlers->mSetLegacyUlaPrefix != NULL))
2503 {
2504 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
2505 }
2506
2507exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002508 return error;
Buke Po818998e2017-08-04 01:19:07 +08002509}
2510
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002511otError NcpBase::GetPropertyHandler_NEST_LEGACY_LAST_NODE_JOINED(void)
Buke Po818998e2017-08-04 01:19:07 +08002512{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002513
Buke Po818998e2017-08-04 01:19:07 +08002514 if (!mLegacyNodeDidJoin)
2515 {
2516 memset(&mLegacyLastJoinedNode, 0, sizeof(mLegacyLastJoinedNode));
2517 }
2518
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002519 return mEncoder.WriteEui64(mLegacyLastJoinedNode);
Buke Po818998e2017-08-04 01:19:07 +08002520}
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07002521
2522void NcpBase::StartLegacy(void)
2523{
2524 mLegacyNodeDidJoin = false;
2525
2526 if ((mLegacyHandlers != NULL) && (mLegacyHandlers->mStartLegacy != NULL))
2527 {
2528 mLegacyHandlers->mStartLegacy();
2529 }
2530}
2531
2532void NcpBase::StopLegacy(void)
2533{
2534 mLegacyNodeDidJoin = false;
2535
2536 if ((mLegacyHandlers != NULL) && (mLegacyHandlers->mStopLegacy != NULL))
2537 {
2538 mLegacyHandlers->mStopLegacy();
2539 }
2540}
2541
Buke Po818998e2017-08-04 01:19:07 +08002542#endif // OPENTHREAD_ENABLE_LEGACY
2543
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08002544otError NcpBase::EncodeChannelMask(uint32_t aChannelMask)
Buke Po818998e2017-08-04 01:19:07 +08002545{
2546 otError error = OT_ERROR_NONE;
2547
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002548 for (uint8_t i = 0; i < 32; i++)
Buke Po818998e2017-08-04 01:19:07 +08002549 {
2550 if (0 != (aChannelMask & (1 << i)))
2551 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002552 SuccessOrExit(error = mEncoder.WriteUint8(i));
Buke Po818998e2017-08-04 01:19:07 +08002553 }
2554 }
2555
Buke Po818998e2017-08-04 01:19:07 +08002556exit:
2557 return error;
2558}
2559
Abtin Keshavarzian053557c2018-02-09 11:22:37 -08002560otError NcpBase::DecodeChannelMask(uint32_t &aChannelMask)
2561{
2562 otError error = OT_ERROR_NONE;
2563 uint8_t channel;
2564
2565 aChannelMask = 0;
2566
2567 while (!mDecoder.IsAllReadInStruct())
2568 {
2569 SuccessOrExit(error = mDecoder.ReadUint8(channel));
2570 VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
2571 aChannelMask |= (1U << channel);
2572 }
2573
2574exit:
2575 return error;
2576}
Buke Po818998e2017-08-04 01:19:07 +08002577
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002578otError NcpBase::GetPropertyHandler_MAC_SCAN_MASK(void)
Buke Po818998e2017-08-04 01:19:07 +08002579{
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08002580 return EncodeChannelMask(mChannelMask);
Buke Po818998e2017-08-04 01:19:07 +08002581}
2582
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002583otError NcpBase::SetPropertyHandler_MAC_SCAN_MASK(void)
Buke Po818998e2017-08-04 01:19:07 +08002584{
2585 uint32_t newMask = 0;
2586 otError error = OT_ERROR_NONE;
2587
Abtin Keshavarzian053557c2018-02-09 11:22:37 -08002588 SuccessOrExit(error = DecodeChannelMask(newMask));
2589 VerifyOrExit((~mSupportedChannelMask & newMask) == 0, error = OT_ERROR_INVALID_ARGS);
Buke Po818998e2017-08-04 01:19:07 +08002590
2591 mChannelMask = newMask;
2592
2593exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002594 return error;
Buke Po818998e2017-08-04 01:19:07 +08002595}
2596
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002597otError NcpBase::GetPropertyHandler_MAC_SCAN_PERIOD(void)
Buke Po818998e2017-08-04 01:19:07 +08002598{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002599 return mEncoder.WriteUint16(mScanPeriod);
Buke Po818998e2017-08-04 01:19:07 +08002600}
2601
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002602otError NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(void)
Buke Po818998e2017-08-04 01:19:07 +08002603{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002604 return mDecoder.ReadUint16(mScanPeriod);
Buke Po818998e2017-08-04 01:19:07 +08002605}
2606
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002607otError NcpBase::GetPropertyHandler_MAC_SCAN_STATE(void)
Buke Po818998e2017-08-04 01:19:07 +08002608{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002609 uint8_t scanState = SPINEL_SCAN_STATE_IDLE;
Buke Po818998e2017-08-04 01:19:07 +08002610
2611#if OPENTHREAD_ENABLE_RAW_LINK_API
2612
2613 if (otLinkRawIsEnabled(mInstance))
2614 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002615 scanState = (mCurScanChannel == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE : SPINEL_SCAN_STATE_ENERGY;
Buke Po818998e2017-08-04 01:19:07 +08002616 }
2617 else
2618
2619#endif // OPENTHREAD_ENABLE_RAW_LINK_API
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002620
Buke Po818998e2017-08-04 01:19:07 +08002621 {
2622 if (otLinkIsActiveScanInProgress(mInstance))
2623 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002624 scanState = SPINEL_SCAN_STATE_BEACON;
2625
Buke Po818998e2017-08-04 01:19:07 +08002626 }
2627 else if (otLinkIsEnergyScanInProgress(mInstance))
2628 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002629 scanState = SPINEL_SCAN_STATE_ENERGY;
Buke Po818998e2017-08-04 01:19:07 +08002630 }
2631 else if (otThreadIsDiscoverInProgress(mInstance))
2632 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002633 scanState = SPINEL_SCAN_STATE_DISCOVER;
Buke Po818998e2017-08-04 01:19:07 +08002634 }
2635 else
2636 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002637 scanState = SPINEL_SCAN_STATE_IDLE;
Buke Po818998e2017-08-04 01:19:07 +08002638 }
2639 }
2640
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002641 return mEncoder.WriteUint8(scanState);
Buke Po818998e2017-08-04 01:19:07 +08002642}
2643
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002644otError NcpBase::SetPropertyHandler_MAC_SCAN_STATE(void)
Buke Po818998e2017-08-04 01:19:07 +08002645{
2646 uint8_t state = 0;
Buke Po818998e2017-08-04 01:19:07 +08002647 otError error = OT_ERROR_NONE;
2648
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002649 SuccessOrExit(error = mDecoder.ReadUint8(state));
Buke Po818998e2017-08-04 01:19:07 +08002650
2651 switch (state)
2652 {
2653 case SPINEL_SCAN_STATE_IDLE:
2654 error = OT_ERROR_NONE;
2655 break;
2656
2657 case SPINEL_SCAN_STATE_BEACON:
Yakun Xu96ed7cc2018-04-17 00:28:00 +08002658#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
Buke Po818998e2017-08-04 01:19:07 +08002659 if (otLinkRawIsEnabled(mInstance))
2660 {
2661 error = OT_ERROR_NOT_IMPLEMENTED;
2662 }
2663 else
Yakun Xu96ed7cc2018-04-17 00:28:00 +08002664#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
Buke Po818998e2017-08-04 01:19:07 +08002665 {
2666 error = otLinkActiveScan(
2667 mInstance,
2668 mChannelMask,
2669 mScanPeriod,
2670 &HandleActiveScanResult_Jump,
2671 this
2672 );
2673 }
2674
2675 SuccessOrExit(error);
2676 break;
2677
2678 case SPINEL_SCAN_STATE_ENERGY:
Yakun Xu96ed7cc2018-04-17 00:28:00 +08002679#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
Buke Po818998e2017-08-04 01:19:07 +08002680 if (otLinkRawIsEnabled(mInstance))
2681 {
2682 uint8_t scanChannel;
2683
2684 // Make sure we aren't already scanning and that we have
2685 // only 1 bit set for the channel mask.
2686 VerifyOrExit(mCurScanChannel == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
2687 VerifyOrExit(HasOnly1BitSet(mChannelMask), error = OT_ERROR_INVALID_ARGS);
2688
2689 scanChannel = IndexOfMSB(mChannelMask);
2690 mCurScanChannel = (int8_t)scanChannel;
2691
2692 error = otLinkRawEnergyScan(
2693 mInstance,
2694 scanChannel,
2695 mScanPeriod,
2696 LinkRawEnergyScanDone
2697 );
2698 }
2699 else
Yakun Xu96ed7cc2018-04-17 00:28:00 +08002700#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
Buke Po818998e2017-08-04 01:19:07 +08002701 {
2702 error = otLinkEnergyScan(
2703 mInstance,
2704 mChannelMask,
2705 mScanPeriod,
2706 &HandleEnergyScanResult_Jump,
2707 this
2708 );
2709 }
2710
2711 SuccessOrExit(error);
2712 break;
2713
2714 case SPINEL_SCAN_STATE_DISCOVER:
2715 error = otThreadDiscover(
2716 mInstance,
2717 mChannelMask,
2718 mDiscoveryScanPanId,
2719 mDiscoveryScanJoinerFlag,
2720 mDiscoveryScanEnableFiltering,
2721 &HandleActiveScanResult_Jump,
2722 this
2723 );
2724
2725 SuccessOrExit(error);
2726 break;
2727
2728 default:
2729 error = OT_ERROR_INVALID_ARGS;
2730 break;
2731 }
2732
2733exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002734 return error;
Buke Po818998e2017-08-04 01:19:07 +08002735}
2736
2737void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext)
2738{
2739 static_cast<NcpBase *>(aContext)->HandleActiveScanResult(aResult);
2740}
2741
2742// ----------------------------------------------------------------------------
2743// MARK: Scan Results Glue
2744// ----------------------------------------------------------------------------
2745
2746void NcpBase::HandleActiveScanResult(otActiveScanResult *aResult)
2747{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002748 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002749
2750 if (aResult)
2751 {
2752 uint8_t flags = static_cast<uint8_t>(aResult->mVersion << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT);
2753
2754 if (aResult->mIsJoinable)
2755 {
2756 flags |= SPINEL_BEACON_THREAD_FLAG_JOINABLE;
2757 }
2758
2759 if (aResult->mIsNative)
2760 {
2761 flags |= SPINEL_BEACON_THREAD_FLAG_NATIVE;
2762 }
2763
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002764 SuccessOrExit(error = mEncoder.BeginFrame(
2765 SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
2766 SPINEL_CMD_PROP_VALUE_INSERTED,
2767 SPINEL_PROP_MAC_SCAN_BEACON
2768 ));
2769 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
2770 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mRssi));
Buke Po818998e2017-08-04 01:19:07 +08002771
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002772 SuccessOrExit(error = mEncoder.OpenStruct()); // "mac-layer data"
2773 SuccessOrExit(error = mEncoder.WriteEui64(aResult->mExtAddress));
2774 SuccessOrExit(error = mEncoder.WriteUint16(0xffff)); // short address, not given
2775 SuccessOrExit(error = mEncoder.WriteUint16(aResult->mPanId));
2776 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mLqi));
2777 SuccessOrExit(error = mEncoder.CloseStruct());
2778
2779 SuccessOrExit(error = mEncoder.OpenStruct()); // "net-layer data"
2780 SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD)); // type
2781 SuccessOrExit(error = mEncoder.WriteUint8(flags));
2782 SuccessOrExit(error = mEncoder.WriteUtf8(aResult->mNetworkName.m8));
2783 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
2784 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mSteeringData.m8, aResult->mSteeringData.mLength));
2785 SuccessOrExit(error = mEncoder.CloseStruct());
2786
2787 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08002788 }
2789 else
2790 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002791 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002792 // scan state update.
2793 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
2794 mUpdateChangedPropsTask.Post();
2795 }
Buke Po818998e2017-08-04 01:19:07 +08002796
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002797exit:
2798
2799 if (error != OT_ERROR_NONE)
2800 {
2801 // We ran out of buffer adding a scan result so remember to send
2802 // an async `LAST_STATUS(NOMEM)` when buffer space becomes
Buke Po818998e2017-08-04 01:19:07 +08002803 // available.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002804 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
2805 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08002806 }
2807}
2808
2809void NcpBase::HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext)
2810{
2811 static_cast<NcpBase *>(aContext)->HandleEnergyScanResult(aResult);
2812}
2813
2814void NcpBase::HandleEnergyScanResult(otEnergyScanResult *aResult)
2815{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002816 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002817
2818 if (aResult)
2819 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002820 SuccessOrExit(error = mEncoder.BeginFrame(
2821 SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
2822 SPINEL_CMD_PROP_VALUE_INSERTED,
Tomas Cerskus10a1db72017-11-27 18:01:03 +00002823 SPINEL_PROP_MAC_ENERGY_SCAN_RESULT
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002824 ));
2825 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
2826 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mMaxRssi));
2827 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08002828 }
2829 else
2830 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002831 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002832 // scan state update.
2833 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
2834 mUpdateChangedPropsTask.Post();
2835 }
Buke Po818998e2017-08-04 01:19:07 +08002836
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002837exit:
2838
2839 if (error != OT_ERROR_NONE)
2840 {
2841 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
2842 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08002843 }
2844}
2845
Buke Po818998e2017-08-04 01:19:07 +08002846// ----------------------------------------------------------------------------
2847// MARK: Outbound Datagram Handling
2848// ----------------------------------------------------------------------------
2849
2850void NcpBase::HandleDatagramFromStack(otMessage *aMessage, void *aContext)
2851{
2852 static_cast<NcpBase *>(aContext)->HandleDatagramFromStack(aMessage);
2853}
2854
2855void NcpBase::HandleDatagramFromStack(otMessage *aMessage)
2856{
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002857 VerifyOrExit(aMessage != NULL);
2858
2859 SuccessOrExit(otMessageQueueEnqueue(&mMessageQueue, aMessage));
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08002860
2861 // If there is no queued spinel command response, try to write/send
2862 // the datagram message immediately. If there is a queued response
2863 // or if currently out of buffer space, the IPv6 datagram message
2864 // will be sent from `HandleFrameRemovedFromNcpBuffer()` when buffer
2865 // space becomes available and after any pending spinel command
2866 // response.
2867
2868 if (IsResponseQueueEmpty())
2869 {
2870 IgnoreReturnValue(SendQueuedDatagramMessages());
2871 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002872
2873exit:
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002874 return;
2875}
2876
2877otError NcpBase::SendDatagramMessage(otMessage *aMessage)
2878{
Buke Po818998e2017-08-04 01:19:07 +08002879 otError error = OT_ERROR_NONE;
2880 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
2881 bool isSecure = otMessageIsLinkSecurityEnabled(aMessage);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002882 spinel_prop_key_t propKey = isSecure ? SPINEL_PROP_STREAM_NET : SPINEL_PROP_STREAM_NET_INSECURE;
Buke Po818998e2017-08-04 01:19:07 +08002883
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002884 SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, propKey));
2885 SuccessOrExit(error = mEncoder.WriteUint16(otMessageGetLength(aMessage)));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002886 SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
Buke Po818998e2017-08-04 01:19:07 +08002887
Buke Po818998e2017-08-04 01:19:07 +08002888 // Append any metadata (rssi, lqi, channel, etc) here!
2889
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002890 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08002891
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002892 if (isSecure)
Buke Po818998e2017-08-04 01:19:07 +08002893 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002894 mOutboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002895 }
2896 else
2897 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002898 mOutboundInsecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002899 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002900
2901exit:
2902 return error;
Buke Po818998e2017-08-04 01:19:07 +08002903}
2904
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07002905otError NcpBase::SendQueuedDatagramMessages(void)
2906{
2907 otError error = OT_ERROR_NONE;
2908 otMessage *message;
2909
2910 while ((message = otMessageQueueGetHead(&mMessageQueue)) != NULL)
2911 {
2912 // Since an `otMessage` instance can be in one queue at a time,
2913 // it is first dequeued from `mMessageQueue` before attempting
2914 // to include it in a spinel frame by calling `SendDatagramMessage()`
2915 // If forming of the spinel frame fails, the message is enqueued
2916 // back at the front of `mMessageQueue`.
2917
2918 otMessageQueueDequeue(&mMessageQueue, message);
2919
2920 error = SendDatagramMessage(message);
2921
2922 if (error != OT_ERROR_NONE)
2923 {
2924 otMessageQueueEnqueueAtHead(&mMessageQueue, message);
2925 }
2926
2927 SuccessOrExit(error);
2928 }
2929
2930exit:
2931 return error;
2932}
Buke Po818998e2017-08-04 01:19:07 +08002933
2934// ----------------------------------------------------------------------------
2935// MARK: Property/Status Changed
2936// ----------------------------------------------------------------------------
2937
Abtin Keshavarzian5b25a572017-12-13 21:50:30 -08002938void NcpBase::HandleStateChanged(uint32_t aFlags, void *aContext)
Buke Po818998e2017-08-04 01:19:07 +08002939{
2940 NcpBase *ncp = static_cast<NcpBase *>(aContext);
2941
2942 ncp->mThreadChangedFlags |= aFlags;
2943 ncp->mUpdateChangedPropsTask.Post();
2944}
2945
2946void NcpBase::ProcessThreadChangedFlags(void)
2947{
2948 static const struct
2949 {
2950 uint32_t mThreadFlag;
2951 spinel_prop_key_t mPropKey;
2952 } kFlags[] =
2953 {
2954 { OT_CHANGED_IP6_ADDRESS_ADDED, SPINEL_PROP_IPV6_ADDRESS_TABLE },
2955 { OT_CHANGED_IP6_ADDRESS_REMOVED, SPINEL_PROP_IPV6_ADDRESS_TABLE },
2956 { OT_CHANGED_THREAD_ROLE, SPINEL_PROP_NET_ROLE },
2957 { OT_CHANGED_THREAD_LL_ADDR, SPINEL_PROP_IPV6_LL_ADDR },
2958 { OT_CHANGED_THREAD_ML_ADDR, SPINEL_PROP_IPV6_ML_ADDR },
2959 { OT_CHANGED_THREAD_PARTITION_ID, SPINEL_PROP_NET_PARTITION_ID },
2960 { OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER, SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER },
2961 { OT_CHANGED_THREAD_NETDATA, SPINEL_PROP_THREAD_LEADER_NETWORK_DATA },
2962 { OT_CHANGED_THREAD_CHILD_ADDED, SPINEL_PROP_THREAD_CHILD_TABLE },
2963 { OT_CHANGED_THREAD_CHILD_REMOVED, SPINEL_PROP_THREAD_CHILD_TABLE },
2964 { OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE },
2965 { OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE },
Abtin Keshavarzian5b25a572017-12-13 21:50:30 -08002966 { OT_CHANGED_THREAD_CHANNEL, SPINEL_PROP_PHY_CHAN },
2967 { OT_CHANGED_THREAD_PANID, SPINEL_PROP_MAC_15_4_PANID },
2968 { OT_CHANGED_THREAD_NETWORK_NAME, SPINEL_PROP_NET_NETWORK_NAME },
2969 { OT_CHANGED_THREAD_EXT_PANID, SPINEL_PROP_NET_XPANID },
2970 { OT_CHANGED_MASTER_KEY, SPINEL_PROP_NET_MASTER_KEY },
2971 { OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC },
Buke Po818998e2017-08-04 01:19:07 +08002972 };
2973
2974 VerifyOrExit(mThreadChangedFlags != 0);
2975
2976 // If thread role has changed, check for possible "join" error.
2977
2978 if ((mThreadChangedFlags & OT_CHANGED_THREAD_ROLE) != 0)
2979 {
2980 if (mRequireJoinExistingNetwork)
2981 {
2982 switch (otThreadGetDeviceRole(mInstance))
2983 {
2984 case OT_DEVICE_ROLE_DETACHED:
2985 case OT_DEVICE_ROLE_DISABLED:
2986 break;
2987
2988 default:
2989 mRequireJoinExistingNetwork = false;
2990 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING);
2991 break;
2992 }
2993
2994 if ((otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_LEADER)
2995 && otThreadIsSingleton(mInstance)
2996#if OPENTHREAD_ENABLE_LEGACY
2997 && !mLegacyNodeDidJoin
2998#endif
2999 )
3000 {
3001 mThreadChangedFlags &= ~static_cast<uint32_t>(OT_CHANGED_THREAD_PARTITION_ID);
3002 otThreadSetEnabled(mInstance, false);
3003
3004 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_STACK_UP);
3005 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE);
3006 }
3007 }
3008 }
3009
3010 // Convert OT_CHANGED flags to corresponding NCP property update.
3011
3012 for (unsigned i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++)
3013 {
3014 uint32_t threadFlag = kFlags[i].mThreadFlag;
3015
3016 if (mThreadChangedFlags & threadFlag)
3017 {
Abtin Keshavarzian73922002017-10-31 14:15:04 -07003018 spinel_prop_key_t propKey = kFlags[i].mPropKey;
3019 bool shouldAddProperty = true;
3020
3021 // Child table changes are reported using the `HandleChildAdded()` and
3022 // `HandleChildRemoved()` callbacks emitting spinel `VALUE_INSERTED` and
3023 // `VALUE_REMOVED` async spinel frames. If the spinel frames could not be
3024 // added (e.g., out of NCP buffer) from the above callbacks, the flag
3025 // `mShouldEmitChildTableUpdate` is set to `true` so that the entire
3026 // child table is emitted as an unsolicited `VALUE_IS` update.
3027
3028 if (propKey == SPINEL_PROP_THREAD_CHILD_TABLE)
3029 {
3030 shouldAddProperty = mShouldEmitChildTableUpdate;
3031 mShouldEmitChildTableUpdate = false;
3032 }
3033
3034 if (shouldAddProperty)
3035 {
3036 mChangedPropsSet.AddProperty(propKey);
3037 }
Buke Po818998e2017-08-04 01:19:07 +08003038
3039 if (threadFlag == OT_CHANGED_THREAD_NETDATA)
3040 {
3041 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_ON_MESH_NETS);
3042 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_OFF_MESH_ROUTES);
3043 }
3044
3045 mThreadChangedFlags &= ~threadFlag;
3046 VerifyOrExit(mThreadChangedFlags != 0);
3047 }
3048 }
3049
3050 // Clear any remaining ThreadFlag that has no matching
3051 // NCP property update (e.g., OT_CHANGED_THREAD_RLOC_ADDED)
3052
3053 mThreadChangedFlags = 0;
3054
3055exit:
3056 return;
3057}
3058
Buke Po818998e2017-08-04 01:19:07 +08003059} // namespace Ncp
3060} // namespace ot
3061
3062// ----------------------------------------------------------------------------
3063// MARK: Legacy network APIs
3064// ----------------------------------------------------------------------------
3065
3066void otNcpRegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
3067{
3068#if OPENTHREAD_ENABLE_LEGACY
3069 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3070
3071 if (ncp != NULL)
3072 {
3073 ncp->RegisterLegacyHandlers(aHandlers);
3074 }
3075
3076#else
3077 OT_UNUSED_VARIABLE(aHandlers);
3078#endif
3079}
3080
3081void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
3082{
3083#if OPENTHREAD_ENABLE_LEGACY
3084 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3085
3086 if (ncp != NULL)
3087 {
3088 ncp->HandleDidReceiveNewLegacyUlaPrefix(aUlaPrefix);
3089 }
3090
3091#else
3092 OT_UNUSED_VARIABLE(aUlaPrefix);
3093#endif
3094}
3095
3096void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
3097{
3098#if OPENTHREAD_ENABLE_LEGACY
3099 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3100
3101 if (ncp != NULL)
3102 {
3103 ncp->HandleLegacyNodeDidJoin(aExtAddr);
3104 }
3105
3106#else
3107 OT_UNUSED_VARIABLE(aExtAddr);
3108#endif
3109}
3110
3111#endif // OPENTHREAD_MTD || OPENTHREAD_FTD