1 /*
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 full thread device specified Spinel interface to the OpenThread stack.
31 */
32
33 #include "ncp_base.hpp"
34 #include <openthread/config.h>
35
36 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
37 #include <openthread/backbone_router_ftd.h>
38 #endif
39 #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
40 #include <openthread/channel_manager.h>
41 #endif
42 #include <openthread/child_supervision.h>
43 #include <openthread/dataset.h>
44 #include <openthread/dataset_ftd.h>
45 #include <openthread/diag.h>
46 #include <openthread/icmp6.h>
47 #include <openthread/ncp.h>
48 #include <openthread/thread_ftd.h>
49 #include <openthread/platform/misc.h>
50
51 #include "common/code_utils.hpp"
52 #include "common/debug.hpp"
53 #include "instance/instance.hpp"
54 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
55 #include "meshcop/commissioner.hpp"
56 #endif
57
58 #if OPENTHREAD_FTD
59 namespace ot {
60 namespace Ncp {
61
EncodeChildInfo(const otChildInfo & aChildInfo)62 otError NcpBase::EncodeChildInfo(const otChildInfo &aChildInfo)
63 {
64 otError error = OT_ERROR_NONE;
65 uint8_t modeFlags;
66
67 modeFlags =
68 LinkFlagsToFlagByte(aChildInfo.mRxOnWhenIdle, aChildInfo.mFullThreadDevice, aChildInfo.mFullNetworkData);
69
70 SuccessOrExit(error = mEncoder.WriteEui64(aChildInfo.mExtAddress));
71 SuccessOrExit(error = mEncoder.WriteUint16(aChildInfo.mRloc16));
72 SuccessOrExit(error = mEncoder.WriteUint32(aChildInfo.mTimeout));
73 SuccessOrExit(error = mEncoder.WriteUint32(aChildInfo.mAge));
74 SuccessOrExit(error = mEncoder.WriteUint8(aChildInfo.mNetworkDataVersion));
75 SuccessOrExit(error = mEncoder.WriteUint8(aChildInfo.mLinkQualityIn));
76 SuccessOrExit(error = mEncoder.WriteInt8(aChildInfo.mAverageRssi));
77 SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
78 SuccessOrExit(error = mEncoder.WriteInt8(aChildInfo.mLastRssi));
79
80 exit:
81 return error;
82 }
83
84 // ----------------------------------------------------------------------------
85 // MARK: Property/Status Changed
86 // ----------------------------------------------------------------------------
87
88 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
HandleParentResponseInfo(otThreadParentResponseInfo * aInfo,void * aContext)89 void NcpBase::HandleParentResponseInfo(otThreadParentResponseInfo *aInfo, void *aContext)
90 {
91 VerifyOrExit(aInfo && aContext);
92
93 static_cast<NcpBase *>(aContext)->HandleParentResponseInfo(*aInfo);
94
95 exit:
96 return;
97 }
98
HandleParentResponseInfo(const otThreadParentResponseInfo & aInfo)99 void NcpBase::HandleParentResponseInfo(const otThreadParentResponseInfo &aInfo)
100 {
101 VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(SPINEL_PROP_PARENT_RESPONSE_INFO));
102
103 SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
104 SPINEL_PROP_PARENT_RESPONSE_INFO));
105
106 SuccessOrExit(mEncoder.WriteEui64(aInfo.mExtAddr));
107 SuccessOrExit(mEncoder.WriteUint16(aInfo.mRloc16));
108 SuccessOrExit(mEncoder.WriteInt8(aInfo.mRssi));
109 SuccessOrExit(mEncoder.WriteInt8(aInfo.mPriority));
110 SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality3));
111 SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality2));
112 SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality1));
113 SuccessOrExit(mEncoder.WriteBool(aInfo.mIsAttached));
114
115 SuccessOrExit(mEncoder.EndFrame());
116
117 exit:
118 return;
119 }
120 #endif // OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
121
HandleNeighborTableChanged(otNeighborTableEvent aEvent,const otNeighborTableEntryInfo * aEntry)122 void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry)
123 {
124 GetNcpInstance()->HandleNeighborTableChanged(aEvent, *aEntry);
125 }
126
HandleNeighborTableChanged(otNeighborTableEvent aEvent,const otNeighborTableEntryInfo & aEntry)127 void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry)
128 {
129 otError error = OT_ERROR_NONE;
130 unsigned int command = SPINEL_CMD_PROP_VALUE_REMOVED;
131 spinel_prop_key_t property;
132
133 switch (aEvent)
134 {
135 case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
136 command = SPINEL_CMD_PROP_VALUE_INSERTED;
137
138 OT_FALL_THROUGH;
139
140 case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
141 property = SPINEL_PROP_THREAD_CHILD_TABLE;
142 VerifyOrExit(!aEntry.mInfo.mChild.mIsStateRestoring);
143 break;
144
145 case OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED:
146 command = SPINEL_CMD_PROP_VALUE_INSERTED;
147
148 OT_FALL_THROUGH;
149
150 case OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED:
151 property = SPINEL_PROP_THREAD_NEIGHBOR_TABLE;
152 break;
153
154 default:
155 ExitNow();
156 }
157
158 VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(property));
159
160 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, command, property));
161
162 if (property == SPINEL_PROP_THREAD_CHILD_TABLE)
163 {
164 SuccessOrExit(error = EncodeChildInfo(aEntry.mInfo.mChild));
165 }
166 else
167 {
168 SuccessOrExit(error = EncodeNeighborInfo(aEntry.mInfo.mRouter));
169 }
170
171 SuccessOrExit(error = mEncoder.EndFrame());
172
173 exit:
174
175 // If the frame can not be added (out of NCP buffer space), we remember
176 // to send an async `LAST_STATUS(NOMEM)` when buffer space becomes
177 // available. Also `mShouldEmitChildTableUpdate` flag is set to `true` so
178 // that the entire child table is later emitted as `VALUE_IS` spinel frame
179 // update from `ProcessThreadChangedFlags()`.
180
181 if (error != OT_ERROR_NONE)
182 {
183 if (property == SPINEL_PROP_THREAD_CHILD_TABLE)
184 {
185 mShouldEmitChildTableUpdate = true;
186 }
187
188 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
189 mUpdateChangedPropsTask.Post();
190 }
191 }
192
193 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
194
HandleBorderAgentMeshCoPServiceChanged(void * aContext)195 void NcpBase::HandleBorderAgentMeshCoPServiceChanged(void *aContext)
196 {
197 static_cast<NcpBase *>(aContext)->HandleBorderAgentMeshCoPServiceChanged();
198 }
199
HandleBorderAgentMeshCoPServiceChanged(void)200 void NcpBase::HandleBorderAgentMeshCoPServiceChanged(void)
201 {
202 mChangedPropsSet.AddProperty(SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE);
203 mUpdateChangedPropsTask.Post();
204 }
205
206 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
207
208 // ----------------------------------------------------------------------------
209 // MARK: Individual Property Handlers
210 // ----------------------------------------------------------------------------
211
HandlePropertyGet(void)212 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT>(void)
213 {
214 return mEncoder.WriteUint8(otThreadGetLocalLeaderWeight(mInstance));
215 }
216
HandlePropertyGet(void)217 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_WEIGHT>(void)
218 {
219 return mEncoder.WriteUint8(otThreadGetLeaderWeight(mInstance));
220 }
221
HandlePropertyGet(void)222 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TABLE>(void)
223 {
224 otError error = OT_ERROR_NONE;
225 otChildInfo childInfo;
226 uint16_t maxChildren;
227
228 maxChildren = otThreadGetMaxAllowedChildren(mInstance);
229
230 for (uint16_t index = 0; index < maxChildren; index++)
231 {
232 if ((otThreadGetChildInfoByIndex(mInstance, index, &childInfo) != OT_ERROR_NONE) || childInfo.mIsStateRestoring)
233 {
234 continue;
235 }
236
237 SuccessOrExit(error = mEncoder.OpenStruct());
238 SuccessOrExit(error = EncodeChildInfo(childInfo));
239 SuccessOrExit(error = mEncoder.CloseStruct());
240 }
241
242 exit:
243 return error;
244 }
245
HandlePropertyGet(void)246 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_TABLE>(void)
247 {
248 otError error = OT_ERROR_NONE;
249 otRouterInfo routerInfo;
250 uint8_t maxRouterId;
251
252 maxRouterId = otThreadGetMaxRouterId(mInstance);
253
254 for (uint8_t routerId = 0; routerId <= maxRouterId; routerId++)
255 {
256 if ((otThreadGetRouterInfo(mInstance, routerId, &routerInfo) != OT_ERROR_NONE) || !routerInfo.mAllocated)
257 {
258 continue;
259 }
260
261 SuccessOrExit(error = mEncoder.OpenStruct());
262
263 SuccessOrExit(error = mEncoder.WriteEui64(routerInfo.mExtAddress));
264 SuccessOrExit(error = mEncoder.WriteUint16(routerInfo.mRloc16));
265 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mRouterId));
266 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mNextHop));
267 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mPathCost));
268 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mLinkQualityIn));
269 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mLinkQualityOut));
270 SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mAge));
271 SuccessOrExit(error = mEncoder.WriteBool(routerInfo.mLinkEstablished));
272
273 SuccessOrExit(error = mEncoder.CloseStruct());
274 }
275
276 exit:
277 return error;
278 }
279
HandlePropertyGet(void)280 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES>(void)
281 {
282 otError error = OT_ERROR_NONE;
283 otChildInfo childInfo;
284 uint16_t maxChildren;
285 otIp6Address ip6Address;
286 otChildIp6AddressIterator iterator = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;
287
288 maxChildren = otThreadGetMaxAllowedChildren(mInstance);
289
290 for (uint16_t childIndex = 0; childIndex < maxChildren; childIndex++)
291 {
292 if ((otThreadGetChildInfoByIndex(mInstance, childIndex, &childInfo) != OT_ERROR_NONE) ||
293 childInfo.mIsStateRestoring)
294 {
295 continue;
296 }
297
298 SuccessOrExit(error = mEncoder.OpenStruct());
299
300 SuccessOrExit(error = mEncoder.WriteEui64(childInfo.mExtAddress));
301 SuccessOrExit(error = mEncoder.WriteUint16(childInfo.mRloc16));
302
303 iterator = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;
304
305 while (otThreadGetChildNextIp6Address(mInstance, childIndex, &iterator, &ip6Address) == OT_ERROR_NONE)
306 {
307 SuccessOrExit(error = mEncoder.WriteIp6Address(ip6Address));
308 }
309
310 SuccessOrExit(error = mEncoder.CloseStruct());
311 }
312
313 exit:
314 return error;
315 }
316
HandlePropertyGet(void)317 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED>(void)
318 {
319 return mEncoder.WriteBool(otThreadIsRouterEligible(mInstance));
320 }
321
HandlePropertySet(void)322 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED>(void)
323 {
324 bool eligible;
325 otError error = OT_ERROR_NONE;
326
327 SuccessOrExit(error = mDecoder.ReadBool(eligible));
328
329 error = otThreadSetRouterEligible(mInstance, eligible);
330
331 exit:
332 return error;
333 }
334
HandlePropertyGet(void)335 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT>(void)
336 {
337 return mEncoder.WriteUint8(otLinkGetMaxFrameRetriesIndirect(mInstance));
338 }
339
HandlePropertySet(void)340 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT>(void)
341 {
342 uint8_t maxFrameRetriesIndirect;
343 otError error = OT_ERROR_NONE;
344
345 SuccessOrExit(error = mDecoder.ReadUint8(maxFrameRetriesIndirect));
346 otLinkSetMaxFrameRetriesIndirect(mInstance, maxFrameRetriesIndirect);
347
348 exit:
349 return error;
350 }
351
352 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
HandlePropertyGet(void)353 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
354 {
355 return mEncoder.WriteUtf8(otThreadGetDomainName(mInstance));
356 }
357
HandlePropertySet(void)358 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
359 {
360 otError error = OT_ERROR_NONE;
361 const char *domainName;
362
363 SuccessOrExit(error = mDecoder.ReadUtf8(domainName));
364
365 error = otThreadSetDomainName(mInstance, domainName);
366
367 exit:
368 return error;
369 }
370 #endif
371
372 #if OPENTHREAD_CONFIG_DUA_ENABLE
HandlePropertyGet(void)373 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DUA_ID>(void)
374 {
375 const otIp6InterfaceIdentifier *iid = otThreadGetFixedDuaInterfaceIdentifier(mInstance);
376 otError error = OT_ERROR_NONE;
377
378 if (iid == nullptr)
379 {
380 // send empty response
381 }
382 else
383 {
384 for (uint8_t i : iid->mFields.m8)
385 {
386 SuccessOrExit(error = mEncoder.WriteUint8(i));
387 }
388 }
389
390 exit:
391 return error;
392 }
393
HandlePropertySet(void)394 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DUA_ID>(void)
395 {
396 otError error = OT_ERROR_NONE;
397
398 if (mDecoder.GetRemainingLength() == 0)
399 {
400 SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, nullptr));
401 }
402 else
403 {
404 otIp6InterfaceIdentifier iid;
405
406 for (uint8_t &i : iid.mFields.m8)
407 {
408 SuccessOrExit(error = mDecoder.ReadUint8(i));
409 }
410
411 SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, &iid));
412 }
413
414 exit:
415 return error;
416 }
417 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
418
419 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
HandlePropertyGet(void)420 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
421 {
422 uint8_t state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;
423
424 switch (otBackboneRouterGetState(mInstance))
425 {
426 case OT_BACKBONE_ROUTER_STATE_DISABLED:
427 state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;
428 break;
429
430 case OT_BACKBONE_ROUTER_STATE_SECONDARY:
431 state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_SECONDARY;
432 break;
433
434 case OT_BACKBONE_ROUTER_STATE_PRIMARY:
435 state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY;
436 break;
437 }
438
439 return mEncoder.WriteUint8(state);
440 }
441
HandlePropertySet(void)442 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
443 {
444 uint8_t state;
445 otError error = OT_ERROR_NONE;
446
447 SuccessOrExit(error = mDecoder.ReadUint8(state));
448
449 if (state)
450 {
451 otBackboneRouterSetEnabled(mInstance, true);
452 }
453 else
454 {
455 otBackboneRouterSetEnabled(mInstance, false);
456 }
457
458 exit:
459 return error;
460 }
461
HandlePropertyGet(void)462 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
463 {
464 otError error = OT_ERROR_NONE;
465 otBackboneRouterConfig bbrConfig;
466
467 otBackboneRouterGetConfig(mInstance, &bbrConfig);
468
469 SuccessOrExit(error = mEncoder.WriteUint16(bbrConfig.mReregistrationDelay));
470 SuccessOrExit(error = mEncoder.WriteUint32(bbrConfig.mMlrTimeout));
471 SuccessOrExit(error = mEncoder.WriteUint8(bbrConfig.mSequenceNumber));
472
473 exit:
474 return error;
475 }
476
HandlePropertySet(void)477 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
478 {
479 otError error = OT_ERROR_NONE;
480 otBackboneRouterConfig bbrConfig;
481
482 SuccessOrExit(error = mDecoder.ReadUint16(bbrConfig.mReregistrationDelay));
483 SuccessOrExit(error = mDecoder.ReadUint32(bbrConfig.mMlrTimeout));
484 SuccessOrExit(error = mDecoder.ReadUint8(bbrConfig.mSequenceNumber));
485
486 SuccessOrExit(error = otBackboneRouterSetConfig(mInstance, &bbrConfig));
487
488 exit:
489 return error;
490 }
491
HandlePropertySet(void)492 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER>(void)
493 {
494 return otBackboneRouterRegister(mInstance);
495 }
496
HandlePropertyGet(void)497 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
498 {
499 uint8_t jitter = otBackboneRouterGetRegistrationJitter(mInstance);
500
501 return mEncoder.WriteUint8(jitter);
502 }
503
HandlePropertySet(void)504 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
505 {
506 otError error = OT_ERROR_NONE;
507 uint8_t jitter;
508
509 SuccessOrExit(error = mDecoder.ReadUint8(jitter));
510
511 otBackboneRouterSetRegistrationJitter(mInstance, jitter);
512
513 exit:
514 return error;
515 }
516 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
517
HandlePropertyGet(void)518 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_PSKC>(void)
519 {
520 Pskc pskc;
521
522 otThreadGetPskc(mInstance, &pskc);
523
524 return mEncoder.WriteData(pskc.m8, sizeof(spinel_net_pskc_t));
525 }
526
HandlePropertySet(void)527 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_PSKC>(void)
528 {
529 const uint8_t *ptr = nullptr;
530 uint16_t len;
531 otError error = OT_ERROR_NONE;
532
533 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
534
535 VerifyOrExit(len == sizeof(spinel_net_pskc_t), error = OT_ERROR_PARSE);
536
537 error = otThreadSetPskc(mInstance, reinterpret_cast<const otPskc *>(ptr));
538
539 exit:
540 return error;
541 }
542
543 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
HandlePropertySet(void)544 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_PARTITION_ID>(void)
545 {
546 uint32_t partitionId = 0;
547 otError error = OT_ERROR_NONE;
548
549 SuccessOrExit(error = mDecoder.ReadUint32(partitionId));
550
551 otThreadSetPreferredLeaderPartitionId(mInstance, partitionId);
552
553 exit:
554 return error;
555 }
556 #endif
557
HandlePropertyGet(void)558 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_COUNT_MAX>(void)
559 {
560 return mEncoder.WriteUint8(static_cast<uint8_t>(otThreadGetMaxAllowedChildren(mInstance)));
561 }
562
HandlePropertySet(void)563 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CHILD_COUNT_MAX>(void)
564 {
565 uint8_t maxChildren = 0;
566 otError error = OT_ERROR_NONE;
567
568 SuccessOrExit(error = mDecoder.ReadUint8(maxChildren));
569
570 error = otThreadSetMaxAllowedChildren(mInstance, maxChildren);
571
572 exit:
573 return error;
574 }
575
HandlePropertyGet(void)576 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD>(void)
577 {
578 return mEncoder.WriteUint8(otThreadGetRouterUpgradeThreshold(mInstance));
579 }
580
HandlePropertySet(void)581 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD>(void)
582 {
583 uint8_t threshold = 0;
584 otError error = OT_ERROR_NONE;
585
586 SuccessOrExit(error = mDecoder.ReadUint8(threshold));
587
588 otThreadSetRouterUpgradeThreshold(mInstance, threshold);
589
590 exit:
591 return error;
592 }
593
HandlePropertyGet(void)594 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD>(void)
595 {
596 return mEncoder.WriteUint8(otThreadGetRouterDowngradeThreshold(mInstance));
597 }
598
HandlePropertySet(void)599 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD>(void)
600 {
601 uint8_t threshold = 0;
602 otError error = OT_ERROR_NONE;
603
604 SuccessOrExit(error = mDecoder.ReadUint8(threshold));
605
606 otThreadSetRouterDowngradeThreshold(mInstance, threshold);
607
608 exit:
609 return error;
610 }
611
HandlePropertyGet(void)612 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER>(void)
613 {
614 return mEncoder.WriteUint8(otThreadGetRouterSelectionJitter(mInstance));
615 }
616
HandlePropertySet(void)617 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER>(void)
618 {
619 uint8_t jitter = 0;
620 otError error = OT_ERROR_NONE;
621
622 SuccessOrExit(error = mDecoder.ReadUint8(jitter));
623
624 otThreadSetRouterSelectionJitter(mInstance, jitter);
625
626 exit:
627 return error;
628 }
629
HandlePropertyGet(void)630 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY>(void)
631 {
632 return mEncoder.WriteUint32(otThreadGetContextIdReuseDelay(mInstance));
633 }
634
HandlePropertySet(void)635 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY>(void)
636 {
637 uint32_t delay = 0;
638 otError error = OT_ERROR_NONE;
639
640 SuccessOrExit(error = mDecoder.ReadUint32(delay));
641
642 otThreadSetContextIdReuseDelay(mInstance, delay);
643
644 exit:
645 return error;
646 }
647
HandlePropertyGet(void)648 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT>(void)
649 {
650 return mEncoder.WriteUint8(otThreadGetNetworkIdTimeout(mInstance));
651 }
652
HandlePropertySet(void)653 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT>(void)
654 {
655 uint8_t timeout = 0;
656 otError error = OT_ERROR_NONE;
657
658 SuccessOrExit(error = mDecoder.ReadUint8(timeout));
659
660 otThreadSetNetworkIdTimeout(mInstance, timeout);
661
662 exit:
663 return error;
664 }
665
HandlePropertyGet(void)666 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEW_DATASET>(void)
667 {
668 otError error;
669 otOperationalDataset dataset;
670
671 error = otDatasetCreateNewNetwork(mInstance, &dataset);
672
673 if (error == OT_ERROR_NONE)
674 {
675 error = EncodeOperationalDataset(dataset);
676 }
677 else
678 {
679 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
680 }
681
682 return error;
683 }
684
685 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
686
HandlePropertyGet(void)687 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_STATE>(void)
688 {
689 uint8_t state = SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED;
690
691 switch (otCommissionerGetState(mInstance))
692 {
693 case OT_COMMISSIONER_STATE_DISABLED:
694 state = SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED;
695 break;
696
697 case OT_COMMISSIONER_STATE_PETITION:
698 state = SPINEL_MESHCOP_COMMISSIONER_STATE_PETITION;
699 break;
700
701 case OT_COMMISSIONER_STATE_ACTIVE:
702 state = SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE;
703 break;
704 }
705
706 return mEncoder.WriteUint8(state);
707 }
708
HandlePropertySet(void)709 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_STATE>(void)
710 {
711 uint8_t state;
712 otError error = OT_ERROR_NONE;
713
714 SuccessOrExit(error = mDecoder.ReadUint8(state));
715
716 switch (state)
717 {
718 case SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED:
719 error = otCommissionerStop(mInstance);
720 break;
721
722 case SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE:
723 error = otCommissionerStart(mInstance, nullptr, nullptr, nullptr);
724 break;
725
726 default:
727 error = OT_ERROR_INVALID_ARGS;
728 break;
729 }
730
731 exit:
732 return error;
733 }
734
HandlePropertyGet(void)735 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
736 {
737 otError error = OT_ERROR_NONE;
738 uint16_t iter = 0;
739 otJoinerInfo joinerInfo;
740
741 while (otCommissionerGetNextJoinerInfo(mInstance, &iter, &joinerInfo) == OT_ERROR_NONE)
742 {
743 SuccessOrExit(error = mEncoder.OpenStruct());
744
745 SuccessOrExit(error = mEncoder.OpenStruct()); // Joiner Id (any, EUI64 or a Joiner Discerner) struct
746
747 switch (joinerInfo.mType)
748 {
749 case OT_JOINER_INFO_TYPE_ANY:
750 break;
751
752 case OT_JOINER_INFO_TYPE_EUI64:
753 SuccessOrExit(error = mEncoder.WriteEui64(joinerInfo.mSharedId.mEui64));
754 break;
755
756 case OT_JOINER_INFO_TYPE_DISCERNER:
757 SuccessOrExit(error = mEncoder.WriteUint8(joinerInfo.mSharedId.mDiscerner.mLength));
758 SuccessOrExit(error = mEncoder.WriteUint64(joinerInfo.mSharedId.mDiscerner.mValue));
759 break;
760 }
761
762 SuccessOrExit(error = mEncoder.CloseStruct());
763
764 SuccessOrExit(error = mEncoder.WriteUint32(joinerInfo.mExpirationTime));
765 SuccessOrExit(error = mEncoder.WriteUtf8(joinerInfo.mPskd.m8));
766
767 SuccessOrExit(error = mEncoder.CloseStruct());
768 }
769
770 exit:
771 return error;
772 }
773
HandlePropertyInsert(void)774 template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
775 {
776 otError error = OT_ERROR_NONE;
777 otJoinerDiscerner discerner;
778 bool withDiscerner = false;
779 const otExtAddress *eui64;
780 uint32_t timeout;
781 const char *psk;
782
783 SuccessOrExit(error = mDecoder.OpenStruct());
784
785 switch (mDecoder.GetRemainingLengthInStruct())
786 {
787 case 0:
788 // Empty struct indicates any joiner
789 eui64 = nullptr;
790 break;
791
792 case sizeof(spinel_eui64_t):
793 SuccessOrExit(error = mDecoder.ReadEui64(eui64));
794 break;
795
796 default:
797 SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
798 SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
799 withDiscerner = true;
800 break;
801 }
802
803 SuccessOrExit(error = mDecoder.CloseStruct());
804
805 SuccessOrExit(error = mDecoder.ReadUint32(timeout));
806 SuccessOrExit(error = mDecoder.ReadUtf8(psk));
807
808 if (withDiscerner)
809 {
810 error = otCommissionerAddJoinerWithDiscerner(mInstance, &discerner, psk, timeout);
811 }
812 else
813 {
814 error = otCommissionerAddJoiner(mInstance, eui64, psk, timeout);
815 }
816
817 exit:
818 return error;
819 }
820
HandlePropertyRemove(void)821 template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
822 {
823 otError error = OT_ERROR_NONE;
824 otJoinerDiscerner discerner;
825 bool withDiscerner = false;
826 const otExtAddress *eui64;
827
828 SuccessOrExit(error = mDecoder.OpenStruct());
829
830 switch (mDecoder.GetRemainingLengthInStruct())
831 {
832 case 0:
833 // Empty struct indicates any joiner
834 eui64 = nullptr;
835 break;
836
837 case sizeof(spinel_eui64_t):
838 SuccessOrExit(error = mDecoder.ReadEui64(eui64));
839 break;
840
841 default:
842 SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
843 SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
844 withDiscerner = true;
845 break;
846 }
847
848 SuccessOrExit(error = mDecoder.CloseStruct());
849
850 if (withDiscerner)
851 {
852 error = otCommissionerRemoveJoinerWithDiscerner(mInstance, &discerner);
853 }
854 else
855 {
856 error = otCommissionerRemoveJoiner(mInstance, eui64);
857 }
858
859 exit:
860 return error;
861 }
862
HandlePropertyGet(void)863 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL>(void)
864 {
865 return mEncoder.WriteUtf8(otCommissionerGetProvisioningUrl(mInstance));
866 }
867
HandlePropertySet(void)868 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL>(void)
869 {
870 otError error = OT_ERROR_NONE;
871 const char *url;
872
873 SuccessOrExit(error = mDecoder.ReadUtf8(url));
874
875 error = otCommissionerSetProvisioningUrl(mInstance, url);
876
877 exit:
878 return error;
879 }
880
HandlePropertyGet(void)881 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID>(void)
882 {
883 return mEncoder.WriteUint16(otCommissionerGetSessionId(mInstance));
884 }
885
HandlePropertySet(void)886 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN>(void)
887 {
888 otError error = OT_ERROR_NONE;
889 uint32_t channelMask;
890 uint8_t count;
891 uint16_t period;
892 const otIp6Address *address;
893
894 SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
895 SuccessOrExit(error = mDecoder.ReadUint8(count));
896 SuccessOrExit(error = mDecoder.ReadUint16(period));
897 SuccessOrExit(error = mDecoder.ReadIp6Address(address));
898
899 error = otCommissionerAnnounceBegin(mInstance, channelMask, count, period, address);
900
901 exit:
902 return error;
903 }
904
HandlePropertySet(void)905 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN>(void)
906 {
907 otError error = OT_ERROR_NONE;
908 uint32_t channelMask;
909 uint8_t count;
910 uint16_t period;
911 uint16_t scanDuration;
912 const otIp6Address *address;
913
914 SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
915 SuccessOrExit(error = mDecoder.ReadUint8(count));
916 SuccessOrExit(error = mDecoder.ReadUint16(period));
917 SuccessOrExit(error = mDecoder.ReadUint16(scanDuration));
918 SuccessOrExit(error = mDecoder.ReadIp6Address(address));
919
920 error = otCommissionerEnergyScan(mInstance, channelMask, count, period, scanDuration, address,
921 &NcpBase::HandleCommissionerEnergyReport_Jump, this);
922
923 exit:
924 return error;
925 }
926
HandleCommissionerEnergyReport_Jump(uint32_t aChannelMask,const uint8_t * aEnergyData,uint8_t aLength,void * aContext)927 void NcpBase::HandleCommissionerEnergyReport_Jump(uint32_t aChannelMask,
928 const uint8_t *aEnergyData,
929 uint8_t aLength,
930 void *aContext)
931 {
932 static_cast<NcpBase *>(aContext)->HandleCommissionerEnergyReport(aChannelMask, aEnergyData, aLength);
933 }
934
HandleCommissionerEnergyReport(uint32_t aChannelMask,const uint8_t * aEnergyData,uint8_t aLength)935 void NcpBase::HandleCommissionerEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyData, uint8_t aLength)
936 {
937 otError error = OT_ERROR_NONE;
938
939 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_INSERTED,
940 SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT));
941 SuccessOrExit(error = mEncoder.WriteUint32(aChannelMask));
942 SuccessOrExit(error = mEncoder.WriteDataWithLen(aEnergyData, aLength));
943 SuccessOrExit(error = mEncoder.EndFrame());
944
945 exit:
946
947 if (error != OT_ERROR_NONE)
948 {
949 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
950 mUpdateChangedPropsTask.Post();
951 }
952 }
953
HandlePropertySet(void)954 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_QUERY>(void)
955 {
956 otError error = OT_ERROR_NONE;
957 uint16_t panId;
958 uint32_t channelMask;
959 const otIp6Address *address;
960
961 SuccessOrExit(error = mDecoder.ReadUint16(panId));
962 SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
963 SuccessOrExit(error = mDecoder.ReadIp6Address(address));
964
965 error = otCommissionerPanIdQuery(mInstance, panId, channelMask, address,
966 &NcpBase::HandleCommissionerPanIdConflict_Jump, this);
967
968 exit:
969 return error;
970 }
971
HandleCommissionerPanIdConflict_Jump(uint16_t aPanId,uint32_t aChannelMask,void * aContext)972 void NcpBase::HandleCommissionerPanIdConflict_Jump(uint16_t aPanId, uint32_t aChannelMask, void *aContext)
973 {
974 static_cast<NcpBase *>(aContext)->HandleCommissionerPanIdConflict(aPanId, aChannelMask);
975 }
976
HandleCommissionerPanIdConflict(uint16_t aPanId,uint32_t aChannelMask)977 void NcpBase::HandleCommissionerPanIdConflict(uint16_t aPanId, uint32_t aChannelMask)
978 {
979 otError error = OT_ERROR_NONE;
980
981 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_INSERTED,
982 SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT));
983
984 SuccessOrExit(error = mEncoder.WriteUint16(aPanId));
985 SuccessOrExit(error = mEncoder.WriteUint32(aChannelMask));
986 SuccessOrExit(error = mEncoder.EndFrame());
987
988 exit:
989
990 if (error != OT_ERROR_NONE)
991 {
992 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
993 mUpdateChangedPropsTask.Post();
994 }
995 }
996
HandlePropertySet(void)997 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET>(void)
998 {
999 otError error = OT_ERROR_NONE;
1000 const uint8_t *tlvs;
1001 uint16_t length;
1002
1003 SuccessOrExit(error = mDecoder.ReadDataWithLen(tlvs, length));
1004 VerifyOrExit(length <= 255, error = OT_ERROR_INVALID_ARGS);
1005
1006 error = otCommissionerSendMgmtGet(mInstance, tlvs, static_cast<uint8_t>(length));
1007
1008 exit:
1009 return error;
1010 }
1011
HandlePropertySet(void)1012 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET>(void)
1013 {
1014 otError error = OT_ERROR_NONE;
1015 const uint8_t *tlvs;
1016 uint16_t length;
1017 otCommissioningDataset dataset;
1018
1019 SuccessOrExit(error = mDecoder.ReadDataWithLen(tlvs, length));
1020 VerifyOrExit(length <= 255, error = OT_ERROR_INVALID_ARGS);
1021
1022 memset(&dataset, 0, sizeof(otCommissioningDataset));
1023 error = otCommissionerSendMgmtSet(mInstance, &dataset, tlvs, static_cast<uint8_t>(length));
1024
1025 exit:
1026 return error;
1027 }
1028
HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(uint8_t aHeader)1029 otError NcpBase::HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(uint8_t aHeader)
1030 {
1031 otError error = OT_ERROR_NONE;
1032 const char *passPhrase;
1033 const char *networkName;
1034 const uint8_t *extPanIdData;
1035 uint16_t length;
1036 otPskc pskc;
1037
1038 SuccessOrExit(error = mDecoder.ReadUtf8(passPhrase));
1039 SuccessOrExit(error = mDecoder.ReadUtf8(networkName));
1040 SuccessOrExit(error = mDecoder.ReadDataWithLen(extPanIdData, length));
1041 VerifyOrExit(length == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);
1042
1043 SuccessOrExit(error = otDatasetGeneratePskc(passPhrase, reinterpret_cast<const otNetworkName *>(networkName),
1044 reinterpret_cast<const otExtendedPanId *>(extPanIdData), &pskc));
1045
1046 SuccessOrExit(
1047 error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC));
1048 SuccessOrExit(error = mEncoder.WriteData(pskc.m8, sizeof(pskc)));
1049 SuccessOrExit(error = mEncoder.EndFrame());
1050
1051 exit:
1052 return error;
1053 }
1054
1055 // SPINEL_PROP_THREAD_COMMISSIONER_ENABLED is replaced by SPINEL_PROP_MESHCOP_COMMISSIONER_STATE. Please use the new
1056 // property. The old property/implementation remains for backward compatibility.
1057
HandlePropertyGet(void)1058 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_COMMISSIONER_ENABLED>(void)
1059 {
1060 return mEncoder.WriteBool(otCommissionerGetState(mInstance) == OT_COMMISSIONER_STATE_ACTIVE);
1061 }
1062
HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader)1063 otError NcpBase::HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader)
1064 {
1065 bool enabled = false;
1066 otError error = OT_ERROR_NONE;
1067
1068 SuccessOrExit(error = mDecoder.ReadBool(enabled));
1069
1070 if (!enabled)
1071 {
1072 error = otCommissionerStop(mInstance);
1073 }
1074 else
1075 {
1076 error = otCommissionerStart(mInstance, nullptr, nullptr, nullptr);
1077 }
1078
1079 exit:
1080 return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error));
1081 }
1082
1083 // SPINEL_PROP_THREAD_JOINERS is replaced by SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS. Please us the new property.
1084 // The old property/implementation remains for backward compatibility.
1085
HandlePropertyInsert(void)1086 template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_JOINERS>(void)
1087 {
1088 otError error = OT_ERROR_NONE;
1089 const otExtAddress *eui64 = nullptr;
1090 const char *pskd = nullptr;
1091 uint32_t joinerTimeout = 0;
1092
1093 SuccessOrExit(error = mDecoder.ReadUtf8(pskd));
1094 SuccessOrExit(error = mDecoder.ReadUint32(joinerTimeout));
1095
1096 if (mDecoder.ReadEui64(eui64) != OT_ERROR_NONE)
1097 {
1098 eui64 = nullptr;
1099 }
1100
1101 error = otCommissionerAddJoiner(mInstance, eui64, pskd, joinerTimeout);
1102
1103 exit:
1104 return error;
1105 }
1106 #endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
1107
HandlePropertySet(void)1108 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT>(void)
1109 {
1110 uint8_t weight;
1111 otError error = OT_ERROR_NONE;
1112
1113 SuccessOrExit(error = mDecoder.ReadUint8(weight));
1114
1115 otThreadSetLocalLeaderWeight(mInstance, weight);
1116
1117 exit:
1118 return error;
1119 }
1120
1121 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
1122
HandlePropertyGet(void)1123 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STEERING_DATA>(void)
1124 {
1125 return mEncoder.WriteEui64(mSteeringDataAddress);
1126 }
1127
HandlePropertySet(void)1128 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_STEERING_DATA>(void)
1129 {
1130 otError error = OT_ERROR_NONE;
1131
1132 SuccessOrExit(error = mDecoder.ReadEui64(mSteeringDataAddress));
1133
1134 otThreadSetSteeringData(mInstance, &mSteeringDataAddress);
1135
1136 exit:
1137 return error;
1138 }
1139 #endif // #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
1140
HandlePropertyGet(void)1141 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID>(void)
1142 {
1143 return mEncoder.WriteUint8(mPreferredRouteId);
1144 }
1145
HandlePropertySet(void)1146 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID>(void)
1147 {
1148 otError error = OT_ERROR_NONE;
1149
1150 SuccessOrExit(error = mDecoder.ReadUint8(mPreferredRouteId));
1151
1152 SuccessOrExit(error = otThreadSetPreferredRouterId(mInstance, mPreferredRouteId));
1153
1154 exit:
1155 return error;
1156 }
1157
HandlePropertyRemove(void)1158 template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS>(void)
1159 {
1160 otError error = OT_ERROR_NONE;
1161 uint8_t routerId;
1162
1163 SuccessOrExit(error = mDecoder.ReadUint8(routerId));
1164
1165 error = otThreadReleaseRouterId(mInstance, routerId);
1166
1167 // `INVALID_STATE` is returned when router ID was not allocated (i.e. not in the list)
1168 // in such a case, the "remove" operation can be considered successful.
1169
1170 if (error == OT_ERROR_INVALID_STATE)
1171 {
1172 error = OT_ERROR_NONE;
1173 }
1174
1175 exit:
1176 return error;
1177 }
1178
HandlePropertyGet(void)1179 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE>(void)
1180 {
1181 otError error = OT_ERROR_NONE;
1182 otCacheEntryIterator iterator;
1183 otCacheEntryInfo entry;
1184
1185 memset(&iterator, 0, sizeof(iterator));
1186
1187 for (uint8_t index = 0;; index++)
1188 {
1189 SuccessOrExit(otThreadGetNextCacheEntry(mInstance, &entry, &iterator));
1190
1191 SuccessOrExit(error = mEncoder.OpenStruct());
1192 SuccessOrExit(error = mEncoder.WriteIp6Address(entry.mTarget));
1193 SuccessOrExit(error = mEncoder.WriteUint16(entry.mRloc16));
1194 SuccessOrExit(error = mEncoder.WriteUint8(index));
1195
1196 switch (entry.mState)
1197 {
1198 case OT_CACHE_ENTRY_STATE_CACHED:
1199 SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED));
1200 break;
1201 case OT_CACHE_ENTRY_STATE_SNOOPED:
1202 SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_SNOOPED));
1203 break;
1204 case OT_CACHE_ENTRY_STATE_QUERY:
1205 SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_QUERY));
1206 break;
1207 case OT_CACHE_ENTRY_STATE_RETRY_QUERY:
1208 SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY));
1209 break;
1210 }
1211
1212 SuccessOrExit(error = mEncoder.OpenStruct());
1213
1214 if (entry.mState == OT_CACHE_ENTRY_STATE_CACHED)
1215 {
1216 SuccessOrExit(error = mEncoder.WriteBool(entry.mValidLastTrans));
1217 SuccessOrExit(error = mEncoder.WriteUint32(entry.mLastTransTime));
1218 SuccessOrExit(error = mEncoder.WriteIp6Address(entry.mMeshLocalEid));
1219 }
1220
1221 SuccessOrExit(error = mEncoder.CloseStruct());
1222
1223 SuccessOrExit(error = mEncoder.OpenStruct());
1224
1225 if (entry.mState != OT_CACHE_ENTRY_STATE_CACHED)
1226 {
1227 SuccessOrExit(error = mEncoder.WriteBool(entry.mCanEvict));
1228 SuccessOrExit(error = mEncoder.WriteUint16(entry.mRampDown ? 0 : entry.mTimeout));
1229 SuccessOrExit(error = mEncoder.WriteUint16(entry.mRetryDelay));
1230 }
1231
1232 SuccessOrExit(error = mEncoder.CloseStruct());
1233
1234 SuccessOrExit(error = mEncoder.CloseStruct());
1235 }
1236
1237 exit:
1238 return error;
1239 }
1240
HandlePropertyGet(void)1241 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHILD_SUPERVISION_INTERVAL>(void)
1242 {
1243 return mEncoder.WriteUint16(otChildSupervisionGetInterval(mInstance));
1244 }
1245
HandlePropertySet(void)1246 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHILD_SUPERVISION_INTERVAL>(void)
1247 {
1248 otError error = OT_ERROR_NONE;
1249 uint16_t interval;
1250
1251 SuccessOrExit(error = mDecoder.ReadUint16(interval));
1252 otChildSupervisionSetInterval(mInstance, interval);
1253
1254 exit:
1255 return error;
1256 }
1257
1258 #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
1259
HandlePropertyGet(void)1260 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL>(void)
1261 {
1262 return mEncoder.WriteUint8(otChannelManagerGetRequestedChannel(mInstance));
1263 }
1264
HandlePropertySet(void)1265 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL>(void)
1266 {
1267 uint8_t channel;
1268 otError error = OT_ERROR_NONE;
1269
1270 SuccessOrExit(error = mDecoder.ReadUint8(channel));
1271
1272 otChannelManagerRequestChannelChange(mInstance, channel);
1273
1274 exit:
1275 return error;
1276 }
1277
HandlePropertyGet(void)1278 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_DELAY>(void)
1279 {
1280 return mEncoder.WriteUint16(otChannelManagerGetDelay(mInstance));
1281 }
1282
HandlePropertySet(void)1283 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_DELAY>(void)
1284 {
1285 uint16_t delay;
1286 otError error = OT_ERROR_NONE;
1287
1288 SuccessOrExit(error = mDecoder.ReadUint16(delay));
1289
1290 error = otChannelManagerSetDelay(mInstance, delay);
1291
1292 exit:
1293 return error;
1294 }
1295
HandlePropertyGet(void)1296 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS>(void)
1297 {
1298 return EncodeChannelMask(otChannelManagerGetSupportedChannels(mInstance));
1299 }
1300
HandlePropertySet(void)1301 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS>(void)
1302 {
1303 uint32_t channelMask = 0;
1304 otError error = OT_ERROR_NONE;
1305
1306 SuccessOrExit(error = DecodeChannelMask(channelMask));
1307 otChannelManagerSetSupportedChannels(mInstance, channelMask);
1308
1309 exit:
1310 return error;
1311 }
1312
HandlePropertyGet(void)1313 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS>(void)
1314 {
1315 return EncodeChannelMask(otChannelManagerGetFavoredChannels(mInstance));
1316 }
1317
HandlePropertySet(void)1318 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS>(void)
1319 {
1320 uint32_t channelMask = 0;
1321 otError error = OT_ERROR_NONE;
1322
1323 SuccessOrExit(error = DecodeChannelMask(channelMask));
1324 otChannelManagerSetFavoredChannels(mInstance, channelMask);
1325
1326 exit:
1327 return error;
1328 }
1329
HandlePropertyGet(void)1330 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT>(void)
1331 {
1332 return mEncoder.WriteBool(false);
1333 }
1334
HandlePropertySet(void)1335 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT>(void)
1336 {
1337 bool skipQualityCheck = false;
1338 otError error = OT_ERROR_NONE;
1339
1340 SuccessOrExit(error = mDecoder.ReadBool(skipQualityCheck));
1341 error = otChannelManagerRequestChannelSelect(mInstance, skipQualityCheck);
1342
1343 exit:
1344 return error;
1345 }
1346
HandlePropertyGet(void)1347 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED>(void)
1348 {
1349 return mEncoder.WriteBool(otChannelManagerGetAutoChannelSelectionEnabled(mInstance));
1350 }
1351
HandlePropertySet(void)1352 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED>(void)
1353 {
1354 bool enabled = false;
1355 otError error = OT_ERROR_NONE;
1356
1357 SuccessOrExit(error = mDecoder.ReadBool(enabled));
1358 otChannelManagerSetAutoChannelSelectionEnabled(mInstance, enabled);
1359
1360 exit:
1361 return error;
1362 }
1363
HandlePropertyGet(void)1364 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL>(void)
1365 {
1366 return mEncoder.WriteUint32(otChannelManagerGetAutoChannelSelectionInterval(mInstance));
1367 }
1368
HandlePropertySet(void)1369 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL>(void)
1370 {
1371 uint32_t interval;
1372 otError error = OT_ERROR_NONE;
1373
1374 SuccessOrExit(error = mDecoder.ReadUint32(interval));
1375 error = otChannelManagerSetAutoChannelSelectionInterval(mInstance, interval);
1376
1377 exit:
1378 return error;
1379 }
1380
1381 #endif // OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
1382
1383 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
HandlePropertyGet(void)1384 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_TIME_SYNC_PERIOD>(void)
1385 {
1386 return mEncoder.WriteUint16(otNetworkTimeGetSyncPeriod(mInstance));
1387 }
1388
HandlePropertySet(void)1389 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_TIME_SYNC_PERIOD>(void)
1390 {
1391 otError error = OT_ERROR_NONE;
1392 uint16_t timeSyncPeriod;
1393
1394 SuccessOrExit(error = mDecoder.ReadUint16(timeSyncPeriod));
1395
1396 SuccessOrExit(error = otNetworkTimeSetSyncPeriod(mInstance, timeSyncPeriod));
1397
1398 exit:
1399 return error;
1400 }
1401
HandlePropertyGet(void)1402 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD>(void)
1403 {
1404 return mEncoder.WriteUint16(otNetworkTimeGetXtalThreshold(mInstance));
1405 }
1406
HandlePropertySet(void)1407 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD>(void)
1408 {
1409 otError error = OT_ERROR_NONE;
1410 uint16_t xtalThreshold;
1411
1412 SuccessOrExit(error = mDecoder.ReadUint16(xtalThreshold));
1413
1414 SuccessOrExit(error = otNetworkTimeSetXtalThreshold(mInstance, xtalThreshold));
1415
1416 exit:
1417 return error;
1418 }
1419 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1420
1421 #if OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
HandlePropertySet(void)1422 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_INFRA_IF_STATE>(void)
1423 {
1424 otError error = OT_ERROR_NONE;
1425 uint32_t infraIfIndex;
1426 bool isInfraRunning;
1427
1428 SuccessOrExit(error = mDecoder.ReadUint32(infraIfIndex));
1429 SuccessOrExit(error = mDecoder.ReadBool(isInfraRunning));
1430
1431 mInfraIfAddrCount = 0;
1432 while (!mDecoder.IsAllReadInStruct())
1433 {
1434 const otIp6Address *addr;
1435
1436 SuccessOrExit(error = mDecoder.ReadIp6Address(addr));
1437 SuccessOrExit(error = InfraIfAddAddress(*addr));
1438 }
1439
1440 if (infraIfIndex != mInfraIfIndex)
1441 {
1442 mInfraIfIndex = infraIfIndex;
1443 IgnoreError(otBorderRoutingSetEnabled(mInstance, /* aEnabled */ false));
1444 SuccessOrExit(error = otBorderRoutingInit(mInstance, mInfraIfIndex, isInfraRunning));
1445 SuccessOrExit(error = otBorderRoutingSetEnabled(mInstance, /* aEnabled */ true));
1446 }
1447 else
1448 {
1449 SuccessOrExit(error = otPlatInfraIfStateChanged(mInstance, mInfraIfIndex, isInfraRunning));
1450 }
1451
1452 exit:
1453 return error;
1454 }
1455
HandlePropertySet(void)1456 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_INFRA_IF_RECV_ICMP6>(void)
1457 {
1458 otError error = OT_ERROR_NONE;
1459 uint32_t infraIfIndex;
1460 const otIp6Address *address;
1461 const uint8_t *icmp6Data = nullptr;
1462 uint16_t len;
1463
1464 SuccessOrExit(error = mDecoder.ReadUint32(infraIfIndex));
1465 VerifyOrExit(mInfraIfIndex == infraIfIndex, error = OT_ERROR_DROP);
1466 SuccessOrExit(error = mDecoder.ReadIp6Address(address));
1467 SuccessOrExit(error = mDecoder.ReadData(icmp6Data, len));
1468
1469 // Currently the ICMP6 messages can only be ND messages.
1470 otPlatInfraIfRecvIcmp6Nd(mInstance, infraIfIndex, address, icmp6Data, len);
1471
1472 exit:
1473 return error;
1474 }
1475
InfraIfAddAddress(const otIp6Address & aAddress)1476 otError NcpBase::InfraIfAddAddress(const otIp6Address &aAddress)
1477 {
1478 otError error = OT_ERROR_NONE;
1479
1480 VerifyOrExit(mInfraIfAddrCount < kMaxInfraIfAddrs, error = OT_ERROR_NO_BUFS);
1481 memcpy(&mInfraIfAddrs[mInfraIfAddrCount++], &aAddress, sizeof(aAddress));
1482 exit:
1483 return error;
1484 }
1485
InfraIfContainsAddress(const otIp6Address & aAddress)1486 bool NcpBase::InfraIfContainsAddress(const otIp6Address &aAddress)
1487 {
1488 bool result = false;
1489
1490 for (uint8_t i = 0; i < mInfraIfAddrCount; i++)
1491 {
1492 if (memcmp(&mInfraIfAddrs[i], &aAddress, sizeof(aAddress)) == 0)
1493 {
1494 result = true;
1495 break;
1496 }
1497 }
1498 return result;
1499 }
1500
InfraIfHasAddress(uint32_t aInfraIfIndex,const otIp6Address * aAddress)1501 bool NcpBase::InfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress)
1502 {
1503 return aInfraIfIndex == mInfraIfIndex && InfraIfContainsAddress(*aAddress);
1504 }
1505
InfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,const otIp6Address * aDestAddress,const uint8_t * aBuffer,uint16_t aBufferLength)1506 otError NcpBase::InfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
1507 const otIp6Address *aDestAddress,
1508 const uint8_t *aBuffer,
1509 uint16_t aBufferLength)
1510 {
1511 otError error = OT_ERROR_NONE;
1512 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
1513
1514 SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_INFRA_IF_SEND_ICMP6));
1515 SuccessOrExit(error = mEncoder.WriteUint32(aInfraIfIndex));
1516 SuccessOrExit(error = mEncoder.WriteIp6Address(*aDestAddress));
1517 SuccessOrExit(error = mEncoder.WriteDataWithLen(aBuffer, aBufferLength));
1518 SuccessOrExit(error = mEncoder.EndFrame());
1519
1520 exit:
1521 return error;
1522 }
1523
1524 #endif // OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1525
1526 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
HandlePropertySet(void)1527 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_SERVER_ENABLED>(void)
1528 {
1529 otError error = OT_ERROR_NONE;
1530 bool enable;
1531
1532 SuccessOrExit(error = mDecoder.ReadBool(enable));
1533 otSrpServerSetEnabled(mInstance, enable);
1534
1535 exit:
1536 return error;
1537 }
1538
HandlePropertyGet(void)1539 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_SERVER_ENABLED>(void)
1540 {
1541 otSrpServerState srpServerState = otSrpServerGetState(mInstance);
1542
1543 return mEncoder.WriteBool(srpServerState != OT_SRP_SERVER_STATE_DISABLED);
1544 }
1545
1546 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
HandlePropertySet(void)1547 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE>(void)
1548 {
1549 otError error = OT_ERROR_NONE;
1550 bool enable;
1551
1552 SuccessOrExit(error = mDecoder.ReadBool(enable));
1553 otSrpServerSetAutoEnableMode(mInstance, enable);
1554
1555 exit:
1556 return error;
1557 }
1558
HandlePropertyGet(void)1559 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE>(void)
1560 {
1561 return mEncoder.WriteBool(otSrpServerIsAutoEnableMode(mInstance));
1562 }
1563 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1564 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
1565
1566 #if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
1567
DnssdRegisterHost(const otPlatDnssdHost * aHost,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1568 void NcpBase::DnssdRegisterHost(const otPlatDnssdHost *aHost,
1569 otPlatDnssdRequestId aRequestId,
1570 otPlatDnssdRegisterCallback aCallback)
1571 {
1572 DnssdUpdate(aHost, aRequestId, aCallback, /* aRegister */ true);
1573 }
1574
DnssdUnregisterHost(const otPlatDnssdHost * aHost,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1575 void NcpBase::DnssdUnregisterHost(const otPlatDnssdHost *aHost,
1576 otPlatDnssdRequestId aRequestId,
1577 otPlatDnssdRegisterCallback aCallback)
1578 {
1579 DnssdUpdate(aHost, aRequestId, aCallback, /* aRegister */ false);
1580 }
1581
DnssdRegisterService(const otPlatDnssdService * aService,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1582 void NcpBase::DnssdRegisterService(const otPlatDnssdService *aService,
1583 otPlatDnssdRequestId aRequestId,
1584 otPlatDnssdRegisterCallback aCallback)
1585 {
1586 DnssdUpdate(aService, aRequestId, aCallback, /* aRegister */ true);
1587 }
1588
DnssdUnregisterService(const otPlatDnssdService * aService,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1589 void NcpBase::DnssdUnregisterService(const otPlatDnssdService *aService,
1590 otPlatDnssdRequestId aRequestId,
1591 otPlatDnssdRegisterCallback aCallback)
1592 {
1593 DnssdUpdate(aService, aRequestId, aCallback, /* aRegister */ false);
1594 }
1595
DnssdRegisterKey(const otPlatDnssdKey * aKey,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1596 void NcpBase::DnssdRegisterKey(const otPlatDnssdKey *aKey,
1597 otPlatDnssdRequestId aRequestId,
1598 otPlatDnssdRegisterCallback aCallback)
1599 {
1600 DnssdUpdate(aKey, aRequestId, aCallback, /* aRegister */ true);
1601 }
1602
DnssdUnregisterKey(const otPlatDnssdKey * aKey,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)1603 void NcpBase::DnssdUnregisterKey(const otPlatDnssdKey *aKey,
1604 otPlatDnssdRequestId aRequestId,
1605 otPlatDnssdRegisterCallback aCallback)
1606 {
1607 DnssdUpdate(aKey, aRequestId, aCallback, /* aRegister */ false);
1608 }
1609
DnssdGetState(void)1610 otPlatDnssdState NcpBase::DnssdGetState(void) { return mDnssdState; }
1611
HandlePropertySet(void)1612 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_DNSSD_STATE>(void)
1613 {
1614 otError error = OT_ERROR_NONE;
1615 uint8_t state;
1616
1617 SuccessOrExit(error = mDecoder.ReadUint8(state));
1618
1619 if (state != mDnssdState)
1620 {
1621 mDnssdState = static_cast<otPlatDnssdState>(state);
1622 otPlatDnssdStateHandleStateChange(mInstance);
1623 }
1624
1625 exit:
1626 return error;
1627 }
1628
HandlePropertySet(void)1629 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_DNSSD_REQUEST_RESULT>(void)
1630 {
1631 otError error = OT_ERROR_NONE;
1632 otPlatDnssdRequestId requestId;
1633 uint8_t result;
1634 otPlatDnssdRegisterCallback callback = nullptr;
1635 const uint8_t *context;
1636 uint16_t contextLen;
1637
1638 SuccessOrExit(error = mDecoder.ReadUint8(result));
1639 SuccessOrExit(error = mDecoder.ReadUint32(requestId));
1640 SuccessOrExit(error = mDecoder.ReadData(context, contextLen));
1641 VerifyOrExit(contextLen == sizeof(otPlatDnssdRegisterCallback), error = OT_ERROR_PARSE);
1642 callback = *reinterpret_cast<const otPlatDnssdRegisterCallback *>(context);
1643 callback(mInstance, requestId, static_cast<otError>(result));
1644
1645 exit:
1646 return error;
1647 }
1648
1649 #endif // OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
1650
1651 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
1652
HandlePropertyGet(void)1653 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE>(void)
1654 {
1655 otError error = OT_ERROR_NONE;
1656 otBorderAgentMeshCoPServiceTxtData txtData;
1657
1658 SuccessOrExit(error = otBorderAgentGetMeshCoPServiceTxtData(mInstance, &txtData));
1659 SuccessOrExit(error = mEncoder.WriteBool(otBorderAgentIsActive(mInstance)));
1660 SuccessOrExit(error = mEncoder.WriteUint16(otBorderAgentGetUdpPort(mInstance)));
1661 SuccessOrExit(error = mEncoder.WriteData(txtData.mData, txtData.mLength));
1662
1663 exit:
1664 return error;
1665 }
1666
1667 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
1668
1669 } // namespace Ncp
1670 } // namespace ot
1671
1672 #endif // OPENTHREAD_FTD
1673