• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2016, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * @file
30  *   This file contains definitions a spinel interface to the OpenThread stack.
31  */
32 
33 #ifndef NCP_BASE_HPP_
34 #define NCP_BASE_HPP_
35 
36 #include "openthread-core-config.h"
37 
38 #include "ncp/ncp_config.h"
39 
40 #if OPENTHREAD_MTD || OPENTHREAD_FTD
41 #include <openthread/ip6.h>
42 #else
43 #include <openthread/platform/radio.h>
44 #endif
45 #if OPENTHREAD_FTD
46 #include <openthread/thread_ftd.h>
47 #endif
48 #include <openthread/message.h>
49 #include <openthread/ncp.h>
50 #if OPENTHREAD_CONFIG_MULTI_RADIO
51 #include <openthread/multi_radio.h>
52 #endif
53 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
54 #include <openthread/srp_client.h>
55 #endif
56 
57 #include "changed_props_set.hpp"
58 #include "common/instance.hpp"
59 #include "common/tasklet.hpp"
60 #include "lib/spinel/spinel.h"
61 #include "lib/spinel/spinel_buffer.hpp"
62 #include "lib/spinel/spinel_decoder.hpp"
63 #include "lib/spinel/spinel_encoder.hpp"
64 
65 namespace ot {
66 namespace Ncp {
67 
68 class NcpBase
69 {
70 public:
71     enum
72     {
73         kSpinelCmdHeaderSize = 2, ///< Size of spinel command header (in bytes).
74         kSpinelPropIdSize    = 3, ///< Size of spinel property identifier (in bytes).
75     };
76 
77     /**
78      * This constructor creates and initializes an NcpBase instance.
79      *
80      * @param[in]  aInstance  The OpenThread instance structure.
81      *
82      */
83     explicit NcpBase(Instance *aInstance);
84 
85     /**
86      * This static method returns the pointer to the single NCP instance.
87      *
88      * @returns Pointer to the single NCP instance.
89      *
90      */
91     static NcpBase *GetNcpInstance(void);
92 
93     /**
94      * This method sends data to host via specific stream.
95      *
96      *
97      * @param[in]  aStreamId  A numeric identifier for the stream to write to.
98      *                        If set to '0', will default to the debug stream.
99      * @param[in]  aDataPtr   A pointer to the data to send on the stream.
100      *                        If aDataLen is non-zero, this param MUST NOT be nullptr.
101      * @param[in]  aDataLen   The number of bytes of data from aDataPtr to send.
102      *
103      * @retval OT_ERROR_NONE         The data was queued for delivery to the host.
104      * @retval OT_ERROR_BUSY         There are not enough resources to complete this
105      *                               request. This is usually a temporary condition.
106      * @retval OT_ERROR_INVALID_ARGS The given aStreamId was invalid.
107      *
108      */
109     otError StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen);
110 
111     /**
112      * This method send an OpenThread log message to host via `SPINEL_PROP_STREAM_LOG` property.
113      *
114      * @param[in] aLogLevel   The log level
115      * @param[in] aLogRegion  The log region
116      * @param[in] aLogString  The log string
117      *
118      */
119     void Log(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogString);
120 
121 #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
122     /**
123      * This method registers peek/poke delegate functions with NCP module.
124      *
125      * @param[in] aAllowPeekDelegate      Delegate function pointer for peek operation.
126      * @param[in] aAllowPokeDelegate      Delegate function pointer for poke operation.
127      *
128      */
129     void RegisterPeekPokeDelagates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,
130                                    otNcpDelegateAllowPeekPoke aAllowPokeDelegate);
131 #endif
132 
133 #if OPENTHREAD_MTD || OPENTHREAD_FTD
134 #if OPENTHREAD_CONFIG_LEGACY_ENABLE
135     /**
136      * This callback is invoked by the legacy stack to notify that a new
137      * legacy node did join the network.
138      *
139      * @param[in]   aExtAddr    The extended address of the joined node.
140      *
141      */
142     void HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
143 
144     /**
145      * This callback is invoked by the legacy stack to notify that the
146      * legacy ULA prefix has changed.
147      *
148      * param[in]    aUlaPrefix  The changed ULA prefix.
149      *
150      */
151     void HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
152 
153     /**
154      * This method registers a set of legacy handlers with NCP.
155      *
156      * @param[in] aHandlers    A pointer to a handler struct.
157      *
158      */
159     void RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers);
160 #endif
161 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
162 
163     /**
164      * This method is called by the framer whenever a framing error is detected.
165      */
166     void IncrementFrameErrorCounter(void);
167 
168     /**
169      * Called by the subclass to indicate when a frame has been received.
170      */
171     void HandleReceive(const uint8_t *aBuf, uint16_t aBufLength);
172 
173     /**
174      * Called by the subclass to learn when the host wake operation must be issued.
175      */
176     bool ShouldWakeHost(void);
177 
178     /**
179      * Called by the subclass to learn when the transfer to the host should be deferred.
180      */
181     bool ShouldDeferHostSend(void);
182 
183 protected:
184     typedef otError (NcpBase::*PropertyHandler)(void);
185 
186     /**
187      * This enumeration represents the `ResponseEntry` type.
188      *
189      */
190     enum ResponseType
191     {
192         kResponseTypeGet = 0,    ///< Response entry is for a `VALUE_GET` command.
193         kResponseTypeSet,        ///< Response entry is for a `VALUE_SET` command.
194         kResponseTypeLastStatus, ///< Response entry is a `VALUE_IS(LAST_STATUS)`.
195     };
196 
197     /**
198      * This struct represents a spinel response entry.
199      *
200      */
201     struct ResponseEntry
202     {
203         uint8_t      mTid : 4;              ///< Spinel transaction id.
204         bool         mIsInUse : 1;          ///< `true` if this entry is in use, `false` otherwise.
205         ResponseType mType : 2;             ///< Response type.
206         uint32_t     mPropKeyOrStatus : 24; ///< 3 bytes for either property key or spinel status.
207     };
208 
209     struct HandlerEntry
210     {
211         spinel_prop_key_t        mKey;
212         NcpBase::PropertyHandler mHandler;
213     };
214 
215     Spinel::Buffer::FrameTag GetLastOutboundFrameTag(void);
216 
217     otError HandleCommand(uint8_t aHeader);
218 
219 #if __cplusplus >= 201103L
220     static constexpr bool AreHandlerEntriesSorted(const HandlerEntry *aHandlerEntries, size_t aSize);
221 #endif
222 
223     static PropertyHandler FindPropertyHandler(const HandlerEntry *aHandlerEntries,
224                                                size_t              aSize,
225                                                spinel_prop_key_t   aKey);
226     static PropertyHandler FindGetPropertyHandler(spinel_prop_key_t aKey);
227     static PropertyHandler FindSetPropertyHandler(spinel_prop_key_t aKey);
228     static PropertyHandler FindInsertPropertyHandler(spinel_prop_key_t aKey);
229     static PropertyHandler FindRemovePropertyHandler(spinel_prop_key_t aKey);
230 
231     bool    HandlePropertySetForSpecialProperties(uint8_t aHeader, spinel_prop_key_t aKey, otError &aError);
232     otError HandleCommandPropertySet(uint8_t aHeader, spinel_prop_key_t aKey);
233     otError HandleCommandPropertyInsertRemove(uint8_t aHeader, spinel_prop_key_t aKey, unsigned int aCommand);
234 
235     otError WriteLastStatusFrame(uint8_t aHeader, spinel_status_t aLastStatus);
236     otError WritePropertyValueIsFrame(uint8_t aHeader, spinel_prop_key_t aPropKey, bool aIsGetResponse = true);
237     otError WritePropertyValueInsertedRemovedFrame(uint8_t           aHeader,
238                                                    unsigned int      aResponseCommand,
239                                                    spinel_prop_key_t aPropKey,
240                                                    const uint8_t *   aValuePtr,
241                                                    uint16_t          aValueLen);
242 
243     otError SendQueuedResponses(void);
IsResponseQueueEmpty(void) const244     bool    IsResponseQueueEmpty(void) const { return (mResponseQueueHead == mResponseQueueTail); }
245     otError EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned int aPropKeyOrStatus);
246 
PrepareGetResponse(uint8_t aHeader,spinel_prop_key_t aPropKey)247     otError PrepareGetResponse(uint8_t aHeader, spinel_prop_key_t aPropKey)
248     {
249         return EnqueueResponse(aHeader, kResponseTypeGet, aPropKey);
250     }
PrepareSetResponse(uint8_t aHeader,spinel_prop_key_t aPropKey)251     otError PrepareSetResponse(uint8_t aHeader, spinel_prop_key_t aPropKey)
252     {
253         return EnqueueResponse(aHeader, kResponseTypeSet, aPropKey);
254     }
PrepareLastStatusResponse(uint8_t aHeader,spinel_status_t aStatus)255     otError PrepareLastStatusResponse(uint8_t aHeader, spinel_status_t aStatus)
256     {
257         return EnqueueResponse(aHeader, kResponseTypeLastStatus, aStatus);
258     }
259 
260     static uint8_t GetWrappedResponseQueueIndex(uint8_t aPosition);
261 
262     static void UpdateChangedProps(Tasklet &aTasklet);
263     void        UpdateChangedProps(void);
264 
265     static void HandleFrameRemovedFromNcpBuffer(void *                   aContext,
266                                                 Spinel::Buffer::FrameTag aFrameTag,
267                                                 Spinel::Buffer::Priority aPriority,
268                                                 Spinel::Buffer *         aNcpBuffer);
269     void        HandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag);
270 
271     otError EncodeChannelMask(uint32_t aChannelMask);
272     otError DecodeChannelMask(uint32_t &aChannelMask);
273 
274 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
275     otError PackRadioFrame(otRadioFrame *aFrame, otError aError);
276 
277     static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
278     void        LinkRawReceiveDone(otRadioFrame *aFrame, otError aError);
279 
280     static void LinkRawTransmitDone(otInstance *  aInstance,
281                                     otRadioFrame *aFrame,
282                                     otRadioFrame *aAckFrame,
283                                     otError       aError);
284     void        LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
285 
286     static void LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi);
287     void        LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi);
288 
289 #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
290 
291 #if OPENTHREAD_MTD || OPENTHREAD_FTD
292     static void HandleStateChanged(otChangedFlags aFlags, void *aContext);
293     void        ProcessThreadChangedFlags(void);
294 
295     static void HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
296     void        HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx);
297 
298     static void HandleTimeSyncUpdate(void *aContext);
299     void        HandleTimeSyncUpdate(void);
300 
301 #if OPENTHREAD_FTD
302     static void HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry);
303     void        HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry);
304 
305     static void HandleParentResponseInfo(otThreadParentResponseInfo *aInfo, void *aContext);
306     void        HandleParentResponseInfo(const otThreadParentResponseInfo &aInfo);
307 #endif
308 
309     static void HandleDatagramFromStack(otMessage *aMessage, void *aContext);
310     void        HandleDatagramFromStack(otMessage *aMessage);
311 
312     otError SendQueuedDatagramMessages(void);
313     otError SendDatagramMessage(otMessage *aMessage);
314 
315     static void HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext);
316     void        HandleActiveScanResult(otActiveScanResult *aResult);
317 
318     static void HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext);
319     void        HandleEnergyScanResult(otEnergyScanResult *aResult);
320 
321     static void HandleJamStateChange_Jump(bool aJamState, void *aContext);
322     void        HandleJamStateChange(bool aJamState);
323 
324 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
325     static void HandleCommissionerEnergyReport_Jump(uint32_t       aChannelMask,
326                                                     const uint8_t *aEnergyData,
327                                                     uint8_t        aLength,
328                                                     void *         aContext);
329     void        HandleCommissionerEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyData, uint8_t aLength);
330 
331     static void HandleCommissionerPanIdConflict_Jump(uint16_t aPanId, uint32_t aChannelMask, void *aContext);
332     void        HandleCommissionerPanIdConflict(uint16_t aPanId, uint32_t aChannelMask);
333 #endif
334 
335 #if OPENTHREAD_CONFIG_JOINER_ENABLE
336     static void HandleJoinerCallback_Jump(otError aError, void *aContext);
337     void        HandleJoinerCallback(otError aError);
338 #endif
339 
340 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
341     static void HandleLinkMetricsReport_Jump(const otIp6Address *       aSource,
342                                              const otLinkMetricsValues *aMetricsValues,
343                                              uint8_t                    aStatus,
344                                              void *                     aContext);
345 
346     void HandleLinkMetricsReport(const otIp6Address *       aSource,
347                                  const otLinkMetricsValues *aMetricsValues,
348                                  uint8_t                    aStatus);
349 
350     static void HandleLinkMetricsMgmtResponse_Jump(const otIp6Address *aSource, uint8_t aStatus, void *aContext);
351 
352     void HandleLinkMetricsMgmtResponse(const otIp6Address *aSource, uint8_t aStatus);
353 
354     static void HandleLinkMetricsEnhAckProbingIeReport_Jump(otShortAddress             aShortAddress,
355                                                             const otExtAddress *       aExtAddress,
356                                                             const otLinkMetricsValues *aMetricsValues,
357                                                             void *                     aContext);
358 
359     void HandleLinkMetricsEnhAckProbingIeReport(otShortAddress             aShortAddress,
360                                                 const otExtAddress *       aExtAddress,
361                                                 const otLinkMetricsValues *aMetricsValues);
362 #endif
363 
364     static void HandleMlrRegResult_Jump(void *              aContext,
365                                         otError             aError,
366                                         uint8_t             aMlrStatus,
367                                         const otIp6Address *aFailedAddresses,
368                                         uint8_t             aFailedAddressNum);
369     void        HandleMlrRegResult(otError             aError,
370                                    uint8_t             aMlrStatus,
371                                    const otIp6Address *aFailedAddresses,
372                                    uint8_t             aFailedAddressNum);
373 
374     otError EncodeOperationalDataset(const otOperationalDataset &aDataset);
375 
376     otError DecodeOperationalDataset(otOperationalDataset &aDataset,
377                                      const uint8_t **      aTlvs             = nullptr,
378                                      uint8_t *             aTlvsLength       = nullptr,
379                                      const otIp6Address ** aDestIpAddress    = nullptr,
380                                      bool                  aAllowEmptyValues = false);
381 
382     otError EncodeNeighborInfo(const otNeighborInfo &aNeighborInfo);
383 #if OPENTHREAD_CONFIG_MULTI_RADIO
384     otError EncodeNeighborMultiRadioInfo(uint32_t aSpinelRadioLink, const otRadioLinkInfo &aInfo);
385 #endif
386 
387 #if OPENTHREAD_FTD
388     otError EncodeChildInfo(const otChildInfo &aChildInfo);
389 #endif
390 
391 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
392     otError EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues);
393 #endif
394 
395 #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
396     static void HandleUdpForwardStream(otMessage *   aMessage,
397                                        uint16_t      aPeerPort,
398                                        otIp6Address *aPeerAddr,
399                                        uint16_t      aSockPort,
400                                        void *        aContext);
401     void HandleUdpForwardStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort);
402 #endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
403 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
404 
405 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
406     otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount);
407 #endif
408 
409     otError CommandHandler_NOOP(uint8_t aHeader);
410     otError CommandHandler_RESET(uint8_t aHeader);
411     // Combined command handler for `VALUE_GET`, `VALUE_SET`, `VALUE_INSERT` and `VALUE_REMOVE`.
412     otError CommandHandler_PROP_VALUE_update(uint8_t aHeader, unsigned int aCommand);
413 #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
414     otError CommandHandler_PEEK(uint8_t aHeader);
415     otError CommandHandler_POKE(uint8_t aHeader);
416 #endif
417 #if OPENTHREAD_MTD || OPENTHREAD_FTD
418     otError CommandHandler_NET_CLEAR(uint8_t aHeader);
419 #endif
420 
421     // ----------------------------------------------------------------------------
422     // Property Handlers
423     // ----------------------------------------------------------------------------
424     //
425     // There are 4 types of property handlers for "get", "set", "insert", and
426     // "remove" commands.
427     //
428     // "Get" handlers should get/retrieve the property value and then encode and
429     // write the value into the NCP buffer. If the "get" operation itself fails,
430     // "get" handler should write a `LAST_STATUS` with the error status into the NCP
431     // buffer. The `otError` returned from a "get" handler is the error of writing
432     // into the NCP buffer (e.g., running out buffer), and not of the "get" operation
433     // itself.
434     //
435     // "Set/Insert/Remove" handlers should first decode/parse the value from the
436     // input Spinel frame and then perform the corresponding set/insert/remove
437     // operation. They are not responsible for preparing the Spinel response and
438     // therefore should not write anything to the NCP buffer. The `otError` returned
439     // from a "set/insert/remove" handler indicates the error in either parsing of
440     // the input or the error of set/insert/remove operation.
441     //
442     // The corresponding command handler (e.g., `HandleCommandPropertySet()` for
443     // `VALUE_SET` command) will take care of preparing the Spinel response after
444     // invoking the "set/insert/remove" handler for a given property. For example,
445     // for a `VALUE_SET` command, if the "set" handler returns an error, then a
446     // `LAST_STATUS` update response is prepared, otherwise on success the "get"
447     // handler for the property is used to prepare a `VALUE_IS` Spinel response (in
448     // cases where there is no "get" handler for the property, the input value is
449     // echoed in the response).
450     //
451     // Few properties require special treatment where the response needs to be
452     // prepared directly in the  "set"  handler (e.g., `HOST_POWER_STATE` or
453     // `NEST_STREAM_MFG`). These properties have a different handler method format
454     // (they expect `aHeader` as an input argument) and are processed separately in
455     // `HandleCommandPropertySet()`.
456 
457     template <spinel_prop_key_t aKey> otError HandlePropertyGet(void);
458     template <spinel_prop_key_t aKey> otError HandlePropertySet(void);
459     template <spinel_prop_key_t aKey> otError HandlePropertyInsert(void);
460     template <spinel_prop_key_t aKey> otError HandlePropertyRemove(void);
461 
462     // --------------------------------------------------------------------------
463     // Property "set" handlers for special properties for which the spinel
464     // response needs to be created from within the set handler.
465 
466     otError HandlePropertySet_SPINEL_PROP_HOST_POWER_STATE(uint8_t aHeader);
467 
468 #if OPENTHREAD_CONFIG_DIAG_ENABLE
469     static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <=
470                       OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE - kSpinelCmdHeaderSize - kSpinelPropIdSize,
471                   "diag output buffer should be smaller than NCP HDLC tx buffer");
472 
473     otError HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader);
474 #endif
475 
476 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
477     otError HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(uint8_t aHeader);
478     otError HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader);
479 #endif // OPENTHREAD_FTD
480 
481 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
482     otError DecodeStreamRawTxRequest(otRadioFrame &aFrame);
483     otError HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader);
484 #endif
485 
486     void ResetCounters(void);
487 
488 #if OPENTHREAD_CONFIG_LEGACY_ENABLE
489     void StartLegacy(void);
490     void StopLegacy(void);
491 #else
StartLegacy(void)492     void StartLegacy(void) {}
StopLegacy(void)493     void StopLegacy(void) {}
494 #endif
495 
496     static uint8_t      ConvertLogLevel(otLogLevel aLogLevel);
497     static unsigned int ConvertLogRegion(otLogRegion aLogRegion);
498 
499 #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
500     /**
501      * This method defines a vendor "command handler" hook to process vendor-specific spinel commands.
502      *
503      * @param[in] aHeader   The spinel frame header.
504      * @param[in] aCommand  The spinel command key.
505      *
506      * @retval OT_ERROR_NONE     The response is prepared.
507      * @retval OT_ERROR_NO_BUFS  Out of buffer while preparing the response.
508      *
509      */
510     otError VendorCommandHandler(uint8_t aHeader, unsigned int aCommand);
511 
512     /**
513      * This method is a callback which mirrors `NcpBase::HandleFrameRemovedFromNcpBuffer()`. It is called when a
514      * spinel frame is sent and removed from NCP buffer.
515      *
516      * (a) This can be used to track and verify that a vendor spinel frame response is delivered to the host (tracking
517      *     the frame using its tag).
518      *
519      * (b) It indicates that NCP buffer space is now available (since a spinel frame is removed). This can be used to
520      *     implement mechanisms to re-send a failed/pending response or an async spinel frame.
521      *
522      * @param[in] aFrameTag    The tag of the frame removed from NCP buffer.
523      *
524      */
525     void VendorHandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag);
526 
527     /**
528      * This method defines a vendor "get property handler" hook to process vendor spinel properties.
529      *
530      * The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "get" operation for the
531      * given property key. Otherwise, the vendor handler should behave like other property get handlers, i.e., it
532      * should retrieve the property value and then encode and write the value into the NCP buffer. If the "get"
533      * operation itself fails, handler should write a `LAST_STATUS` with the error status into the NCP buffer.
534      *
535      * @param[in] aPropKey            The spinel property key.
536      *
537      * @retval OT_ERROR_NONE          Successfully retrieved the property value and prepared the response.
538      * @retval OT_ERROR_NOT_FOUND     Does not support the given property key.
539      * @retval OT_ERROR_NO_BUFS       Out of buffer while preparing the response.
540      *
541      */
542     otError VendorGetPropertyHandler(spinel_prop_key_t aPropKey);
543 
544     /**
545      * This method defines a vendor "set property handler" hook to process vendor spinel properties.
546      *
547      * The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "set" operation for the
548      * given property key. Otherwise, the vendor handler should behave like other property set handlers, i.e., it
549      * should first decode the value from the input spinel frame and then perform the corresponding set operation. The
550      * handler should not prepare the spinel response and therefore should not write anything to the NCP buffer. The
551      * `otError` returned from handler (other than `OT_ERROR_NOT_FOUND`) indicates the error in either parsing of the
552      * input or the error of the set operation. In case of a successful "set", `NcpBase` set command handler will call
553      * the `VendorGetPropertyHandler()` for the same property key to prepare the response.
554      *
555      * @param[in] aPropKey  The spinel property key.
556      *
557      * @returns OT_ERROR_NOT_FOUND if it does not support the given property key, otherwise the error in either parsing
558      *          of the input or the "set" operation.
559      *
560      */
561     otError VendorSetPropertyHandler(spinel_prop_key_t aPropKey);
562 
563 #endif // OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
564 
565 protected:
566     static NcpBase *       sNcpInstance;
567     static spinel_status_t ThreadErrorToSpinelStatus(otError aError);
568     static uint8_t         LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aDeviceType, bool aNetworkData);
569     Instance *             mInstance;
570     Spinel::Buffer         mTxFrameBuffer;
571     Spinel::Encoder        mEncoder;
572     Spinel::Decoder        mDecoder;
573     bool                   mHostPowerStateInProgress;
574 
575     enum
576     {
577         kTxBufferSize       = OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE, // Tx Buffer size (used by mTxFrameBuffer).
578         kResponseQueueSize  = OPENTHREAD_CONFIG_NCP_SPINEL_RESPONSE_QUEUE_SIZE,
579         kInvalidScanChannel = -1, // Invalid scan channel.
580     };
581 
582     spinel_status_t mLastStatus;
583     uint32_t        mScanChannelMask;
584     uint16_t        mScanPeriod;
585     bool            mDiscoveryScanJoinerFlag;
586     bool            mDiscoveryScanEnableFiltering;
587     uint16_t        mDiscoveryScanPanId;
588 
589     Tasklet         mUpdateChangedPropsTask;
590     uint32_t        mThreadChangedFlags;
591     ChangedPropsSet mChangedPropsSet;
592 
593     spinel_host_power_state_t mHostPowerState;
594     Spinel::Buffer::FrameTag  mHostPowerReplyFrameTag;
595     uint8_t                   mHostPowerStateHeader;
596 
597 #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
598     otNcpDelegateAllowPeekPoke mAllowPeekDelegate;
599     otNcpDelegateAllowPeekPoke mAllowPokeDelegate;
600 #endif
601 
602     uint8_t mTxBuffer[kTxBufferSize];
603 
604     spinel_tid_t mNextExpectedTid;
605 
606     uint8_t       mResponseQueueHead;
607     uint8_t       mResponseQueueTail;
608     ResponseEntry mResponseQueue[kResponseQueueSize];
609 
610     bool mAllowLocalNetworkDataChange;
611     bool mRequireJoinExistingNetwork;
612     bool mIsRawStreamEnabled;
613     bool mPcapEnabled;
614     bool mDisableStreamWrite;
615     bool mShouldEmitChildTableUpdate;
616 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
617     bool mAllowLocalServerDataChange;
618 #endif
619 
620 #if OPENTHREAD_FTD
621 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
622     otExtAddress mSteeringDataAddress;
623 #endif
624     uint8_t mPreferredRouteId;
625 #endif
626 
627 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
628     uint8_t mCurTransmitTID;
629     int8_t  mCurScanChannel;
630     bool    mSrcMatchEnabled;
631 #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
632 
633 #if OPENTHREAD_MTD || OPENTHREAD_FTD
634     otMessageQueue mMessageQueue;
635 
636     uint32_t mInboundSecureIpFrameCounter;    // Number of secure inbound data/IP frames.
637     uint32_t mInboundInsecureIpFrameCounter;  // Number of insecure inbound data/IP frames.
638     uint32_t mOutboundSecureIpFrameCounter;   // Number of secure outbound data/IP frames.
639     uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames.
640     uint32_t mDroppedOutboundIpFrameCounter;  // Number of dropped outbound data/IP frames.
641     uint32_t mDroppedInboundIpFrameCounter;   // Number of dropped inbound data/IP frames.
642 
643 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
644     enum : uint8_t
645     {
646         kSrpClientMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES,
647     };
648 
649     otError EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo);
650     otError EncodeSrpClientServices(const otSrpClientService *aServices);
651 
652     static void HandleSrpClientCallback(otError                    aError,
653                                         const otSrpClientHostInfo *aHostInfo,
654                                         const otSrpClientService * aServices,
655                                         const otSrpClientService * aRemovedServices,
656                                         void *                     aContext);
657     void        HandleSrpClientCallback(otError                    aError,
658                                         const otSrpClientHostInfo *aHostInfo,
659                                         const otSrpClientService * aServices,
660                                         const otSrpClientService * aRemovedServices);
661 
662     bool mSrpClientCallbackEnabled;
663 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
664 
665 #if OPENTHREAD_CONFIG_LEGACY_ENABLE
666     const otNcpLegacyHandlers *mLegacyHandlers;
667     uint8_t                    mLegacyUlaPrefix[OT_NCP_LEGACY_ULA_PREFIX_LENGTH];
668     otExtAddress               mLegacyLastJoinedNode;
669     bool                       mLegacyNodeDidJoin;
670 #endif
671 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
672 
673     uint32_t mFramingErrorCounter;          // Number of improperly formed received spinel frames.
674     uint32_t mRxSpinelFrameCounter;         // Number of received (inbound) spinel frames.
675     uint32_t mRxSpinelOutOfOrderTidCounter; // Number of out of order received spinel frames (tid increase > 1).
676     uint32_t mTxSpinelFrameCounter;         // Number of sent (outbound) spinel frames.
677 
678     bool mDidInitialUpdates;
679 
680     uint64_t mLogTimestampBase; // Timestamp base used for logging
681 };
682 
683 } // namespace Ncp
684 } // namespace ot
685 
686 #endif // NCP_BASE_HPP_
687