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 RegisterPeekPokeDelegates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate, 130 otNcpDelegateAllowPeekPoke aAllowPokeDelegate); 131 #endif 132 133 /** 134 * This method is called by the framer whenever a framing error is detected. 135 */ 136 void IncrementFrameErrorCounter(void); 137 138 /** 139 * Called by the subclass to indicate when a frame has been received. 140 */ 141 void HandleReceive(const uint8_t *aBuf, uint16_t aBufLength); 142 143 /** 144 * Called by the subclass to learn when the host wake operation must be issued. 145 */ 146 bool ShouldWakeHost(void); 147 148 /** 149 * Called by the subclass to learn when the transfer to the host should be deferred. 150 */ 151 bool ShouldDeferHostSend(void); 152 153 protected: 154 typedef otError (NcpBase::*PropertyHandler)(void); 155 156 /** 157 * This enumeration represents the `ResponseEntry` type. 158 * 159 */ 160 enum ResponseType 161 { 162 kResponseTypeGet = 0, ///< Response entry is for a `VALUE_GET` command. 163 kResponseTypeSet, ///< Response entry is for a `VALUE_SET` command. 164 kResponseTypeLastStatus, ///< Response entry is a `VALUE_IS(LAST_STATUS)`. 165 }; 166 167 /** 168 * This struct represents a spinel response entry. 169 * 170 */ 171 struct ResponseEntry 172 { 173 uint8_t mTid : 4; ///< Spinel transaction id. 174 bool mIsInUse : 1; ///< `true` if this entry is in use, `false` otherwise. 175 ResponseType mType : 2; ///< Response type. 176 uint32_t mPropKeyOrStatus : 24; ///< 3 bytes for either property key or spinel status. 177 }; 178 179 struct HandlerEntry 180 { 181 spinel_prop_key_t mKey; 182 NcpBase::PropertyHandler mHandler; 183 }; 184 185 Spinel::Buffer::FrameTag GetLastOutboundFrameTag(void); 186 187 otError HandleCommand(uint8_t aHeader); 188 189 #if __cplusplus >= 201103L 190 static constexpr bool AreHandlerEntriesSorted(const HandlerEntry *aHandlerEntries, size_t aSize); 191 #endif 192 193 static PropertyHandler FindPropertyHandler(const HandlerEntry *aHandlerEntries, 194 size_t aSize, 195 spinel_prop_key_t aKey); 196 static PropertyHandler FindGetPropertyHandler(spinel_prop_key_t aKey); 197 static PropertyHandler FindSetPropertyHandler(spinel_prop_key_t aKey); 198 static PropertyHandler FindInsertPropertyHandler(spinel_prop_key_t aKey); 199 static PropertyHandler FindRemovePropertyHandler(spinel_prop_key_t aKey); 200 201 bool HandlePropertySetForSpecialProperties(uint8_t aHeader, spinel_prop_key_t aKey, otError &aError); 202 otError HandleCommandPropertySet(uint8_t aHeader, spinel_prop_key_t aKey); 203 otError HandleCommandPropertyInsertRemove(uint8_t aHeader, spinel_prop_key_t aKey, unsigned int aCommand); 204 205 otError WriteLastStatusFrame(uint8_t aHeader, spinel_status_t aLastStatus); 206 otError WritePropertyValueIsFrame(uint8_t aHeader, spinel_prop_key_t aPropKey, bool aIsGetResponse = true); 207 otError WritePropertyValueInsertedRemovedFrame(uint8_t aHeader, 208 unsigned int aResponseCommand, 209 spinel_prop_key_t aPropKey, 210 const uint8_t *aValuePtr, 211 uint16_t aValueLen); 212 213 otError SendQueuedResponses(void); IsResponseQueueEmpty(void) const214 bool IsResponseQueueEmpty(void) const { return (mResponseQueueHead == mResponseQueueTail); } 215 otError EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned int aPropKeyOrStatus); 216 PrepareGetResponse(uint8_t aHeader,spinel_prop_key_t aPropKey)217 otError PrepareGetResponse(uint8_t aHeader, spinel_prop_key_t aPropKey) 218 { 219 return EnqueueResponse(aHeader, kResponseTypeGet, aPropKey); 220 } PrepareSetResponse(uint8_t aHeader,spinel_prop_key_t aPropKey)221 otError PrepareSetResponse(uint8_t aHeader, spinel_prop_key_t aPropKey) 222 { 223 return EnqueueResponse(aHeader, kResponseTypeSet, aPropKey); 224 } PrepareLastStatusResponse(uint8_t aHeader,spinel_status_t aStatus)225 otError PrepareLastStatusResponse(uint8_t aHeader, spinel_status_t aStatus) 226 { 227 return EnqueueResponse(aHeader, kResponseTypeLastStatus, aStatus); 228 } 229 230 static uint8_t GetWrappedResponseQueueIndex(uint8_t aPosition); 231 232 static void UpdateChangedProps(Tasklet &aTasklet); 233 void UpdateChangedProps(void); 234 235 static void HandleFrameRemovedFromNcpBuffer(void *aContext, 236 Spinel::Buffer::FrameTag aFrameTag, 237 Spinel::Buffer::Priority aPriority, 238 Spinel::Buffer *aNcpBuffer); 239 void HandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag); 240 241 otError EncodeChannelMask(uint32_t aChannelMask); 242 otError DecodeChannelMask(uint32_t &aChannelMask); 243 244 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE 245 otError PackRadioFrame(otRadioFrame *aFrame, otError aError); 246 247 static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError); 248 void LinkRawReceiveDone(otRadioFrame *aFrame, otError aError); 249 250 static void LinkRawTransmitDone(otInstance *aInstance, 251 otRadioFrame *aFrame, 252 otRadioFrame *aAckFrame, 253 otError aError); 254 void LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError); 255 256 static void LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi); 257 void LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi); 258 259 #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE 260 261 #if OPENTHREAD_MTD || OPENTHREAD_FTD 262 static void HandleStateChanged(otChangedFlags aFlags, void *aContext); 263 void ProcessThreadChangedFlags(void); 264 265 static void HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx, void *aContext); 266 void HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx); 267 268 static void HandleTimeSyncUpdate(void *aContext); 269 void HandleTimeSyncUpdate(void); 270 271 #if OPENTHREAD_FTD 272 static void HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry); 273 void HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry); 274 275 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE 276 static void HandleParentResponseInfo(otThreadParentResponseInfo *aInfo, void *aContext); 277 void HandleParentResponseInfo(const otThreadParentResponseInfo &aInfo); 278 #endif 279 #endif 280 281 static void HandleDatagramFromStack(otMessage *aMessage, void *aContext); 282 void HandleDatagramFromStack(otMessage *aMessage); 283 284 otError SendQueuedDatagramMessages(void); 285 otError SendDatagramMessage(otMessage *aMessage); 286 287 static void HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext); 288 void HandleActiveScanResult(otActiveScanResult *aResult); 289 290 static void HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext); 291 void HandleEnergyScanResult(otEnergyScanResult *aResult); 292 293 static void HandleJamStateChange_Jump(bool aJamState, void *aContext); 294 void HandleJamStateChange(bool aJamState); 295 296 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 297 static void HandleCommissionerEnergyReport_Jump(uint32_t aChannelMask, 298 const uint8_t *aEnergyData, 299 uint8_t aLength, 300 void *aContext); 301 void HandleCommissionerEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyData, uint8_t aLength); 302 303 static void HandleCommissionerPanIdConflict_Jump(uint16_t aPanId, uint32_t aChannelMask, void *aContext); 304 void HandleCommissionerPanIdConflict(uint16_t aPanId, uint32_t aChannelMask); 305 #endif 306 307 #if OPENTHREAD_CONFIG_JOINER_ENABLE 308 static void HandleJoinerCallback_Jump(otError aError, void *aContext); 309 void HandleJoinerCallback(otError aError); 310 #endif 311 312 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 313 static void HandleLinkMetricsReport_Jump(const otIp6Address *aSource, 314 const otLinkMetricsValues *aMetricsValues, 315 uint8_t aStatus, 316 void *aContext); 317 318 void HandleLinkMetricsReport(const otIp6Address *aSource, 319 const otLinkMetricsValues *aMetricsValues, 320 uint8_t aStatus); 321 322 static void HandleLinkMetricsMgmtResponse_Jump(const otIp6Address *aSource, uint8_t aStatus, void *aContext); 323 324 void HandleLinkMetricsMgmtResponse(const otIp6Address *aSource, uint8_t aStatus); 325 326 static void HandleLinkMetricsEnhAckProbingIeReport_Jump(otShortAddress aShortAddress, 327 const otExtAddress *aExtAddress, 328 const otLinkMetricsValues *aMetricsValues, 329 void *aContext); 330 331 void HandleLinkMetricsEnhAckProbingIeReport(otShortAddress aShortAddress, 332 const otExtAddress *aExtAddress, 333 const otLinkMetricsValues *aMetricsValues); 334 #endif 335 336 static void HandleMlrRegResult_Jump(void *aContext, 337 otError aError, 338 uint8_t aMlrStatus, 339 const otIp6Address *aFailedAddresses, 340 uint8_t aFailedAddressNum); 341 void HandleMlrRegResult(otError aError, 342 uint8_t aMlrStatus, 343 const otIp6Address *aFailedAddresses, 344 uint8_t aFailedAddressNum); 345 346 otError EncodeOperationalDataset(const otOperationalDataset &aDataset); 347 348 otError DecodeOperationalDataset(otOperationalDataset &aDataset, 349 const uint8_t **aTlvs = nullptr, 350 uint8_t *aTlvsLength = nullptr, 351 const otIp6Address **aDestIpAddress = nullptr, 352 bool aAllowEmptyValues = false); 353 354 otError EncodeNeighborInfo(const otNeighborInfo &aNeighborInfo); 355 #if OPENTHREAD_CONFIG_MULTI_RADIO 356 otError EncodeNeighborMultiRadioInfo(uint32_t aSpinelRadioLink, const otRadioLinkInfo &aInfo); 357 #endif 358 359 #if OPENTHREAD_FTD 360 otError EncodeChildInfo(const otChildInfo &aChildInfo); 361 #endif 362 363 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 364 otError EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues); 365 #endif 366 367 #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 368 static void HandleUdpForwardStream(otMessage *aMessage, 369 uint16_t aPeerPort, 370 otIp6Address *aPeerAddr, 371 uint16_t aSockPort, 372 void *aContext); 373 void HandleUdpForwardStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort); 374 #endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 375 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD 376 377 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 378 otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount); 379 #endif 380 381 otError CommandHandler_NOOP(uint8_t aHeader); 382 otError CommandHandler_RESET(uint8_t aHeader); 383 // Combined command handler for `VALUE_GET`, `VALUE_SET`, `VALUE_INSERT` and `VALUE_REMOVE`. 384 otError CommandHandler_PROP_VALUE_update(uint8_t aHeader, unsigned int aCommand); 385 #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE 386 otError CommandHandler_PEEK(uint8_t aHeader); 387 otError CommandHandler_POKE(uint8_t aHeader); 388 #endif 389 #if OPENTHREAD_MTD || OPENTHREAD_FTD 390 otError CommandHandler_NET_CLEAR(uint8_t aHeader); 391 #endif 392 393 // ---------------------------------------------------------------------------- 394 // Property Handlers 395 // ---------------------------------------------------------------------------- 396 // 397 // There are 4 types of property handlers for "get", "set", "insert", and 398 // "remove" commands. 399 // 400 // "Get" handlers should get/retrieve the property value and then encode and 401 // write the value into the NCP buffer. If the "get" operation itself fails, 402 // "get" handler should write a `LAST_STATUS` with the error status into the NCP 403 // buffer. The `otError` returned from a "get" handler is the error of writing 404 // into the NCP buffer (e.g., running out buffer), and not of the "get" operation 405 // itself. 406 // 407 // "Set/Insert/Remove" handlers should first decode/parse the value from the 408 // input Spinel frame and then perform the corresponding set/insert/remove 409 // operation. They are not responsible for preparing the Spinel response and 410 // therefore should not write anything to the NCP buffer. The `otError` returned 411 // from a "set/insert/remove" handler indicates the error in either parsing of 412 // the input or the error of set/insert/remove operation. 413 // 414 // The corresponding command handler (e.g., `HandleCommandPropertySet()` for 415 // `VALUE_SET` command) will take care of preparing the Spinel response after 416 // invoking the "set/insert/remove" handler for a given property. For example, 417 // for a `VALUE_SET` command, if the "set" handler returns an error, then a 418 // `LAST_STATUS` update response is prepared, otherwise on success the "get" 419 // handler for the property is used to prepare a `VALUE_IS` Spinel response (in 420 // cases where there is no "get" handler for the property, the input value is 421 // echoed in the response). 422 // 423 // Few properties require special treatment where the response needs to be 424 // prepared directly in the "set" handler (e.g., `HOST_POWER_STATE` or 425 // `NEST_STREAM_MFG`). These properties have a different handler method format 426 // (they expect `aHeader` as an input argument) and are processed separately in 427 // `HandleCommandPropertySet()`. 428 429 template <spinel_prop_key_t aKey> otError HandlePropertyGet(void); 430 template <spinel_prop_key_t aKey> otError HandlePropertySet(void); 431 template <spinel_prop_key_t aKey> otError HandlePropertyInsert(void); 432 template <spinel_prop_key_t aKey> otError HandlePropertyRemove(void); 433 434 // -------------------------------------------------------------------------- 435 // Property "set" handlers for special properties for which the spinel 436 // response needs to be created from within the set handler. 437 438 otError HandlePropertySet_SPINEL_PROP_HOST_POWER_STATE(uint8_t aHeader); 439 440 #if OPENTHREAD_CONFIG_DIAG_ENABLE 441 static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <= 442 OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE - kSpinelCmdHeaderSize - kSpinelPropIdSize, 443 "diag output buffer should be smaller than NCP HDLC tx buffer"); 444 445 otError HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader); 446 #endif 447 448 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 449 otError HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(uint8_t aHeader); 450 otError HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader); 451 #endif // OPENTHREAD_FTD 452 453 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE 454 otError DecodeStreamRawTxRequest(otRadioFrame &aFrame); 455 otError HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader); 456 #endif 457 458 void ResetCounters(void); 459 460 static uint8_t ConvertLogLevel(otLogLevel aLogLevel); 461 static unsigned int ConvertLogRegion(otLogRegion aLogRegion); 462 463 #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 464 /** 465 * This method defines a vendor "command handler" hook to process vendor-specific spinel commands. 466 * 467 * @param[in] aHeader The spinel frame header. 468 * @param[in] aCommand The spinel command key. 469 * 470 * @retval OT_ERROR_NONE The response is prepared. 471 * @retval OT_ERROR_NO_BUFS Out of buffer while preparing the response. 472 * 473 */ 474 otError VendorCommandHandler(uint8_t aHeader, unsigned int aCommand); 475 476 /** 477 * This method is a callback which mirrors `NcpBase::HandleFrameRemovedFromNcpBuffer()`. It is called when a 478 * spinel frame is sent and removed from NCP buffer. 479 * 480 * (a) This can be used to track and verify that a vendor spinel frame response is delivered to the host (tracking 481 * the frame using its tag). 482 * 483 * (b) It indicates that NCP buffer space is now available (since a spinel frame is removed). This can be used to 484 * implement mechanisms to re-send a failed/pending response or an async spinel frame. 485 * 486 * @param[in] aFrameTag The tag of the frame removed from NCP buffer. 487 * 488 */ 489 void VendorHandleFrameRemovedFromNcpBuffer(Spinel::Buffer::FrameTag aFrameTag); 490 491 /** 492 * This method defines a vendor "get property handler" hook to process vendor spinel properties. 493 * 494 * The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "get" operation for the 495 * given property key. Otherwise, the vendor handler should behave like other property get handlers, i.e., it 496 * should retrieve the property value and then encode and write the value into the NCP buffer. If the "get" 497 * operation itself fails, handler should write a `LAST_STATUS` with the error status into the NCP buffer. 498 * 499 * @param[in] aPropKey The spinel property key. 500 * 501 * @retval OT_ERROR_NONE Successfully retrieved the property value and prepared the response. 502 * @retval OT_ERROR_NOT_FOUND Does not support the given property key. 503 * @retval OT_ERROR_NO_BUFS Out of buffer while preparing the response. 504 * 505 */ 506 otError VendorGetPropertyHandler(spinel_prop_key_t aPropKey); 507 508 /** 509 * This method defines a vendor "set property handler" hook to process vendor spinel properties. 510 * 511 * The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "set" operation for the 512 * given property key. Otherwise, the vendor handler should behave like other property set handlers, i.e., it 513 * should first decode the value from the input spinel frame and then perform the corresponding set operation. The 514 * handler should not prepare the spinel response and therefore should not write anything to the NCP buffer. The 515 * `otError` returned from handler (other than `OT_ERROR_NOT_FOUND`) indicates the error in either parsing of the 516 * input or the error of the set operation. In case of a successful "set", `NcpBase` set command handler will call 517 * the `VendorGetPropertyHandler()` for the same property key to prepare the response. 518 * 519 * @param[in] aPropKey The spinel property key. 520 * 521 * @returns OT_ERROR_NOT_FOUND if it does not support the given property key, otherwise the error in either parsing 522 * of the input or the "set" operation. 523 * 524 */ 525 otError VendorSetPropertyHandler(spinel_prop_key_t aPropKey); 526 527 #endif // OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 528 529 protected: 530 static NcpBase *sNcpInstance; 531 static spinel_status_t ThreadErrorToSpinelStatus(otError aError); 532 static uint8_t LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aDeviceType, bool aNetworkData); 533 Instance *mInstance; 534 Spinel::Buffer mTxFrameBuffer; 535 Spinel::Encoder mEncoder; 536 Spinel::Decoder mDecoder; 537 bool mHostPowerStateInProgress; 538 539 enum 540 { 541 kTxBufferSize = OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE, // Tx Buffer size (used by mTxFrameBuffer). 542 kResponseQueueSize = OPENTHREAD_CONFIG_NCP_SPINEL_RESPONSE_QUEUE_SIZE, 543 kInvalidScanChannel = -1, // Invalid scan channel. 544 }; 545 546 spinel_status_t mLastStatus; 547 uint32_t mScanChannelMask; 548 uint16_t mScanPeriod; 549 bool mDiscoveryScanJoinerFlag; 550 bool mDiscoveryScanEnableFiltering; 551 uint16_t mDiscoveryScanPanId; 552 553 Tasklet mUpdateChangedPropsTask; 554 uint32_t mThreadChangedFlags; 555 ChangedPropsSet mChangedPropsSet; 556 557 spinel_host_power_state_t mHostPowerState; 558 Spinel::Buffer::FrameTag mHostPowerReplyFrameTag; 559 uint8_t mHostPowerStateHeader; 560 561 #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE 562 otNcpDelegateAllowPeekPoke mAllowPeekDelegate; 563 otNcpDelegateAllowPeekPoke mAllowPokeDelegate; 564 #endif 565 566 uint8_t mTxBuffer[kTxBufferSize]; 567 568 spinel_tid_t mNextExpectedTid; 569 570 uint8_t mResponseQueueHead; 571 uint8_t mResponseQueueTail; 572 ResponseEntry mResponseQueue[kResponseQueueSize]; 573 574 bool mAllowLocalNetworkDataChange; 575 bool mRequireJoinExistingNetwork; 576 bool mIsRawStreamEnabled; 577 bool mPcapEnabled; 578 bool mDisableStreamWrite; 579 bool mShouldEmitChildTableUpdate; 580 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 581 bool mAllowLocalServerDataChange; 582 #endif 583 584 #if OPENTHREAD_FTD 585 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE 586 otExtAddress mSteeringDataAddress; 587 #endif 588 uint8_t mPreferredRouteId; 589 #endif 590 591 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE 592 uint8_t mCurTransmitTID; 593 int8_t mCurScanChannel; 594 bool mSrcMatchEnabled; 595 #endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE 596 597 #if OPENTHREAD_MTD || OPENTHREAD_FTD 598 otMessageQueue mMessageQueue; 599 600 uint32_t mInboundSecureIpFrameCounter; // Number of secure inbound data/IP frames. 601 uint32_t mInboundInsecureIpFrameCounter; // Number of insecure inbound data/IP frames. 602 uint32_t mOutboundSecureIpFrameCounter; // Number of secure outbound data/IP frames. 603 uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames. 604 uint32_t mDroppedOutboundIpFrameCounter; // Number of dropped outbound data/IP frames. 605 uint32_t mDroppedInboundIpFrameCounter; // Number of dropped inbound data/IP frames. 606 607 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 608 enum : uint8_t 609 { 610 kSrpClientMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES, 611 }; 612 613 otError EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo); 614 otError EncodeSrpClientServices(const otSrpClientService *aServices); 615 616 static void HandleSrpClientCallback(otError aError, 617 const otSrpClientHostInfo *aHostInfo, 618 const otSrpClientService *aServices, 619 const otSrpClientService *aRemovedServices, 620 void *aContext); 621 void HandleSrpClientCallback(otError aError, 622 const otSrpClientHostInfo *aHostInfo, 623 const otSrpClientService *aServices, 624 const otSrpClientService *aRemovedServices); 625 626 bool mSrpClientCallbackEnabled; 627 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 628 629 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD 630 631 uint32_t mFramingErrorCounter; // Number of improperly formed received spinel frames. 632 uint32_t mRxSpinelFrameCounter; // Number of received (inbound) spinel frames. 633 uint32_t mRxSpinelOutOfOrderTidCounter; // Number of out of order received spinel frames (tid increase > 1). 634 uint32_t mTxSpinelFrameCounter; // Number of sent (outbound) spinel frames. 635 636 bool mDidInitialUpdates; 637 638 uint64_t mLogTimestampBase; // Timestamp base used for logging 639 }; 640 641 } // namespace Ncp 642 } // namespace ot 643 644 #endif // NCP_BASE_HPP_ 645