xref: /aosp_15_r20/external/openthread/src/ncp/ncp_base.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *    Copyright (c) 2016-2017, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *    All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *    Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *    modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *       documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *    3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *       names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *       derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*cfb92d14SAndroid Build Coastguard Worker  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*cfb92d14SAndroid Build Coastguard Worker  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*cfb92d14SAndroid Build Coastguard Worker  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20*cfb92d14SAndroid Build Coastguard Worker  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*cfb92d14SAndroid Build Coastguard Worker  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*cfb92d14SAndroid Build Coastguard Worker  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*cfb92d14SAndroid Build Coastguard Worker  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*cfb92d14SAndroid Build Coastguard Worker  */
27*cfb92d14SAndroid Build Coastguard Worker 
28*cfb92d14SAndroid Build Coastguard Worker /**
29*cfb92d14SAndroid Build Coastguard Worker  * @file
30*cfb92d14SAndroid Build Coastguard Worker  *   This file implements general thread device required Spinel interface to the OpenThread stack.
31*cfb92d14SAndroid Build Coastguard Worker  */
32*cfb92d14SAndroid Build Coastguard Worker 
33*cfb92d14SAndroid Build Coastguard Worker #include "ncp_base.hpp"
34*cfb92d14SAndroid Build Coastguard Worker 
35*cfb92d14SAndroid Build Coastguard Worker #include <stdarg.h>
36*cfb92d14SAndroid Build Coastguard Worker #include <stdlib.h>
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker #include <openthread/diag.h>
39*cfb92d14SAndroid Build Coastguard Worker #include <openthread/icmp6.h>
40*cfb92d14SAndroid Build Coastguard Worker #include <openthread/link.h>
41*cfb92d14SAndroid Build Coastguard Worker #include <openthread/logging.h>
42*cfb92d14SAndroid Build Coastguard Worker #include <openthread/ncp.h>
43*cfb92d14SAndroid Build Coastguard Worker #include <openthread/network_time.h>
44*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/misc.h>
45*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/radio.h>
46*cfb92d14SAndroid Build Coastguard Worker 
47*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
48*cfb92d14SAndroid Build Coastguard Worker #include "common/debug.hpp"
49*cfb92d14SAndroid Build Coastguard Worker #include "radio/radio.hpp"
50*cfb92d14SAndroid Build Coastguard Worker 
51*cfb92d14SAndroid Build Coastguard Worker namespace ot {
52*cfb92d14SAndroid Build Coastguard Worker namespace Ncp {
53*cfb92d14SAndroid Build Coastguard Worker 
54*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
55*cfb92d14SAndroid Build Coastguard Worker // MARK: Utility Functions
56*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
57*cfb92d14SAndroid Build Coastguard Worker 
InstanceToIid(Instance * aInstance)58*cfb92d14SAndroid Build Coastguard Worker uint8_t NcpBase::InstanceToIid(Instance *aInstance)
59*cfb92d14SAndroid Build Coastguard Worker {
60*cfb92d14SAndroid Build Coastguard Worker     uint8_t index = 0;
61*cfb92d14SAndroid Build Coastguard Worker 
62*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aInstance);
63*cfb92d14SAndroid Build Coastguard Worker 
64*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
65*cfb92d14SAndroid Build Coastguard Worker     index = SPINEL_HEADER_GET_IID(SPINEL_HEADER_IID_BROADCAST); // use broadcast if no match
66*cfb92d14SAndroid Build Coastguard Worker 
67*cfb92d14SAndroid Build Coastguard Worker     for (int i = 0; i < kSpinelInterfaceCount; i++)
68*cfb92d14SAndroid Build Coastguard Worker     {
69*cfb92d14SAndroid Build Coastguard Worker         if (aInstance == mInstances[i])
70*cfb92d14SAndroid Build Coastguard Worker         {
71*cfb92d14SAndroid Build Coastguard Worker             index = i;
72*cfb92d14SAndroid Build Coastguard Worker             break;
73*cfb92d14SAndroid Build Coastguard Worker         }
74*cfb92d14SAndroid Build Coastguard Worker     }
75*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE  && OPENTHREAD_RADIO
76*cfb92d14SAndroid Build Coastguard Worker 
77*cfb92d14SAndroid Build Coastguard Worker     return index;
78*cfb92d14SAndroid Build Coastguard Worker }
79*cfb92d14SAndroid Build Coastguard Worker 
IidToInstance(uint8_t aIid)80*cfb92d14SAndroid Build Coastguard Worker Instance *NcpBase::IidToInstance(uint8_t aIid)
81*cfb92d14SAndroid Build Coastguard Worker {
82*cfb92d14SAndroid Build Coastguard Worker     Instance *instance;
83*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(aIid < kSpinelInterfaceCount);
84*cfb92d14SAndroid Build Coastguard Worker 
85*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
86*cfb92d14SAndroid Build Coastguard Worker     instance = mInstances[aIid];
87*cfb92d14SAndroid Build Coastguard Worker #else
88*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aIid);
89*cfb92d14SAndroid Build Coastguard Worker     instance = mInstance;
90*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE  && OPENTHREAD_RADIO
91*cfb92d14SAndroid Build Coastguard Worker 
92*cfb92d14SAndroid Build Coastguard Worker     return instance;
93*cfb92d14SAndroid Build Coastguard Worker }
94*cfb92d14SAndroid Build Coastguard Worker 
95*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
HasOnly1BitSet(uint32_t aValue)96*cfb92d14SAndroid Build Coastguard Worker static bool HasOnly1BitSet(uint32_t aValue) { return aValue != 0 && ((aValue & (aValue - 1)) == 0); }
97*cfb92d14SAndroid Build Coastguard Worker 
IndexOfMSB(uint32_t aValue)98*cfb92d14SAndroid Build Coastguard Worker static uint8_t IndexOfMSB(uint32_t aValue)
99*cfb92d14SAndroid Build Coastguard Worker {
100*cfb92d14SAndroid Build Coastguard Worker     uint8_t index = 0;
101*cfb92d14SAndroid Build Coastguard Worker 
102*cfb92d14SAndroid Build Coastguard Worker     while (aValue >>= 1)
103*cfb92d14SAndroid Build Coastguard Worker     {
104*cfb92d14SAndroid Build Coastguard Worker         index++;
105*cfb92d14SAndroid Build Coastguard Worker     }
106*cfb92d14SAndroid Build Coastguard Worker 
107*cfb92d14SAndroid Build Coastguard Worker     return index;
108*cfb92d14SAndroid Build Coastguard Worker }
109*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
110*cfb92d14SAndroid Build Coastguard Worker 
ThreadErrorToSpinelStatus(otError aError)111*cfb92d14SAndroid Build Coastguard Worker spinel_status_t NcpBase::ThreadErrorToSpinelStatus(otError aError)
112*cfb92d14SAndroid Build Coastguard Worker {
113*cfb92d14SAndroid Build Coastguard Worker     spinel_status_t ret;
114*cfb92d14SAndroid Build Coastguard Worker 
115*cfb92d14SAndroid Build Coastguard Worker     switch (aError)
116*cfb92d14SAndroid Build Coastguard Worker     {
117*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NONE:
118*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_OK;
119*cfb92d14SAndroid Build Coastguard Worker         break;
120*cfb92d14SAndroid Build Coastguard Worker 
121*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_FAILED:
122*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_FAILURE;
123*cfb92d14SAndroid Build Coastguard Worker         break;
124*cfb92d14SAndroid Build Coastguard Worker 
125*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_DROP:
126*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_DROPPED;
127*cfb92d14SAndroid Build Coastguard Worker         break;
128*cfb92d14SAndroid Build Coastguard Worker 
129*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NO_BUFS:
130*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_NOMEM;
131*cfb92d14SAndroid Build Coastguard Worker         break;
132*cfb92d14SAndroid Build Coastguard Worker 
133*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_BUSY:
134*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_BUSY;
135*cfb92d14SAndroid Build Coastguard Worker         break;
136*cfb92d14SAndroid Build Coastguard Worker 
137*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_PARSE:
138*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_PARSE_ERROR;
139*cfb92d14SAndroid Build Coastguard Worker         break;
140*cfb92d14SAndroid Build Coastguard Worker 
141*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_INVALID_ARGS:
142*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_INVALID_ARGUMENT;
143*cfb92d14SAndroid Build Coastguard Worker         break;
144*cfb92d14SAndroid Build Coastguard Worker 
145*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NOT_IMPLEMENTED:
146*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_UNIMPLEMENTED;
147*cfb92d14SAndroid Build Coastguard Worker         break;
148*cfb92d14SAndroid Build Coastguard Worker 
149*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_INVALID_STATE:
150*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_INVALID_STATE;
151*cfb92d14SAndroid Build Coastguard Worker         break;
152*cfb92d14SAndroid Build Coastguard Worker 
153*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NO_ACK:
154*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_NO_ACK;
155*cfb92d14SAndroid Build Coastguard Worker         break;
156*cfb92d14SAndroid Build Coastguard Worker 
157*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_CHANNEL_ACCESS_FAILURE:
158*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_CCA_FAILURE;
159*cfb92d14SAndroid Build Coastguard Worker         break;
160*cfb92d14SAndroid Build Coastguard Worker 
161*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_ALREADY:
162*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_ALREADY;
163*cfb92d14SAndroid Build Coastguard Worker         break;
164*cfb92d14SAndroid Build Coastguard Worker 
165*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NOT_FOUND:
166*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_ITEM_NOT_FOUND;
167*cfb92d14SAndroid Build Coastguard Worker         break;
168*cfb92d14SAndroid Build Coastguard Worker 
169*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_UNKNOWN_NEIGHBOR:
170*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_UNKNOWN_NEIGHBOR;
171*cfb92d14SAndroid Build Coastguard Worker         break;
172*cfb92d14SAndroid Build Coastguard Worker 
173*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NOT_CAPABLE:
174*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_NOT_CAPABLE;
175*cfb92d14SAndroid Build Coastguard Worker         break;
176*cfb92d14SAndroid Build Coastguard Worker 
177*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_RESPONSE_TIMEOUT:
178*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESPONSE_TIMEOUT;
179*cfb92d14SAndroid Build Coastguard Worker         break;
180*cfb92d14SAndroid Build Coastguard Worker 
181*cfb92d14SAndroid Build Coastguard Worker     default:
182*cfb92d14SAndroid Build Coastguard Worker         // Unknown error code. Wrap it as a Spinel status and return that.
183*cfb92d14SAndroid Build Coastguard Worker         ret = static_cast<spinel_status_t>(SPINEL_STATUS_STACK_NATIVE__BEGIN + static_cast<uint32_t>(aError));
184*cfb92d14SAndroid Build Coastguard Worker         break;
185*cfb92d14SAndroid Build Coastguard Worker     }
186*cfb92d14SAndroid Build Coastguard Worker 
187*cfb92d14SAndroid Build Coastguard Worker     return ret;
188*cfb92d14SAndroid Build Coastguard Worker }
189*cfb92d14SAndroid Build Coastguard Worker 
ResetReasonToSpinelStatus(otPlatResetReason aReason)190*cfb92d14SAndroid Build Coastguard Worker static spinel_status_t ResetReasonToSpinelStatus(otPlatResetReason aReason)
191*cfb92d14SAndroid Build Coastguard Worker {
192*cfb92d14SAndroid Build Coastguard Worker     spinel_status_t ret;
193*cfb92d14SAndroid Build Coastguard Worker 
194*cfb92d14SAndroid Build Coastguard Worker     switch (aReason)
195*cfb92d14SAndroid Build Coastguard Worker     {
196*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_POWER_ON:
197*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_POWER_ON;
198*cfb92d14SAndroid Build Coastguard Worker         break;
199*cfb92d14SAndroid Build Coastguard Worker 
200*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_EXTERNAL:
201*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_EXTERNAL;
202*cfb92d14SAndroid Build Coastguard Worker         break;
203*cfb92d14SAndroid Build Coastguard Worker 
204*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_SOFTWARE:
205*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_SOFTWARE;
206*cfb92d14SAndroid Build Coastguard Worker         break;
207*cfb92d14SAndroid Build Coastguard Worker 
208*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_FAULT:
209*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_FAULT;
210*cfb92d14SAndroid Build Coastguard Worker         break;
211*cfb92d14SAndroid Build Coastguard Worker 
212*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_CRASH:
213*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_CRASH;
214*cfb92d14SAndroid Build Coastguard Worker         break;
215*cfb92d14SAndroid Build Coastguard Worker 
216*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_ASSERT:
217*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_ASSERT;
218*cfb92d14SAndroid Build Coastguard Worker         break;
219*cfb92d14SAndroid Build Coastguard Worker 
220*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_WATCHDOG:
221*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_WATCHDOG;
222*cfb92d14SAndroid Build Coastguard Worker         break;
223*cfb92d14SAndroid Build Coastguard Worker 
224*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_RESET_REASON_OTHER:
225*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_OTHER;
226*cfb92d14SAndroid Build Coastguard Worker         break;
227*cfb92d14SAndroid Build Coastguard Worker 
228*cfb92d14SAndroid Build Coastguard Worker     default:
229*cfb92d14SAndroid Build Coastguard Worker         ret = SPINEL_STATUS_RESET_UNKNOWN;
230*cfb92d14SAndroid Build Coastguard Worker         break;
231*cfb92d14SAndroid Build Coastguard Worker     }
232*cfb92d14SAndroid Build Coastguard Worker 
233*cfb92d14SAndroid Build Coastguard Worker     return ret;
234*cfb92d14SAndroid Build Coastguard Worker }
235*cfb92d14SAndroid Build Coastguard Worker 
236*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
237*cfb92d14SAndroid Build Coastguard Worker // MARK: Class Boilerplate
238*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
239*cfb92d14SAndroid Build Coastguard Worker 
240*cfb92d14SAndroid Build Coastguard Worker NcpBase *NcpBase::sNcpInstance = nullptr;
241*cfb92d14SAndroid Build Coastguard Worker 
242*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
NcpBase(Instance ** aInstances,uint8_t aCount)243*cfb92d14SAndroid Build Coastguard Worker NcpBase::NcpBase(Instance **aInstances, uint8_t aCount)
244*cfb92d14SAndroid Build Coastguard Worker     : NcpBase(aInstances[0])
245*cfb92d14SAndroid Build Coastguard Worker {
246*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(aCount > 0);
247*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(aCount < SPINEL_HEADER_IID_MAX); // One IID reserved for broadcast
248*cfb92d14SAndroid Build Coastguard Worker 
249*cfb92d14SAndroid Build Coastguard Worker     uint8_t skipped = 0;
250*cfb92d14SAndroid Build Coastguard Worker 
251*cfb92d14SAndroid Build Coastguard Worker     for (int i = 0; i < aCount; i++)
252*cfb92d14SAndroid Build Coastguard Worker     {
253*cfb92d14SAndroid Build Coastguard Worker         if ((i + skipped) == SPINEL_HEADER_GET_IID(SPINEL_HEADER_IID_BROADCAST))
254*cfb92d14SAndroid Build Coastguard Worker         {
255*cfb92d14SAndroid Build Coastguard Worker             mInstances[i + skipped] = nullptr;
256*cfb92d14SAndroid Build Coastguard Worker             skipped++;
257*cfb92d14SAndroid Build Coastguard Worker         }
258*cfb92d14SAndroid Build Coastguard Worker 
259*cfb92d14SAndroid Build Coastguard Worker         OT_ASSERT(i + skipped <= SPINEL_HEADER_IID_MAX);
260*cfb92d14SAndroid Build Coastguard Worker         mInstances[i + skipped] = aInstances[i];
261*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DIAG_ENABLE
262*cfb92d14SAndroid Build Coastguard Worker         otDiagSetOutputCallback(mInstances[i + skipped], &NcpBase::HandleDiagOutput_Jump, this);
263*cfb92d14SAndroid Build Coastguard Worker #endif
264*cfb92d14SAndroid Build Coastguard Worker     }
265*cfb92d14SAndroid Build Coastguard Worker }
266*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE  && OPENTHREAD_RADIO
267*cfb92d14SAndroid Build Coastguard Worker 
NcpBase(Instance * aInstance)268*cfb92d14SAndroid Build Coastguard Worker NcpBase::NcpBase(Instance *aInstance)
269*cfb92d14SAndroid Build Coastguard Worker     : mInstance(aInstance)
270*cfb92d14SAndroid Build Coastguard Worker     , mTxFrameBuffer(mTxBuffer, sizeof(mTxBuffer))
271*cfb92d14SAndroid Build Coastguard Worker     , mEncoder(mTxFrameBuffer)
272*cfb92d14SAndroid Build Coastguard Worker     , mHostPowerStateInProgress(false)
273*cfb92d14SAndroid Build Coastguard Worker     , mLastStatus(SPINEL_STATUS_OK)
274*cfb92d14SAndroid Build Coastguard Worker     , mScanChannelMask(Radio::kSupportedChannels)
275*cfb92d14SAndroid Build Coastguard Worker     , mScanPeriod(200)
276*cfb92d14SAndroid Build Coastguard Worker     , mDiscoveryScanJoinerFlag(false)
277*cfb92d14SAndroid Build Coastguard Worker     , mDiscoveryScanEnableFiltering(false)
278*cfb92d14SAndroid Build Coastguard Worker     , mDiscoveryScanPanId(0xffff)
279*cfb92d14SAndroid Build Coastguard Worker     , mUpdateChangedPropsTask(*aInstance, NcpBase::UpdateChangedProps)
280*cfb92d14SAndroid Build Coastguard Worker     , mThreadChangedFlags(0)
281*cfb92d14SAndroid Build Coastguard Worker     , mHostPowerState(SPINEL_HOST_POWER_STATE_ONLINE)
282*cfb92d14SAndroid Build Coastguard Worker     , mHostPowerReplyFrameTag(Spinel::Buffer::kInvalidTag)
283*cfb92d14SAndroid Build Coastguard Worker     , mHostPowerStateHeader(0)
284*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
285*cfb92d14SAndroid Build Coastguard Worker     , mAllowPeekDelegate(nullptr)
286*cfb92d14SAndroid Build Coastguard Worker     , mAllowPokeDelegate(nullptr)
287*cfb92d14SAndroid Build Coastguard Worker #endif
288*cfb92d14SAndroid Build Coastguard Worker     , mResponseQueueHead(0)
289*cfb92d14SAndroid Build Coastguard Worker     , mResponseQueueTail(0)
290*cfb92d14SAndroid Build Coastguard Worker     , mAllowLocalNetworkDataChange(false)
291*cfb92d14SAndroid Build Coastguard Worker     , mRequireJoinExistingNetwork(false)
292*cfb92d14SAndroid Build Coastguard Worker     , mPcapEnabled(false)
293*cfb92d14SAndroid Build Coastguard Worker     , mDisableStreamWrite(false)
294*cfb92d14SAndroid Build Coastguard Worker     , mShouldEmitChildTableUpdate(false)
295*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
296*cfb92d14SAndroid Build Coastguard Worker     , mAllowLocalServerDataChange(false)
297*cfb92d14SAndroid Build Coastguard Worker #endif
298*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD
299*cfb92d14SAndroid Build Coastguard Worker     , mPreferredRouteId(0)
300*cfb92d14SAndroid Build Coastguard Worker #endif
301*cfb92d14SAndroid Build Coastguard Worker     , mCurCommandIid(0)
302*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
303*cfb92d14SAndroid Build Coastguard Worker     , mInboundSecureIpFrameCounter(0)
304*cfb92d14SAndroid Build Coastguard Worker     , mInboundInsecureIpFrameCounter(0)
305*cfb92d14SAndroid Build Coastguard Worker     , mOutboundSecureIpFrameCounter(0)
306*cfb92d14SAndroid Build Coastguard Worker     , mOutboundInsecureIpFrameCounter(0)
307*cfb92d14SAndroid Build Coastguard Worker     , mDroppedOutboundIpFrameCounter(0)
308*cfb92d14SAndroid Build Coastguard Worker     , mDroppedInboundIpFrameCounter(0)
309*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
310*cfb92d14SAndroid Build Coastguard Worker     , mSrpClientCallbackEnabled(false)
311*cfb92d14SAndroid Build Coastguard Worker #endif
312*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
313*cfb92d14SAndroid Build Coastguard Worker     , mFramingErrorCounter(0)
314*cfb92d14SAndroid Build Coastguard Worker     , mRxSpinelFrameCounter(0)
315*cfb92d14SAndroid Build Coastguard Worker     , mRxSpinelOutOfOrderTidCounter(0)
316*cfb92d14SAndroid Build Coastguard Worker     , mTxSpinelFrameCounter(0)
317*cfb92d14SAndroid Build Coastguard Worker     , mDidInitialUpdates(false)
318*cfb92d14SAndroid Build Coastguard Worker     , mDatasetSendMgmtPendingSetResult(SPINEL_STATUS_OK)
319*cfb92d14SAndroid Build Coastguard Worker     , mLogTimestampBase(0)
320*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DIAG_ENABLE
321*cfb92d14SAndroid Build Coastguard Worker     , mDiagOutput(nullptr)
322*cfb92d14SAndroid Build Coastguard Worker     , mDiagOutputLen(0)
323*cfb92d14SAndroid Build Coastguard Worker #endif
324*cfb92d14SAndroid Build Coastguard Worker {
325*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(mInstance != nullptr);
326*cfb92d14SAndroid Build Coastguard Worker 
327*cfb92d14SAndroid Build Coastguard Worker     sNcpInstance = this;
328*cfb92d14SAndroid Build Coastguard Worker 
329*cfb92d14SAndroid Build Coastguard Worker     mTxFrameBuffer.SetFrameRemovedCallback(&NcpBase::HandleFrameRemovedFromNcpBuffer, this);
330*cfb92d14SAndroid Build Coastguard Worker 
331*cfb92d14SAndroid Build Coastguard Worker     memset(&mResponseQueue, 0, sizeof(mResponseQueue));
332*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
333*cfb92d14SAndroid Build Coastguard Worker     memset(mCurTransmitTID, 0, sizeof(mCurTransmitTID));
334*cfb92d14SAndroid Build Coastguard Worker     memset(mSrcMatchEnabled, 0, sizeof(mSrcMatchEnabled));
335*cfb92d14SAndroid Build Coastguard Worker     memset(mCurScanChannel, kInvalidScanChannel, sizeof(mCurScanChannel));
336*cfb92d14SAndroid Build Coastguard Worker #endif
337*cfb92d14SAndroid Build Coastguard Worker     memset(mIsRawStreamEnabled, 0, sizeof(mIsRawStreamEnabled));
338*cfb92d14SAndroid Build Coastguard Worker     memset(mNextExpectedTid, 0, sizeof(mNextExpectedTid));
339*cfb92d14SAndroid Build Coastguard Worker 
340*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
341*cfb92d14SAndroid Build Coastguard Worker     otMessageQueueInit(&mMessageQueue);
342*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(otSetStateChangedCallback(mInstance, &NcpBase::HandleStateChanged, this));
343*cfb92d14SAndroid Build Coastguard Worker     otIp6SetReceiveCallback(mInstance, &NcpBase::HandleDatagramFromStack, this);
344*cfb92d14SAndroid Build Coastguard Worker     otIp6SetReceiveFilterEnabled(mInstance, true);
345*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
346*cfb92d14SAndroid Build Coastguard Worker     otNetworkTimeSyncSetCallback(mInstance, &NcpBase::HandleTimeSyncUpdate, this);
347*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
348*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
349*cfb92d14SAndroid Build Coastguard Worker     otUdpForwardSetForwarder(mInstance, &NcpBase::HandleUdpForwardStream, this);
350*cfb92d14SAndroid Build Coastguard Worker #endif
351*cfb92d14SAndroid Build Coastguard Worker     otIcmp6SetEchoMode(mInstance, OT_ICMP6_ECHO_HANDLER_RLOC_ALOC_ONLY);
352*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD
353*cfb92d14SAndroid Build Coastguard Worker     otThreadRegisterNeighborTableCallback(mInstance, &NcpBase::HandleNeighborTableChanged);
354*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
355*cfb92d14SAndroid Build Coastguard Worker     memset(&mSteeringDataAddress, 0, sizeof(mSteeringDataAddress));
356*cfb92d14SAndroid Build Coastguard Worker #endif
357*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
358*cfb92d14SAndroid Build Coastguard Worker     otThreadRegisterParentResponseCallback(mInstance, &NcpBase::HandleParentResponseInfo, static_cast<void *>(this));
359*cfb92d14SAndroid Build Coastguard Worker #endif
360*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_FTD
361*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
362*cfb92d14SAndroid Build Coastguard Worker     otSrpClientSetCallback(mInstance, HandleSrpClientCallback, this);
363*cfb92d14SAndroid Build Coastguard Worker #endif
364*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
365*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DIAG_ENABLE
366*cfb92d14SAndroid Build Coastguard Worker     otDiagSetOutputCallback(mInstance, &NcpBase::HandleDiagOutput_Jump, this);
367*cfb92d14SAndroid Build Coastguard Worker #endif
368*cfb92d14SAndroid Build Coastguard Worker     mChangedPropsSet.AddLastStatus(SPINEL_STATUS_RESET_UNKNOWN);
369*cfb92d14SAndroid Build Coastguard Worker     mUpdateChangedPropsTask.Post();
370*cfb92d14SAndroid Build Coastguard Worker 
371*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
372*cfb92d14SAndroid Build Coastguard Worker     aInstance->Get<Extension::ExtensionBase>().SignalNcpInit(*this);
373*cfb92d14SAndroid Build Coastguard Worker #endif
374*cfb92d14SAndroid Build Coastguard Worker }
375*cfb92d14SAndroid Build Coastguard Worker 
GetNcpInstance(void)376*cfb92d14SAndroid Build Coastguard Worker NcpBase *NcpBase::GetNcpInstance(void) { return sNcpInstance; }
377*cfb92d14SAndroid Build Coastguard Worker 
GetCurCommandIid(void) const378*cfb92d14SAndroid Build Coastguard Worker spinel_iid_t NcpBase::GetCurCommandIid(void) const { return mCurCommandIid; }
379*cfb92d14SAndroid Build Coastguard Worker 
ResetCounters(void)380*cfb92d14SAndroid Build Coastguard Worker void NcpBase::ResetCounters(void)
381*cfb92d14SAndroid Build Coastguard Worker {
382*cfb92d14SAndroid Build Coastguard Worker     mFramingErrorCounter          = 0;
383*cfb92d14SAndroid Build Coastguard Worker     mRxSpinelFrameCounter         = 0;
384*cfb92d14SAndroid Build Coastguard Worker     mRxSpinelOutOfOrderTidCounter = 0;
385*cfb92d14SAndroid Build Coastguard Worker     mTxSpinelFrameCounter         = 0;
386*cfb92d14SAndroid Build Coastguard Worker 
387*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
388*cfb92d14SAndroid Build Coastguard Worker     mInboundSecureIpFrameCounter    = 0;
389*cfb92d14SAndroid Build Coastguard Worker     mInboundInsecureIpFrameCounter  = 0;
390*cfb92d14SAndroid Build Coastguard Worker     mOutboundSecureIpFrameCounter   = 0;
391*cfb92d14SAndroid Build Coastguard Worker     mOutboundInsecureIpFrameCounter = 0;
392*cfb92d14SAndroid Build Coastguard Worker     mDroppedOutboundIpFrameCounter  = 0;
393*cfb92d14SAndroid Build Coastguard Worker     mDroppedInboundIpFrameCounter   = 0;
394*cfb92d14SAndroid Build Coastguard Worker #endif
395*cfb92d14SAndroid Build Coastguard Worker }
396*cfb92d14SAndroid Build Coastguard Worker 
397*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
398*cfb92d14SAndroid Build Coastguard Worker // MARK: Serial Traffic Glue
399*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
400*cfb92d14SAndroid Build Coastguard Worker 
GetLastOutboundFrameTag(void)401*cfb92d14SAndroid Build Coastguard Worker Spinel::Buffer::FrameTag NcpBase::GetLastOutboundFrameTag(void) { return mTxFrameBuffer.InFrameGetLastTag(); }
402*cfb92d14SAndroid Build Coastguard Worker 
HandleReceive(const uint8_t * aBuf,uint16_t aBufLength)403*cfb92d14SAndroid Build Coastguard Worker void NcpBase::HandleReceive(const uint8_t *aBuf, uint16_t aBufLength)
404*cfb92d14SAndroid Build Coastguard Worker {
405*cfb92d14SAndroid Build Coastguard Worker     otError      error  = OT_ERROR_NONE;
406*cfb92d14SAndroid Build Coastguard Worker     uint8_t      header = 0;
407*cfb92d14SAndroid Build Coastguard Worker     spinel_tid_t tid    = 0;
408*cfb92d14SAndroid Build Coastguard Worker 
409*cfb92d14SAndroid Build Coastguard Worker     mDisableStreamWrite = true;
410*cfb92d14SAndroid Build Coastguard Worker 
411*cfb92d14SAndroid Build Coastguard Worker     // Initialize the decoder with the newly received spinel frame.
412*cfb92d14SAndroid Build Coastguard Worker     mDecoder.Init(aBuf, aBufLength);
413*cfb92d14SAndroid Build Coastguard Worker 
414*cfb92d14SAndroid Build Coastguard Worker     // Receiving any message from the host has the side effect of transitioning the host power state to online.
415*cfb92d14SAndroid Build Coastguard Worker     mHostPowerState           = SPINEL_HOST_POWER_STATE_ONLINE;
416*cfb92d14SAndroid Build Coastguard Worker     mHostPowerStateInProgress = false;
417*cfb92d14SAndroid Build Coastguard Worker 
418*cfb92d14SAndroid Build Coastguard Worker     // Skip if there is no header byte to read or this isn't a spinel frame.
419*cfb92d14SAndroid Build Coastguard Worker 
420*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(mDecoder.ReadUint8(header));
421*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit((SPINEL_HEADER_FLAG & header) == SPINEL_HEADER_FLAG);
422*cfb92d14SAndroid Build Coastguard Worker 
423*cfb92d14SAndroid Build Coastguard Worker     mRxSpinelFrameCounter++;
424*cfb92d14SAndroid Build Coastguard Worker 
425*cfb92d14SAndroid Build Coastguard Worker     mCurCommandIid = SPINEL_HEADER_GET_IID(header);
426*cfb92d14SAndroid Build Coastguard Worker 
427*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
428*cfb92d14SAndroid Build Coastguard Worker     if (mCurCommandIid > SPINEL_HEADER_IID_MAX)
429*cfb92d14SAndroid Build Coastguard Worker #else
430*cfb92d14SAndroid Build Coastguard Worker     if (mCurCommandIid != 0)
431*cfb92d14SAndroid Build Coastguard Worker #endif
432*cfb92d14SAndroid Build Coastguard Worker     {
433*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(WriteLastStatusFrame(header, SPINEL_STATUS_INVALID_INTERFACE));
434*cfb92d14SAndroid Build Coastguard Worker         ExitNow();
435*cfb92d14SAndroid Build Coastguard Worker     }
436*cfb92d14SAndroid Build Coastguard Worker 
437*cfb92d14SAndroid Build Coastguard Worker     mInstance = IidToInstance(mCurCommandIid);
438*cfb92d14SAndroid Build Coastguard Worker     if (mInstance == nullptr)
439*cfb92d14SAndroid Build Coastguard Worker     {
440*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(WriteLastStatusFrame(header, SPINEL_STATUS_INVALID_INTERFACE));
441*cfb92d14SAndroid Build Coastguard Worker         ExitNow();
442*cfb92d14SAndroid Build Coastguard Worker     }
443*cfb92d14SAndroid Build Coastguard Worker 
444*cfb92d14SAndroid Build Coastguard Worker     error = HandleCommand(header);
445*cfb92d14SAndroid Build Coastguard Worker 
446*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
447*cfb92d14SAndroid Build Coastguard Worker     {
448*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(PrepareLastStatusResponse(header, ThreadErrorToSpinelStatus(error)));
449*cfb92d14SAndroid Build Coastguard Worker     }
450*cfb92d14SAndroid Build Coastguard Worker 
451*cfb92d14SAndroid Build Coastguard Worker     if (!IsResponseQueueEmpty())
452*cfb92d14SAndroid Build Coastguard Worker     {
453*cfb92d14SAndroid Build Coastguard Worker         // A response may have been prepared and queued for this command,
454*cfb92d14SAndroid Build Coastguard Worker         // so we attempt to send/write any queued responses. Note that
455*cfb92d14SAndroid Build Coastguard Worker         // if the response was prepared but cannot be sent now (not
456*cfb92d14SAndroid Build Coastguard Worker         // enough buffer space available), it will be attempted again
457*cfb92d14SAndroid Build Coastguard Worker         // from `HandleFrameRemovedFromNcpBuffer()` when buffer space
458*cfb92d14SAndroid Build Coastguard Worker         // becomes available.
459*cfb92d14SAndroid Build Coastguard Worker 
460*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(SendQueuedResponses());
461*cfb92d14SAndroid Build Coastguard Worker     }
462*cfb92d14SAndroid Build Coastguard Worker 
463*cfb92d14SAndroid Build Coastguard Worker     // Check for out of sequence TIDs and update `mNextExpectedTid`,
464*cfb92d14SAndroid Build Coastguard Worker 
465*cfb92d14SAndroid Build Coastguard Worker     tid = SPINEL_HEADER_GET_TID(header);
466*cfb92d14SAndroid Build Coastguard Worker 
467*cfb92d14SAndroid Build Coastguard Worker     if ((mNextExpectedTid[mCurCommandIid] != 0) && (tid != mNextExpectedTid[mCurCommandIid]))
468*cfb92d14SAndroid Build Coastguard Worker     {
469*cfb92d14SAndroid Build Coastguard Worker         mRxSpinelOutOfOrderTidCounter++;
470*cfb92d14SAndroid Build Coastguard Worker     }
471*cfb92d14SAndroid Build Coastguard Worker 
472*cfb92d14SAndroid Build Coastguard Worker     mNextExpectedTid[mCurCommandIid] = SPINEL_GET_NEXT_TID(tid);
473*cfb92d14SAndroid Build Coastguard Worker 
474*cfb92d14SAndroid Build Coastguard Worker exit:
475*cfb92d14SAndroid Build Coastguard Worker     mDisableStreamWrite = false;
476*cfb92d14SAndroid Build Coastguard Worker }
477*cfb92d14SAndroid Build Coastguard Worker 
HandleFrameRemovedFromNcpBuffer(void * aContext,Spinel::Buffer::FrameTag aFrameTag,Spinel::Buffer::Priority aPriority,Spinel::Buffer * aNcpBuffer)478*cfb92d14SAndroid Build Coastguard Worker void NcpBase::HandleFrameRemovedFromNcpBuffer(void                    *aContext,
479*cfb92d14SAndroid Build Coastguard Worker                                               Spinel::Buffer::FrameTag aFrameTag,
480*cfb92d14SAndroid Build Coastguard Worker                                               Spinel::Buffer::Priority aPriority,
481*cfb92d14SAndroid Build Coastguard Worker                                               Spinel::Buffer          *aNcpBuffer)
482*cfb92d14SAndroid Build Coastguard Worker {
483*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aNcpBuffer);
484*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aPriority);
485*cfb92d14SAndroid Build Coastguard Worker 
486*cfb92d14SAndroid Build Coastguard Worker     static_cast<NcpBase *>(aContext)->HandleFrameRemovedFromNcpBuffer(aFrameTag);
487*cfb92d14SAndroid Build Coastguard Worker }
488*cfb92d14SAndroid Build Coastguard Worker 
HandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag)489*cfb92d14SAndroid Build Coastguard Worker void NcpBase::HandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag)
490*cfb92d14SAndroid Build Coastguard Worker {
491*cfb92d14SAndroid Build Coastguard Worker     if (mHostPowerStateInProgress)
492*cfb92d14SAndroid Build Coastguard Worker     {
493*cfb92d14SAndroid Build Coastguard Worker         if (aFrameTag == mHostPowerReplyFrameTag)
494*cfb92d14SAndroid Build Coastguard Worker         {
495*cfb92d14SAndroid Build Coastguard Worker             mHostPowerStateInProgress = false;
496*cfb92d14SAndroid Build Coastguard Worker         }
497*cfb92d14SAndroid Build Coastguard Worker     }
498*cfb92d14SAndroid Build Coastguard Worker 
499*cfb92d14SAndroid Build Coastguard Worker     // A frame was removed from NCP TX buffer, so more space is now available.
500*cfb92d14SAndroid Build Coastguard Worker     // We attempt to write/send any pending frames. Order of the checks
501*cfb92d14SAndroid Build Coastguard Worker     // below is important: First any queued command responses, then
502*cfb92d14SAndroid Build Coastguard Worker     // any queued IPv6 datagram messages, then any asynchronous property updates.
503*cfb92d14SAndroid Build Coastguard Worker     // If a frame still can not fit in the available buffer, we exit immediately
504*cfb92d14SAndroid Build Coastguard Worker     // and wait for next time this callback is invoked (when another frame is
505*cfb92d14SAndroid Build Coastguard Worker     // removed and more buffer space becomes available).
506*cfb92d14SAndroid Build Coastguard Worker 
507*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(SendQueuedResponses());
508*cfb92d14SAndroid Build Coastguard Worker 
509*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
510*cfb92d14SAndroid Build Coastguard Worker     VendorHandleFrameRemovedFromNcpBuffer(aFrameTag);
511*cfb92d14SAndroid Build Coastguard Worker #endif
512*cfb92d14SAndroid Build Coastguard Worker 
513*cfb92d14SAndroid Build Coastguard Worker     // Check if `HOST_POWER_STATE` property update is required.
514*cfb92d14SAndroid Build Coastguard Worker 
515*cfb92d14SAndroid Build Coastguard Worker     if (mHostPowerStateHeader)
516*cfb92d14SAndroid Build Coastguard Worker     {
517*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(WritePropertyValueIsFrame(mHostPowerStateHeader, SPINEL_PROP_HOST_POWER_STATE));
518*cfb92d14SAndroid Build Coastguard Worker 
519*cfb92d14SAndroid Build Coastguard Worker         mHostPowerStateHeader = 0;
520*cfb92d14SAndroid Build Coastguard Worker 
521*cfb92d14SAndroid Build Coastguard Worker         if (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE)
522*cfb92d14SAndroid Build Coastguard Worker         {
523*cfb92d14SAndroid Build Coastguard Worker             mHostPowerReplyFrameTag   = GetLastOutboundFrameTag();
524*cfb92d14SAndroid Build Coastguard Worker             mHostPowerStateInProgress = true;
525*cfb92d14SAndroid Build Coastguard Worker         }
526*cfb92d14SAndroid Build Coastguard Worker     }
527*cfb92d14SAndroid Build Coastguard Worker 
528*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
529*cfb92d14SAndroid Build Coastguard Worker 
530*cfb92d14SAndroid Build Coastguard Worker     // Send any queued IPv6 datagram message.
531*cfb92d14SAndroid Build Coastguard Worker 
532*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(SendQueuedDatagramMessages());
533*cfb92d14SAndroid Build Coastguard Worker #endif
534*cfb92d14SAndroid Build Coastguard Worker 
535*cfb92d14SAndroid Build Coastguard Worker     // Send any unsolicited event-triggered property updates.
536*cfb92d14SAndroid Build Coastguard Worker 
537*cfb92d14SAndroid Build Coastguard Worker     UpdateChangedProps();
538*cfb92d14SAndroid Build Coastguard Worker 
539*cfb92d14SAndroid Build Coastguard Worker exit:
540*cfb92d14SAndroid Build Coastguard Worker     return;
541*cfb92d14SAndroid Build Coastguard Worker }
542*cfb92d14SAndroid Build Coastguard Worker 
ShouldWakeHost(void)543*cfb92d14SAndroid Build Coastguard Worker bool NcpBase::ShouldWakeHost(void)
544*cfb92d14SAndroid Build Coastguard Worker {
545*cfb92d14SAndroid Build Coastguard Worker     return (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE && !mHostPowerStateInProgress);
546*cfb92d14SAndroid Build Coastguard Worker }
547*cfb92d14SAndroid Build Coastguard Worker 
ShouldDeferHostSend(void)548*cfb92d14SAndroid Build Coastguard Worker bool NcpBase::ShouldDeferHostSend(void)
549*cfb92d14SAndroid Build Coastguard Worker {
550*cfb92d14SAndroid Build Coastguard Worker     return (mHostPowerState == SPINEL_HOST_POWER_STATE_DEEP_SLEEP && !mHostPowerStateInProgress);
551*cfb92d14SAndroid Build Coastguard Worker }
552*cfb92d14SAndroid Build Coastguard Worker 
IncrementFrameErrorCounter(void)553*cfb92d14SAndroid Build Coastguard Worker void NcpBase::IncrementFrameErrorCounter(void) { mFramingErrorCounter++; }
554*cfb92d14SAndroid Build Coastguard Worker 
StreamWrite(int aStreamId,const uint8_t * aDataPtr,int aDataLen)555*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen)
556*cfb92d14SAndroid Build Coastguard Worker {
557*cfb92d14SAndroid Build Coastguard Worker     otError           error  = OT_ERROR_NONE;
558*cfb92d14SAndroid Build Coastguard Worker     uint8_t           header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID;
559*cfb92d14SAndroid Build Coastguard Worker     spinel_prop_key_t streamPropKey;
560*cfb92d14SAndroid Build Coastguard Worker 
561*cfb92d14SAndroid Build Coastguard Worker     if (aStreamId == 0)
562*cfb92d14SAndroid Build Coastguard Worker     {
563*cfb92d14SAndroid Build Coastguard Worker         streamPropKey = SPINEL_PROP_STREAM_DEBUG;
564*cfb92d14SAndroid Build Coastguard Worker     }
565*cfb92d14SAndroid Build Coastguard Worker     else
566*cfb92d14SAndroid Build Coastguard Worker     {
567*cfb92d14SAndroid Build Coastguard Worker         streamPropKey = static_cast<spinel_prop_key_t>(aStreamId);
568*cfb92d14SAndroid Build Coastguard Worker     }
569*cfb92d14SAndroid Build Coastguard Worker 
570*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mDisableStreamWrite, error = OT_ERROR_INVALID_STATE);
571*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(streamPropKey), error = OT_ERROR_INVALID_STATE);
572*cfb92d14SAndroid Build Coastguard Worker 
573*cfb92d14SAndroid Build Coastguard Worker     // If there is a pending queued response we do not allow any new log
574*cfb92d14SAndroid Build Coastguard Worker     // stream writes. This is to ensure that log messages can not continue
575*cfb92d14SAndroid Build Coastguard Worker     // to use the NCP buffer space and block other spinel frames.
576*cfb92d14SAndroid Build Coastguard Worker 
577*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(IsResponseQueueEmpty(), error = OT_ERROR_NO_BUFS);
578*cfb92d14SAndroid Build Coastguard Worker 
579*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, streamPropKey));
580*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteData(aDataPtr, static_cast<uint16_t>(aDataLen)));
581*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.EndFrame());
582*cfb92d14SAndroid Build Coastguard Worker 
583*cfb92d14SAndroid Build Coastguard Worker exit:
584*cfb92d14SAndroid Build Coastguard Worker 
585*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NO_BUFS)
586*cfb92d14SAndroid Build Coastguard Worker     {
587*cfb92d14SAndroid Build Coastguard Worker         mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
588*cfb92d14SAndroid Build Coastguard Worker         mUpdateChangedPropsTask.Post();
589*cfb92d14SAndroid Build Coastguard Worker     }
590*cfb92d14SAndroid Build Coastguard Worker 
591*cfb92d14SAndroid Build Coastguard Worker     return error;
592*cfb92d14SAndroid Build Coastguard Worker }
593*cfb92d14SAndroid Build Coastguard Worker 
ConvertLogLevel(otLogLevel aLogLevel)594*cfb92d14SAndroid Build Coastguard Worker uint8_t NcpBase::ConvertLogLevel(otLogLevel aLogLevel)
595*cfb92d14SAndroid Build Coastguard Worker {
596*cfb92d14SAndroid Build Coastguard Worker     uint8_t spinelLogLevel = SPINEL_NCP_LOG_LEVEL_EMERG;
597*cfb92d14SAndroid Build Coastguard Worker 
598*cfb92d14SAndroid Build Coastguard Worker     switch (aLogLevel)
599*cfb92d14SAndroid Build Coastguard Worker     {
600*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_NONE:
601*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_EMERG;
602*cfb92d14SAndroid Build Coastguard Worker         break;
603*cfb92d14SAndroid Build Coastguard Worker 
604*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_CRIT:
605*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_CRIT;
606*cfb92d14SAndroid Build Coastguard Worker         break;
607*cfb92d14SAndroid Build Coastguard Worker 
608*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_WARN:
609*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_WARN;
610*cfb92d14SAndroid Build Coastguard Worker         break;
611*cfb92d14SAndroid Build Coastguard Worker 
612*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_NOTE:
613*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_NOTICE;
614*cfb92d14SAndroid Build Coastguard Worker         break;
615*cfb92d14SAndroid Build Coastguard Worker 
616*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_INFO:
617*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_INFO;
618*cfb92d14SAndroid Build Coastguard Worker         break;
619*cfb92d14SAndroid Build Coastguard Worker 
620*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_LEVEL_DEBG:
621*cfb92d14SAndroid Build Coastguard Worker         spinelLogLevel = SPINEL_NCP_LOG_LEVEL_DEBUG;
622*cfb92d14SAndroid Build Coastguard Worker         break;
623*cfb92d14SAndroid Build Coastguard Worker     }
624*cfb92d14SAndroid Build Coastguard Worker 
625*cfb92d14SAndroid Build Coastguard Worker     return spinelLogLevel;
626*cfb92d14SAndroid Build Coastguard Worker }
627*cfb92d14SAndroid Build Coastguard Worker 
ConvertLogRegion(otLogRegion aLogRegion)628*cfb92d14SAndroid Build Coastguard Worker unsigned int NcpBase::ConvertLogRegion(otLogRegion aLogRegion)
629*cfb92d14SAndroid Build Coastguard Worker {
630*cfb92d14SAndroid Build Coastguard Worker     unsigned int spinelLogRegion = SPINEL_NCP_LOG_REGION_NONE;
631*cfb92d14SAndroid Build Coastguard Worker 
632*cfb92d14SAndroid Build Coastguard Worker     switch (aLogRegion)
633*cfb92d14SAndroid Build Coastguard Worker     {
634*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_API:
635*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_API;
636*cfb92d14SAndroid Build Coastguard Worker         break;
637*cfb92d14SAndroid Build Coastguard Worker 
638*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_MLE:
639*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_MLE;
640*cfb92d14SAndroid Build Coastguard Worker         break;
641*cfb92d14SAndroid Build Coastguard Worker 
642*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_ARP:
643*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_ARP;
644*cfb92d14SAndroid Build Coastguard Worker         break;
645*cfb92d14SAndroid Build Coastguard Worker 
646*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_NET_DATA:
647*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_NET_DATA;
648*cfb92d14SAndroid Build Coastguard Worker         break;
649*cfb92d14SAndroid Build Coastguard Worker 
650*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_ICMP:
651*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_ICMP;
652*cfb92d14SAndroid Build Coastguard Worker         break;
653*cfb92d14SAndroid Build Coastguard Worker 
654*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_IP6:
655*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_IP6;
656*cfb92d14SAndroid Build Coastguard Worker         break;
657*cfb92d14SAndroid Build Coastguard Worker 
658*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_TCP:
659*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_TCP;
660*cfb92d14SAndroid Build Coastguard Worker         break;
661*cfb92d14SAndroid Build Coastguard Worker 
662*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_MAC:
663*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_MAC;
664*cfb92d14SAndroid Build Coastguard Worker         break;
665*cfb92d14SAndroid Build Coastguard Worker 
666*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_MEM:
667*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_MEM;
668*cfb92d14SAndroid Build Coastguard Worker         break;
669*cfb92d14SAndroid Build Coastguard Worker 
670*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_NCP:
671*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_NCP;
672*cfb92d14SAndroid Build Coastguard Worker         break;
673*cfb92d14SAndroid Build Coastguard Worker 
674*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_MESH_COP:
675*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_MESH_COP;
676*cfb92d14SAndroid Build Coastguard Worker         break;
677*cfb92d14SAndroid Build Coastguard Worker 
678*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_NET_DIAG:
679*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_NET_DIAG;
680*cfb92d14SAndroid Build Coastguard Worker         break;
681*cfb92d14SAndroid Build Coastguard Worker 
682*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_PLATFORM:
683*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_PLATFORM;
684*cfb92d14SAndroid Build Coastguard Worker         break;
685*cfb92d14SAndroid Build Coastguard Worker 
686*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_COAP:
687*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_COAP;
688*cfb92d14SAndroid Build Coastguard Worker         break;
689*cfb92d14SAndroid Build Coastguard Worker 
690*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_CLI:
691*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_CLI;
692*cfb92d14SAndroid Build Coastguard Worker         break;
693*cfb92d14SAndroid Build Coastguard Worker 
694*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_CORE:
695*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_CORE;
696*cfb92d14SAndroid Build Coastguard Worker         break;
697*cfb92d14SAndroid Build Coastguard Worker 
698*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_UTIL:
699*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_UTIL;
700*cfb92d14SAndroid Build Coastguard Worker         break;
701*cfb92d14SAndroid Build Coastguard Worker 
702*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_BBR:
703*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_BBR;
704*cfb92d14SAndroid Build Coastguard Worker         break;
705*cfb92d14SAndroid Build Coastguard Worker 
706*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_MLR:
707*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_MLR;
708*cfb92d14SAndroid Build Coastguard Worker         break;
709*cfb92d14SAndroid Build Coastguard Worker 
710*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_DUA:
711*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_DUA;
712*cfb92d14SAndroid Build Coastguard Worker         break;
713*cfb92d14SAndroid Build Coastguard Worker 
714*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_BR:
715*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_BR;
716*cfb92d14SAndroid Build Coastguard Worker         break;
717*cfb92d14SAndroid Build Coastguard Worker 
718*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_SRP:
719*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_SRP;
720*cfb92d14SAndroid Build Coastguard Worker         break;
721*cfb92d14SAndroid Build Coastguard Worker 
722*cfb92d14SAndroid Build Coastguard Worker     case OT_LOG_REGION_DNS:
723*cfb92d14SAndroid Build Coastguard Worker         spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_DNS;
724*cfb92d14SAndroid Build Coastguard Worker         break;
725*cfb92d14SAndroid Build Coastguard Worker     }
726*cfb92d14SAndroid Build Coastguard Worker 
727*cfb92d14SAndroid Build Coastguard Worker     return spinelLogRegion;
728*cfb92d14SAndroid Build Coastguard Worker }
729*cfb92d14SAndroid Build Coastguard Worker 
Log(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aLogString)730*cfb92d14SAndroid Build Coastguard Worker void NcpBase::Log(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogString)
731*cfb92d14SAndroid Build Coastguard Worker {
732*cfb92d14SAndroid Build Coastguard Worker     otError error  = OT_ERROR_NONE;
733*cfb92d14SAndroid Build Coastguard Worker     uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID;
734*cfb92d14SAndroid Build Coastguard Worker 
735*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mDisableStreamWrite, error = OT_ERROR_INVALID_STATE);
736*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(SPINEL_PROP_STREAM_LOG));
737*cfb92d14SAndroid Build Coastguard Worker 
738*cfb92d14SAndroid Build Coastguard Worker     // If there is a pending queued response we do not allow any new log
739*cfb92d14SAndroid Build Coastguard Worker     // stream writes. This is to ensure that log messages can not continue
740*cfb92d14SAndroid Build Coastguard Worker     // to use the NCP buffer space and block other spinel frames.
741*cfb92d14SAndroid Build Coastguard Worker 
742*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(IsResponseQueueEmpty(), error = OT_ERROR_NO_BUFS);
743*cfb92d14SAndroid Build Coastguard Worker 
744*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_LOG));
745*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUtf8(aLogString));
746*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint8(ConvertLogLevel(aLogLevel)));
747*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(ConvertLogRegion(aLogRegion)));
748*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint64(mLogTimestampBase + otPlatAlarmMilliGetNow()));
749*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.EndFrame());
750*cfb92d14SAndroid Build Coastguard Worker 
751*cfb92d14SAndroid Build Coastguard Worker exit:
752*cfb92d14SAndroid Build Coastguard Worker 
753*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NO_BUFS)
754*cfb92d14SAndroid Build Coastguard Worker     {
755*cfb92d14SAndroid Build Coastguard Worker         mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
756*cfb92d14SAndroid Build Coastguard Worker         mUpdateChangedPropsTask.Post();
757*cfb92d14SAndroid Build Coastguard Worker     }
758*cfb92d14SAndroid Build Coastguard Worker }
759*cfb92d14SAndroid Build Coastguard Worker 
760*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
761*cfb92d14SAndroid Build Coastguard Worker 
RegisterPeekPokeDelegates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,otNcpDelegateAllowPeekPoke aAllowPokeDelegate)762*cfb92d14SAndroid Build Coastguard Worker void NcpBase::RegisterPeekPokeDelegates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,
763*cfb92d14SAndroid Build Coastguard Worker                                         otNcpDelegateAllowPeekPoke aAllowPokeDelegate)
764*cfb92d14SAndroid Build Coastguard Worker {
765*cfb92d14SAndroid Build Coastguard Worker     mAllowPeekDelegate = aAllowPeekDelegate;
766*cfb92d14SAndroid Build Coastguard Worker     mAllowPokeDelegate = aAllowPokeDelegate;
767*cfb92d14SAndroid Build Coastguard Worker }
768*cfb92d14SAndroid Build Coastguard Worker 
769*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
770*cfb92d14SAndroid Build Coastguard Worker 
771*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
772*cfb92d14SAndroid Build Coastguard Worker // MARK: Spinel Response Handling
773*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
774*cfb92d14SAndroid Build Coastguard Worker 
GetWrappedResponseQueueIndex(uint8_t aPosition)775*cfb92d14SAndroid Build Coastguard Worker uint8_t NcpBase::GetWrappedResponseQueueIndex(uint8_t aPosition)
776*cfb92d14SAndroid Build Coastguard Worker {
777*cfb92d14SAndroid Build Coastguard Worker     while (aPosition >= kResponseQueueSize)
778*cfb92d14SAndroid Build Coastguard Worker     {
779*cfb92d14SAndroid Build Coastguard Worker         aPosition -= kResponseQueueSize;
780*cfb92d14SAndroid Build Coastguard Worker     }
781*cfb92d14SAndroid Build Coastguard Worker 
782*cfb92d14SAndroid Build Coastguard Worker     return aPosition;
783*cfb92d14SAndroid Build Coastguard Worker }
784*cfb92d14SAndroid Build Coastguard Worker 
EnqueueResponse(uint8_t aHeader,ResponseType aType,unsigned int aPropKeyOrStatus)785*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned int aPropKeyOrStatus)
786*cfb92d14SAndroid Build Coastguard Worker {
787*cfb92d14SAndroid Build Coastguard Worker     otError        error = OT_ERROR_NONE;
788*cfb92d14SAndroid Build Coastguard Worker     spinel_iid_t   iid   = SPINEL_HEADER_GET_IID(aHeader);
789*cfb92d14SAndroid Build Coastguard Worker     spinel_tid_t   tid   = SPINEL_HEADER_GET_TID(aHeader);
790*cfb92d14SAndroid Build Coastguard Worker     ResponseEntry *entry;
791*cfb92d14SAndroid Build Coastguard Worker 
792*cfb92d14SAndroid Build Coastguard Worker     if (tid == 0)
793*cfb92d14SAndroid Build Coastguard Worker     {
794*cfb92d14SAndroid Build Coastguard Worker         // No response is required for TID zero. But we may emit a
795*cfb92d14SAndroid Build Coastguard Worker         // `LAST_STATUS` error status (if not filtered) for TID
796*cfb92d14SAndroid Build Coastguard Worker         // zero (e.g., for a dropped `STREAM_NET` set command).
797*cfb92d14SAndroid Build Coastguard Worker 
798*cfb92d14SAndroid Build Coastguard Worker         if (aType == kResponseTypeLastStatus)
799*cfb92d14SAndroid Build Coastguard Worker         {
800*cfb92d14SAndroid Build Coastguard Worker             mChangedPropsSet.AddLastStatus(static_cast<spinel_status_t>(aPropKeyOrStatus));
801*cfb92d14SAndroid Build Coastguard Worker         }
802*cfb92d14SAndroid Build Coastguard Worker 
803*cfb92d14SAndroid Build Coastguard Worker         ExitNow();
804*cfb92d14SAndroid Build Coastguard Worker     }
805*cfb92d14SAndroid Build Coastguard Worker 
806*cfb92d14SAndroid Build Coastguard Worker     if ((mResponseQueueTail - mResponseQueueHead) >= kResponseQueueSize)
807*cfb92d14SAndroid Build Coastguard Worker     {
808*cfb92d14SAndroid Build Coastguard Worker         // If there is no room a for a response, emit an unsolicited
809*cfb92d14SAndroid Build Coastguard Worker         // `DROPPED` error status to indicate a spinel response was
810*cfb92d14SAndroid Build Coastguard Worker         // dropped.
811*cfb92d14SAndroid Build Coastguard Worker 
812*cfb92d14SAndroid Build Coastguard Worker         mChangedPropsSet.AddLastStatus(SPINEL_STATUS_DROPPED);
813*cfb92d14SAndroid Build Coastguard Worker 
814*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_NO_BUFS);
815*cfb92d14SAndroid Build Coastguard Worker     }
816*cfb92d14SAndroid Build Coastguard Worker 
817*cfb92d14SAndroid Build Coastguard Worker     // Transaction IDs are expected to come in sequence, if however, we
818*cfb92d14SAndroid Build Coastguard Worker     // get an out of sequence TID, check if we already have a response
819*cfb92d14SAndroid Build Coastguard Worker     // queued for this TID and if so mark the old entry as deleted.
820*cfb92d14SAndroid Build Coastguard Worker 
821*cfb92d14SAndroid Build Coastguard Worker     if (tid != mNextExpectedTid[iid])
822*cfb92d14SAndroid Build Coastguard Worker     {
823*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t cur = mResponseQueueHead; cur < mResponseQueueTail; cur++)
824*cfb92d14SAndroid Build Coastguard Worker         {
825*cfb92d14SAndroid Build Coastguard Worker             entry = &mResponseQueue[GetWrappedResponseQueueIndex(cur)];
826*cfb92d14SAndroid Build Coastguard Worker 
827*cfb92d14SAndroid Build Coastguard Worker             if (entry->mIsInUse && (entry->mIid == iid) && (entry->mTid == tid))
828*cfb92d14SAndroid Build Coastguard Worker             {
829*cfb92d14SAndroid Build Coastguard Worker                 // Entry is just marked here and will be removed
830*cfb92d14SAndroid Build Coastguard Worker                 // from `SendQueuedResponses()`.
831*cfb92d14SAndroid Build Coastguard Worker 
832*cfb92d14SAndroid Build Coastguard Worker                 entry->mIsInUse = false;
833*cfb92d14SAndroid Build Coastguard Worker                 break;
834*cfb92d14SAndroid Build Coastguard Worker             }
835*cfb92d14SAndroid Build Coastguard Worker         }
836*cfb92d14SAndroid Build Coastguard Worker     }
837*cfb92d14SAndroid Build Coastguard Worker 
838*cfb92d14SAndroid Build Coastguard Worker     // Add the new entry in the queue at tail.
839*cfb92d14SAndroid Build Coastguard Worker 
840*cfb92d14SAndroid Build Coastguard Worker     entry = &mResponseQueue[GetWrappedResponseQueueIndex(mResponseQueueTail)];
841*cfb92d14SAndroid Build Coastguard Worker 
842*cfb92d14SAndroid Build Coastguard Worker     entry->mIid             = iid;
843*cfb92d14SAndroid Build Coastguard Worker     entry->mTid             = tid;
844*cfb92d14SAndroid Build Coastguard Worker     entry->mIsInUse         = true;
845*cfb92d14SAndroid Build Coastguard Worker     entry->mType            = aType;
846*cfb92d14SAndroid Build Coastguard Worker     entry->mPropKeyOrStatus = aPropKeyOrStatus;
847*cfb92d14SAndroid Build Coastguard Worker 
848*cfb92d14SAndroid Build Coastguard Worker     mResponseQueueTail++;
849*cfb92d14SAndroid Build Coastguard Worker 
850*cfb92d14SAndroid Build Coastguard Worker exit:
851*cfb92d14SAndroid Build Coastguard Worker     return error;
852*cfb92d14SAndroid Build Coastguard Worker }
853*cfb92d14SAndroid Build Coastguard Worker 
SendQueuedResponses(void)854*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::SendQueuedResponses(void)
855*cfb92d14SAndroid Build Coastguard Worker {
856*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
857*cfb92d14SAndroid Build Coastguard Worker 
858*cfb92d14SAndroid Build Coastguard Worker     while (mResponseQueueHead != mResponseQueueTail)
859*cfb92d14SAndroid Build Coastguard Worker     {
860*cfb92d14SAndroid Build Coastguard Worker         ResponseEntry &entry = mResponseQueue[mResponseQueueHead];
861*cfb92d14SAndroid Build Coastguard Worker 
862*cfb92d14SAndroid Build Coastguard Worker         if (entry.mIsInUse)
863*cfb92d14SAndroid Build Coastguard Worker         {
864*cfb92d14SAndroid Build Coastguard Worker             uint8_t header = SPINEL_HEADER_FLAG;
865*cfb92d14SAndroid Build Coastguard Worker             header |= SPINEL_HEADER_IID(entry.mIid);
866*cfb92d14SAndroid Build Coastguard Worker             header |= static_cast<uint8_t>(entry.mTid << SPINEL_HEADER_TID_SHIFT);
867*cfb92d14SAndroid Build Coastguard Worker 
868*cfb92d14SAndroid Build Coastguard Worker             if (entry.mType == kResponseTypeLastStatus)
869*cfb92d14SAndroid Build Coastguard Worker             {
870*cfb92d14SAndroid Build Coastguard Worker                 spinel_status_t status = static_cast<spinel_status_t>(entry.mPropKeyOrStatus);
871*cfb92d14SAndroid Build Coastguard Worker 
872*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = WriteLastStatusFrame(header, status));
873*cfb92d14SAndroid Build Coastguard Worker             }
874*cfb92d14SAndroid Build Coastguard Worker             else
875*cfb92d14SAndroid Build Coastguard Worker             {
876*cfb92d14SAndroid Build Coastguard Worker                 spinel_prop_key_t propKey       = static_cast<spinel_prop_key_t>(entry.mPropKeyOrStatus);
877*cfb92d14SAndroid Build Coastguard Worker                 bool              isGetResponse = (entry.mType == kResponseTypeGet);
878*cfb92d14SAndroid Build Coastguard Worker 
879*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = WritePropertyValueIsFrame(header, propKey, isGetResponse));
880*cfb92d14SAndroid Build Coastguard Worker             }
881*cfb92d14SAndroid Build Coastguard Worker         }
882*cfb92d14SAndroid Build Coastguard Worker 
883*cfb92d14SAndroid Build Coastguard Worker         // Remove the response entry.
884*cfb92d14SAndroid Build Coastguard Worker 
885*cfb92d14SAndroid Build Coastguard Worker         entry.mIsInUse = false;
886*cfb92d14SAndroid Build Coastguard Worker 
887*cfb92d14SAndroid Build Coastguard Worker         mResponseQueueHead++;
888*cfb92d14SAndroid Build Coastguard Worker 
889*cfb92d14SAndroid Build Coastguard Worker         if (mResponseQueueHead == kResponseQueueSize)
890*cfb92d14SAndroid Build Coastguard Worker         {
891*cfb92d14SAndroid Build Coastguard Worker             // Only when `head` wraps, the `tail` will be wrapped as well.
892*cfb92d14SAndroid Build Coastguard Worker             //
893*cfb92d14SAndroid Build Coastguard Worker             // This ensures that `tail` is always bigger than `head` and
894*cfb92d14SAndroid Build Coastguard Worker             // `(tail - head)` to correctly give the number of items in
895*cfb92d14SAndroid Build Coastguard Worker             // the queue.
896*cfb92d14SAndroid Build Coastguard Worker 
897*cfb92d14SAndroid Build Coastguard Worker             mResponseQueueHead = 0;
898*cfb92d14SAndroid Build Coastguard Worker             mResponseQueueTail = GetWrappedResponseQueueIndex(mResponseQueueTail);
899*cfb92d14SAndroid Build Coastguard Worker         }
900*cfb92d14SAndroid Build Coastguard Worker     }
901*cfb92d14SAndroid Build Coastguard Worker 
902*cfb92d14SAndroid Build Coastguard Worker exit:
903*cfb92d14SAndroid Build Coastguard Worker     return error;
904*cfb92d14SAndroid Build Coastguard Worker }
905*cfb92d14SAndroid Build Coastguard Worker 
906*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
907*cfb92d14SAndroid Build Coastguard Worker // MARK: Property/Status Changed
908*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
909*cfb92d14SAndroid Build Coastguard Worker 
UpdateChangedProps(Tasklet & aTasklet)910*cfb92d14SAndroid Build Coastguard Worker void NcpBase::UpdateChangedProps(Tasklet &aTasklet)
911*cfb92d14SAndroid Build Coastguard Worker {
912*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aTasklet);
913*cfb92d14SAndroid Build Coastguard Worker     GetNcpInstance()->UpdateChangedProps();
914*cfb92d14SAndroid Build Coastguard Worker }
915*cfb92d14SAndroid Build Coastguard Worker 
UpdateChangedProps(void)916*cfb92d14SAndroid Build Coastguard Worker void NcpBase::UpdateChangedProps(void)
917*cfb92d14SAndroid Build Coastguard Worker {
918*cfb92d14SAndroid Build Coastguard Worker     uint8_t                       numEntries;
919*cfb92d14SAndroid Build Coastguard Worker     spinel_prop_key_t             propKey;
920*cfb92d14SAndroid Build Coastguard Worker     const ChangedPropsSet::Entry *entry;
921*cfb92d14SAndroid Build Coastguard Worker 
922*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
923*cfb92d14SAndroid Build Coastguard Worker     ProcessThreadChangedFlags();
924*cfb92d14SAndroid Build Coastguard Worker #endif
925*cfb92d14SAndroid Build Coastguard Worker 
926*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mChangedPropsSet.IsEmpty());
927*cfb92d14SAndroid Build Coastguard Worker 
928*cfb92d14SAndroid Build Coastguard Worker     entry = mChangedPropsSet.GetSupportedEntries(numEntries);
929*cfb92d14SAndroid Build Coastguard Worker 
930*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
931*cfb92d14SAndroid Build Coastguard Worker     {
932*cfb92d14SAndroid Build Coastguard Worker         if (!mChangedPropsSet.IsEntryChanged(index))
933*cfb92d14SAndroid Build Coastguard Worker         {
934*cfb92d14SAndroid Build Coastguard Worker             continue;
935*cfb92d14SAndroid Build Coastguard Worker         }
936*cfb92d14SAndroid Build Coastguard Worker 
937*cfb92d14SAndroid Build Coastguard Worker         propKey = entry->mPropKey;
938*cfb92d14SAndroid Build Coastguard Worker 
939*cfb92d14SAndroid Build Coastguard Worker         if (propKey == SPINEL_PROP_LAST_STATUS)
940*cfb92d14SAndroid Build Coastguard Worker         {
941*cfb92d14SAndroid Build Coastguard Worker             spinel_status_t status = entry->mStatus;
942*cfb92d14SAndroid Build Coastguard Worker 
943*cfb92d14SAndroid Build Coastguard Worker             if (status == SPINEL_STATUS_RESET_UNKNOWN)
944*cfb92d14SAndroid Build Coastguard Worker             {
945*cfb92d14SAndroid Build Coastguard Worker                 status = ResetReasonToSpinelStatus(otPlatGetResetReason(mInstance));
946*cfb92d14SAndroid Build Coastguard Worker             }
947*cfb92d14SAndroid Build Coastguard Worker 
948*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID, status));
949*cfb92d14SAndroid Build Coastguard Worker         }
950*cfb92d14SAndroid Build Coastguard Worker         else if (mDidInitialUpdates)
951*cfb92d14SAndroid Build Coastguard Worker         {
952*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID, propKey));
953*cfb92d14SAndroid Build Coastguard Worker         }
954*cfb92d14SAndroid Build Coastguard Worker 
955*cfb92d14SAndroid Build Coastguard Worker         mChangedPropsSet.RemoveEntry(index);
956*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(!mChangedPropsSet.IsEmpty());
957*cfb92d14SAndroid Build Coastguard Worker     }
958*cfb92d14SAndroid Build Coastguard Worker 
959*cfb92d14SAndroid Build Coastguard Worker exit:
960*cfb92d14SAndroid Build Coastguard Worker     mDidInitialUpdates = true;
961*cfb92d14SAndroid Build Coastguard Worker }
962*cfb92d14SAndroid Build Coastguard Worker 
963*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
964*cfb92d14SAndroid Build Coastguard Worker // MARK: Inbound Command Handler
965*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
966*cfb92d14SAndroid Build Coastguard Worker 
HandleCommand(uint8_t aHeader)967*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::HandleCommand(uint8_t aHeader)
968*cfb92d14SAndroid Build Coastguard Worker {
969*cfb92d14SAndroid Build Coastguard Worker     otError      error = OT_ERROR_NONE;
970*cfb92d14SAndroid Build Coastguard Worker     unsigned int command;
971*cfb92d14SAndroid Build Coastguard Worker 
972*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUintPacked(command));
973*cfb92d14SAndroid Build Coastguard Worker 
974*cfb92d14SAndroid Build Coastguard Worker     switch (command)
975*cfb92d14SAndroid Build Coastguard Worker     {
976*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_NOOP:
977*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_NOOP(aHeader);
978*cfb92d14SAndroid Build Coastguard Worker         break;
979*cfb92d14SAndroid Build Coastguard Worker 
980*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_RESET:
981*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_RESET(aHeader);
982*cfb92d14SAndroid Build Coastguard Worker         break;
983*cfb92d14SAndroid Build Coastguard Worker 
984*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_GET:
985*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_SET:
986*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_INSERT:
987*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_REMOVE:
988*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_PROP_VALUE_update(aHeader, command);
989*cfb92d14SAndroid Build Coastguard Worker         break;
990*cfb92d14SAndroid Build Coastguard Worker 
991*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
992*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PEEK:
993*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_PEEK(aHeader);
994*cfb92d14SAndroid Build Coastguard Worker         break;
995*cfb92d14SAndroid Build Coastguard Worker 
996*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_POKE:
997*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_POKE(aHeader);
998*cfb92d14SAndroid Build Coastguard Worker         break;
999*cfb92d14SAndroid Build Coastguard Worker #endif
1000*cfb92d14SAndroid Build Coastguard Worker 
1001*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1002*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_NET_SAVE:
1003*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_NET_RECALL:
1004*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_NOT_IMPLEMENTED;
1005*cfb92d14SAndroid Build Coastguard Worker         break;
1006*cfb92d14SAndroid Build Coastguard Worker 
1007*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_NET_CLEAR:
1008*cfb92d14SAndroid Build Coastguard Worker         error = CommandHandler_NET_CLEAR(aHeader);
1009*cfb92d14SAndroid Build Coastguard Worker         break;
1010*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
1011*cfb92d14SAndroid Build Coastguard Worker 
1012*cfb92d14SAndroid Build Coastguard Worker     default:
1013*cfb92d14SAndroid Build Coastguard Worker 
1014*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
1015*cfb92d14SAndroid Build Coastguard Worker         if (command >= SPINEL_CMD_VENDOR__BEGIN && command < SPINEL_CMD_VENDOR__END)
1016*cfb92d14SAndroid Build Coastguard Worker         {
1017*cfb92d14SAndroid Build Coastguard Worker             error = VendorCommandHandler(aHeader, command);
1018*cfb92d14SAndroid Build Coastguard Worker             break;
1019*cfb92d14SAndroid Build Coastguard Worker         }
1020*cfb92d14SAndroid Build Coastguard Worker #endif
1021*cfb92d14SAndroid Build Coastguard Worker 
1022*cfb92d14SAndroid Build Coastguard Worker         error = PrepareLastStatusResponse(aHeader, SPINEL_STATUS_INVALID_COMMAND);
1023*cfb92d14SAndroid Build Coastguard Worker         break;
1024*cfb92d14SAndroid Build Coastguard Worker     }
1025*cfb92d14SAndroid Build Coastguard Worker 
1026*cfb92d14SAndroid Build Coastguard Worker exit:
1027*cfb92d14SAndroid Build Coastguard Worker     return error;
1028*cfb92d14SAndroid Build Coastguard Worker }
1029*cfb92d14SAndroid Build Coastguard Worker 
1030*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1031*cfb92d14SAndroid Build Coastguard Worker // MARK: Property Get/Set/Insert/Remove Commands
1032*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1033*cfb92d14SAndroid Build Coastguard Worker 
1034*cfb92d14SAndroid Build Coastguard Worker // Returns `true` and updates the `aError` on success.
HandlePropertySetForSpecialProperties(uint8_t aHeader,spinel_prop_key_t aKey,otError & aError)1035*cfb92d14SAndroid Build Coastguard Worker bool NcpBase::HandlePropertySetForSpecialProperties(uint8_t aHeader, spinel_prop_key_t aKey, otError &aError)
1036*cfb92d14SAndroid Build Coastguard Worker {
1037*cfb92d14SAndroid Build Coastguard Worker     bool didHandle = true;
1038*cfb92d14SAndroid Build Coastguard Worker 
1039*cfb92d14SAndroid Build Coastguard Worker     // Here the properties that require special treatment are handled.
1040*cfb92d14SAndroid Build Coastguard Worker     // These properties are expected to form/write the response from
1041*cfb92d14SAndroid Build Coastguard Worker     // their set handler directly.
1042*cfb92d14SAndroid Build Coastguard Worker 
1043*cfb92d14SAndroid Build Coastguard Worker     switch (aKey)
1044*cfb92d14SAndroid Build Coastguard Worker     {
1045*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_PROP_HOST_POWER_STATE:
1046*cfb92d14SAndroid Build Coastguard Worker         ExitNow(aError = HandlePropertySet_SPINEL_PROP_HOST_POWER_STATE(aHeader));
1047*cfb92d14SAndroid Build Coastguard Worker 
1048*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DIAG_ENABLE
1049*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_PROP_NEST_STREAM_MFG:
1050*cfb92d14SAndroid Build Coastguard Worker         ExitNow(aError = HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(aHeader));
1051*cfb92d14SAndroid Build Coastguard Worker #endif
1052*cfb92d14SAndroid Build Coastguard Worker 
1053*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
1054*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC:
1055*cfb92d14SAndroid Build Coastguard Worker         ExitNow(aError = HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(aHeader));
1056*cfb92d14SAndroid Build Coastguard Worker 
1057*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_PROP_THREAD_COMMISSIONER_ENABLED:
1058*cfb92d14SAndroid Build Coastguard Worker         ExitNow(aError = HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(aHeader));
1059*cfb92d14SAndroid Build Coastguard Worker #endif
1060*cfb92d14SAndroid Build Coastguard Worker 
1061*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1062*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_PROP_STREAM_RAW:
1063*cfb92d14SAndroid Build Coastguard Worker         ExitNow(aError = HandlePropertySet_SPINEL_PROP_STREAM_RAW(aHeader));
1064*cfb92d14SAndroid Build Coastguard Worker #endif
1065*cfb92d14SAndroid Build Coastguard Worker 
1066*cfb92d14SAndroid Build Coastguard Worker     default:
1067*cfb92d14SAndroid Build Coastguard Worker         didHandle = false;
1068*cfb92d14SAndroid Build Coastguard Worker         break;
1069*cfb92d14SAndroid Build Coastguard Worker     }
1070*cfb92d14SAndroid Build Coastguard Worker 
1071*cfb92d14SAndroid Build Coastguard Worker exit:
1072*cfb92d14SAndroid Build Coastguard Worker     return didHandle;
1073*cfb92d14SAndroid Build Coastguard Worker }
1074*cfb92d14SAndroid Build Coastguard Worker 
HandleCommandPropertySet(uint8_t aHeader,spinel_prop_key_t aKey)1075*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::HandleCommandPropertySet(uint8_t aHeader, spinel_prop_key_t aKey)
1076*cfb92d14SAndroid Build Coastguard Worker {
1077*cfb92d14SAndroid Build Coastguard Worker     otError         error   = OT_ERROR_NONE;
1078*cfb92d14SAndroid Build Coastguard Worker     PropertyHandler handler = FindSetPropertyHandler(aKey);
1079*cfb92d14SAndroid Build Coastguard Worker 
1080*cfb92d14SAndroid Build Coastguard Worker     if (handler != nullptr)
1081*cfb92d14SAndroid Build Coastguard Worker     {
1082*cfb92d14SAndroid Build Coastguard Worker         mDisableStreamWrite = false;
1083*cfb92d14SAndroid Build Coastguard Worker         error               = (this->*handler)();
1084*cfb92d14SAndroid Build Coastguard Worker         mDisableStreamWrite = true;
1085*cfb92d14SAndroid Build Coastguard Worker     }
1086*cfb92d14SAndroid Build Coastguard Worker     else
1087*cfb92d14SAndroid Build Coastguard Worker     {
1088*cfb92d14SAndroid Build Coastguard Worker         // If there is no "set" handler, check if this property is one of the
1089*cfb92d14SAndroid Build Coastguard Worker         // ones that require different treatment.
1090*cfb92d14SAndroid Build Coastguard Worker 
1091*cfb92d14SAndroid Build Coastguard Worker         bool didHandle = HandlePropertySetForSpecialProperties(aHeader, aKey, error);
1092*cfb92d14SAndroid Build Coastguard Worker 
1093*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(!didHandle);
1094*cfb92d14SAndroid Build Coastguard Worker 
1095*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
1096*cfb92d14SAndroid Build Coastguard Worker         if (aKey >= SPINEL_PROP_VENDOR__BEGIN && aKey < SPINEL_PROP_VENDOR__END)
1097*cfb92d14SAndroid Build Coastguard Worker         {
1098*cfb92d14SAndroid Build Coastguard Worker             mDisableStreamWrite = false;
1099*cfb92d14SAndroid Build Coastguard Worker             error               = VendorSetPropertyHandler(aKey);
1100*cfb92d14SAndroid Build Coastguard Worker             mDisableStreamWrite = true;
1101*cfb92d14SAndroid Build Coastguard Worker 
1102*cfb92d14SAndroid Build Coastguard Worker             // An `OT_ERROR_NOT_FOUND` status from vendor handler indicates
1103*cfb92d14SAndroid Build Coastguard Worker             // that it does not support the given property key. In that
1104*cfb92d14SAndroid Build Coastguard Worker             // case, `didHandle` is set to `false` so a `LAST_STATUS` with
1105*cfb92d14SAndroid Build Coastguard Worker             // `PROP_NOT_FOUND` is emitted. Otherwise, we fall through to
1106*cfb92d14SAndroid Build Coastguard Worker             // prepare the response.
1107*cfb92d14SAndroid Build Coastguard Worker 
1108*cfb92d14SAndroid Build Coastguard Worker             didHandle = (error != OT_ERROR_NOT_FOUND);
1109*cfb92d14SAndroid Build Coastguard Worker         }
1110*cfb92d14SAndroid Build Coastguard Worker #endif
1111*cfb92d14SAndroid Build Coastguard Worker 
1112*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(didHandle, error = PrepareLastStatusResponse(aHeader, SPINEL_STATUS_PROP_NOT_FOUND));
1113*cfb92d14SAndroid Build Coastguard Worker     }
1114*cfb92d14SAndroid Build Coastguard Worker 
1115*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
1116*cfb92d14SAndroid Build Coastguard Worker     {
1117*cfb92d14SAndroid Build Coastguard Worker         error = PrepareSetResponse(aHeader, aKey);
1118*cfb92d14SAndroid Build Coastguard Worker     }
1119*cfb92d14SAndroid Build Coastguard Worker     else
1120*cfb92d14SAndroid Build Coastguard Worker     {
1121*cfb92d14SAndroid Build Coastguard Worker         error = PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error));
1122*cfb92d14SAndroid Build Coastguard Worker     }
1123*cfb92d14SAndroid Build Coastguard Worker 
1124*cfb92d14SAndroid Build Coastguard Worker exit:
1125*cfb92d14SAndroid Build Coastguard Worker     return error;
1126*cfb92d14SAndroid Build Coastguard Worker }
1127*cfb92d14SAndroid Build Coastguard Worker 
HandleCommandPropertyInsertRemove(uint8_t aHeader,spinel_prop_key_t aKey,unsigned int aCommand)1128*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::HandleCommandPropertyInsertRemove(uint8_t aHeader, spinel_prop_key_t aKey, unsigned int aCommand)
1129*cfb92d14SAndroid Build Coastguard Worker {
1130*cfb92d14SAndroid Build Coastguard Worker     otError         error           = OT_ERROR_NONE;
1131*cfb92d14SAndroid Build Coastguard Worker     PropertyHandler handler         = nullptr;
1132*cfb92d14SAndroid Build Coastguard Worker     unsigned int    responseCommand = 0;
1133*cfb92d14SAndroid Build Coastguard Worker     const uint8_t  *valuePtr;
1134*cfb92d14SAndroid Build Coastguard Worker     uint16_t        valueLen;
1135*cfb92d14SAndroid Build Coastguard Worker 
1136*cfb92d14SAndroid Build Coastguard Worker     switch (aCommand)
1137*cfb92d14SAndroid Build Coastguard Worker     {
1138*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_INSERT:
1139*cfb92d14SAndroid Build Coastguard Worker         handler         = FindInsertPropertyHandler(aKey);
1140*cfb92d14SAndroid Build Coastguard Worker         responseCommand = SPINEL_CMD_PROP_VALUE_INSERTED;
1141*cfb92d14SAndroid Build Coastguard Worker         break;
1142*cfb92d14SAndroid Build Coastguard Worker 
1143*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_REMOVE:
1144*cfb92d14SAndroid Build Coastguard Worker         handler         = FindRemovePropertyHandler(aKey);
1145*cfb92d14SAndroid Build Coastguard Worker         responseCommand = SPINEL_CMD_PROP_VALUE_REMOVED;
1146*cfb92d14SAndroid Build Coastguard Worker         break;
1147*cfb92d14SAndroid Build Coastguard Worker 
1148*cfb92d14SAndroid Build Coastguard Worker     default:
1149*cfb92d14SAndroid Build Coastguard Worker         OT_ASSERT(false);
1150*cfb92d14SAndroid Build Coastguard Worker     }
1151*cfb92d14SAndroid Build Coastguard Worker 
1152*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(handler != nullptr, error = PrepareLastStatusResponse(aHeader, SPINEL_STATUS_PROP_NOT_FOUND));
1153*cfb92d14SAndroid Build Coastguard Worker 
1154*cfb92d14SAndroid Build Coastguard Worker     // Save current read position in the decoder. Read the entire
1155*cfb92d14SAndroid Build Coastguard Worker     // content as a data blob (which is used in forming the response
1156*cfb92d14SAndroid Build Coastguard Worker     // in case of success), then reset the read position back so
1157*cfb92d14SAndroid Build Coastguard Worker     // that the `PropertyHandler` method can parse the content.
1158*cfb92d14SAndroid Build Coastguard Worker 
1159*cfb92d14SAndroid Build Coastguard Worker     mDecoder.SavePosition();
1160*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(mDecoder.ReadData(valuePtr, valueLen));
1161*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(mDecoder.ResetToSaved());
1162*cfb92d14SAndroid Build Coastguard Worker 
1163*cfb92d14SAndroid Build Coastguard Worker     mDisableStreamWrite = false;
1164*cfb92d14SAndroid Build Coastguard Worker 
1165*cfb92d14SAndroid Build Coastguard Worker     error = (this->*handler)();
1166*cfb92d14SAndroid Build Coastguard Worker 
1167*cfb92d14SAndroid Build Coastguard Worker     mDisableStreamWrite = true;
1168*cfb92d14SAndroid Build Coastguard Worker 
1169*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(error == OT_ERROR_NONE, error = PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error)));
1170*cfb92d14SAndroid Build Coastguard Worker 
1171*cfb92d14SAndroid Build Coastguard Worker     error = WritePropertyValueInsertedRemovedFrame(aHeader, responseCommand, aKey, valuePtr, valueLen);
1172*cfb92d14SAndroid Build Coastguard Worker 
1173*cfb92d14SAndroid Build Coastguard Worker     // If the full response cannot be written now, instead prepare
1174*cfb92d14SAndroid Build Coastguard Worker     // a `LAST_STATUS(STATUS_OK)` update as response.
1175*cfb92d14SAndroid Build Coastguard Worker 
1176*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
1177*cfb92d14SAndroid Build Coastguard Worker     {
1178*cfb92d14SAndroid Build Coastguard Worker         error = PrepareLastStatusResponse(aHeader, SPINEL_STATUS_OK);
1179*cfb92d14SAndroid Build Coastguard Worker     }
1180*cfb92d14SAndroid Build Coastguard Worker 
1181*cfb92d14SAndroid Build Coastguard Worker exit:
1182*cfb92d14SAndroid Build Coastguard Worker     return error;
1183*cfb92d14SAndroid Build Coastguard Worker }
1184*cfb92d14SAndroid Build Coastguard Worker 
1185*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1186*cfb92d14SAndroid Build Coastguard Worker // MARK: Outbound Frame Methods
1187*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1188*cfb92d14SAndroid Build Coastguard Worker 
WriteLastStatusFrame(uint8_t aHeader,spinel_status_t aLastStatus)1189*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::WriteLastStatusFrame(uint8_t aHeader, spinel_status_t aLastStatus)
1190*cfb92d14SAndroid Build Coastguard Worker {
1191*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1192*cfb92d14SAndroid Build Coastguard Worker 
1193*cfb92d14SAndroid Build Coastguard Worker     if (SPINEL_HEADER_GET_IID(aHeader) == SPINEL_HEADER_GET_IID(SPINEL_HEADER_TX_NOTIFICATION_IID))
1194*cfb92d14SAndroid Build Coastguard Worker     {
1195*cfb92d14SAndroid Build Coastguard Worker         mLastStatus = aLastStatus;
1196*cfb92d14SAndroid Build Coastguard Worker     }
1197*cfb92d14SAndroid Build Coastguard Worker 
1198*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_LAST_STATUS));
1199*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(aLastStatus));
1200*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.EndFrame());
1201*cfb92d14SAndroid Build Coastguard Worker 
1202*cfb92d14SAndroid Build Coastguard Worker exit:
1203*cfb92d14SAndroid Build Coastguard Worker     return error;
1204*cfb92d14SAndroid Build Coastguard Worker }
1205*cfb92d14SAndroid Build Coastguard Worker 
WritePropertyValueIsFrame(uint8_t aHeader,spinel_prop_key_t aPropKey,bool aIsGetResponse)1206*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::WritePropertyValueIsFrame(uint8_t aHeader, spinel_prop_key_t aPropKey, bool aIsGetResponse)
1207*cfb92d14SAndroid Build Coastguard Worker {
1208*cfb92d14SAndroid Build Coastguard Worker     otError         error   = OT_ERROR_NONE;
1209*cfb92d14SAndroid Build Coastguard Worker     PropertyHandler handler = FindGetPropertyHandler(aPropKey);
1210*cfb92d14SAndroid Build Coastguard Worker 
1211*cfb92d14SAndroid Build Coastguard Worker     if (handler != nullptr)
1212*cfb92d14SAndroid Build Coastguard Worker     {
1213*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aPropKey));
1214*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = (this->*handler)());
1215*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = mEncoder.EndFrame());
1216*cfb92d14SAndroid Build Coastguard Worker     }
1217*cfb92d14SAndroid Build Coastguard Worker 
1218*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
1219*cfb92d14SAndroid Build Coastguard Worker     if (aPropKey >= SPINEL_PROP_VENDOR__BEGIN && aPropKey < SPINEL_PROP_VENDOR__END)
1220*cfb92d14SAndroid Build Coastguard Worker     {
1221*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aPropKey));
1222*cfb92d14SAndroid Build Coastguard Worker 
1223*cfb92d14SAndroid Build Coastguard Worker         error = VendorGetPropertyHandler(aPropKey);
1224*cfb92d14SAndroid Build Coastguard Worker 
1225*cfb92d14SAndroid Build Coastguard Worker         // An `OT_ERROR_NOT_FOUND` status from vendor handler indicates that
1226*cfb92d14SAndroid Build Coastguard Worker         // it did not support the given property key. In that case, we fall
1227*cfb92d14SAndroid Build Coastguard Worker         // through to prepare a `LAST_STATUS` response.
1228*cfb92d14SAndroid Build Coastguard Worker 
1229*cfb92d14SAndroid Build Coastguard Worker         if (error != OT_ERROR_NOT_FOUND)
1230*cfb92d14SAndroid Build Coastguard Worker         {
1231*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error);
1232*cfb92d14SAndroid Build Coastguard Worker             ExitNow(error = mEncoder.EndFrame());
1233*cfb92d14SAndroid Build Coastguard Worker         }
1234*cfb92d14SAndroid Build Coastguard Worker     }
1235*cfb92d14SAndroid Build Coastguard Worker #endif
1236*cfb92d14SAndroid Build Coastguard Worker 
1237*cfb92d14SAndroid Build Coastguard Worker     if (aIsGetResponse)
1238*cfb92d14SAndroid Build Coastguard Worker     {
1239*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = WriteLastStatusFrame(aHeader, SPINEL_STATUS_PROP_NOT_FOUND));
1240*cfb92d14SAndroid Build Coastguard Worker     }
1241*cfb92d14SAndroid Build Coastguard Worker     else
1242*cfb92d14SAndroid Build Coastguard Worker     {
1243*cfb92d14SAndroid Build Coastguard Worker         // Send a STATUS_OK for "set" response to a property that
1244*cfb92d14SAndroid Build Coastguard Worker         // has no corresponding get handler.
1245*cfb92d14SAndroid Build Coastguard Worker 
1246*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = WriteLastStatusFrame(aHeader, SPINEL_STATUS_OK));
1247*cfb92d14SAndroid Build Coastguard Worker     }
1248*cfb92d14SAndroid Build Coastguard Worker 
1249*cfb92d14SAndroid Build Coastguard Worker exit:
1250*cfb92d14SAndroid Build Coastguard Worker     return error;
1251*cfb92d14SAndroid Build Coastguard Worker }
1252*cfb92d14SAndroid Build Coastguard Worker 
WritePropertyValueInsertedRemovedFrame(uint8_t aHeader,unsigned int aResponseCommand,spinel_prop_key_t aPropKey,const uint8_t * aValuePtr,uint16_t aValueLen)1253*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::WritePropertyValueInsertedRemovedFrame(uint8_t           aHeader,
1254*cfb92d14SAndroid Build Coastguard Worker                                                         unsigned int      aResponseCommand,
1255*cfb92d14SAndroid Build Coastguard Worker                                                         spinel_prop_key_t aPropKey,
1256*cfb92d14SAndroid Build Coastguard Worker                                                         const uint8_t    *aValuePtr,
1257*cfb92d14SAndroid Build Coastguard Worker                                                         uint16_t          aValueLen)
1258*cfb92d14SAndroid Build Coastguard Worker {
1259*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1260*cfb92d14SAndroid Build Coastguard Worker 
1261*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.BeginFrame(aHeader, aResponseCommand, aPropKey));
1262*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteData(aValuePtr, aValueLen));
1263*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.EndFrame());
1264*cfb92d14SAndroid Build Coastguard Worker 
1265*cfb92d14SAndroid Build Coastguard Worker exit:
1266*cfb92d14SAndroid Build Coastguard Worker     return error;
1267*cfb92d14SAndroid Build Coastguard Worker }
1268*cfb92d14SAndroid Build Coastguard Worker 
1269*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1270*cfb92d14SAndroid Build Coastguard Worker // MARK: Individual Command Handlers
1271*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1272*cfb92d14SAndroid Build Coastguard Worker 
CommandHandler_NOOP(uint8_t aHeader)1273*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::CommandHandler_NOOP(uint8_t aHeader) { return PrepareLastStatusResponse(aHeader, SPINEL_STATUS_OK); }
1274*cfb92d14SAndroid Build Coastguard Worker 
CommandHandler_RESET(uint8_t aHeader)1275*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::CommandHandler_RESET(uint8_t aHeader)
1276*cfb92d14SAndroid Build Coastguard Worker {
1277*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aHeader);
1278*cfb92d14SAndroid Build Coastguard Worker 
1279*cfb92d14SAndroid Build Coastguard Worker     otError error      = OT_ERROR_NONE;
1280*cfb92d14SAndroid Build Coastguard Worker     uint8_t reset_type = SPINEL_RESET_STACK;
1281*cfb92d14SAndroid Build Coastguard Worker 
1282*cfb92d14SAndroid Build Coastguard Worker     if (mDecoder.GetRemainingLengthInStruct() > 0)
1283*cfb92d14SAndroid Build Coastguard Worker     {
1284*cfb92d14SAndroid Build Coastguard Worker         SuccessOrAssert(error = mDecoder.ReadUint8(reset_type));
1285*cfb92d14SAndroid Build Coastguard Worker     }
1286*cfb92d14SAndroid Build Coastguard Worker 
1287*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO
1288*cfb92d14SAndroid Build Coastguard Worker     if (reset_type == SPINEL_RESET_STACK)
1289*cfb92d14SAndroid Build Coastguard Worker     {
1290*cfb92d14SAndroid Build Coastguard Worker         otInstanceResetRadioStack(mInstance);
1291*cfb92d14SAndroid Build Coastguard Worker 
1292*cfb92d14SAndroid Build Coastguard Worker         mIsRawStreamEnabled[mCurCommandIid] = false;
1293*cfb92d14SAndroid Build Coastguard Worker         mCurTransmitTID[mCurCommandIid]     = 0;
1294*cfb92d14SAndroid Build Coastguard Worker         mCurScanChannel[mCurCommandIid]     = kInvalidScanChannel;
1295*cfb92d14SAndroid Build Coastguard Worker         mSrcMatchEnabled[mCurCommandIid]    = false;
1296*cfb92d14SAndroid Build Coastguard Worker 
1297*cfb92d14SAndroid Build Coastguard Worker         ResetCounters();
1298*cfb92d14SAndroid Build Coastguard Worker 
1299*cfb92d14SAndroid Build Coastguard Worker         mEncoder.ClearNcpBuffer();
1300*cfb92d14SAndroid Build Coastguard Worker 
1301*cfb92d14SAndroid Build Coastguard Worker         SuccessOrAssert(error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID,
1302*cfb92d14SAndroid Build Coastguard Worker                                                      SPINEL_STATUS_RESET_POWER_ON));
1303*cfb92d14SAndroid Build Coastguard Worker     }
1304*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
1305*cfb92d14SAndroid Build Coastguard Worker     else if (reset_type == SPINEL_RESET_BOOTLOADER)
1306*cfb92d14SAndroid Build Coastguard Worker     {
1307*cfb92d14SAndroid Build Coastguard Worker         // Signal a platform reset to bootloader mode.
1308*cfb92d14SAndroid Build Coastguard Worker         // If implemented, this function shouldn't return.
1309*cfb92d14SAndroid Build Coastguard Worker         error = otInstanceResetToBootloader(mInstance);
1310*cfb92d14SAndroid Build Coastguard Worker     }
1311*cfb92d14SAndroid Build Coastguard Worker #endif
1312*cfb92d14SAndroid Build Coastguard Worker     else
1313*cfb92d14SAndroid Build Coastguard Worker #endif
1314*cfb92d14SAndroid Build Coastguard Worker     {
1315*cfb92d14SAndroid Build Coastguard Worker         // Signal a platform reset. If implemented, this function
1316*cfb92d14SAndroid Build Coastguard Worker         // shouldn't return.
1317*cfb92d14SAndroid Build Coastguard Worker         otInstanceReset(mInstance);
1318*cfb92d14SAndroid Build Coastguard Worker 
1319*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1320*cfb92d14SAndroid Build Coastguard Worker         // We only get to this point if the
1321*cfb92d14SAndroid Build Coastguard Worker         // platform doesn't support resetting.
1322*cfb92d14SAndroid Build Coastguard Worker         // In such a case we fake it.
1323*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(otThreadSetEnabled(mInstance, false));
1324*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(otIp6SetEnabled(mInstance, false));
1325*cfb92d14SAndroid Build Coastguard Worker #endif
1326*cfb92d14SAndroid Build Coastguard Worker 
1327*cfb92d14SAndroid Build Coastguard Worker         sNcpInstance = nullptr;
1328*cfb92d14SAndroid Build Coastguard Worker     }
1329*cfb92d14SAndroid Build Coastguard Worker 
1330*cfb92d14SAndroid Build Coastguard Worker     return error;
1331*cfb92d14SAndroid Build Coastguard Worker }
1332*cfb92d14SAndroid Build Coastguard Worker 
CommandHandler_PROP_VALUE_update(uint8_t aHeader,unsigned int aCommand)1333*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::CommandHandler_PROP_VALUE_update(uint8_t aHeader, unsigned int aCommand)
1334*cfb92d14SAndroid Build Coastguard Worker {
1335*cfb92d14SAndroid Build Coastguard Worker     otError      error   = OT_ERROR_NONE;
1336*cfb92d14SAndroid Build Coastguard Worker     unsigned int propKey = 0;
1337*cfb92d14SAndroid Build Coastguard Worker 
1338*cfb92d14SAndroid Build Coastguard Worker     error = mDecoder.ReadUintPacked(propKey);
1339*cfb92d14SAndroid Build Coastguard Worker 
1340*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(error == OT_ERROR_NONE, error = PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error)));
1341*cfb92d14SAndroid Build Coastguard Worker 
1342*cfb92d14SAndroid Build Coastguard Worker     switch (aCommand)
1343*cfb92d14SAndroid Build Coastguard Worker     {
1344*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_GET:
1345*cfb92d14SAndroid Build Coastguard Worker         error = PrepareGetResponse(aHeader, static_cast<spinel_prop_key_t>(propKey));
1346*cfb92d14SAndroid Build Coastguard Worker         break;
1347*cfb92d14SAndroid Build Coastguard Worker 
1348*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_SET:
1349*cfb92d14SAndroid Build Coastguard Worker         error = HandleCommandPropertySet(aHeader, static_cast<spinel_prop_key_t>(propKey));
1350*cfb92d14SAndroid Build Coastguard Worker         break;
1351*cfb92d14SAndroid Build Coastguard Worker 
1352*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_INSERT:
1353*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_CMD_PROP_VALUE_REMOVE:
1354*cfb92d14SAndroid Build Coastguard Worker         error = HandleCommandPropertyInsertRemove(aHeader, static_cast<spinel_prop_key_t>(propKey), aCommand);
1355*cfb92d14SAndroid Build Coastguard Worker         break;
1356*cfb92d14SAndroid Build Coastguard Worker 
1357*cfb92d14SAndroid Build Coastguard Worker     default:
1358*cfb92d14SAndroid Build Coastguard Worker         break;
1359*cfb92d14SAndroid Build Coastguard Worker     }
1360*cfb92d14SAndroid Build Coastguard Worker 
1361*cfb92d14SAndroid Build Coastguard Worker exit:
1362*cfb92d14SAndroid Build Coastguard Worker     return error;
1363*cfb92d14SAndroid Build Coastguard Worker }
1364*cfb92d14SAndroid Build Coastguard Worker 
1365*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
1366*cfb92d14SAndroid Build Coastguard Worker 
CommandHandler_PEEK(uint8_t aHeader)1367*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::CommandHandler_PEEK(uint8_t aHeader)
1368*cfb92d14SAndroid Build Coastguard Worker {
1369*cfb92d14SAndroid Build Coastguard Worker     otError  parseError    = OT_ERROR_NONE;
1370*cfb92d14SAndroid Build Coastguard Worker     otError  responseError = OT_ERROR_NONE;
1371*cfb92d14SAndroid Build Coastguard Worker     uint32_t address;
1372*cfb92d14SAndroid Build Coastguard Worker     uint16_t count;
1373*cfb92d14SAndroid Build Coastguard Worker 
1374*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(parseError = mDecoder.ReadUint32(address));
1375*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(parseError = mDecoder.ReadUint16(count));
1376*cfb92d14SAndroid Build Coastguard Worker 
1377*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(count != 0, parseError = OT_ERROR_INVALID_ARGS);
1378*cfb92d14SAndroid Build Coastguard Worker 
1379*cfb92d14SAndroid Build Coastguard Worker     if (mAllowPeekDelegate != nullptr)
1380*cfb92d14SAndroid Build Coastguard Worker     {
1381*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(mAllowPeekDelegate(address, count), parseError = OT_ERROR_INVALID_ARGS);
1382*cfb92d14SAndroid Build Coastguard Worker     }
1383*cfb92d14SAndroid Build Coastguard Worker 
1384*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(responseError = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PEEK_RET));
1385*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(responseError = mEncoder.WriteUint32(address));
1386*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(responseError = mEncoder.WriteUint16(count));
1387*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(responseError = mEncoder.WriteData(reinterpret_cast<const uint8_t *>(address), count));
1388*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(responseError = mEncoder.EndFrame());
1389*cfb92d14SAndroid Build Coastguard Worker 
1390*cfb92d14SAndroid Build Coastguard Worker exit:
1391*cfb92d14SAndroid Build Coastguard Worker     if (parseError != OT_ERROR_NONE)
1392*cfb92d14SAndroid Build Coastguard Worker     {
1393*cfb92d14SAndroid Build Coastguard Worker         responseError = PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(parseError));
1394*cfb92d14SAndroid Build Coastguard Worker     }
1395*cfb92d14SAndroid Build Coastguard Worker 
1396*cfb92d14SAndroid Build Coastguard Worker     return responseError;
1397*cfb92d14SAndroid Build Coastguard Worker }
1398*cfb92d14SAndroid Build Coastguard Worker 
CommandHandler_POKE(uint8_t aHeader)1399*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::CommandHandler_POKE(uint8_t aHeader)
1400*cfb92d14SAndroid Build Coastguard Worker {
1401*cfb92d14SAndroid Build Coastguard Worker     otError        parseError = OT_ERROR_NONE;
1402*cfb92d14SAndroid Build Coastguard Worker     uint32_t       address;
1403*cfb92d14SAndroid Build Coastguard Worker     uint16_t       count;
1404*cfb92d14SAndroid Build Coastguard Worker     const uint8_t *dataPtr = nullptr;
1405*cfb92d14SAndroid Build Coastguard Worker     uint16_t       dataLen;
1406*cfb92d14SAndroid Build Coastguard Worker 
1407*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(parseError = mDecoder.ReadUint32(address));
1408*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(parseError = mDecoder.ReadUint16(count));
1409*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(parseError = mDecoder.ReadData(dataPtr, dataLen));
1410*cfb92d14SAndroid Build Coastguard Worker 
1411*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(count != 0, parseError = OT_ERROR_INVALID_ARGS);
1412*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(count <= dataLen, parseError = OT_ERROR_INVALID_ARGS);
1413*cfb92d14SAndroid Build Coastguard Worker 
1414*cfb92d14SAndroid Build Coastguard Worker     if (mAllowPokeDelegate != nullptr)
1415*cfb92d14SAndroid Build Coastguard Worker     {
1416*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(mAllowPokeDelegate(address, count), parseError = OT_ERROR_INVALID_ARGS);
1417*cfb92d14SAndroid Build Coastguard Worker     }
1418*cfb92d14SAndroid Build Coastguard Worker 
1419*cfb92d14SAndroid Build Coastguard Worker     memcpy(reinterpret_cast<uint8_t *>(address), dataPtr, count);
1420*cfb92d14SAndroid Build Coastguard Worker 
1421*cfb92d14SAndroid Build Coastguard Worker exit:
1422*cfb92d14SAndroid Build Coastguard Worker     return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(parseError));
1423*cfb92d14SAndroid Build Coastguard Worker }
1424*cfb92d14SAndroid Build Coastguard Worker 
1425*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
1426*cfb92d14SAndroid Build Coastguard Worker 
1427*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1428*cfb92d14SAndroid Build Coastguard Worker // MARK: Individual Property Getters and Setters
1429*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1430*cfb92d14SAndroid Build Coastguard Worker 
1431*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DIAG_ENABLE
HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)1432*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)
1433*cfb92d14SAndroid Build Coastguard Worker {
1434*cfb92d14SAndroid Build Coastguard Worker     const char *string                                            = nullptr;
1435*cfb92d14SAndroid Build Coastguard Worker     char        output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE] = {0};
1436*cfb92d14SAndroid Build Coastguard Worker     otError     error                                             = OT_ERROR_NONE;
1437*cfb92d14SAndroid Build Coastguard Worker 
1438*cfb92d14SAndroid Build Coastguard Worker     error = mDecoder.ReadUtf8(string);
1439*cfb92d14SAndroid Build Coastguard Worker 
1440*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(error == OT_ERROR_NONE, error = WriteLastStatusFrame(aHeader, ThreadErrorToSpinelStatus(error)));
1441*cfb92d14SAndroid Build Coastguard Worker 
1442*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1443*cfb92d14SAndroid Build Coastguard Worker     // TODO do not pass mfg prefix
1444*cfb92d14SAndroid Build Coastguard Worker     // skip mfg prefix from wpantund
1445*cfb92d14SAndroid Build Coastguard Worker     if (memcmp(string, "mfg ", 4) == 0)
1446*cfb92d14SAndroid Build Coastguard Worker     {
1447*cfb92d14SAndroid Build Coastguard Worker         string += 4;
1448*cfb92d14SAndroid Build Coastguard Worker     }
1449*cfb92d14SAndroid Build Coastguard Worker #endif
1450*cfb92d14SAndroid Build Coastguard Worker 
1451*cfb92d14SAndroid Build Coastguard Worker     mDiagOutput    = output;
1452*cfb92d14SAndroid Build Coastguard Worker     mDiagOutputLen = sizeof(output);
1453*cfb92d14SAndroid Build Coastguard Worker 
1454*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otDiagProcessCmdLine(mInstance, string));
1455*cfb92d14SAndroid Build Coastguard Worker 
1456*cfb92d14SAndroid Build Coastguard Worker     // Prepare the response
1457*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
1458*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUtf8(output));
1459*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.EndFrame());
1460*cfb92d14SAndroid Build Coastguard Worker 
1461*cfb92d14SAndroid Build Coastguard Worker exit:
1462*cfb92d14SAndroid Build Coastguard Worker     mDiagOutput    = nullptr;
1463*cfb92d14SAndroid Build Coastguard Worker     mDiagOutputLen = 0;
1464*cfb92d14SAndroid Build Coastguard Worker 
1465*cfb92d14SAndroid Build Coastguard Worker     return error;
1466*cfb92d14SAndroid Build Coastguard Worker }
1467*cfb92d14SAndroid Build Coastguard Worker 
HandleDiagOutput_Jump(const char * aFormat,va_list aArguments,void * aContext)1468*cfb92d14SAndroid Build Coastguard Worker void NcpBase::HandleDiagOutput_Jump(const char *aFormat, va_list aArguments, void *aContext)
1469*cfb92d14SAndroid Build Coastguard Worker {
1470*cfb92d14SAndroid Build Coastguard Worker     static_cast<NcpBase *>(aContext)->HandleDiagOutput(aFormat, aArguments);
1471*cfb92d14SAndroid Build Coastguard Worker }
1472*cfb92d14SAndroid Build Coastguard Worker 
HandleDiagOutput(const char * aFormat,va_list aArguments)1473*cfb92d14SAndroid Build Coastguard Worker void NcpBase::HandleDiagOutput(const char *aFormat, va_list aArguments)
1474*cfb92d14SAndroid Build Coastguard Worker {
1475*cfb92d14SAndroid Build Coastguard Worker     int charsWritten;
1476*cfb92d14SAndroid Build Coastguard Worker 
1477*cfb92d14SAndroid Build Coastguard Worker     if (mDiagOutput != nullptr)
1478*cfb92d14SAndroid Build Coastguard Worker     {
1479*cfb92d14SAndroid Build Coastguard Worker         charsWritten = vsnprintf(mDiagOutput, mDiagOutputLen, aFormat, aArguments);
1480*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(charsWritten > 0);
1481*cfb92d14SAndroid Build Coastguard Worker         charsWritten = (mDiagOutputLen <= charsWritten) ? mDiagOutputLen : charsWritten;
1482*cfb92d14SAndroid Build Coastguard Worker         mDiagOutput += charsWritten;
1483*cfb92d14SAndroid Build Coastguard Worker         mDiagOutputLen -= charsWritten;
1484*cfb92d14SAndroid Build Coastguard Worker     }
1485*cfb92d14SAndroid Build Coastguard Worker     else
1486*cfb92d14SAndroid Build Coastguard Worker     {
1487*cfb92d14SAndroid Build Coastguard Worker         uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
1488*cfb92d14SAndroid Build Coastguard Worker         char    output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
1489*cfb92d14SAndroid Build Coastguard Worker 
1490*cfb92d14SAndroid Build Coastguard Worker         charsWritten = vsnprintf(output, sizeof(output), aFormat, aArguments);
1491*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(charsWritten >= 0);
1492*cfb92d14SAndroid Build Coastguard Worker 
1493*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
1494*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(mEncoder.WriteUtf8(output));
1495*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(mEncoder.EndFrame());
1496*cfb92d14SAndroid Build Coastguard Worker     }
1497*cfb92d14SAndroid Build Coastguard Worker 
1498*cfb92d14SAndroid Build Coastguard Worker exit:
1499*cfb92d14SAndroid Build Coastguard Worker     return;
1500*cfb92d14SAndroid Build Coastguard Worker }
1501*cfb92d14SAndroid Build Coastguard Worker 
1502*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_DIAG_ENABLE
1503*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1504*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_ENABLED>(void)
1505*cfb92d14SAndroid Build Coastguard Worker {
1506*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1507*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteBool(otLinkRawIsEnabled(mInstance));
1508*cfb92d14SAndroid Build Coastguard Worker #else
1509*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteBool(false);
1510*cfb92d14SAndroid Build Coastguard Worker #endif
1511*cfb92d14SAndroid Build Coastguard Worker }
1512*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1513*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN>(void)
1514*cfb92d14SAndroid Build Coastguard Worker {
1515*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(otLinkGetChannel(mInstance));
1516*cfb92d14SAndroid Build Coastguard Worker }
1517*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1518*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN>(void)
1519*cfb92d14SAndroid Build Coastguard Worker {
1520*cfb92d14SAndroid Build Coastguard Worker     unsigned int channel = 0;
1521*cfb92d14SAndroid Build Coastguard Worker     otError      error   = OT_ERROR_NONE;
1522*cfb92d14SAndroid Build Coastguard Worker 
1523*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUintPacked(channel));
1524*cfb92d14SAndroid Build Coastguard Worker 
1525*cfb92d14SAndroid Build Coastguard Worker     error = otLinkSetChannel(mInstance, static_cast<uint8_t>(channel));
1526*cfb92d14SAndroid Build Coastguard Worker 
1527*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1528*cfb92d14SAndroid Build Coastguard Worker 
1529*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error);
1530*cfb92d14SAndroid Build Coastguard Worker 
1531*cfb92d14SAndroid Build Coastguard Worker     // Make sure we are update the receiving channel if raw link is enabled and we have raw
1532*cfb92d14SAndroid Build Coastguard Worker     // stream enabled already
1533*cfb92d14SAndroid Build Coastguard Worker     if (otLinkRawIsEnabled(mInstance) && mIsRawStreamEnabled[mCurCommandIid])
1534*cfb92d14SAndroid Build Coastguard Worker     {
1535*cfb92d14SAndroid Build Coastguard Worker         error = otLinkRawReceive(mInstance);
1536*cfb92d14SAndroid Build Coastguard Worker     }
1537*cfb92d14SAndroid Build Coastguard Worker 
1538*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1539*cfb92d14SAndroid Build Coastguard Worker 
1540*cfb92d14SAndroid Build Coastguard Worker exit:
1541*cfb92d14SAndroid Build Coastguard Worker     return error;
1542*cfb92d14SAndroid Build Coastguard Worker }
1543*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1544*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_PROMISCUOUS_MODE>(void)
1545*cfb92d14SAndroid Build Coastguard Worker {
1546*cfb92d14SAndroid Build Coastguard Worker     bool isPromiscuous;
1547*cfb92d14SAndroid Build Coastguard Worker 
1548*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1549*cfb92d14SAndroid Build Coastguard Worker     isPromiscuous = otLinkRawGetPromiscuous(mInstance);
1550*cfb92d14SAndroid Build Coastguard Worker #else
1551*cfb92d14SAndroid Build Coastguard Worker     isPromiscuous = otLinkIsPromiscuous(mInstance);
1552*cfb92d14SAndroid Build Coastguard Worker #endif
1553*cfb92d14SAndroid Build Coastguard Worker 
1554*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(isPromiscuous ? SPINEL_MAC_PROMISCUOUS_MODE_FULL : SPINEL_MAC_PROMISCUOUS_MODE_OFF);
1555*cfb92d14SAndroid Build Coastguard Worker }
1556*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1557*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_PROMISCUOUS_MODE>(void)
1558*cfb92d14SAndroid Build Coastguard Worker {
1559*cfb92d14SAndroid Build Coastguard Worker     uint8_t mode  = 0;
1560*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1561*cfb92d14SAndroid Build Coastguard Worker 
1562*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(mode));
1563*cfb92d14SAndroid Build Coastguard Worker 
1564*cfb92d14SAndroid Build Coastguard Worker     switch (mode)
1565*cfb92d14SAndroid Build Coastguard Worker     {
1566*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MAC_PROMISCUOUS_MODE_OFF:
1567*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1568*cfb92d14SAndroid Build Coastguard Worker         error = otLinkRawSetPromiscuous(mInstance, false);
1569*cfb92d14SAndroid Build Coastguard Worker #else
1570*cfb92d14SAndroid Build Coastguard Worker         error = otLinkSetPromiscuous(mInstance, false);
1571*cfb92d14SAndroid Build Coastguard Worker #endif
1572*cfb92d14SAndroid Build Coastguard Worker         break;
1573*cfb92d14SAndroid Build Coastguard Worker 
1574*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MAC_PROMISCUOUS_MODE_NETWORK:
1575*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MAC_PROMISCUOUS_MODE_FULL:
1576*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1577*cfb92d14SAndroid Build Coastguard Worker         error = otLinkRawSetPromiscuous(mInstance, true);
1578*cfb92d14SAndroid Build Coastguard Worker #else
1579*cfb92d14SAndroid Build Coastguard Worker         error = otLinkSetPromiscuous(mInstance, true);
1580*cfb92d14SAndroid Build Coastguard Worker #endif
1581*cfb92d14SAndroid Build Coastguard Worker         break;
1582*cfb92d14SAndroid Build Coastguard Worker 
1583*cfb92d14SAndroid Build Coastguard Worker     default:
1584*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_INVALID_ARGS;
1585*cfb92d14SAndroid Build Coastguard Worker         break;
1586*cfb92d14SAndroid Build Coastguard Worker     }
1587*cfb92d14SAndroid Build Coastguard Worker 
1588*cfb92d14SAndroid Build Coastguard Worker exit:
1589*cfb92d14SAndroid Build Coastguard Worker     return error;
1590*cfb92d14SAndroid Build Coastguard Worker }
1591*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1592*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE>(void)
1593*cfb92d14SAndroid Build Coastguard Worker {
1594*cfb92d14SAndroid Build Coastguard Worker     bool    enabled;
1595*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1596*cfb92d14SAndroid Build Coastguard Worker 
1597*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadBool(enabled));
1598*cfb92d14SAndroid Build Coastguard Worker     otPlatRadioSetRxOnWhenIdle(mInstance, enabled);
1599*cfb92d14SAndroid Build Coastguard Worker 
1600*cfb92d14SAndroid Build Coastguard Worker exit:
1601*cfb92d14SAndroid Build Coastguard Worker     return error;
1602*cfb92d14SAndroid Build Coastguard Worker }
1603*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1604*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_15_4_PANID>(void)
1605*cfb92d14SAndroid Build Coastguard Worker {
1606*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint16(otLinkGetPanId(mInstance));
1607*cfb92d14SAndroid Build Coastguard Worker }
1608*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1609*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_15_4_PANID>(void)
1610*cfb92d14SAndroid Build Coastguard Worker {
1611*cfb92d14SAndroid Build Coastguard Worker     uint16_t panid;
1612*cfb92d14SAndroid Build Coastguard Worker     otError  error = OT_ERROR_NONE;
1613*cfb92d14SAndroid Build Coastguard Worker 
1614*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint16(panid));
1615*cfb92d14SAndroid Build Coastguard Worker 
1616*cfb92d14SAndroid Build Coastguard Worker     error = otLinkSetPanId(mInstance, panid);
1617*cfb92d14SAndroid Build Coastguard Worker 
1618*cfb92d14SAndroid Build Coastguard Worker exit:
1619*cfb92d14SAndroid Build Coastguard Worker     return error;
1620*cfb92d14SAndroid Build Coastguard Worker }
1621*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1622*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_15_4_LADDR>(void)
1623*cfb92d14SAndroid Build Coastguard Worker {
1624*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
1625*cfb92d14SAndroid Build Coastguard Worker }
1626*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1627*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_15_4_LADDR>(void)
1628*cfb92d14SAndroid Build Coastguard Worker {
1629*cfb92d14SAndroid Build Coastguard Worker     const otExtAddress *extAddress;
1630*cfb92d14SAndroid Build Coastguard Worker     otError             error = OT_ERROR_NONE;
1631*cfb92d14SAndroid Build Coastguard Worker 
1632*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
1633*cfb92d14SAndroid Build Coastguard Worker 
1634*cfb92d14SAndroid Build Coastguard Worker     error = otLinkSetExtendedAddress(mInstance, extAddress);
1635*cfb92d14SAndroid Build Coastguard Worker 
1636*cfb92d14SAndroid Build Coastguard Worker exit:
1637*cfb92d14SAndroid Build Coastguard Worker     return error;
1638*cfb92d14SAndroid Build Coastguard Worker }
1639*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1640*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_15_4_SADDR>(void)
1641*cfb92d14SAndroid Build Coastguard Worker {
1642*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint16(otLinkGetShortAddress(mInstance));
1643*cfb92d14SAndroid Build Coastguard Worker }
1644*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1645*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_RAW_STREAM_ENABLED>(void)
1646*cfb92d14SAndroid Build Coastguard Worker {
1647*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteBool(mIsRawStreamEnabled[mCurCommandIid]);
1648*cfb92d14SAndroid Build Coastguard Worker }
1649*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1650*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RAW_STREAM_ENABLED>(void)
1651*cfb92d14SAndroid Build Coastguard Worker {
1652*cfb92d14SAndroid Build Coastguard Worker     bool    enabled = false;
1653*cfb92d14SAndroid Build Coastguard Worker     otError error   = OT_ERROR_NONE;
1654*cfb92d14SAndroid Build Coastguard Worker 
1655*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadBool(enabled));
1656*cfb92d14SAndroid Build Coastguard Worker 
1657*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1658*cfb92d14SAndroid Build Coastguard Worker 
1659*cfb92d14SAndroid Build Coastguard Worker     if (otLinkRawIsEnabled(mInstance))
1660*cfb92d14SAndroid Build Coastguard Worker     {
1661*cfb92d14SAndroid Build Coastguard Worker         if (enabled)
1662*cfb92d14SAndroid Build Coastguard Worker         {
1663*cfb92d14SAndroid Build Coastguard Worker             error = otLinkRawReceive(mInstance);
1664*cfb92d14SAndroid Build Coastguard Worker         }
1665*cfb92d14SAndroid Build Coastguard Worker         else
1666*cfb92d14SAndroid Build Coastguard Worker         {
1667*cfb92d14SAndroid Build Coastguard Worker             error = otLinkRawSleep(mInstance);
1668*cfb92d14SAndroid Build Coastguard Worker         }
1669*cfb92d14SAndroid Build Coastguard Worker     }
1670*cfb92d14SAndroid Build Coastguard Worker 
1671*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1672*cfb92d14SAndroid Build Coastguard Worker 
1673*cfb92d14SAndroid Build Coastguard Worker     mIsRawStreamEnabled[mCurCommandIid] = enabled;
1674*cfb92d14SAndroid Build Coastguard Worker 
1675*cfb92d14SAndroid Build Coastguard Worker exit:
1676*cfb92d14SAndroid Build Coastguard Worker     return error;
1677*cfb92d14SAndroid Build Coastguard Worker }
1678*cfb92d14SAndroid Build Coastguard Worker 
1679*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
HandlePropertyGet(void)1680*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_CSL_ACCURACY>(void)
1681*cfb92d14SAndroid Build Coastguard Worker {
1682*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(otPlatRadioGetCslAccuracy(mInstance));
1683*cfb92d14SAndroid Build Coastguard Worker }
1684*cfb92d14SAndroid Build Coastguard Worker #endif
1685*cfb92d14SAndroid Build Coastguard Worker 
1686*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
HandlePropertyGet(void)1687*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_CSL_UNCERTAINTY>(void)
1688*cfb92d14SAndroid Build Coastguard Worker {
1689*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(otPlatRadioGetCslUncertainty(mInstance));
1690*cfb92d14SAndroid Build Coastguard Worker }
1691*cfb92d14SAndroid Build Coastguard Worker #endif
1692*cfb92d14SAndroid Build Coastguard Worker 
EncodeChannelMask(uint32_t aChannelMask)1693*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::EncodeChannelMask(uint32_t aChannelMask)
1694*cfb92d14SAndroid Build Coastguard Worker {
1695*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1696*cfb92d14SAndroid Build Coastguard Worker 
1697*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < 32; i++)
1698*cfb92d14SAndroid Build Coastguard Worker     {
1699*cfb92d14SAndroid Build Coastguard Worker         if (0 != (aChannelMask & (1 << i)))
1700*cfb92d14SAndroid Build Coastguard Worker         {
1701*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = mEncoder.WriteUint8(i));
1702*cfb92d14SAndroid Build Coastguard Worker         }
1703*cfb92d14SAndroid Build Coastguard Worker     }
1704*cfb92d14SAndroid Build Coastguard Worker 
1705*cfb92d14SAndroid Build Coastguard Worker exit:
1706*cfb92d14SAndroid Build Coastguard Worker     return error;
1707*cfb92d14SAndroid Build Coastguard Worker }
1708*cfb92d14SAndroid Build Coastguard Worker 
DecodeChannelMask(uint32_t & aChannelMask)1709*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::DecodeChannelMask(uint32_t &aChannelMask)
1710*cfb92d14SAndroid Build Coastguard Worker {
1711*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1712*cfb92d14SAndroid Build Coastguard Worker     uint8_t channel;
1713*cfb92d14SAndroid Build Coastguard Worker 
1714*cfb92d14SAndroid Build Coastguard Worker     aChannelMask = 0;
1715*cfb92d14SAndroid Build Coastguard Worker 
1716*cfb92d14SAndroid Build Coastguard Worker     while (!mDecoder.IsAllReadInStruct())
1717*cfb92d14SAndroid Build Coastguard Worker     {
1718*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = mDecoder.ReadUint8(channel));
1719*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
1720*cfb92d14SAndroid Build Coastguard Worker         aChannelMask |= (1UL << channel);
1721*cfb92d14SAndroid Build Coastguard Worker     }
1722*cfb92d14SAndroid Build Coastguard Worker 
1723*cfb92d14SAndroid Build Coastguard Worker exit:
1724*cfb92d14SAndroid Build Coastguard Worker     return error;
1725*cfb92d14SAndroid Build Coastguard Worker }
1726*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1727*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>(void)
1728*cfb92d14SAndroid Build Coastguard Worker {
1729*cfb92d14SAndroid Build Coastguard Worker     return EncodeChannelMask(mScanChannelMask);
1730*cfb92d14SAndroid Build Coastguard Worker }
1731*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1732*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>(void)
1733*cfb92d14SAndroid Build Coastguard Worker {
1734*cfb92d14SAndroid Build Coastguard Worker     uint32_t newMask = 0;
1735*cfb92d14SAndroid Build Coastguard Worker     otError  error   = OT_ERROR_NONE;
1736*cfb92d14SAndroid Build Coastguard Worker 
1737*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = DecodeChannelMask(newMask));
1738*cfb92d14SAndroid Build Coastguard Worker     mScanChannelMask = newMask;
1739*cfb92d14SAndroid Build Coastguard Worker 
1740*cfb92d14SAndroid Build Coastguard Worker exit:
1741*cfb92d14SAndroid Build Coastguard Worker     return error;
1742*cfb92d14SAndroid Build Coastguard Worker }
1743*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1744*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
1745*cfb92d14SAndroid Build Coastguard Worker {
1746*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint16(mScanPeriod);
1747*cfb92d14SAndroid Build Coastguard Worker }
1748*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1749*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
1750*cfb92d14SAndroid Build Coastguard Worker {
1751*cfb92d14SAndroid Build Coastguard Worker     return mDecoder.ReadUint16(mScanPeriod);
1752*cfb92d14SAndroid Build Coastguard Worker }
1753*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1754*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>(void)
1755*cfb92d14SAndroid Build Coastguard Worker {
1756*cfb92d14SAndroid Build Coastguard Worker     uint8_t scanState = SPINEL_SCAN_STATE_IDLE;
1757*cfb92d14SAndroid Build Coastguard Worker 
1758*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1759*cfb92d14SAndroid Build Coastguard Worker 
1760*cfb92d14SAndroid Build Coastguard Worker     if (otLinkRawIsEnabled(mInstance))
1761*cfb92d14SAndroid Build Coastguard Worker     {
1762*cfb92d14SAndroid Build Coastguard Worker         scanState = (mCurScanChannel[mCurCommandIid] == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE
1763*cfb92d14SAndroid Build Coastguard Worker                                                                              : SPINEL_SCAN_STATE_ENERGY;
1764*cfb92d14SAndroid Build Coastguard Worker     }
1765*cfb92d14SAndroid Build Coastguard Worker     else
1766*cfb92d14SAndroid Build Coastguard Worker 
1767*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1768*cfb92d14SAndroid Build Coastguard Worker 
1769*cfb92d14SAndroid Build Coastguard Worker     {
1770*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1771*cfb92d14SAndroid Build Coastguard Worker         if (otLinkIsActiveScanInProgress(mInstance))
1772*cfb92d14SAndroid Build Coastguard Worker         {
1773*cfb92d14SAndroid Build Coastguard Worker             scanState = SPINEL_SCAN_STATE_BEACON;
1774*cfb92d14SAndroid Build Coastguard Worker         }
1775*cfb92d14SAndroid Build Coastguard Worker         else if (otLinkIsEnergyScanInProgress(mInstance))
1776*cfb92d14SAndroid Build Coastguard Worker         {
1777*cfb92d14SAndroid Build Coastguard Worker             scanState = SPINEL_SCAN_STATE_ENERGY;
1778*cfb92d14SAndroid Build Coastguard Worker         }
1779*cfb92d14SAndroid Build Coastguard Worker         else if (otThreadIsDiscoverInProgress(mInstance))
1780*cfb92d14SAndroid Build Coastguard Worker         {
1781*cfb92d14SAndroid Build Coastguard Worker             scanState = SPINEL_SCAN_STATE_DISCOVER;
1782*cfb92d14SAndroid Build Coastguard Worker         }
1783*cfb92d14SAndroid Build Coastguard Worker         else
1784*cfb92d14SAndroid Build Coastguard Worker         {
1785*cfb92d14SAndroid Build Coastguard Worker             scanState = SPINEL_SCAN_STATE_IDLE;
1786*cfb92d14SAndroid Build Coastguard Worker         }
1787*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
1788*cfb92d14SAndroid Build Coastguard Worker     }
1789*cfb92d14SAndroid Build Coastguard Worker 
1790*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(scanState);
1791*cfb92d14SAndroid Build Coastguard Worker }
1792*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1793*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
1794*cfb92d14SAndroid Build Coastguard Worker {
1795*cfb92d14SAndroid Build Coastguard Worker     uint8_t state = 0;
1796*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1797*cfb92d14SAndroid Build Coastguard Worker 
1798*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(state));
1799*cfb92d14SAndroid Build Coastguard Worker 
1800*cfb92d14SAndroid Build Coastguard Worker     switch (state)
1801*cfb92d14SAndroid Build Coastguard Worker     {
1802*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_SCAN_STATE_IDLE:
1803*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_NONE;
1804*cfb92d14SAndroid Build Coastguard Worker         break;
1805*cfb92d14SAndroid Build Coastguard Worker 
1806*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1807*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_SCAN_STATE_BEACON:
1808*cfb92d14SAndroid Build Coastguard Worker         error = otLinkActiveScan(mInstance, mScanChannelMask, mScanPeriod, &HandleActiveScanResult_Jump, this);
1809*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error);
1810*cfb92d14SAndroid Build Coastguard Worker         break;
1811*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
1812*cfb92d14SAndroid Build Coastguard Worker 
1813*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_SCAN_STATE_ENERGY:
1814*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1815*cfb92d14SAndroid Build Coastguard Worker         if (otLinkRawIsEnabled(mInstance))
1816*cfb92d14SAndroid Build Coastguard Worker         {
1817*cfb92d14SAndroid Build Coastguard Worker             uint8_t scanChannel;
1818*cfb92d14SAndroid Build Coastguard Worker 
1819*cfb92d14SAndroid Build Coastguard Worker             // Make sure we aren't already scanning and that we have
1820*cfb92d14SAndroid Build Coastguard Worker             // only 1 bit set for the channel mask.
1821*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(mCurScanChannel[mCurCommandIid] == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
1822*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(HasOnly1BitSet(mScanChannelMask), error = OT_ERROR_INVALID_ARGS);
1823*cfb92d14SAndroid Build Coastguard Worker 
1824*cfb92d14SAndroid Build Coastguard Worker             scanChannel                     = IndexOfMSB(mScanChannelMask);
1825*cfb92d14SAndroid Build Coastguard Worker             mCurScanChannel[mCurCommandIid] = static_cast<int8_t>(scanChannel);
1826*cfb92d14SAndroid Build Coastguard Worker 
1827*cfb92d14SAndroid Build Coastguard Worker             error = otLinkRawEnergyScan(mInstance, scanChannel, mScanPeriod, LinkRawEnergyScanDone);
1828*cfb92d14SAndroid Build Coastguard Worker         }
1829*cfb92d14SAndroid Build Coastguard Worker         else
1830*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1831*cfb92d14SAndroid Build Coastguard Worker         {
1832*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1833*cfb92d14SAndroid Build Coastguard Worker             error = otLinkEnergyScan(mInstance, mScanChannelMask, mScanPeriod, &HandleEnergyScanResult_Jump, this);
1834*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
1835*cfb92d14SAndroid Build Coastguard Worker         }
1836*cfb92d14SAndroid Build Coastguard Worker 
1837*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error);
1838*cfb92d14SAndroid Build Coastguard Worker         break;
1839*cfb92d14SAndroid Build Coastguard Worker 
1840*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
1841*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_SCAN_STATE_DISCOVER:
1842*cfb92d14SAndroid Build Coastguard Worker         error = otThreadDiscover(mInstance, mScanChannelMask, mDiscoveryScanPanId, mDiscoveryScanJoinerFlag,
1843*cfb92d14SAndroid Build Coastguard Worker                                  mDiscoveryScanEnableFiltering, &HandleActiveScanResult_Jump, this);
1844*cfb92d14SAndroid Build Coastguard Worker 
1845*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error);
1846*cfb92d14SAndroid Build Coastguard Worker         break;
1847*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
1848*cfb92d14SAndroid Build Coastguard Worker 
1849*cfb92d14SAndroid Build Coastguard Worker     default:
1850*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_NOT_IMPLEMENTED;
1851*cfb92d14SAndroid Build Coastguard Worker         break;
1852*cfb92d14SAndroid Build Coastguard Worker     }
1853*cfb92d14SAndroid Build Coastguard Worker 
1854*cfb92d14SAndroid Build Coastguard Worker exit:
1855*cfb92d14SAndroid Build Coastguard Worker     return error;
1856*cfb92d14SAndroid Build Coastguard Worker }
1857*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1858*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_UNSOL_UPDATE_FILTER>(void)
1859*cfb92d14SAndroid Build Coastguard Worker {
1860*cfb92d14SAndroid Build Coastguard Worker     otError                       error = OT_ERROR_NONE;
1861*cfb92d14SAndroid Build Coastguard Worker     uint8_t                       numEntries;
1862*cfb92d14SAndroid Build Coastguard Worker     const ChangedPropsSet::Entry *entry;
1863*cfb92d14SAndroid Build Coastguard Worker 
1864*cfb92d14SAndroid Build Coastguard Worker     entry = mChangedPropsSet.GetSupportedEntries(numEntries);
1865*cfb92d14SAndroid Build Coastguard Worker 
1866*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
1867*cfb92d14SAndroid Build Coastguard Worker     {
1868*cfb92d14SAndroid Build Coastguard Worker         if (mChangedPropsSet.IsEntryFiltered(index))
1869*cfb92d14SAndroid Build Coastguard Worker         {
1870*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = mEncoder.WriteUintPacked(entry->mPropKey));
1871*cfb92d14SAndroid Build Coastguard Worker         }
1872*cfb92d14SAndroid Build Coastguard Worker     }
1873*cfb92d14SAndroid Build Coastguard Worker 
1874*cfb92d14SAndroid Build Coastguard Worker exit:
1875*cfb92d14SAndroid Build Coastguard Worker     return error;
1876*cfb92d14SAndroid Build Coastguard Worker }
1877*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)1878*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_UNSOL_UPDATE_FILTER>(void)
1879*cfb92d14SAndroid Build Coastguard Worker {
1880*cfb92d14SAndroid Build Coastguard Worker     unsigned int propKey;
1881*cfb92d14SAndroid Build Coastguard Worker     otError      error = OT_ERROR_NONE;
1882*cfb92d14SAndroid Build Coastguard Worker 
1883*cfb92d14SAndroid Build Coastguard Worker     // First clear the current filter.
1884*cfb92d14SAndroid Build Coastguard Worker     mChangedPropsSet.ClearFilter();
1885*cfb92d14SAndroid Build Coastguard Worker 
1886*cfb92d14SAndroid Build Coastguard Worker     while (mDecoder.GetRemainingLengthInStruct() > 0)
1887*cfb92d14SAndroid Build Coastguard Worker     {
1888*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = mDecoder.ReadUintPacked(propKey));
1889*cfb92d14SAndroid Build Coastguard Worker 
1890*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(mChangedPropsSet.EnablePropertyFilter(static_cast<spinel_prop_key_t>(propKey), true));
1891*cfb92d14SAndroid Build Coastguard Worker     }
1892*cfb92d14SAndroid Build Coastguard Worker 
1893*cfb92d14SAndroid Build Coastguard Worker exit:
1894*cfb92d14SAndroid Build Coastguard Worker     // If we had an error, we may have actually changed
1895*cfb92d14SAndroid Build Coastguard Worker     // the state of the filter, So we need to report
1896*cfb92d14SAndroid Build Coastguard Worker     // those incomplete changes via an asynchronous
1897*cfb92d14SAndroid Build Coastguard Worker     // change event.
1898*cfb92d14SAndroid Build Coastguard Worker 
1899*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
1900*cfb92d14SAndroid Build Coastguard Worker     {
1901*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID,
1902*cfb92d14SAndroid Build Coastguard Worker                                               SPINEL_PROP_UNSOL_UPDATE_FILTER));
1903*cfb92d14SAndroid Build Coastguard Worker     }
1904*cfb92d14SAndroid Build Coastguard Worker 
1905*cfb92d14SAndroid Build Coastguard Worker     return error;
1906*cfb92d14SAndroid Build Coastguard Worker }
1907*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyInsert(void)1908*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_UNSOL_UPDATE_FILTER>(void)
1909*cfb92d14SAndroid Build Coastguard Worker {
1910*cfb92d14SAndroid Build Coastguard Worker     otError      error = OT_ERROR_NONE;
1911*cfb92d14SAndroid Build Coastguard Worker     unsigned int propKey;
1912*cfb92d14SAndroid Build Coastguard Worker 
1913*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUintPacked(propKey));
1914*cfb92d14SAndroid Build Coastguard Worker 
1915*cfb92d14SAndroid Build Coastguard Worker     error = mChangedPropsSet.EnablePropertyFilter(static_cast<spinel_prop_key_t>(propKey), true);
1916*cfb92d14SAndroid Build Coastguard Worker 
1917*cfb92d14SAndroid Build Coastguard Worker exit:
1918*cfb92d14SAndroid Build Coastguard Worker     return error;
1919*cfb92d14SAndroid Build Coastguard Worker }
1920*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyRemove(void)1921*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_UNSOL_UPDATE_FILTER>(void)
1922*cfb92d14SAndroid Build Coastguard Worker {
1923*cfb92d14SAndroid Build Coastguard Worker     otError      error = OT_ERROR_NONE;
1924*cfb92d14SAndroid Build Coastguard Worker     unsigned int propKey;
1925*cfb92d14SAndroid Build Coastguard Worker 
1926*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUintPacked(propKey));
1927*cfb92d14SAndroid Build Coastguard Worker 
1928*cfb92d14SAndroid Build Coastguard Worker     error = mChangedPropsSet.EnablePropertyFilter(static_cast<spinel_prop_key_t>(propKey), false);
1929*cfb92d14SAndroid Build Coastguard Worker 
1930*cfb92d14SAndroid Build Coastguard Worker exit:
1931*cfb92d14SAndroid Build Coastguard Worker     return error;
1932*cfb92d14SAndroid Build Coastguard Worker }
1933*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1934*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_LAST_STATUS>(void)
1935*cfb92d14SAndroid Build Coastguard Worker {
1936*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUintPacked(mLastStatus);
1937*cfb92d14SAndroid Build Coastguard Worker }
1938*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1939*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PROTOCOL_VERSION>(void)
1940*cfb92d14SAndroid Build Coastguard Worker {
1941*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1942*cfb92d14SAndroid Build Coastguard Worker 
1943*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_VERSION_THREAD_MAJOR));
1944*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_VERSION_THREAD_MINOR));
1945*cfb92d14SAndroid Build Coastguard Worker 
1946*cfb92d14SAndroid Build Coastguard Worker exit:
1947*cfb92d14SAndroid Build Coastguard Worker     return error;
1948*cfb92d14SAndroid Build Coastguard Worker }
1949*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1950*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_INTERFACE_TYPE>(void)
1951*cfb92d14SAndroid Build Coastguard Worker {
1952*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD);
1953*cfb92d14SAndroid Build Coastguard Worker }
1954*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1955*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_VENDOR_ID>(void)
1956*cfb92d14SAndroid Build Coastguard Worker {
1957*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUintPacked(0); // Vendor ID. Zero for unknown.
1958*cfb92d14SAndroid Build Coastguard Worker }
1959*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)1960*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
1961*cfb92d14SAndroid Build Coastguard Worker {
1962*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1963*cfb92d14SAndroid Build Coastguard Worker 
1964*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_COUNTERS));
1965*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_UNSOL_UPDATE_FILTER));
1966*cfb92d14SAndroid Build Coastguard Worker 
1967*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
1968*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MCU_POWER_STATE));
1969*cfb92d14SAndroid Build Coastguard Worker #endif
1970*cfb92d14SAndroid Build Coastguard Worker 
1971*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
1972*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_802_15_4_2450MHZ_OQPSK));
1973*cfb92d14SAndroid Build Coastguard Worker #endif
1974*cfb92d14SAndroid Build Coastguard Worker 
1975*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
1976*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_802_15_4_915MHZ_OQPSK));
1977*cfb92d14SAndroid Build Coastguard Worker #endif
1978*cfb92d14SAndroid Build Coastguard Worker 
1979*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD
1980*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CONFIG_FTD));
1981*cfb92d14SAndroid Build Coastguard Worker #elif OPENTHREAD_MTD
1982*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CONFIG_MTD));
1983*cfb92d14SAndroid Build Coastguard Worker #elif OPENTHREAD_RADIO
1984*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CONFIG_RADIO));
1985*cfb92d14SAndroid Build Coastguard Worker #endif
1986*cfb92d14SAndroid Build Coastguard Worker 
1987*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
1988*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_RAW));
1989*cfb92d14SAndroid Build Coastguard Worker #endif
1990*cfb92d14SAndroid Build Coastguard Worker 
1991*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO
1992*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_API_VERSION));
1993*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_MIN_HOST_API_VERSION));
1994*cfb92d14SAndroid Build Coastguard Worker #endif
1995*cfb92d14SAndroid Build Coastguard Worker 
1996*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
1997*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER));
1998*cfb92d14SAndroid Build Coastguard Worker #endif
1999*cfb92d14SAndroid Build Coastguard Worker 
2000*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
2001*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_LOG_CRASH_DUMP));
2002*cfb92d14SAndroid Build Coastguard Worker #endif
2003*cfb92d14SAndroid Build Coastguard Worker 
2004*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_PLATFORM_POSIX
2005*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX));
2006*cfb92d14SAndroid Build Coastguard Worker #endif
2007*cfb92d14SAndroid Build Coastguard Worker 
2008*cfb92d14SAndroid Build Coastguard Worker #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_APP)
2009*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_OPENTHREAD_LOG_METADATA));
2010*cfb92d14SAndroid Build Coastguard Worker #endif
2011*cfb92d14SAndroid Build Coastguard Worker 
2012*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_MTD || OPENTHREAD_FTD
2013*cfb92d14SAndroid Build Coastguard Worker 
2014*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_1));
2015*cfb92d14SAndroid Build Coastguard Worker 
2016*cfb92d14SAndroid Build Coastguard Worker #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
2017*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_2));
2018*cfb92d14SAndroid Build Coastguard Worker #endif
2019*cfb92d14SAndroid Build Coastguard Worker 
2020*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_PCAP));
2021*cfb92d14SAndroid Build Coastguard Worker 
2022*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
2023*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_ALLOWLIST));
2024*cfb92d14SAndroid Build Coastguard Worker #endif
2025*cfb92d14SAndroid Build Coastguard Worker 
2026*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
2027*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_JAM_DETECT));
2028*cfb92d14SAndroid Build Coastguard Worker #endif
2029*cfb92d14SAndroid Build Coastguard Worker 
2030*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CHILD_SUPERVISION));
2031*cfb92d14SAndroid Build Coastguard Worker 
2032*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
2033*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CHANNEL_MONITOR));
2034*cfb92d14SAndroid Build Coastguard Worker #endif
2035*cfb92d14SAndroid Build Coastguard Worker 
2036*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
2037*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CHANNEL_MANAGER));
2038*cfb92d14SAndroid Build Coastguard Worker #endif
2039*cfb92d14SAndroid Build Coastguard Worker 
2040*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
2041*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_TIME_SYNC));
2042*cfb92d14SAndroid Build Coastguard Worker #endif
2043*cfb92d14SAndroid Build Coastguard Worker 
2044*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ERROR_RATE_TRACKING));
2045*cfb92d14SAndroid Build Coastguard Worker 
2046*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
2047*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_OOB_STEERING_DATA));
2048*cfb92d14SAndroid Build Coastguard Worker #endif
2049*cfb92d14SAndroid Build Coastguard Worker 
2050*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
2051*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_SLAAC));
2052*cfb92d14SAndroid Build Coastguard Worker #endif
2053*cfb92d14SAndroid Build Coastguard Worker 
2054*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
2055*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RADIO_COEX));
2056*cfb92d14SAndroid Build Coastguard Worker #endif
2057*cfb92d14SAndroid Build Coastguard Worker 
2058*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2059*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_RETRY_HISTOGRAM));
2060*cfb92d14SAndroid Build Coastguard Worker #endif
2061*cfb92d14SAndroid Build Coastguard Worker 
2062*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
2063*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_PEEK_POKE));
2064*cfb92d14SAndroid Build Coastguard Worker #endif
2065*cfb92d14SAndroid Build Coastguard Worker 
2066*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_MAX_CHILDREN > 0
2067*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ROLE_ROUTER));
2068*cfb92d14SAndroid Build Coastguard Worker #endif
2069*cfb92d14SAndroid Build Coastguard Worker 
2070*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ROLE_SLEEPY));
2071*cfb92d14SAndroid Build Coastguard Worker 
2072*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
2073*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_COMMISSIONER));
2074*cfb92d14SAndroid Build Coastguard Worker #endif
2075*cfb92d14SAndroid Build Coastguard Worker 
2076*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_JOINER_ENABLE
2077*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_JOINER));
2078*cfb92d14SAndroid Build Coastguard Worker #endif
2079*cfb92d14SAndroid Build Coastguard Worker 
2080*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
2081*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_BORDER_ROUTER));
2082*cfb92d14SAndroid Build Coastguard Worker #endif
2083*cfb92d14SAndroid Build Coastguard Worker 
2084*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
2085*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_UDP_FORWARD));
2086*cfb92d14SAndroid Build Coastguard Worker #endif
2087*cfb92d14SAndroid Build Coastguard Worker 
2088*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
2089*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_SERVICE));
2090*cfb92d14SAndroid Build Coastguard Worker #endif
2091*cfb92d14SAndroid Build Coastguard Worker 
2092*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
2093*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_CSL_RECEIVER));
2094*cfb92d14SAndroid Build Coastguard Worker #endif
2095*cfb92d14SAndroid Build Coastguard Worker 
2096*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTI_RADIO
2097*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MULTI_RADIO));
2098*cfb92d14SAndroid Build Coastguard Worker #endif
2099*cfb92d14SAndroid Build Coastguard Worker 
2100*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
2101*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_SRP_CLIENT));
2102*cfb92d14SAndroid Build Coastguard Worker #endif
2103*cfb92d14SAndroid Build Coastguard Worker 
2104*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
2105*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_LINK_METRICS));
2106*cfb92d14SAndroid Build Coastguard Worker #endif
2107*cfb92d14SAndroid Build Coastguard Worker 
2108*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_DUA_ENABLE
2109*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_DUA));
2110*cfb92d14SAndroid Build Coastguard Worker #endif
2111*cfb92d14SAndroid Build Coastguard Worker 
2112*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2113*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_REFERENCE_DEVICE));
2114*cfb92d14SAndroid Build Coastguard Worker #endif
2115*cfb92d14SAndroid Build Coastguard Worker 
2116*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
2117*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_BACKBONE_ROUTER));
2118*cfb92d14SAndroid Build Coastguard Worker #endif
2119*cfb92d14SAndroid Build Coastguard Worker 
2120*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
2121*cfb92d14SAndroid Build Coastguard Worker 
2122*cfb92d14SAndroid Build Coastguard Worker exit:
2123*cfb92d14SAndroid Build Coastguard Worker     return error;
2124*cfb92d14SAndroid Build Coastguard Worker }
2125*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2126*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NCP_VERSION>(void)
2127*cfb92d14SAndroid Build Coastguard Worker {
2128*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUtf8(otGetVersionString());
2129*cfb92d14SAndroid Build Coastguard Worker }
2130*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2131*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_INTERFACE_COUNT>(void)
2132*cfb92d14SAndroid Build Coastguard Worker {
2133*cfb92d14SAndroid Build Coastguard Worker     uint8_t instances = 1;
2134*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
2135*cfb92d14SAndroid Build Coastguard Worker     instances = 0;
2136*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t i = 0; i <= SPINEL_HEADER_IID_MAX; i++)
2137*cfb92d14SAndroid Build Coastguard Worker     {
2138*cfb92d14SAndroid Build Coastguard Worker         if (mInstances[i] != nullptr)
2139*cfb92d14SAndroid Build Coastguard Worker         {
2140*cfb92d14SAndroid Build Coastguard Worker             instances++;
2141*cfb92d14SAndroid Build Coastguard Worker         }
2142*cfb92d14SAndroid Build Coastguard Worker     }
2143*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE  && OPENTHREAD_RADIO
2144*cfb92d14SAndroid Build Coastguard Worker 
2145*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(instances);
2146*cfb92d14SAndroid Build Coastguard Worker }
2147*cfb92d14SAndroid Build Coastguard Worker 
2148*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
2149*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2150*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MCU_POWER_STATE>(void)
2151*cfb92d14SAndroid Build Coastguard Worker {
2152*cfb92d14SAndroid Build Coastguard Worker     spinel_mcu_power_state_t state = SPINEL_MCU_POWER_STATE_ON;
2153*cfb92d14SAndroid Build Coastguard Worker 
2154*cfb92d14SAndroid Build Coastguard Worker     switch (otPlatGetMcuPowerState(mInstance))
2155*cfb92d14SAndroid Build Coastguard Worker     {
2156*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_MCU_POWER_STATE_ON:
2157*cfb92d14SAndroid Build Coastguard Worker         state = SPINEL_MCU_POWER_STATE_ON;
2158*cfb92d14SAndroid Build Coastguard Worker         break;
2159*cfb92d14SAndroid Build Coastguard Worker 
2160*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_MCU_POWER_STATE_LOW_POWER:
2161*cfb92d14SAndroid Build Coastguard Worker         state = SPINEL_MCU_POWER_STATE_LOW_POWER;
2162*cfb92d14SAndroid Build Coastguard Worker         break;
2163*cfb92d14SAndroid Build Coastguard Worker 
2164*cfb92d14SAndroid Build Coastguard Worker     case OT_PLAT_MCU_POWER_STATE_OFF:
2165*cfb92d14SAndroid Build Coastguard Worker         state = SPINEL_MCU_POWER_STATE_OFF;
2166*cfb92d14SAndroid Build Coastguard Worker         break;
2167*cfb92d14SAndroid Build Coastguard Worker     }
2168*cfb92d14SAndroid Build Coastguard Worker 
2169*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(state);
2170*cfb92d14SAndroid Build Coastguard Worker }
2171*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2172*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MCU_POWER_STATE>(void)
2173*cfb92d14SAndroid Build Coastguard Worker {
2174*cfb92d14SAndroid Build Coastguard Worker     otError             error = OT_ERROR_NONE;
2175*cfb92d14SAndroid Build Coastguard Worker     otPlatMcuPowerState powerState;
2176*cfb92d14SAndroid Build Coastguard Worker     uint8_t             state;
2177*cfb92d14SAndroid Build Coastguard Worker 
2178*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(state));
2179*cfb92d14SAndroid Build Coastguard Worker 
2180*cfb92d14SAndroid Build Coastguard Worker     switch (state)
2181*cfb92d14SAndroid Build Coastguard Worker     {
2182*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MCU_POWER_STATE_ON:
2183*cfb92d14SAndroid Build Coastguard Worker         powerState = OT_PLAT_MCU_POWER_STATE_ON;
2184*cfb92d14SAndroid Build Coastguard Worker         break;
2185*cfb92d14SAndroid Build Coastguard Worker 
2186*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MCU_POWER_STATE_LOW_POWER:
2187*cfb92d14SAndroid Build Coastguard Worker         powerState = OT_PLAT_MCU_POWER_STATE_LOW_POWER;
2188*cfb92d14SAndroid Build Coastguard Worker         break;
2189*cfb92d14SAndroid Build Coastguard Worker 
2190*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_MCU_POWER_STATE_OFF:
2191*cfb92d14SAndroid Build Coastguard Worker         powerState = OT_PLAT_MCU_POWER_STATE_OFF;
2192*cfb92d14SAndroid Build Coastguard Worker         break;
2193*cfb92d14SAndroid Build Coastguard Worker 
2194*cfb92d14SAndroid Build Coastguard Worker     default:
2195*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_INVALID_ARGS);
2196*cfb92d14SAndroid Build Coastguard Worker     }
2197*cfb92d14SAndroid Build Coastguard Worker 
2198*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otPlatSetMcuPowerState(mInstance, powerState));
2199*cfb92d14SAndroid Build Coastguard Worker 
2200*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_FTD || OPENTHREAD_MTD
2201*cfb92d14SAndroid Build Coastguard Worker 
2202*cfb92d14SAndroid Build Coastguard Worker     // If the call `otPlatSetMcuPowerState()` was successful and the desire
2203*cfb92d14SAndroid Build Coastguard Worker     // state is `OFF`, ensure to disable Thread (MLE) operation (and stop
2204*cfb92d14SAndroid Build Coastguard Worker     // legacy) and also bring the IPv6 interface down.
2205*cfb92d14SAndroid Build Coastguard Worker 
2206*cfb92d14SAndroid Build Coastguard Worker     if (powerState == OT_PLAT_MCU_POWER_STATE_OFF)
2207*cfb92d14SAndroid Build Coastguard Worker     {
2208*cfb92d14SAndroid Build Coastguard Worker         if (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED)
2209*cfb92d14SAndroid Build Coastguard Worker         {
2210*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(otThreadSetEnabled(mInstance, false));
2211*cfb92d14SAndroid Build Coastguard Worker         }
2212*cfb92d14SAndroid Build Coastguard Worker 
2213*cfb92d14SAndroid Build Coastguard Worker         if (otIp6IsEnabled(mInstance))
2214*cfb92d14SAndroid Build Coastguard Worker         {
2215*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(otIp6SetEnabled(mInstance, false));
2216*cfb92d14SAndroid Build Coastguard Worker         }
2217*cfb92d14SAndroid Build Coastguard Worker     }
2218*cfb92d14SAndroid Build Coastguard Worker #endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
2219*cfb92d14SAndroid Build Coastguard Worker 
2220*cfb92d14SAndroid Build Coastguard Worker exit:
2221*cfb92d14SAndroid Build Coastguard Worker     return error;
2222*cfb92d14SAndroid Build Coastguard Worker }
2223*cfb92d14SAndroid Build Coastguard Worker 
2224*cfb92d14SAndroid Build Coastguard Worker #else // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
2225*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2226*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MCU_POWER_STATE>(void)
2227*cfb92d14SAndroid Build Coastguard Worker {
2228*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(SPINEL_MCU_POWER_STATE_ON);
2229*cfb92d14SAndroid Build Coastguard Worker }
2230*cfb92d14SAndroid Build Coastguard Worker 
2231*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
2232*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2233*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_POWER_STATE>(void)
2234*cfb92d14SAndroid Build Coastguard Worker {
2235*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(SPINEL_POWER_STATE_ONLINE);
2236*cfb92d14SAndroid Build Coastguard Worker }
2237*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2238*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_POWER_STATE>(void) { return OT_ERROR_NOT_IMPLEMENTED; }
2239*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2240*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_HWADDR>(void)
2241*cfb92d14SAndroid Build Coastguard Worker {
2242*cfb92d14SAndroid Build Coastguard Worker     otExtAddress hwAddr;
2243*cfb92d14SAndroid Build Coastguard Worker 
2244*cfb92d14SAndroid Build Coastguard Worker     otLinkGetFactoryAssignedIeeeEui64(mInstance, &hwAddr);
2245*cfb92d14SAndroid Build Coastguard Worker 
2246*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteEui64(hwAddr);
2247*cfb92d14SAndroid Build Coastguard Worker }
2248*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2249*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_LOCK>(void)
2250*cfb92d14SAndroid Build Coastguard Worker {
2251*cfb92d14SAndroid Build Coastguard Worker     // TODO: Implement property lock (Needs API!)
2252*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
2253*cfb92d14SAndroid Build Coastguard Worker }
2254*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2255*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_HOST_POWER_STATE>(void)
2256*cfb92d14SAndroid Build Coastguard Worker {
2257*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(mHostPowerState);
2258*cfb92d14SAndroid Build Coastguard Worker }
2259*cfb92d14SAndroid Build Coastguard Worker 
2260*cfb92d14SAndroid Build Coastguard Worker // Setting `HOST_POWER_STATE` is treated and implemented differently from other
2261*cfb92d14SAndroid Build Coastguard Worker // handlers as it requires two special behaviors (a) the response frame for the
2262*cfb92d14SAndroid Build Coastguard Worker // set operation should be tracked and only when it is delivered we can assume
2263*cfb92d14SAndroid Build Coastguard Worker // that host is sleep (b) the response is critical so if there is no spinel
2264*cfb92d14SAndroid Build Coastguard Worker // buffer to prepare the response, the current spinel header is saved to
2265*cfb92d14SAndroid Build Coastguard Worker // prepare and send the response as soon as buffer space becomes available.
HandlePropertySet_SPINEL_PROP_HOST_POWER_STATE(uint8_t aHeader)2266*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::HandlePropertySet_SPINEL_PROP_HOST_POWER_STATE(uint8_t aHeader)
2267*cfb92d14SAndroid Build Coastguard Worker {
2268*cfb92d14SAndroid Build Coastguard Worker     uint8_t powerState;
2269*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2270*cfb92d14SAndroid Build Coastguard Worker 
2271*cfb92d14SAndroid Build Coastguard Worker     error = mDecoder.ReadUint8(powerState);
2272*cfb92d14SAndroid Build Coastguard Worker 
2273*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
2274*cfb92d14SAndroid Build Coastguard Worker     {
2275*cfb92d14SAndroid Build Coastguard Worker         switch (powerState)
2276*cfb92d14SAndroid Build Coastguard Worker         {
2277*cfb92d14SAndroid Build Coastguard Worker         case SPINEL_HOST_POWER_STATE_OFFLINE:
2278*cfb92d14SAndroid Build Coastguard Worker         case SPINEL_HOST_POWER_STATE_DEEP_SLEEP:
2279*cfb92d14SAndroid Build Coastguard Worker         case SPINEL_HOST_POWER_STATE_LOW_POWER:
2280*cfb92d14SAndroid Build Coastguard Worker         case SPINEL_HOST_POWER_STATE_ONLINE:
2281*cfb92d14SAndroid Build Coastguard Worker             // Adopt the requested power state.
2282*cfb92d14SAndroid Build Coastguard Worker             mHostPowerState = static_cast<spinel_host_power_state_t>(powerState);
2283*cfb92d14SAndroid Build Coastguard Worker             break;
2284*cfb92d14SAndroid Build Coastguard Worker 
2285*cfb92d14SAndroid Build Coastguard Worker         case SPINEL_HOST_POWER_STATE_RESERVED:
2286*cfb92d14SAndroid Build Coastguard Worker             // Per the specification, treat this as synonymous with SPINEL_HOST_POWER_STATE_DEEP_SLEEP.
2287*cfb92d14SAndroid Build Coastguard Worker             mHostPowerState = SPINEL_HOST_POWER_STATE_DEEP_SLEEP;
2288*cfb92d14SAndroid Build Coastguard Worker             break;
2289*cfb92d14SAndroid Build Coastguard Worker 
2290*cfb92d14SAndroid Build Coastguard Worker         default:
2291*cfb92d14SAndroid Build Coastguard Worker             // Per the specification, treat unrecognized values as synonymous with SPINEL_HOST_POWER_STATE_LOW_POWER.
2292*cfb92d14SAndroid Build Coastguard Worker             mHostPowerState = SPINEL_HOST_POWER_STATE_LOW_POWER;
2293*cfb92d14SAndroid Build Coastguard Worker             break;
2294*cfb92d14SAndroid Build Coastguard Worker         }
2295*cfb92d14SAndroid Build Coastguard Worker 
2296*cfb92d14SAndroid Build Coastguard Worker         mHostPowerStateHeader = 0;
2297*cfb92d14SAndroid Build Coastguard Worker 
2298*cfb92d14SAndroid Build Coastguard Worker         error = WritePropertyValueIsFrame(aHeader, SPINEL_PROP_HOST_POWER_STATE);
2299*cfb92d14SAndroid Build Coastguard Worker 
2300*cfb92d14SAndroid Build Coastguard Worker         if (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE)
2301*cfb92d14SAndroid Build Coastguard Worker         {
2302*cfb92d14SAndroid Build Coastguard Worker             if (error == OT_ERROR_NONE)
2303*cfb92d14SAndroid Build Coastguard Worker             {
2304*cfb92d14SAndroid Build Coastguard Worker                 mHostPowerReplyFrameTag = GetLastOutboundFrameTag();
2305*cfb92d14SAndroid Build Coastguard Worker             }
2306*cfb92d14SAndroid Build Coastguard Worker             else
2307*cfb92d14SAndroid Build Coastguard Worker             {
2308*cfb92d14SAndroid Build Coastguard Worker                 mHostPowerReplyFrameTag = Spinel::Buffer::kInvalidTag;
2309*cfb92d14SAndroid Build Coastguard Worker             }
2310*cfb92d14SAndroid Build Coastguard Worker 
2311*cfb92d14SAndroid Build Coastguard Worker             mHostPowerStateInProgress = true;
2312*cfb92d14SAndroid Build Coastguard Worker         }
2313*cfb92d14SAndroid Build Coastguard Worker 
2314*cfb92d14SAndroid Build Coastguard Worker         if (error != OT_ERROR_NONE)
2315*cfb92d14SAndroid Build Coastguard Worker         {
2316*cfb92d14SAndroid Build Coastguard Worker             mHostPowerStateHeader = aHeader;
2317*cfb92d14SAndroid Build Coastguard Worker 
2318*cfb92d14SAndroid Build Coastguard Worker             // The reply will be queued when buffer space becomes available
2319*cfb92d14SAndroid Build Coastguard Worker             // in the NCP tx buffer so we return `success` to avoid sending a
2320*cfb92d14SAndroid Build Coastguard Worker             // NOMEM status for the same tid through `mDroppedReplyTid` list.
2321*cfb92d14SAndroid Build Coastguard Worker 
2322*cfb92d14SAndroid Build Coastguard Worker             error = OT_ERROR_NONE;
2323*cfb92d14SAndroid Build Coastguard Worker         }
2324*cfb92d14SAndroid Build Coastguard Worker     }
2325*cfb92d14SAndroid Build Coastguard Worker     else
2326*cfb92d14SAndroid Build Coastguard Worker     {
2327*cfb92d14SAndroid Build Coastguard Worker         error = WriteLastStatusFrame(aHeader, ThreadErrorToSpinelStatus(error));
2328*cfb92d14SAndroid Build Coastguard Worker     }
2329*cfb92d14SAndroid Build Coastguard Worker 
2330*cfb92d14SAndroid Build Coastguard Worker     return error;
2331*cfb92d14SAndroid Build Coastguard Worker }
2332*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2333*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_UNSOL_UPDATE_LIST>(void)
2334*cfb92d14SAndroid Build Coastguard Worker {
2335*cfb92d14SAndroid Build Coastguard Worker     otError                       error = OT_ERROR_NONE;
2336*cfb92d14SAndroid Build Coastguard Worker     uint8_t                       numEntries;
2337*cfb92d14SAndroid Build Coastguard Worker     const ChangedPropsSet::Entry *entry;
2338*cfb92d14SAndroid Build Coastguard Worker 
2339*cfb92d14SAndroid Build Coastguard Worker     entry = mChangedPropsSet.GetSupportedEntries(numEntries);
2340*cfb92d14SAndroid Build Coastguard Worker 
2341*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
2342*cfb92d14SAndroid Build Coastguard Worker     {
2343*cfb92d14SAndroid Build Coastguard Worker         if (entry->mFilterable)
2344*cfb92d14SAndroid Build Coastguard Worker         {
2345*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = mEncoder.WriteUintPacked(entry->mPropKey));
2346*cfb92d14SAndroid Build Coastguard Worker         }
2347*cfb92d14SAndroid Build Coastguard Worker     }
2348*cfb92d14SAndroid Build Coastguard Worker 
2349*cfb92d14SAndroid Build Coastguard Worker exit:
2350*cfb92d14SAndroid Build Coastguard Worker     return error;
2351*cfb92d14SAndroid Build Coastguard Worker }
2352*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2353*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_RSSI>(void)
2354*cfb92d14SAndroid Build Coastguard Worker {
2355*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteInt8(otPlatRadioGetRssi(mInstance));
2356*cfb92d14SAndroid Build Coastguard Worker }
2357*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2358*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_RX_SENSITIVITY>(void)
2359*cfb92d14SAndroid Build Coastguard Worker {
2360*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteInt8(otPlatRadioGetReceiveSensitivity(mInstance));
2361*cfb92d14SAndroid Build Coastguard Worker }
2362*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2363*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>(void)
2364*cfb92d14SAndroid Build Coastguard Worker {
2365*cfb92d14SAndroid Build Coastguard Worker     uint32_t      freq_khz(0);
2366*cfb92d14SAndroid Build Coastguard Worker     const uint8_t chan(otLinkGetChannel(mInstance));
2367*cfb92d14SAndroid Build Coastguard Worker 
2368*cfb92d14SAndroid Build Coastguard Worker     if (chan == 0)
2369*cfb92d14SAndroid Build Coastguard Worker     {
2370*cfb92d14SAndroid Build Coastguard Worker         freq_khz = 868300;
2371*cfb92d14SAndroid Build Coastguard Worker     }
2372*cfb92d14SAndroid Build Coastguard Worker     else if (chan < 11)
2373*cfb92d14SAndroid Build Coastguard Worker     {
2374*cfb92d14SAndroid Build Coastguard Worker         freq_khz = 906000 - (2000 * 1) + 2000 * (chan);
2375*cfb92d14SAndroid Build Coastguard Worker     }
2376*cfb92d14SAndroid Build Coastguard Worker     else if (chan < 26)
2377*cfb92d14SAndroid Build Coastguard Worker     {
2378*cfb92d14SAndroid Build Coastguard Worker         freq_khz = 2405000 - (5000 * 11) + 5000 * (chan);
2379*cfb92d14SAndroid Build Coastguard Worker     }
2380*cfb92d14SAndroid Build Coastguard Worker 
2381*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint32(freq_khz);
2382*cfb92d14SAndroid Build Coastguard Worker }
2383*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2384*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CCA_THRESHOLD>(void)
2385*cfb92d14SAndroid Build Coastguard Worker {
2386*cfb92d14SAndroid Build Coastguard Worker     int8_t  threshold;
2387*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2388*cfb92d14SAndroid Build Coastguard Worker 
2389*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioGetCcaEnergyDetectThreshold(mInstance, &threshold);
2390*cfb92d14SAndroid Build Coastguard Worker 
2391*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
2392*cfb92d14SAndroid Build Coastguard Worker     {
2393*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.WriteInt8(threshold);
2394*cfb92d14SAndroid Build Coastguard Worker     }
2395*cfb92d14SAndroid Build Coastguard Worker     else
2396*cfb92d14SAndroid Build Coastguard Worker     {
2397*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
2398*cfb92d14SAndroid Build Coastguard Worker     }
2399*cfb92d14SAndroid Build Coastguard Worker 
2400*cfb92d14SAndroid Build Coastguard Worker     return error;
2401*cfb92d14SAndroid Build Coastguard Worker }
2402*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2403*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CCA_THRESHOLD>(void)
2404*cfb92d14SAndroid Build Coastguard Worker {
2405*cfb92d14SAndroid Build Coastguard Worker     int8_t  threshold = 0;
2406*cfb92d14SAndroid Build Coastguard Worker     otError error     = OT_ERROR_NONE;
2407*cfb92d14SAndroid Build Coastguard Worker 
2408*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt8(threshold));
2409*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetCcaEnergyDetectThreshold(mInstance, threshold);
2410*cfb92d14SAndroid Build Coastguard Worker 
2411*cfb92d14SAndroid Build Coastguard Worker exit:
2412*cfb92d14SAndroid Build Coastguard Worker     return error;
2413*cfb92d14SAndroid Build Coastguard Worker }
2414*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2415*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_TX_POWER>(void)
2416*cfb92d14SAndroid Build Coastguard Worker {
2417*cfb92d14SAndroid Build Coastguard Worker     int8_t  power;
2418*cfb92d14SAndroid Build Coastguard Worker     otError error;
2419*cfb92d14SAndroid Build Coastguard Worker 
2420*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioGetTransmitPower(mInstance, &power);
2421*cfb92d14SAndroid Build Coastguard Worker 
2422*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
2423*cfb92d14SAndroid Build Coastguard Worker     {
2424*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.WriteInt8(power);
2425*cfb92d14SAndroid Build Coastguard Worker     }
2426*cfb92d14SAndroid Build Coastguard Worker     else
2427*cfb92d14SAndroid Build Coastguard Worker     {
2428*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
2429*cfb92d14SAndroid Build Coastguard Worker     }
2430*cfb92d14SAndroid Build Coastguard Worker 
2431*cfb92d14SAndroid Build Coastguard Worker     return error;
2432*cfb92d14SAndroid Build Coastguard Worker }
2433*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2434*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_TX_POWER>(void)
2435*cfb92d14SAndroid Build Coastguard Worker {
2436*cfb92d14SAndroid Build Coastguard Worker     int8_t  txPower = 0;
2437*cfb92d14SAndroid Build Coastguard Worker     otError error   = OT_ERROR_NONE;
2438*cfb92d14SAndroid Build Coastguard Worker 
2439*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt8(txPower));
2440*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetTransmitPower(mInstance, txPower);
2441*cfb92d14SAndroid Build Coastguard Worker 
2442*cfb92d14SAndroid Build Coastguard Worker exit:
2443*cfb92d14SAndroid Build Coastguard Worker     return error;
2444*cfb92d14SAndroid Build Coastguard Worker }
2445*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2446*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FEM_LNA_GAIN>(void)
2447*cfb92d14SAndroid Build Coastguard Worker {
2448*cfb92d14SAndroid Build Coastguard Worker     int8_t  gain;
2449*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2450*cfb92d14SAndroid Build Coastguard Worker 
2451*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioGetFemLnaGain(mInstance, &gain);
2452*cfb92d14SAndroid Build Coastguard Worker 
2453*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
2454*cfb92d14SAndroid Build Coastguard Worker     {
2455*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.WriteInt8(gain);
2456*cfb92d14SAndroid Build Coastguard Worker     }
2457*cfb92d14SAndroid Build Coastguard Worker     else
2458*cfb92d14SAndroid Build Coastguard Worker     {
2459*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
2460*cfb92d14SAndroid Build Coastguard Worker     }
2461*cfb92d14SAndroid Build Coastguard Worker 
2462*cfb92d14SAndroid Build Coastguard Worker     return error;
2463*cfb92d14SAndroid Build Coastguard Worker }
2464*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2465*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_FEM_LNA_GAIN>(void)
2466*cfb92d14SAndroid Build Coastguard Worker {
2467*cfb92d14SAndroid Build Coastguard Worker     int8_t  gain  = 0;
2468*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2469*cfb92d14SAndroid Build Coastguard Worker 
2470*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt8(gain));
2471*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetFemLnaGain(mInstance, gain);
2472*cfb92d14SAndroid Build Coastguard Worker 
2473*cfb92d14SAndroid Build Coastguard Worker exit:
2474*cfb92d14SAndroid Build Coastguard Worker     return error;
2475*cfb92d14SAndroid Build Coastguard Worker }
2476*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2477*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_MAX_POWER>(void)
2478*cfb92d14SAndroid Build Coastguard Worker {
2479*cfb92d14SAndroid Build Coastguard Worker     uint8_t channel;
2480*cfb92d14SAndroid Build Coastguard Worker     int8_t  maxPower;
2481*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2482*cfb92d14SAndroid Build Coastguard Worker 
2483*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(channel));
2484*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt8(maxPower));
2485*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetChannelMaxTransmitPower(mInstance, channel, maxPower);
2486*cfb92d14SAndroid Build Coastguard Worker 
2487*cfb92d14SAndroid Build Coastguard Worker exit:
2488*cfb92d14SAndroid Build Coastguard Worker     return error;
2489*cfb92d14SAndroid Build Coastguard Worker }
2490*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2491*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_REGION_CODE>(void)
2492*cfb92d14SAndroid Build Coastguard Worker {
2493*cfb92d14SAndroid Build Coastguard Worker     uint16_t regionCode;
2494*cfb92d14SAndroid Build Coastguard Worker     otError  error = OT_ERROR_NONE;
2495*cfb92d14SAndroid Build Coastguard Worker 
2496*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioGetRegion(mInstance, &regionCode);
2497*cfb92d14SAndroid Build Coastguard Worker     if (error == OT_ERROR_NONE)
2498*cfb92d14SAndroid Build Coastguard Worker     {
2499*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.WriteUint16(regionCode);
2500*cfb92d14SAndroid Build Coastguard Worker     }
2501*cfb92d14SAndroid Build Coastguard Worker     else
2502*cfb92d14SAndroid Build Coastguard Worker     {
2503*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
2504*cfb92d14SAndroid Build Coastguard Worker     }
2505*cfb92d14SAndroid Build Coastguard Worker 
2506*cfb92d14SAndroid Build Coastguard Worker     return error;
2507*cfb92d14SAndroid Build Coastguard Worker }
2508*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2509*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_REGION_CODE>(void)
2510*cfb92d14SAndroid Build Coastguard Worker {
2511*cfb92d14SAndroid Build Coastguard Worker     uint16_t regionCode;
2512*cfb92d14SAndroid Build Coastguard Worker     otError  error = OT_ERROR_NONE;
2513*cfb92d14SAndroid Build Coastguard Worker 
2514*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint16(regionCode));
2515*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetRegion(mInstance, regionCode);
2516*cfb92d14SAndroid Build Coastguard Worker 
2517*cfb92d14SAndroid Build Coastguard Worker exit:
2518*cfb92d14SAndroid Build Coastguard Worker     return error;
2519*cfb92d14SAndroid Build Coastguard Worker }
2520*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2521*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_TEST_ASSERT>(void)
2522*cfb92d14SAndroid Build Coastguard Worker {
2523*cfb92d14SAndroid Build Coastguard Worker #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2524*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(false);
2525*cfb92d14SAndroid Build Coastguard Worker #endif
2526*cfb92d14SAndroid Build Coastguard Worker 
2527*cfb92d14SAndroid Build Coastguard Worker     // We only get to this point if `OT_ASSERT(false)`
2528*cfb92d14SAndroid Build Coastguard Worker     // does not cause an NCP reset on the platform.
2529*cfb92d14SAndroid Build Coastguard Worker     // In such a case we return `false` as the
2530*cfb92d14SAndroid Build Coastguard Worker     // property value to indicate this.
2531*cfb92d14SAndroid Build Coastguard Worker 
2532*cfb92d14SAndroid Build Coastguard Worker     OT_UNREACHABLE_CODE(return mEncoder.WriteBool(false);)
2533*cfb92d14SAndroid Build Coastguard Worker }
2534*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2535*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_TEST_WATCHDOG>(void)
2536*cfb92d14SAndroid Build Coastguard Worker {
2537*cfb92d14SAndroid Build Coastguard Worker #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2538*cfb92d14SAndroid Build Coastguard Worker     while (true)
2539*cfb92d14SAndroid Build Coastguard Worker         ;
2540*cfb92d14SAndroid Build Coastguard Worker #endif
2541*cfb92d14SAndroid Build Coastguard Worker 
2542*cfb92d14SAndroid Build Coastguard Worker     OT_UNREACHABLE_CODE(return OT_ERROR_NONE;)
2543*cfb92d14SAndroid Build Coastguard Worker }
2544*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2545*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_NCP_LOG_LEVEL>(void)
2546*cfb92d14SAndroid Build Coastguard Worker {
2547*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint8(ConvertLogLevel(otLoggingGetLevel()));
2548*cfb92d14SAndroid Build Coastguard Worker }
2549*cfb92d14SAndroid Build Coastguard Worker 
2550*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
HandlePropertySet(void)2551*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_DEBUG_NCP_LOG_LEVEL>(void)
2552*cfb92d14SAndroid Build Coastguard Worker {
2553*cfb92d14SAndroid Build Coastguard Worker     otError    error;
2554*cfb92d14SAndroid Build Coastguard Worker     uint8_t    spinelNcpLogLevel = 0;
2555*cfb92d14SAndroid Build Coastguard Worker     otLogLevel logLevel;
2556*cfb92d14SAndroid Build Coastguard Worker 
2557*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(spinelNcpLogLevel));
2558*cfb92d14SAndroid Build Coastguard Worker 
2559*cfb92d14SAndroid Build Coastguard Worker     switch (spinelNcpLogLevel)
2560*cfb92d14SAndroid Build Coastguard Worker     {
2561*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_EMERG:
2562*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_ALERT:
2563*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_NONE;
2564*cfb92d14SAndroid Build Coastguard Worker         break;
2565*cfb92d14SAndroid Build Coastguard Worker 
2566*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_CRIT:
2567*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_CRIT;
2568*cfb92d14SAndroid Build Coastguard Worker         break;
2569*cfb92d14SAndroid Build Coastguard Worker 
2570*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_ERR:
2571*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_WARN:
2572*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_WARN;
2573*cfb92d14SAndroid Build Coastguard Worker         break;
2574*cfb92d14SAndroid Build Coastguard Worker 
2575*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_NOTICE:
2576*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_NOTE;
2577*cfb92d14SAndroid Build Coastguard Worker         break;
2578*cfb92d14SAndroid Build Coastguard Worker 
2579*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_INFO:
2580*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_INFO;
2581*cfb92d14SAndroid Build Coastguard Worker         break;
2582*cfb92d14SAndroid Build Coastguard Worker 
2583*cfb92d14SAndroid Build Coastguard Worker     case SPINEL_NCP_LOG_LEVEL_DEBUG:
2584*cfb92d14SAndroid Build Coastguard Worker         logLevel = OT_LOG_LEVEL_DEBG;
2585*cfb92d14SAndroid Build Coastguard Worker         break;
2586*cfb92d14SAndroid Build Coastguard Worker 
2587*cfb92d14SAndroid Build Coastguard Worker     default:
2588*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_INVALID_ARGS);
2589*cfb92d14SAndroid Build Coastguard Worker     }
2590*cfb92d14SAndroid Build Coastguard Worker 
2591*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(otLoggingSetLevel(logLevel));
2592*cfb92d14SAndroid Build Coastguard Worker 
2593*cfb92d14SAndroid Build Coastguard Worker exit:
2594*cfb92d14SAndroid Build Coastguard Worker     return error;
2595*cfb92d14SAndroid Build Coastguard Worker }
2596*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
2597*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2598*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE>(void)
2599*cfb92d14SAndroid Build Coastguard Worker {
2600*cfb92d14SAndroid Build Coastguard Worker     uint64_t timestampBase = 0;
2601*cfb92d14SAndroid Build Coastguard Worker     otError  error         = OT_ERROR_NONE;
2602*cfb92d14SAndroid Build Coastguard Worker     uint32_t currentTime   = otPlatAlarmMilliGetNow();
2603*cfb92d14SAndroid Build Coastguard Worker 
2604*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint64(timestampBase));
2605*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(timestampBase >= currentTime, error = OT_ERROR_INVALID_ARGS);
2606*cfb92d14SAndroid Build Coastguard Worker 
2607*cfb92d14SAndroid Build Coastguard Worker     mLogTimestampBase = timestampBase - currentTime;
2608*cfb92d14SAndroid Build Coastguard Worker 
2609*cfb92d14SAndroid Build Coastguard Worker exit:
2610*cfb92d14SAndroid Build Coastguard Worker     return error;
2611*cfb92d14SAndroid Build Coastguard Worker }
2612*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2613*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE>(void)
2614*cfb92d14SAndroid Build Coastguard Worker {
2615*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteUint64(mLogTimestampBase);
2616*cfb92d14SAndroid Build Coastguard Worker }
2617*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2618*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
2619*cfb92d14SAndroid Build Coastguard Worker {
2620*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_RADIO
2621*cfb92d14SAndroid Build Coastguard Worker     return EncodeChannelMask(otPlatRadioGetSupportedChannelMask(mInstance));
2622*cfb92d14SAndroid Build Coastguard Worker #else
2623*cfb92d14SAndroid Build Coastguard Worker     return EncodeChannelMask(otLinkGetSupportedChannelMask(mInstance));
2624*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_RADIO
2625*cfb92d14SAndroid Build Coastguard Worker }
2626*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2627*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>(void)
2628*cfb92d14SAndroid Build Coastguard Worker {
2629*cfb92d14SAndroid Build Coastguard Worker     return EncodeChannelMask(otPlatRadioGetPreferredChannelMask(mInstance));
2630*cfb92d14SAndroid Build Coastguard Worker }
2631*cfb92d14SAndroid Build Coastguard Worker 
2632*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
HandlePropertySet(void)2633*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RADIO_COEX_ENABLE>(void)
2634*cfb92d14SAndroid Build Coastguard Worker {
2635*cfb92d14SAndroid Build Coastguard Worker     bool    enabled;
2636*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
2637*cfb92d14SAndroid Build Coastguard Worker 
2638*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadBool(enabled));
2639*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetCoexEnabled(mInstance, enabled);
2640*cfb92d14SAndroid Build Coastguard Worker 
2641*cfb92d14SAndroid Build Coastguard Worker exit:
2642*cfb92d14SAndroid Build Coastguard Worker     return error;
2643*cfb92d14SAndroid Build Coastguard Worker }
2644*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2645*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RADIO_COEX_ENABLE>(void)
2646*cfb92d14SAndroid Build Coastguard Worker {
2647*cfb92d14SAndroid Build Coastguard Worker     return mEncoder.WriteBool(otPlatRadioIsCoexEnabled(mInstance));
2648*cfb92d14SAndroid Build Coastguard Worker }
2649*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyGet(void)2650*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RADIO_COEX_METRICS>(void)
2651*cfb92d14SAndroid Build Coastguard Worker {
2652*cfb92d14SAndroid Build Coastguard Worker     otRadioCoexMetrics coexMetrics;
2653*cfb92d14SAndroid Build Coastguard Worker     otError            error = otPlatRadioGetCoexMetrics(mInstance, &coexMetrics);
2654*cfb92d14SAndroid Build Coastguard Worker 
2655*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
2656*cfb92d14SAndroid Build Coastguard Worker     {
2657*cfb92d14SAndroid Build Coastguard Worker         error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
2658*cfb92d14SAndroid Build Coastguard Worker         ExitNow();
2659*cfb92d14SAndroid Build Coastguard Worker     }
2660*cfb92d14SAndroid Build Coastguard Worker 
2661*cfb92d14SAndroid Build Coastguard Worker     // Encode Tx Request related metrics
2662*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.OpenStruct());
2663*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxRequest));
2664*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantImmediate));
2665*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWait));
2666*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWaitActivated));
2667*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWaitTimeout));
2668*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantDeactivatedDuringRequest));
2669*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxDelayedGrant));
2670*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mAvgTxRequestToGrantTime));
2671*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.CloseStruct());
2672*cfb92d14SAndroid Build Coastguard Worker 
2673*cfb92d14SAndroid Build Coastguard Worker     // Encode Rx Request related metrics
2674*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.OpenStruct());
2675*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxRequest));
2676*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantImmediate));
2677*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWait));
2678*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWaitActivated));
2679*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWaitTimeout));
2680*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantDeactivatedDuringRequest));
2681*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxDelayedGrant));
2682*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mAvgRxRequestToGrantTime));
2683*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantNone));
2684*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.CloseStruct());
2685*cfb92d14SAndroid Build Coastguard Worker 
2686*cfb92d14SAndroid Build Coastguard Worker     // Encode common metrics
2687*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteBool(coexMetrics.mStopped));
2688*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumGrantGlitch));
2689*cfb92d14SAndroid Build Coastguard Worker 
2690*cfb92d14SAndroid Build Coastguard Worker exit:
2691*cfb92d14SAndroid Build Coastguard Worker     return error;
2692*cfb92d14SAndroid Build Coastguard Worker }
2693*cfb92d14SAndroid Build Coastguard Worker #endif
2694*cfb92d14SAndroid Build Coastguard Worker 
2695*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
DecodeLinkMetrics(otLinkMetrics * aMetrics,bool aAllowPduCount)2696*cfb92d14SAndroid Build Coastguard Worker otError NcpBase::DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount)
2697*cfb92d14SAndroid Build Coastguard Worker {
2698*cfb92d14SAndroid Build Coastguard Worker     otError error   = OT_ERROR_NONE;
2699*cfb92d14SAndroid Build Coastguard Worker     uint8_t metrics = 0;
2700*cfb92d14SAndroid Build Coastguard Worker 
2701*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(metrics));
2702*cfb92d14SAndroid Build Coastguard Worker 
2703*cfb92d14SAndroid Build Coastguard Worker     if (metrics & SPINEL_THREAD_LINK_METRIC_PDU_COUNT)
2704*cfb92d14SAndroid Build Coastguard Worker     {
2705*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(aAllowPduCount, error = OT_ERROR_INVALID_ARGS);
2706*cfb92d14SAndroid Build Coastguard Worker         aMetrics->mPduCount = true;
2707*cfb92d14SAndroid Build Coastguard Worker     }
2708*cfb92d14SAndroid Build Coastguard Worker 
2709*cfb92d14SAndroid Build Coastguard Worker     if (metrics & SPINEL_THREAD_LINK_METRIC_LQI)
2710*cfb92d14SAndroid Build Coastguard Worker     {
2711*cfb92d14SAndroid Build Coastguard Worker         aMetrics->mLqi = true;
2712*cfb92d14SAndroid Build Coastguard Worker     }
2713*cfb92d14SAndroid Build Coastguard Worker 
2714*cfb92d14SAndroid Build Coastguard Worker     if (metrics & SPINEL_THREAD_LINK_METRIC_LINK_MARGIN)
2715*cfb92d14SAndroid Build Coastguard Worker     {
2716*cfb92d14SAndroid Build Coastguard Worker         aMetrics->mLinkMargin = true;
2717*cfb92d14SAndroid Build Coastguard Worker     }
2718*cfb92d14SAndroid Build Coastguard Worker 
2719*cfb92d14SAndroid Build Coastguard Worker     if (metrics & SPINEL_THREAD_LINK_METRIC_RSSI)
2720*cfb92d14SAndroid Build Coastguard Worker     {
2721*cfb92d14SAndroid Build Coastguard Worker         aMetrics->mRssi = true;
2722*cfb92d14SAndroid Build Coastguard Worker     }
2723*cfb92d14SAndroid Build Coastguard Worker 
2724*cfb92d14SAndroid Build Coastguard Worker exit:
2725*cfb92d14SAndroid Build Coastguard Worker     return error;
2726*cfb92d14SAndroid Build Coastguard Worker }
2727*cfb92d14SAndroid Build Coastguard Worker #endif
2728*cfb92d14SAndroid Build Coastguard Worker 
2729*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
HandlePropertySet(void)2730*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_TARGET_POWER>(void)
2731*cfb92d14SAndroid Build Coastguard Worker {
2732*cfb92d14SAndroid Build Coastguard Worker     otError error;
2733*cfb92d14SAndroid Build Coastguard Worker     uint8_t channel;
2734*cfb92d14SAndroid Build Coastguard Worker     int16_t targetPower;
2735*cfb92d14SAndroid Build Coastguard Worker 
2736*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(channel));
2737*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt16(targetPower));
2738*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioSetChannelTargetPower(mInstance, channel, targetPower);
2739*cfb92d14SAndroid Build Coastguard Worker 
2740*cfb92d14SAndroid Build Coastguard Worker exit:
2741*cfb92d14SAndroid Build Coastguard Worker     return error;
2742*cfb92d14SAndroid Build Coastguard Worker }
2743*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertyInsert(void)2744*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_PHY_CALIBRATED_POWER>(void)
2745*cfb92d14SAndroid Build Coastguard Worker {
2746*cfb92d14SAndroid Build Coastguard Worker     otError        error;
2747*cfb92d14SAndroid Build Coastguard Worker     uint8_t        channel;
2748*cfb92d14SAndroid Build Coastguard Worker     int16_t        actualPower;
2749*cfb92d14SAndroid Build Coastguard Worker     const uint8_t *dataPtr;
2750*cfb92d14SAndroid Build Coastguard Worker     uint16_t       dataLen;
2751*cfb92d14SAndroid Build Coastguard Worker 
2752*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadUint8(channel));
2753*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadInt16(actualPower));
2754*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = mDecoder.ReadDataWithLen(dataPtr, dataLen));
2755*cfb92d14SAndroid Build Coastguard Worker     error = otPlatRadioAddCalibratedPower(mInstance, channel, actualPower, dataPtr, dataLen);
2756*cfb92d14SAndroid Build Coastguard Worker 
2757*cfb92d14SAndroid Build Coastguard Worker exit:
2758*cfb92d14SAndroid Build Coastguard Worker     return error;
2759*cfb92d14SAndroid Build Coastguard Worker }
2760*cfb92d14SAndroid Build Coastguard Worker 
HandlePropertySet(void)2761*cfb92d14SAndroid Build Coastguard Worker template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CALIBRATED_POWER>(void)
2762*cfb92d14SAndroid Build Coastguard Worker {
2763*cfb92d14SAndroid Build Coastguard Worker     return otPlatRadioClearCalibratedPowers(mInstance);
2764*cfb92d14SAndroid Build Coastguard Worker }
2765*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
2766*cfb92d14SAndroid Build Coastguard Worker 
2767*cfb92d14SAndroid Build Coastguard Worker } // namespace Ncp
2768*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
2769*cfb92d14SAndroid Build Coastguard Worker 
2770*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
2771*cfb92d14SAndroid Build Coastguard Worker // MARK: Peek/Poke delegate API
2772*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
2773*cfb92d14SAndroid Build Coastguard Worker 
2774*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
otNcpRegisterPeekPoke(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,otNcpDelegateAllowPeekPoke aAllowPokeDelegate)2775*cfb92d14SAndroid Build Coastguard Worker void otNcpRegisterPeekPoke(otNcpDelegateAllowPeekPoke aAllowPeekDelegate, otNcpDelegateAllowPeekPoke aAllowPokeDelegate)
2776*cfb92d14SAndroid Build Coastguard Worker {
2777*cfb92d14SAndroid Build Coastguard Worker     ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
2778*cfb92d14SAndroid Build Coastguard Worker 
2779*cfb92d14SAndroid Build Coastguard Worker     if (ncp != nullptr)
2780*cfb92d14SAndroid Build Coastguard Worker     {
2781*cfb92d14SAndroid Build Coastguard Worker         ncp->RegisterPeekPokeDelegates(aAllowPeekDelegate, aAllowPokeDelegate);
2782*cfb92d14SAndroid Build Coastguard Worker     }
2783*cfb92d14SAndroid Build Coastguard Worker }
2784*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
2785*cfb92d14SAndroid Build Coastguard Worker 
2786*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
2787*cfb92d14SAndroid Build Coastguard Worker // MARK: Virtual Datastream I/O (Public API)
2788*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
2789*cfb92d14SAndroid Build Coastguard Worker 
otNcpStreamWrite(int aStreamId,const uint8_t * aDataPtr,int aDataLen)2790*cfb92d14SAndroid Build Coastguard Worker otError otNcpStreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen)
2791*cfb92d14SAndroid Build Coastguard Worker {
2792*cfb92d14SAndroid Build Coastguard Worker     otError           error = OT_ERROR_INVALID_STATE;
2793*cfb92d14SAndroid Build Coastguard Worker     ot::Ncp::NcpBase *ncp   = ot::Ncp::NcpBase::GetNcpInstance();
2794*cfb92d14SAndroid Build Coastguard Worker 
2795*cfb92d14SAndroid Build Coastguard Worker     if (ncp != nullptr)
2796*cfb92d14SAndroid Build Coastguard Worker     {
2797*cfb92d14SAndroid Build Coastguard Worker         error = ncp->StreamWrite(aStreamId, aDataPtr, aDataLen);
2798*cfb92d14SAndroid Build Coastguard Worker     }
2799*cfb92d14SAndroid Build Coastguard Worker 
2800*cfb92d14SAndroid Build Coastguard Worker     return error;
2801*cfb92d14SAndroid Build Coastguard Worker }
2802*cfb92d14SAndroid Build Coastguard Worker 
2803*cfb92d14SAndroid Build Coastguard Worker #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_APP)
2804*cfb92d14SAndroid Build Coastguard Worker 
otPlatLog(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,...)2805*cfb92d14SAndroid Build Coastguard Worker extern "C" void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
2806*cfb92d14SAndroid Build Coastguard Worker {
2807*cfb92d14SAndroid Build Coastguard Worker     va_list           args;
2808*cfb92d14SAndroid Build Coastguard Worker     char              logString[OPENTHREAD_CONFIG_NCP_SPINEL_LOG_MAX_SIZE];
2809*cfb92d14SAndroid Build Coastguard Worker     ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
2810*cfb92d14SAndroid Build Coastguard Worker 
2811*cfb92d14SAndroid Build Coastguard Worker     va_start(args, aFormat);
2812*cfb92d14SAndroid Build Coastguard Worker 
2813*cfb92d14SAndroid Build Coastguard Worker     if (vsnprintf(logString, sizeof(logString), aFormat, args) > 0)
2814*cfb92d14SAndroid Build Coastguard Worker     {
2815*cfb92d14SAndroid Build Coastguard Worker         if (ncp != nullptr)
2816*cfb92d14SAndroid Build Coastguard Worker         {
2817*cfb92d14SAndroid Build Coastguard Worker             ncp->Log(aLogLevel, aLogRegion, logString);
2818*cfb92d14SAndroid Build Coastguard Worker         }
2819*cfb92d14SAndroid Build Coastguard Worker     }
2820*cfb92d14SAndroid Build Coastguard Worker 
2821*cfb92d14SAndroid Build Coastguard Worker     va_end(args);
2822*cfb92d14SAndroid Build Coastguard Worker }
2823*cfb92d14SAndroid Build Coastguard Worker 
2824*cfb92d14SAndroid Build Coastguard Worker #endif // (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_APP)
2825