diff --git a/examples/platforms/posix/Makefile.am b/examples/platforms/posix/Makefile.am index 444fda1ed..d2f49fc23 100644 --- a/examples/platforms/posix/Makefile.am +++ b/examples/platforms/posix/Makefile.am @@ -46,6 +46,12 @@ libopenthread_posix_a_SOURCES = \ uart.c \ $(NULL) +if OPENTHREAD_ENABLE_NCP_SPI +libopenthread_posix_a_SOURCES += \ + spi-stubs.c \ + $(NULL) +endif + noinst_HEADERS = \ platform-posix.h \ $(NULL) diff --git a/examples/platforms/posix/spi-stubs.c b/examples/platforms/posix/spi-stubs.c new file mode 100644 index 000000000..e82cc9fb2 --- /dev/null +++ b/examples/platforms/posix/spi-stubs.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Nest Labs, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +// Spi-slave stubs + +ThreadError otPlatSpiSlaveEnable( + otPlatSpiSlaveTransactionCompleteCallback aCallback, + void *aContext +) +{ + fprintf(stderr, "\nNo SPI support for posix platform."); + exit(0); + + return kThreadError_NotImplemented; +} + +void otPlatSpiSlaveDisable(void) +{ +} + +ThreadError otPlatSpiSlavePrepareTransaction( + uint8_t *anOutputBuf, + uint16_t anOutputBufLen, + uint8_t *anInputBuf, + uint16_t anInputBufLen, + bool aRequestTransactionFlag +) +{ + return kThreadError_NotImplemented; +} + +// Uart + +void otPlatUartSendDone(void) +{ +} + +void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength) +{ + (void)aBuf; + (void)aBufLength; +} diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 06bc4b730..95ee5fb90 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -299,7 +299,6 @@ static spinel_status_t ResetReasonToSpinelStatus(otPlatResetReason reason) // ---------------------------------------------------------------------------- NcpBase::NcpBase(): - mSendDoneTask(&SendDoneTask, this), mUpdateChangedPropsTask(&UpdateChangedProps, this) { mSupportedChannelMask = kPhySupportedChannelMask; @@ -325,57 +324,50 @@ NcpBase::NcpBase(): // MARK: Outbound Datagram Handling // ---------------------------------------------------------------------------- -void NcpBase::HandleDatagramFromStack(otMessage message) +void NcpBase::HandleDatagramFromStack(otMessage aMessage) { - sNcpContext->HandleDatagramFromStack(*static_cast(message)); + sNcpContext->HandleDatagramFromStack(*static_cast(aMessage)); } -void NcpBase::HandleDatagramFromStack(Message &message) +void NcpBase::HandleDatagramFromStack(Message &aMessage) { - ThreadError errorCode; + ThreadError errorCode = kThreadError_None; + Message *message = &aMessage; - if (mSending == false) + SuccessOrExit(errorCode = OutboundFrameBegin()); + + SuccessOrExit( + errorCode = OutboundFrameFeedPacked( + "CiiS", + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_CMD_PROP_VALUE_IS, + message->IsLinkSecurityEnabled() + ? SPINEL_PROP_STREAM_NET + : SPINEL_PROP_STREAM_NET_INSECURE, + message->GetLength() + )); + + SuccessOrExit(errorCode = OutboundFrameFeedMessage(*message)); + + // Set the message pointer to NULL, to indicate that it does not need to be freed at the exit. + // The message is now owned by the OutboundFrame and will be freed when the frame is either successfully sent and + // then removed, or if the frame gets discarded. + message = NULL; + + // Append any metadata (rssi, lqi, channel, etc) here! + + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + + if (message != NULL) { - errorCode = OutboundFrameBegin(); - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked( - "CiiS", - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_CMD_PROP_VALUE_IS, - message.IsLinkSecurityEnabled() - ? SPINEL_PROP_STREAM_NET - : SPINEL_PROP_STREAM_NET_INSECURE, - message.GetLength() - ); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedMessage(message); - } - - // TODO: Append any metadata (rssi, lqi, channel, etc) here! - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - if (errorCode != kThreadError_None) - { - SendLastStatus(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_DROPPED); - } - - Message::Free(message); + Message::Free(*message); } - else + + if (errorCode != kThreadError_None) { - if (mSendQueue.Enqueue(message) != kThreadError_None) - { - Message::Free(message); - } + SendLastStatus(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_DROPPED); } } @@ -395,8 +387,6 @@ void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *result) void NcpBase::HandleActiveScanResult(otActiveScanResult *result) { - VerifyOrExit(mSending == false, ;); - if (result) { uint8_t flags = (result->mVersion << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT); @@ -441,9 +431,6 @@ void NcpBase::HandleActiveScanResult(otActiveScanResult *result) SPINEL_SCAN_STATE_IDLE ); } - -exit: - return; } // ---------------------------------------------------------------------------- @@ -456,10 +443,7 @@ void NcpBase::HandleNetifStateChanged(uint32_t flags, void *context) obj->mChangedFlags |= flags; - if (!obj->mSending) - { - obj->mUpdateChangedPropsTask.Post(); - } + obj->mUpdateChangedPropsTask.Post(); } void NcpBase::UpdateChangedProps(void *context) @@ -468,9 +452,9 @@ void NcpBase::UpdateChangedProps(void *context) obj->UpdateChangedProps(); } -void NcpBase::UpdateChangedProps() +void NcpBase::UpdateChangedProps(void) { - if (!mSending) + while (mChangedFlags != 0) { if ((mChangedFlags & NCP_PLAT_RESET_REASON) != 0) { @@ -490,62 +474,66 @@ void NcpBase::UpdateChangedProps() } else if ((mChangedFlags & OT_IP6_ML_ADDR_CHANGED) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_IPV6_ML_ADDR + )); mChangedFlags &= ~OT_IP6_ML_ADDR_CHANGED; - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_IPV6_ML_ADDR - ); } else if ((mChangedFlags & OT_NET_STATE) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_NET_STATE + )); mChangedFlags &= ~OT_NET_STATE; - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_NET_STATE - ); } else if ((mChangedFlags & OT_NET_ROLE) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_NET_ROLE + )); mChangedFlags &= ~OT_NET_ROLE; - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_NET_ROLE - ); + } else if ((mChangedFlags & OT_NET_PARTITION_ID) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_NET_PARTITION_ID + )); mChangedFlags &= ~OT_NET_PARTITION_ID; - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_NET_PARTITION_ID - ); } else if ((mChangedFlags & OT_NET_KEY_SEQUENCE) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_NET_KEY_SEQUENCE + )); mChangedFlags &= ~OT_NET_KEY_SEQUENCE; - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_NET_KEY_SEQUENCE - ); } else if ((mChangedFlags & (OT_IP6_ADDRESS_ADDED | OT_IP6_ADDRESS_REMOVED)) != 0) { + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_IPV6_ADDRESS_TABLE + )); mChangedFlags &= ~(OT_IP6_ADDRESS_ADDED | OT_IP6_ADDRESS_REMOVED); - HandleCommandPropertyGet( - SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, - SPINEL_PROP_IPV6_ADDRESS_TABLE - ); } else if ((mChangedFlags & (OT_THREAD_CHILD_ADDED | OT_THREAD_CHILD_REMOVED)) != 0) { - mChangedFlags &= ~(OT_THREAD_CHILD_ADDED | OT_THREAD_CHILD_REMOVED); // TODO: Uncomment this once we add support for this property. - //HandleCommandPropertyGet( + //SuccessOrExit(HandleCommandPropertyGet( // SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, // SPINEL_PROP_THREAD_CHILD_TABLE - //); + //)); + mChangedFlags &= ~(OT_THREAD_CHILD_ADDED | OT_THREAD_CHILD_REMOVED); } } + +exit: + return; } // ---------------------------------------------------------------------------- @@ -559,67 +547,98 @@ void NcpBase::HandleReceive(const uint8_t *buf, uint16_t bufLength) spinel_ssize_t parsedLength; const uint8_t *arg_ptr = NULL; unsigned int arg_len = 0; + ThreadError errorCode = kThreadError_None; + spinel_tid_t tid = 0; parsedLength = spinel_datatype_unpack(buf, bufLength, "CiD", &header, &command, &arg_ptr, &arg_len); if (parsedLength == bufLength) { - HandleCommand(header, command, arg_ptr, static_cast(arg_len)); + errorCode = HandleCommand(header, command, arg_ptr, static_cast(arg_len)); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } -} -void NcpBase::SendDoneTask(void *context) -{ - NcpBase *obj = reinterpret_cast(context); - obj->SendDoneTask(); -} + if (errorCode == kThreadError_NoBufs) + { + // If we cannot send a response due to buffer space not being + // available, we remember the TID of command so to send an + // error status when buffer space becomes available later. -void NcpBase::SendDoneTask(void) -{ - if (!mSending) { - if (mSendQueue.GetHead() != NULL) + // Valid TID range is 1-15 (zero being used as special case + // where no reply is expected). TIDs for dropped reply are + // stored in two variables: `mDroppedReplyTidBitSet` which + // is a bit set (bits 1-15 correspond to TID values 1-15). + // The first/next dropped TID value in the set is stored in + // `mDroppedReplyTid` (with value zero indicating that there + // is no dropped reply). + + tid = SPINEL_HEADER_GET_TID(header); + + if (tid != 0) { - Message &message(*mSendQueue.GetHead()); - mSendQueue.Dequeue(message); - HandleDatagramFromStack(message); - } + if (mDroppedReplyTid == 0) + { + mDroppedReplyTid = tid; + } - if (mQueuedGetHeader != 0) - { - HandleCommandPropertyGet(mQueuedGetHeader, mQueuedGetKey); - mQueuedGetHeader = 0; - } - - if (!mSending) - { - UpdateChangedProps(); + mDroppedReplyTidBitSet |= (1 << tid); } } } -void NcpBase::HandleSendDone(void) +void NcpBase::HandleSpaceAvailableInTxBuffer(void) { - mSendDoneTask.Post(); -} + while (mDroppedReplyTid != 0) + { + SuccessOrExit( + SendLastStatus( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | mDroppedReplyTid, + SPINEL_STATUS_NOMEM + ) + ); + mDroppedReplyTidBitSet &= ~(1 << mDroppedReplyTid); + + if (mDroppedReplyTidBitSet == 0) + { + mDroppedReplyTid = 0; + + break; + } + + do + { + mDroppedReplyTid = SPINEL_GET_NEXT_TID(mDroppedReplyTid); + } + while ((mDroppedReplyTidBitSet & (1 << mDroppedReplyTid)) == 0); + } + + UpdateChangedProps(); + +exit: + return; +} // ---------------------------------------------------------------------------- // MARK: Inbound Command Handlers // ---------------------------------------------------------------------------- -void NcpBase::HandleCommand(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +ThreadError NcpBase::HandleCommand(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) { unsigned i; + ThreadError errorCode = kThreadError_None; // Skip if this isn't a spinel frame - VerifyOrExit((SPINEL_HEADER_FLAG & header) == SPINEL_HEADER_FLAG, ;); + VerifyOrExit((SPINEL_HEADER_FLAG & header) == SPINEL_HEADER_FLAG, errorCode = kThreadError_InvalidArgs); // We only support IID zero for now. - VerifyOrExit(SPINEL_HEADER_GET_IID(header) == 0, SendLastStatus(header, SPINEL_STATUS_INVALID_INTERFACE);); + VerifyOrExit( + SPINEL_HEADER_GET_IID(header) == 0, + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_INTERFACE) + ); for (i = 0; i < sizeof(mCommandHandlerTable) / sizeof(mCommandHandlerTable[0]); i++) { @@ -631,34 +650,21 @@ void NcpBase::HandleCommand(uint8_t header, unsigned int command, const uint8_t if (i < sizeof(mCommandHandlerTable) / sizeof(mCommandHandlerTable[0])) { - (this->*mCommandHandlerTable[i].mHandler)(header, command, arg_ptr, arg_len); + errorCode = (this->*mCommandHandlerTable[i].mHandler)(header, command, arg_ptr, arg_len); } else { - SendLastStatus(header, SPINEL_STATUS_INVALID_COMMAND); + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_COMMAND); } exit: - return; + return errorCode; } -void NcpBase::HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key) { unsigned i; - - if (mSending) - { - // If we are currently sending, can can queue up to one - // property get that we can execute immediately after - // the send is complete. - if (mQueuedGetHeader == 0) - { - mQueuedGetHeader = header; - mQueuedGetKey = key; - } - - ExitNow(;); - } + ThreadError errorCode = kThreadError_None; for (i = 0; i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0]); i++) { @@ -670,36 +676,21 @@ void NcpBase::HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key) if (i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0])) { - (this->*mGetPropertyHandlerTable[i].mHandler)(header, key); + errorCode = (this->*mGetPropertyHandlerTable[i].mHandler)(header, key); } else { - SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); + errorCode = SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } -exit: - return; + return errorCode; } -void NcpBase::HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned i; - - if (mSending) - { - // If we are currently sending, can can queue up to one - // property get that we can execute immediately after - // the send is complete. - if (mQueuedGetHeader == 0) - { - mLastStatus = SPINEL_STATUS_FAILURE; - mQueuedGetHeader = header; - mQueuedGetKey = SPINEL_PROP_LAST_STATUS; - } - - ExitNow(;); - } + ThreadError errorCode = kThreadError_None; for (i = 0; i < sizeof(mSetPropertyHandlerTable) / sizeof(mSetPropertyHandlerTable[0]); i++) { @@ -711,36 +702,21 @@ void NcpBase::HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, co if (i < sizeof(mSetPropertyHandlerTable) / sizeof(mSetPropertyHandlerTable[0])) { - (this->*mSetPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); + errorCode = (this->*mSetPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); + errorCode = SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } -exit: - return; + return errorCode; } -void NcpBase::HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned i; - - if (mSending) - { - // If we are currently sending, can can queue up to one - // property get that we can execute immediately after - // the send is complete. - if (mQueuedGetHeader == 0) - { - mLastStatus = SPINEL_STATUS_FAILURE; - mQueuedGetHeader = header; - mQueuedGetKey = SPINEL_PROP_LAST_STATUS; - } - - ExitNow(;); - } + ThreadError errorCode = kThreadError_None; for (i = 0; i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0]); i++) { @@ -752,36 +728,21 @@ void NcpBase::HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, if (i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0])) { - (this->*mInsertPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); + errorCode = (this->*mInsertPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); + errorCode = SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } -exit: - return; + return errorCode; } -void NcpBase::HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned i; - - if (mSending) - { - // If we are currently sending, can can queue up to one - // property get that we can execute immediately after - // the send is complete. - if (mQueuedGetHeader == 0) - { - mLastStatus = SPINEL_STATUS_FAILURE; - mQueuedGetHeader = header; - mQueuedGetKey = SPINEL_PROP_LAST_STATUS; - } - - ExitNow(;); - } + ThreadError errorCode = kThreadError_None; for (i = 0; i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0]); i++) { @@ -793,15 +754,14 @@ void NcpBase::HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, if (i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0])) { - (this->*mRemovePropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); + errorCode = (this->*mRemovePropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); + errorCode = SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } -exit: - return; + return errorCode; } @@ -810,100 +770,80 @@ exit: // ---------------------------------------------------------------------------- -void NcpBase::SendLastStatus(uint8_t header, spinel_status_t lastStatus) +ThreadError NcpBase::SendLastStatus(uint8_t header, spinel_status_t lastStatus) { if (SPINEL_HEADER_GET_IID(header) == 0) { mLastStatus = lastStatus; } - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - SPINEL_PROP_LAST_STATUS, - SPINEL_DATATYPE_UINT_PACKED_S, - lastStatus - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + SPINEL_PROP_LAST_STATUS, + SPINEL_DATATYPE_UINT_PACKED_S, + lastStatus + ); } -ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, const char *pack_format, ...) +ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, + const char *pack_format, ...) { - ThreadError errorCode; - va_list args; + ThreadError errorCode = kThreadError_None; + va_list args; - errorCode = OutboundFrameBegin(); + va_start(args, pack_format); + SuccessOrExit(errorCode = OutboundFrameBegin()); + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, command, key)); + SuccessOrExit(errorCode = OutboundFrameFeedVPacked(pack_format, args)); + SuccessOrExit(errorCode = OutboundFrameSend()); - if (errorCode == kThreadError_None) +exit: + va_end(args); + return errorCode; +} + +ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) +{ + ThreadError errorCode = kThreadError_None; + + SuccessOrExit(errorCode = OutboundFrameBegin()); + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, command, key)); + SuccessOrExit(errorCode = OutboundFrameFeedData(value_ptr, value_len)); + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + return errorCode; +} + +ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, Message &aMessage) +{ + ThreadError errorCode = kThreadError_None; + Message *message = &aMessage; + + SuccessOrExit(errorCode = OutboundFrameBegin()); + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, command, key)); + SuccessOrExit(errorCode = OutboundFrameFeedMessage(*message)); + + // Set the message pointer to NULL, to indicate that it does not need to be freed at the exit. + // The message is now owned by the OutboundFrame and will be freed when the frame is either successfully sent and + // then removed, or if the frame gets discarded. + message = NULL; + + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + + if (message != NULL) { - errorCode = OutboundFrameFeedPacked("Cii", header, command, key); - } - - if (errorCode == kThreadError_None) - { - va_start(args, pack_format); - errorCode = OutboundFrameFeedVPacked(pack_format, args); - va_end(args); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); + Message::Free(*message); } return errorCode; } -ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) -{ - ThreadError errorCode; - - errorCode = OutboundFrameBegin(); - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, command, key); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedData(value_ptr, value_len); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - return errorCode; -} - -ThreadError NcpBase::SendPropertyUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, Message &message) -{ - ThreadError errorCode; - - errorCode = OutboundFrameBegin(); - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, command, key); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedMessage(message); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - return errorCode; -} - -ThreadError -NcpBase::OutboundFrameFeedVPacked(const char *pack_format, va_list args) +ThreadError NcpBase::OutboundFrameFeedVPacked(const char *pack_format, va_list args) { uint8_t buf[64]; ThreadError errorCode = kThreadError_NoBufs; @@ -919,8 +859,7 @@ NcpBase::OutboundFrameFeedVPacked(const char *pack_format, va_list args) return errorCode; } -ThreadError -NcpBase::OutboundFrameFeedPacked(const char *pack_format, ...) +ThreadError NcpBase::OutboundFrameFeedPacked(const char *pack_format, ...) { ThreadError errorCode; va_list args; @@ -932,21 +871,21 @@ NcpBase::OutboundFrameFeedPacked(const char *pack_format, ...) return errorCode; } - // ---------------------------------------------------------------------------- // MARK: Individual Command Handlers // ---------------------------------------------------------------------------- - -void NcpBase::CommandHandler_NOOP(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +ThreadError NcpBase::CommandHandler_NOOP(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) { - SendLastStatus(header, SPINEL_STATUS_OK); (void)command; (void)arg_ptr; (void)arg_len; + + return SendLastStatus(header, SPINEL_STATUS_OK); } -void NcpBase::CommandHandler_RESET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +ThreadError NcpBase::CommandHandler_RESET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len) { // We aren't using any of the arguments to this function. (void)header; @@ -965,88 +904,106 @@ void NcpBase::CommandHandler_RESET(uint8_t header, unsigned int command, const u mChangedFlags |= NCP_PLAT_RESET_REASON; otDisable(); mUpdateChangedPropsTask.Post(); + + return SendLastStatus(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_RESET_SOFTWARE); } -void NcpBase::CommandHandler_PROP_VALUE_GET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, - uint16_t arg_len) +ThreadError NcpBase::CommandHandler_PROP_VALUE_GET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len) { unsigned int propKey = 0; spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack(arg_ptr, arg_len, "i", &propKey); if (parsedLength > 0) { - HandleCommandPropertyGet(header, static_cast(propKey)); + errorCode = HandleCommandPropertyGet(header, static_cast(propKey)); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + (void)command; + + return errorCode; } -void NcpBase::CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, - uint16_t arg_len) +ThreadError NcpBase::CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len) { unsigned int propKey = 0; spinel_ssize_t parsedLength; const uint8_t *value_ptr; unsigned int value_len; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack(arg_ptr, arg_len, "iD", &propKey, &value_ptr, &value_len); if (parsedLength == arg_len) { - HandleCommandPropertySet(header, static_cast(propKey), value_ptr, value_len); + errorCode = HandleCommandPropertySet(header, static_cast(propKey), value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + (void)command; + + return errorCode; } -void NcpBase::CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int command, const uint8_t *arg_ptr, - uint16_t arg_len) +ThreadError NcpBase::CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len) { unsigned int propKey = 0; spinel_ssize_t parsedLength; const uint8_t *value_ptr; unsigned int value_len; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack(arg_ptr, arg_len, "iD", &propKey, &value_ptr, &value_len); if (parsedLength == arg_len) { - HandleCommandPropertyInsert(header, static_cast(propKey), value_ptr, value_len); + errorCode = HandleCommandPropertyInsert(header, static_cast(propKey), value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + (void)command; + + return errorCode; } -void NcpBase::CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int command, const uint8_t *arg_ptr, - uint16_t arg_len) +ThreadError NcpBase::CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len) { unsigned int propKey = 0; spinel_ssize_t parsedLength; const uint8_t *value_ptr; unsigned int value_len; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack(arg_ptr, arg_len, "iD", &propKey, &value_ptr, &value_len); if (parsedLength == arg_len) { - HandleCommandPropertyRemove(header, static_cast(propKey), value_ptr, value_len); + errorCode = HandleCommandPropertyRemove(header, static_cast(propKey), value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + (void)command; + + return errorCode; } @@ -1055,140 +1012,137 @@ void NcpBase::CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int comm // ---------------------------------------------------------------------------- -void NcpBase::GetPropertyHandler_LAST_STATUS(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_LAST_STATUS(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate(header, SPINEL_CMD_PROP_VALUE_IS, key, SPINEL_DATATYPE_UINT_PACKED_S, mLastStatus); + return SendPropertyUpdate(header, SPINEL_CMD_PROP_VALUE_IS, key, SPINEL_DATATYPE_UINT_PACKED_S, mLastStatus); } -void NcpBase::GetPropertyHandler_PROTOCOL_VERSION(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PROTOCOL_VERSION(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT_PACKED_S, - SPINEL_PROTOCOL_VERSION_THREAD_MAJOR, - SPINEL_PROTOCOL_VERSION_THREAD_MINOR - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT_PACKED_S, + SPINEL_PROTOCOL_VERSION_THREAD_MAJOR, + SPINEL_PROTOCOL_VERSION_THREAD_MINOR + ); } -void NcpBase::GetPropertyHandler_INTERFACE_TYPE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_INTERFACE_TYPE(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT_PACKED_S, - SPINEL_PROTOCOL_TYPE_THREAD - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT_PACKED_S, + SPINEL_PROTOCOL_TYPE_THREAD + ); } -void NcpBase::GetPropertyHandler_VENDOR_ID(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_VENDOR_ID(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT_PACKED_S, - 0 // Vendor ID. Zero for unknown. - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT_PACKED_S, + 0 // Vendor ID. Zero for unknown. + ); } -void NcpBase::GetPropertyHandler_CAPS(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_CAPS(uint8_t header, spinel_prop_key_t key) { - ThreadError errorCode(OutboundFrameBegin()); + ThreadError errorCode = kThreadError_None; - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } + SuccessOrExit(errorCode = OutboundFrameBegin()); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); // Begin adding capabilities ////////////////////////////////////////////// - OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_NET_THREAD_1_0); + SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_NET_THREAD_1_0)); - OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_COUNTERS); + SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_COUNTERS)); // TODO: Somehow get the following capability from the radio. - OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_802_15_4_2450MHZ_OQPSK); + SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, + SPINEL_CAP_802_15_4_2450MHZ_OQPSK)); #if OPENTHREAD_CONFIG_MAX_CHILDREN > 0 - OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_ROLE_ROUTER); + SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_ROLE_ROUTER)); #endif // End adding capabilities ///////////////////////////////////////////////// - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } + SuccessOrExit(errorCode = OutboundFrameSend()); - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } +exit: + return errorCode; } -void NcpBase::GetPropertyHandler_NCP_VERSION(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NCP_VERSION(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UTF8_S, - PACKAGE_NAME "/" PACKAGE_VERSION "; " __DATE__ " " __TIME__ - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UTF8_S, + PACKAGE_NAME "/" PACKAGE_VERSION "; " __DATE__ " " __TIME__ + ); } -void NcpBase::GetPropertyHandler_INTERFACE_COUNT(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_INTERFACE_COUNT(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - 1 // Only one interface for now - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + 1 // Only one interface for now + ); } -void NcpBase::GetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key) { // Always online at the moment - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - SPINEL_POWER_STATE_ONLINE - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + SPINEL_POWER_STATE_ONLINE + ); } -void NcpBase::GetPropertyHandler_HWADDR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_HWADDR(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_EUI64_S, - otGetExtendedAddress() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_EUI64_S, + otGetExtendedAddress() + ); } -void NcpBase::GetPropertyHandler_LOCK(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_LOCK(uint8_t header, spinel_prop_key_t key) { // TODO: Implement property lock (Needs API!) - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::GetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key) { // TODO: Implement PHY_ENBLED (Needs API!) - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key) { uint32_t freq_khz(0); const uint8_t chan(otGetChannel()); @@ -1206,173 +1160,166 @@ void NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key) freq_khz = 2405000 - (5000 * 11) + 5000 * (chan); } - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT32_S, - freq_khz - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT32_S, + freq_khz + ); } -void NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t header, spinel_prop_key_t key) { - GetPropertyHandler_ChannelMaskHelper(header, key, mSupportedChannelMask); + return GetPropertyHandler_ChannelMaskHelper(header, key, mSupportedChannelMask); } -void NcpBase::GetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetChannel() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetChannel() + ); } -void NcpBase::GetPropertyHandler_PHY_RSSI(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_PHY_RSSI(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_INT8_S, - otPlatRadioGetNoiseFloor() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_INT8_S, + otPlatRadioGetNoiseFloor() + ); } -void NcpBase::GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key) { + ThreadError errorCode = kThreadError_None; + if (otActiveScanInProgress()) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - SPINEL_SCAN_STATE_BEACON - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + SPINEL_SCAN_STATE_BEACON + ); } else { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - SPINEL_SCAN_STATE_IDLE - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + SPINEL_SCAN_STATE_IDLE + ); } + + return errorCode; } -void NcpBase::GetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT16_S, - mScanPeriod - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT16_S, + mScanPeriod + ); } -void NcpBase::GetPropertyHandler_ChannelMaskHelper(uint8_t header, spinel_prop_key_t key, uint32_t channel_mask) +ThreadError NcpBase::GetPropertyHandler_ChannelMaskHelper(uint8_t header, spinel_prop_key_t key, uint32_t channel_mask) { - ThreadError errorCode(OutboundFrameBegin()); + ThreadError errorCode = kThreadError_None; - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } + SuccessOrExit(errorCode = OutboundFrameBegin()); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); for (int i = 0; i < 32; i++) { - if (errorCode != kThreadError_None) - { - break; - } - if (0 != (channel_mask & (1 << i))) { - errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT8_S, i); + SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT8_S, i)); } } - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } + SuccessOrExit(errorCode = OutboundFrameSend()); - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } +exit: + return errorCode; } -void NcpBase::GetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key) { - GetPropertyHandler_ChannelMaskHelper(header, key, mChannelMask); + return GetPropertyHandler_ChannelMaskHelper(header, key, mChannelMask); } -void NcpBase::GetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT16_S, - otGetPanId() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT16_S, + otGetPanId() + ); } -void NcpBase::GetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_INT8_S, - otPlatRadioGetPromiscuous() - ? SPINEL_MAC_FILTER_MODE_15_4_PROMISCUOUS - : SPINEL_MAC_FILTER_MODE_NORMAL - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_INT8_S, + otPlatRadioGetPromiscuous() + ? SPINEL_MAC_FILTER_MODE_15_4_PROMISCUOUS + : SPINEL_MAC_FILTER_MODE_NORMAL + ); } -void NcpBase::GetPropertyHandler_MAC_15_4_LADDR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_15_4_LADDR(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_EUI64_S, - otGetExtendedAddress() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_EUI64_S, + otGetExtendedAddress() + ); } -void NcpBase::GetPropertyHandler_MAC_15_4_SADDR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_MAC_15_4_SADDR(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT16_S, - otGetShortAddress() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT16_S, + otGetShortAddress() + ); } -void NcpBase::GetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_BOOL_S, - otIsInterfaceUp() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_BOOL_S, + (otGetDeviceRole() != kDeviceRoleDisabled) + ); } -void NcpBase::GetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key) { spinel_net_state_t state(SPINEL_NET_STATE_OFFLINE); @@ -1397,16 +1344,16 @@ void NcpBase::GetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key } } - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - state - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + state + ); } -void NcpBase::GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key) { spinel_net_role_t role(SPINEL_NET_ROLE_NONE); @@ -1430,256 +1377,225 @@ void NcpBase::GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key) break; } - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - role - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + role + ); } -void NcpBase::GetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UTF8_S, - otGetNetworkName() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UTF8_S, + otGetNetworkName() + ); } -void NcpBase::GetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_DATA_S, - otGetExtendedPanId(), - sizeof(spinel_net_xpanid_t) - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_DATA_S, + otGetExtendedPanId(), + sizeof(spinel_net_xpanid_t) + ); } -void NcpBase::GetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key) { const uint8_t *ptr(NULL); uint8_t len(0); ptr = otGetMasterKey(&len); - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_DATA_S, - ptr, - len - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_DATA_S, + ptr, + len + ); } -void NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT32_S, - otGetKeySequenceCounter() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT32_S, + otGetKeySequenceCounter() + ); } -void NcpBase::GetPropertyHandler_NET_PARTITION_ID(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_NET_PARTITION_ID(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT32_S, - otGetPartitionId() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT32_S, + otGetPartitionId() + ); } -void NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetNetworkDataVersion() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetNetworkDataVersion() + ); } -void NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetStableNetworkDataVersion() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetStableNetworkDataVersion() + ); } -void NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) { - ThreadError errorCode(OutboundFrameBegin()); + ThreadError errorCode = kThreadError_None; uint8_t network_data[255]; uint8_t network_data_len = 255; - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } + SuccessOrExit(errorCode = OutboundFrameBegin()); + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); + otGetNetworkDataLocal( + false, // Stable? + network_data, + &network_data_len + ); + SuccessOrExit(errorCode = OutboundFrameFeedData(network_data, network_data_len)); + SuccessOrExit(errorCode = OutboundFrameSend()); - if (errorCode == kThreadError_None) - { - otGetNetworkDataLocal( - false, // Stable? - network_data, - &network_data_len - ); - - errorCode = OutboundFrameFeedData(network_data, network_data_len); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } +exit: + return errorCode; } -void NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) { - ThreadError errorCode(OutboundFrameBegin()); + ThreadError errorCode = kThreadError_None; uint8_t network_data[255]; uint8_t network_data_len = 255; - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } - if (errorCode == kThreadError_None) - { - otGetNetworkDataLocal( - true, // Stable? - network_data, - &network_data_len - ); + SuccessOrExit(errorCode = OutboundFrameBegin()); - errorCode = OutboundFrameFeedData(network_data, network_data_len); - } - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } -} - -void NcpBase::GetPropertyHandler_THREAD_LEADER_RID(uint8_t header, spinel_prop_key_t key) -{ - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetLeaderRouterId() + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); + otGetNetworkDataLocal( + true, // Stable? + network_data, + &network_data_len ); + + SuccessOrExit(errorCode = OutboundFrameFeedData(network_data, network_data_len)); + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + return errorCode; } -void NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_LEADER_RID(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetLocalLeaderWeight() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetLeaderRouterId() + ); } -void NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - otGetLeaderWeight() - ); + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetLocalLeaderWeight() + ); } -void NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key) { - ThreadError errorCode; + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + otGetLeaderWeight() + ); +} + +ThreadError NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key) +{ + ThreadError errorCode = kThreadError_None; otIp6Address address; + errorCode = otGetLeaderRloc(&address); if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_IPv6ADDR_S, - &address - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_IPv6ADDR_S, + &address + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void -NcpBase::GetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key) { - ThreadError errorCode(OutboundFrameBegin()); + ThreadError errorCode = kThreadError_None; uint8_t num_entries = 0; - const uint16_t* ports = otGetUnsecurePorts(&num_entries); + const uint16_t *ports = otGetUnsecurePorts(&num_entries); - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } + SuccessOrExit(errorCode = OutboundFrameBegin()); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); for (; num_entries != 0; ports++, num_entries--) { - if (errorCode != kThreadError_None) - { - break; - } - - errorCode = OutboundFrameFeedPacked("S", ports); + SuccessOrExit(errorCode = OutboundFrameFeedPacked("S", ports)); } - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } + SuccessOrExit(errorCode = OutboundFrameSend()); - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } +exit: + return errorCode; } -void NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key) + +ThreadError NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key) { - SendPropertyUpdate( + return SendPropertyUpdate( header, SPINEL_CMD_PROP_VALUE_IS, key, @@ -1688,8 +1604,10 @@ void NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t head ); } -void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key) + +ThreadError NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key) { + ThreadError errorCode = kThreadError_None; const uint8_t *ml_prefix = otGetMeshLocalPrefix(); if (ml_prefix) @@ -1701,119 +1619,120 @@ void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ // Zero out the last 8 bytes. memset(addr.mFields.m8 + 8, 0, 8); - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S, - &addr, - 64 - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S, + &addr, + 64 + ); } else { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_VOID_S - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_VOID_S + ); } + + return errorCode; } -void NcpBase::GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key) { + ThreadError errorCode = kThreadError_None; const otIp6Address *ml64 = otGetMeshLocalEid(); if (ml64) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_IPv6ADDR_S, - ml64 - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_IPv6ADDR_S, + ml64 + ); } else { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_VOID_S - ); - } -} - -void NcpBase::GetPropertyHandler_IPV6_LL_ADDR(uint8_t header, spinel_prop_key_t key) -{ - // TODO! - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); - (void)key; -} - -void NcpBase::GetPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key) -{ - ThreadError errorCode(OutboundFrameBegin()); - - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); - } - - for (const otNetifAddress *address = otGetUnicastAddresses(); address; address = address->mNext) - { - if (errorCode != kThreadError_None) - { - break; - } - - errorCode = OutboundFrameFeedPacked( - "T(6CLL).", - &address->mAddress, - address->mPrefixLength, - address->mPreferredLifetime, - address->mValidLifetime + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_VOID_S ); } - if (errorCode == kThreadError_None) - { - errorCode = OutboundFrameSend(); - } - - if (errorCode != kThreadError_None) - { - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); - } + return errorCode; } -void NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_IPV6_LL_ADDR(uint8_t header, spinel_prop_key_t key) +{ + // TODO! + (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); +} + +ThreadError NcpBase::GetPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key) +{ + ThreadError errorCode = kThreadError_None; + + SuccessOrExit(errorCode = OutboundFrameBegin()); + + + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); + + for (const otNetifAddress *address = otGetUnicastAddresses(); address; address = address->mNext) + { + + SuccessOrExit(errorCode = OutboundFrameFeedPacked( + "T(6CLL).", + &address->mAddress, + address->mPrefixLength, + address->mPreferredLifetime, + address->mValidLifetime + )); + } + + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + return errorCode; +} + +ThreadError NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t header, spinel_prop_key_t key) { // TODO: Implement get route table - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::GetPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key) { // TODO: Implement get external route table - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key) { // TODO: Implement explicit data poll. - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::GetPropertyHandler_CNTR(uint8_t header, spinel_prop_key_t key) +ThreadError NcpBase::GetPropertyHandler_CNTR(uint8_t header, spinel_prop_key_t key) { uint32_t value; const otMacCounters *macCounters; + ThreadError errorCode = kThreadError_None; macCounters = otGetMacCounters(); @@ -1922,41 +1841,40 @@ void NcpBase::GetPropertyHandler_CNTR(uint8_t header, spinel_prop_key_t key) break; default: - SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_INTERNAL_ERROR); goto bail; break; } - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT32_S, - value - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT32_S, + value + ); bail: - return; + return errorCode; } - - // ---------------------------------------------------------------------------- // MARK: Individual Property Setters // ---------------------------------------------------------------------------- -void NcpBase::SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { // TODO: Implement POWER_STATE - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; (void)value_ptr; (void)value_len; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { bool value = false; spinel_ssize_t parsedLength; @@ -1987,26 +1905,29 @@ void NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t k if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void NcpBase::SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { // TODO: Implement PHY_TX_POWER - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); (void)key; (void)value_ptr; (void)value_len; + + return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } -void NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned int i = 0; spinel_ssize_t parsedLength; @@ -2025,21 +1946,23 @@ void NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { uint8_t i = 0; spinel_ssize_t parsedLength; @@ -2070,30 +1993,33 @@ void NcpBase::SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { ThreadError errorCode = kThreadError_None; uint32_t new_mask(0); for (; value_len != 0; value_len--, value_ptr++) { - if ( (value_ptr[0] > 31) - || (mSupportedChannelMask & (1 << value_ptr[0])) == 0 - ) { + if ((value_ptr[0] > 31) + || (mSupportedChannelMask & (1 << value_ptr[0])) == 0 + ) + { errorCode = kThreadError_InvalidArgs; break; } @@ -2104,19 +2030,22 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t if (errorCode == kThreadError_None) { mChannelMask = new_mask; - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { uint16_t tmp(mScanPeriod); spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack( value_ptr, @@ -2128,16 +2057,18 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key if (parsedLength > 0) { mScanPeriod = tmp; - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { uint8_t i = 0; spinel_ssize_t parsedLength; @@ -2178,22 +2109,23 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_ if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + return errorCode; } -void NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { uint16_t tmp; spinel_ssize_t parsedLength; @@ -2212,21 +2144,23 @@ void NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_ if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { bool value = false; spinel_ssize_t parsedLength; @@ -2257,16 +2191,18 @@ void NcpBase::SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t k if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned int i(0); spinel_ssize_t parsedLength; @@ -2331,14 +2267,15 @@ void NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_IS, - key, - SPINEL_DATATYPE_UINT8_S, - SPINEL_NET_STATE_ATTACHING - ); - return; + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + SPINEL_NET_STATE_ATTACHING + ); + + ExitNow(); } } @@ -2347,21 +2284,24 @@ void NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + +exit: + return errorCode; } -void NcpBase::SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { unsigned int i(0); spinel_ssize_t parsedLength; @@ -2397,21 +2337,24 @@ void NcpBase::SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, + uint16_t value_len) { const char *string(NULL); spinel_ssize_t parsedLength; @@ -2430,25 +2373,28 @@ void NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_ke if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { const uint8_t *ptr = NULL; spinel_size_t len; spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack( value_ptr, @@ -2461,16 +2407,18 @@ void NcpBase::SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t ke if ((parsedLength > 0) && (len == sizeof(spinel_net_xpanid_t))) { otSetExtendedPanId(ptr); - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { const uint8_t *ptr = NULL; spinel_size_t len; @@ -2491,24 +2439,28 @@ void NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_ if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, + uint16_t value_len) { unsigned int i(0); spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; parsedLength = spinel_datatype_unpack( value_ptr, @@ -2520,16 +2472,18 @@ void NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_ke if (parsedLength > 0) { otSetKeySequenceCounter(i); - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key, - const uint8_t *value_ptr, uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { ThreadError errorCode = kThreadError_None; uint8_t value = 0; @@ -2553,18 +2507,20 @@ void NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spin if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -2613,7 +2569,7 @@ void NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop { // Only send a successful status update if // there was a transaction id in the header. - SendLastStatus(header, SPINEL_STATUS_OK); + errorCode = SendLastStatus(header, SPINEL_STATUS_OK); } } else @@ -2623,13 +2579,16 @@ void NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop Message::Free(*message); } - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + (void)key; + + return errorCode; } -void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -2678,7 +2637,7 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke { // Only send a successful status update if // there was a transaction id in the header. - SendLastStatus(header, SPINEL_STATUS_OK); + errorCode = SendLastStatus(header, SPINEL_STATUS_OK); } } else @@ -2688,13 +2647,16 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke Message::Free(*message); } - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + (void)key; + + return errorCode; } -void NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { ThreadError errorCode = kThreadError_None; @@ -2710,20 +2672,22 @@ void NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } + + return errorCode; } -void -NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { ThreadError errorCode = kThreadError_None; uint8_t num_entries = 0; - const uint16_t* ports = otGetUnsecurePorts(&num_entries); + const uint16_t *ports = otGetUnsecurePorts(&num_entries); spinel_ssize_t parsedLength = 0; int ports_changed = 0; @@ -2740,10 +2704,11 @@ NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_k ports_changed++; } - while ( (errorCode == kThreadError_None) - && (parsedLength > 0) - && (value_len >= 2) - ) { + while ((errorCode == kThreadError_None) + && (parsedLength > 0) + && (value_len >= 2) + ) + { uint16_t port; parsedLength = spinel_datatype_unpack( @@ -2772,11 +2737,11 @@ NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_k if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); if (ports_changed) { @@ -2787,10 +2752,11 @@ NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_k HandleCommandPropertyGet(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, key); } } + + return errorCode; } -void -NcpBase::SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key, +ThreadError NcpBase::SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) { bool value = false; @@ -2819,21 +2785,23 @@ NcpBase::SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, s if (errorCode == kThreadError_None) { - HandleCommandPropertyGet(header, key); + errorCode = HandleCommandPropertyGet(header, key); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } if (should_register_with_leader) { otSendServerData(); } + + return errorCode; } -void NcpBase::SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { ThreadError errorCode = kThreadError_None; uint8_t value = 0; @@ -2863,10 +2831,12 @@ void NcpBase::SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t ke errorCode = kThreadError_Parse; } + (void)key; + // There is currently no getter for PROP_CNTR_RESET, so we just // return SPINEL_STATUS_OK for success when the counters are reset. - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); - (void)key; + + return SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } // ---------------------------------------------------------------------------- @@ -2874,8 +2844,8 @@ void NcpBase::SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t ke // ---------------------------------------------------------------------------- -void NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -2933,27 +2903,30 @@ void NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_pr // are updated, and the add/insert operation is considered a success. VerifyOrExit(errorCode == kThreadError_None || errorCode == kThreadError_Busy, - errorStatus = ThreadErrorToSpinelStatus(errorCode)); + errorStatus = ThreadErrorToSpinelStatus(errorCode)); - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_INSERTED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_INSERTED, + key, + value_ptr, + value_len + ); errorStatus = SPINEL_STATUS_OK; exit: + if (errorStatus != SPINEL_STATUS_OK) { - SendLastStatus(header, errorStatus); + errorCode = SendLastStatus(header, errorStatus); } + + return errorCode; } -void NcpBase::InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { const static int kPreferenceOffset = 6; const static int kPreferenceMask = 3 << kPreferenceOffset; @@ -2970,7 +2943,7 @@ void NcpBase::InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_p VerifyOrExit( mAllowLocalNetworkDataChange == true, - SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) ); parsedLength = spinel_datatype_unpack( @@ -2992,30 +2965,30 @@ void NcpBase::InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_p if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_INSERTED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_INSERTED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } exit: - return; + return errorCode; } -void NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { const static int kPreferenceOffset = 6; const static int kPreferenceMask = 3 << kPreferenceOffset; @@ -3038,7 +3011,7 @@ void NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_p VerifyOrExit( mAllowLocalNetworkDataChange == true, - SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) ); parsedLength = spinel_datatype_unpack( @@ -3067,30 +3040,30 @@ void NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_p if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_INSERTED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_INSERTED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } exit: - return; + return errorCode; } -void -NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +ThreadError NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -3109,23 +3082,25 @@ NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_pro if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_REMOVED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } @@ -3134,8 +3109,8 @@ NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_pro // ---------------------------------------------------------------------------- -void NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -3174,32 +3149,34 @@ void NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_pr { netif_addr->mNext = NULL; - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_REMOVED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(kThreadError_NoAddress)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(kThreadError_NoAddress)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } -void NcpBase::RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -3210,7 +3187,7 @@ void NcpBase::RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_p VerifyOrExit( mAllowLocalNetworkDataChange == true, - SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) ); parsedLength = spinel_datatype_unpack( @@ -3228,30 +3205,30 @@ void NcpBase::RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_p if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_REMOVED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } exit: - return; + return errorCode; } -void NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len) +ThreadError NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -3262,7 +3239,7 @@ void NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_p VerifyOrExit( mAllowLocalNetworkDataChange == true, - SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) + errorCode = SendLastStatus(header, SPINEL_STATUS_INVALID_STATE) ); parsedLength = spinel_datatype_unpack( @@ -3280,30 +3257,30 @@ void NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_p if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_REMOVED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } exit: - return; + return errorCode; } -void -NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +ThreadError NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len) { spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -3322,23 +3299,25 @@ NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_pro if (errorCode == kThreadError_None) { - SendPropertyUpdate( - header, - SPINEL_CMD_PROP_VALUE_REMOVED, - key, - value_ptr, - value_len - ); + errorCode = SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); } else { - SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); } } else { - SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); } + + return errorCode; } } // namespace Thread diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 11e4b04b3..7e4d24d81 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -45,40 +45,83 @@ class NcpBase { public: - NcpBase(); + /** + * This constructor creates and initializes an NcpBase instance. + * + */ + NcpBase(void); protected: + /** + * This method is called to start a new outbound frame. + * + * @retval kThreadError_None Successfully started a new frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to start a new frame. + * + */ virtual ThreadError OutboundFrameBegin(void) = 0; - virtual uint16_t OutboundFrameGetRemaining(void) = 0; + /** + * This method adds data to the current outbound frame being written. + * + * If no buffer space is available, this method should discard and clear the frame before returning an error status. + * + * @param[in] aDataBuffer A pointer to data buffer. + * @param[in] aDataBufferLength The length of the data buffer. + * + * @retval kThreadError_None Successfully added new data to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add data. + * + */ + virtual ThreadError OutboundFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength) = 0; - virtual ThreadError OutboundFrameFeedData(const uint8_t *frame, uint16_t frameLength) = 0; - - virtual ThreadError OutboundFrameFeedMessage(Message &message) = 0; + /** + * This method adds a message to the current outbound frame being written. + * + * If no buffer space is available, this method should discard and clear the frame before returning an error status. + * In case of success, the passed-in message @aMessage should be owned by outbound buffer and should be freed + * when either the the frame is successfully sent and removed or if the frame is discarded. + * + * @param[in] aMessage A reference to the message to be added to current frame. + * + * @retval kThreadError_None Successfully added the message to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add message. + * + */ + virtual ThreadError OutboundFrameFeedMessage(Message &aMessage) = 0; + /** + * This method finalizes and sends the current outbound frame + * + * If no buffer space is available, this method should discard and clear the frame before returning an error status. + * + * @retval kThreadError_None Successfully added the message to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add message. + * + */ virtual ThreadError OutboundFrameSend(void) = 0; protected: /** - * Called by the superclass to indicate when a frame has been received. + * Called by the subclass to indicate when a frame has been received. */ void HandleReceive(const uint8_t *buf, uint16_t bufLength); /** - * Called by the superclass to indicate when a send has been completed. + * Called by the subclass to indicate when a frame was removed and some space in tx buffer is available. */ - void HandleSendDone(void); + void HandleSpaceAvailableInTxBuffer(void); private: /** * Trampoline for HandleDatagramFromStack(). */ - static void HandleDatagramFromStack(otMessage message); + static void HandleDatagramFromStack(otMessage aMessage); - void HandleDatagramFromStack(Message &message); + void HandleDatagramFromStack(Message &aMessage); /** * Trampoline for HandleActiveScanResult(). @@ -111,17 +154,20 @@ private: private: - void HandleCommand(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); + ThreadError HandleCommand(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key); + ThreadError HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key); - void HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + ThreadError HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); - void HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + ThreadError HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); - void HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + ThreadError HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); - void SendLastStatus(uint8_t header, spinel_status_t lastStatus); + ThreadError SendLastStatus(uint8_t header, spinel_status_t lastStatus); public: @@ -134,13 +180,13 @@ public: private: - typedef void (NcpBase::*CommandHandlerType)(uint8_t header, unsigned int command, const uint8_t *arg_ptr, - uint16_t arg_len); + typedef ThreadError(NcpBase::*CommandHandlerType)(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len); - typedef void (NcpBase::*GetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key); + typedef ThreadError(NcpBase::*GetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key); - typedef void (NcpBase::*SetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); + typedef ThreadError(NcpBase::*SetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len); struct CommandHandlerEntry { @@ -178,125 +224,137 @@ private: static const InsertPropertyHandlerEntry mInsertPropertyHandlerTable[]; static const RemovePropertyHandlerEntry mRemovePropertyHandlerTable[]; - void CommandHandler_NOOP(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void CommandHandler_RESET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void CommandHandler_PROP_VALUE_GET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); - void CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); + ThreadError CommandHandler_NOOP(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); + ThreadError CommandHandler_RESET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); + ThreadError CommandHandler_PROP_VALUE_GET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len); + ThreadError CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len); + ThreadError CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len); + ThreadError CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int command, const uint8_t *arg_ptr, + uint16_t arg_len); - void GetPropertyHandler_ChannelMaskHelper(uint8_t header, spinel_prop_key_t key, uint32_t channel_mask); + ThreadError GetPropertyHandler_ChannelMaskHelper(uint8_t header, spinel_prop_key_t key, uint32_t channel_mask); - void GetPropertyHandler_LAST_STATUS(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PROTOCOL_VERSION(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_INTERFACE_TYPE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_VENDOR_ID(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_CAPS(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NCP_VERSION(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_INTERFACE_COUNT(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_HWADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_LOCK(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_PHY_RSSI(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_15_4_LADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_15_4_SADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_NET_PARTITION_ID(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LEADER(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_IPV6_LL_ADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LEADER_RID(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key); - void GetPropertyHandler_CNTR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_LAST_STATUS(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PROTOCOL_VERSION(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_INTERFACE_TYPE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_VENDOR_ID(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_CAPS(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NCP_VERSION(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_INTERFACE_COUNT(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_HWADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_LOCK(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_RSSI(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_15_4_LADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_15_4_SADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_NET_PARTITION_ID(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LEADER(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_IPV6_LL_ADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LEADER_RID(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_CNTR(uint8_t header, spinel_prop_key_t key); - void SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + ThreadError SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + ThreadError SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + ThreadError SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - - void SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + ThreadError SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key, + ThreadError SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, + uint16_t value_len); + + ThreadError SetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, uint16_t value_len); + ThreadError SetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); - void SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); + ThreadError SetPropertyHandler_CNTR_RESET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); - void InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); + ThreadError InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError InsertPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, + uint16_t value_len); - void RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); - void RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, - uint16_t value_len); + ThreadError RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError RemovePropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); + ThreadError RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t header, spinel_prop_key_t key, + const uint8_t *value_ptr, + uint16_t value_len); private: enum @@ -311,32 +369,19 @@ private: uint32_t mChannelMask; - uint8_t mQueuedGetHeader; - uint16_t mScanPeriod; - spinel_prop_key_t mQueuedGetKey; - - Tasklet mSendDoneTask; - Tasklet mUpdateChangedPropsTask; - MessageQueue mSendQueue; - uint32_t mChangedFlags; + spinel_tid_t mDroppedReplyTid; + + uint16_t mDroppedReplyTidBitSet; + otNetifAddress mNetifAddresses[kNetifAddressListSize]; bool mAllowLocalNetworkDataChange; - -protected: - /** - * Set to true when there is a send in progress. Set and cleared - * by the superclass. Should be considered read-only by everyone - * except the superclass! - */ - bool mSending; - }; } // namespace Thread diff --git a/src/ncp/ncp_buffer.cpp b/src/ncp/ncp_buffer.cpp index 462af41ab..4a577b98d 100644 --- a/src/ncp/ncp_buffer.cpp +++ b/src/ncp/ncp_buffer.cpp @@ -108,7 +108,7 @@ void NcpFrameBuffer::SetCallbacks(BufferCallback aEmptyBufferCallback, BufferCal uint8_t *NcpFrameBuffer::Next(uint8_t *aBufPtr) const { aBufPtr++; - return (aBufPtr == mBufferEnd)? mBuffer : aBufPtr; + return (aBufPtr == mBufferEnd) ? mBuffer : aBufPtr; } // Returns an advanced (moved forward) version of the given buffer pointer by the given offset. @@ -383,6 +383,7 @@ exit: { mReadState = kReadStateDone; } + return error; } @@ -487,7 +488,7 @@ uint8_t NcpFrameBuffer::OutFrameReadByte(void) // Check if at end of current segment. if (mReadPointer == mReadSegmentTail) { - // Prepare any associated message with this segment. + // Prepare any message associated with this segment. error = OutFramePrepareMessage(); // If there is no message, move to next segment (if any). @@ -508,7 +509,7 @@ uint8_t NcpFrameBuffer::OutFrameReadByte(void) // Check if at the end of content in message buffer. if (mReadPointer == mReadMessageTail) { - // Fill more bytes from current message into message buffer. + // Fill more bytes from current message into message buffer. error = OutFrameFillMessageBuffer(); // If no more bytes in the message, move to next segment (if any). diff --git a/src/ncp/ncp_buffer.hpp b/src/ncp/ncp_buffer.hpp index 0a7196819..0e5285549 100644 --- a/src/ncp/ncp_buffer.hpp +++ b/src/ncp/ncp_buffer.hpp @@ -116,7 +116,8 @@ public: * This method adds a message to the current input frame being written to the buffer. * * If no buffer space is available, this method will discard and clear the frame before returning an error status. - * The passed-in message @aMessage will be freed by the frame buffer when the frame is removed or discarded. + * In case of success, the passed-in message @p aMessage will be owned by the frame buffer instance and will be + * freed when either the the frame is removed or discarded. * * @param[in] aMessage A reference to the message to be added to current frame. * diff --git a/src/ncp/ncp_spi.cpp b/src/ncp/ncp_spi.cpp index 2f75bd5c9..4c98d2c21 100644 --- a/src/ncp/ncp_spi.cpp +++ b/src/ncp/ncp_spi.cpp @@ -89,6 +89,8 @@ NcpSpi::NcpSpi(): memset(mEmptySendFrame, 0, sizeof(SPI_HEADER_LENGTH)); memset(mSendFrame, 0, sizeof(SPI_HEADER_LENGTH)); + mSending = false; + spi_header_set_flag_byte(mSendFrame, SPI_RESET_FLAG); spi_header_set_flag_byte(mEmptySendFrame, SPI_RESET_FLAG); spi_header_set_accept_len(mSendFrame, sizeof(mReceiveFrame) - SPI_HEADER_LENGTH); @@ -327,7 +329,7 @@ void NcpSpi::HandleSendDone(void) mSending = false; mHandlingSendDone = false; - super_t::HandleSendDone(); + super_t::HandleSpaceAvailableInTxBuffer(); } void NcpSpi::HandleRxFrame(void *context) diff --git a/src/ncp/ncp_spi.hpp b/src/ncp/ncp_spi.hpp index c8b611164..91419aafe 100644 --- a/src/ncp/ncp_spi.hpp +++ b/src/ncp/ncp_spi.hpp @@ -79,13 +79,14 @@ private: static void HandleSendDone(void *context); void HandleSendDone(void); + bool mSending; + bool mHandlingRxFrame; Tasklet mHandleRxFrame; bool mHandlingSendDone; Tasklet mHandleSendDone; - uint8_t mEmptySendFrame[SPI_HEADER_LENGTH]; uint8_t mEmptyReceiveFrame[SPI_HEADER_LENGTH]; uint8_t mSendFrame[1500]; diff --git a/src/ncp/ncp_uart.cpp b/src/ncp/ncp_uart.cpp index fd244e083..c3a4e4d43 100644 --- a/src/ncp/ncp_uart.cpp +++ b/src/ncp/ncp_uart.cpp @@ -27,7 +27,7 @@ /** * @file - * This file implements an HDLC interface to the Thread stack. + * This file contains definitions for a UART based NCP interface to the OpenThread stack. */ #include @@ -47,138 +47,158 @@ extern "C" void otNcpInit(void) sNcpUart = new(&sNcpRaw) NcpUart; } -NcpUart::SendHdlcBuffer::SendHdlcBuffer(void) - : BufferWriteIterator() +NcpUart::UartTxBuffer::UartTxBuffer(void) + : Hdlc::Encoder::BufferWriteIterator() { - Reset(); + Clear(); } -void -NcpUart::SendHdlcBuffer::Reset(void) +void NcpUart::UartTxBuffer::Clear(void) { mWritePointer = mBuffer; mRemainingLength = sizeof(mBuffer); } -uint16_t -NcpUart::SendHdlcBuffer::GetLength(void) const +bool NcpUart::UartTxBuffer::IsEmpty(void) const +{ + return mWritePointer == mBuffer; +} + +uint16_t NcpUart::UartTxBuffer::GetLength(void) const { return static_cast(mWritePointer - mBuffer); } -const uint8_t * -NcpUart::SendHdlcBuffer::GetBuffer(void) const +const uint8_t *NcpUart::UartTxBuffer::GetBuffer(void) const { return mBuffer; } -uint16_t -NcpUart::SendHdlcBuffer::GetRemainingLength(void) const -{ - return mRemainingLength; -} - NcpUart::NcpUart(): NcpBase(), - mFrameDecoder(mReceiveFrame, sizeof(mReceiveFrame), &HandleFrame, this), - mSendFrame() + mFrameDecoder(mRxBuffer, sizeof(mRxBuffer), &HandleFrame, this), + mUartBuffer(), + mTxFrameBuffer(mTxBuffer, sizeof(mTxBuffer)), + mUartSendTask(EncodeAndSendToUart, this) { + mState = kStartingFrame; + + mTxFrameBuffer.SetCallbacks(NULL, TxFrameBufferHasData, this); } -uint16_t -NcpUart::OutboundFrameGetRemaining(void) +ThreadError NcpUart::OutboundFrameBegin(void) { - return mSendFrame.GetRemainingLength(); + return mTxFrameBuffer.InFrameBegin(); } -ThreadError -NcpUart::OutboundFrameBegin(void) +ThreadError NcpUart::OutboundFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength) { - ThreadError errorCode; - - mSendFrame.Reset(); - - errorCode = mFrameEncoder.Init(mSendFrame); - - return errorCode; + return mTxFrameBuffer.InFrameFeedData(aDataBuffer, aDataBufferLength); } -ThreadError -NcpUart::OutboundFrameFeedData(const uint8_t *frame, uint16_t frameLength) +ThreadError NcpUart::OutboundFrameFeedMessage(Message &aMessage) { - ThreadError errorCode; - - errorCode = mFrameEncoder.Encode(frame, frameLength, mSendFrame); - - return errorCode; + return mTxFrameBuffer.InFrameFeedMessage(aMessage); } -ThreadError -NcpUart::OutboundFrameFeedMessage(Message &message) +ThreadError NcpUart::OutboundFrameSend(void) { - ThreadError errorCode; - uint16_t inLength; - uint8_t inBuf[16]; + return mTxFrameBuffer.InFrameEnd(); +} - for (int offset = 0; offset < message.GetLength(); offset += sizeof(inBuf)) +void NcpUart::TxFrameBufferHasData(void *aContext, NcpFrameBuffer *aNcpFrameBuffer) +{ + (void)aContext; + (void)aNcpFrameBuffer; + + sNcpUart->TxFrameBufferHasData(); +} + +void NcpUart::TxFrameBufferHasData(void) +{ + if (mUartBuffer.IsEmpty()) { - (void) OutboundFrameGetRemaining(); - inLength = message.Read(offset, sizeof(inBuf), inBuf); + mUartSendTask.Post(); + } +} - errorCode = OutboundFrameFeedData(inBuf, inLength); +void NcpUart::EncodeAndSendToUart(void *aContext) +{ + NcpUart *obj = reinterpret_cast(aContext); - if (errorCode != kThreadError_None) + obj->EncodeAndSendToUart(); +} + +// This method encodes a frame from the tx frame buffer (mTxFrameBuffer) into the uart buffer and sends it over uart. +// If the uart buffer gets full, it sends the current encoded portion. This method remembers current state, so on +// sub-sequent calls, it restarts encoding the bytes from where it left of in the frame . +void NcpUart::EncodeAndSendToUart(void) +{ + uint16_t len; + + while (!mTxFrameBuffer.IsEmpty()) + { + switch (mState) { - break; + case kStartingFrame: + + SuccessOrExit(mFrameEncoder.Init(mUartBuffer)); + + mTxFrameBuffer.OutFrameBegin(); + + mState = kEncodingFrame; + + while (!mTxFrameBuffer.OutFrameHasEnded()) + { + mByte = mTxFrameBuffer.OutFrameReadByte(); + + case kEncodingFrame: + + SuccessOrExit(mFrameEncoder.Encode(mByte, mUartBuffer)); + } + + mTxFrameBuffer.OutFrameRemove(); + + // Notify the super/base class that there is space available in tx frame buffer for a new frame. + super_t::HandleSpaceAvailableInTxBuffer(); + + mState = kFinalizingFrame; + + case kFinalizingFrame: + + SuccessOrExit(mFrameEncoder.Finalize(mUartBuffer)); + + mState = kStartingFrame; } } - return errorCode; -} +exit: + len = mUartBuffer.GetLength(); -ThreadError -NcpUart::OutboundFrameSend(void) -{ - ThreadError errorCode; - - errorCode = mFrameEncoder.Finalize(mSendFrame); - - if (errorCode == kThreadError_None) + if (len > 0) { - // We go ahead and set this to `true` here in case - // `otPlatUartSend()` ends up directly calling - // `otPlatUartSendDone()`. - mSending = true; - - errorCode = otPlatUartSend(mSendFrame.GetBuffer(), mSendFrame.GetLength()); + otPlatUartSend(mUartBuffer.GetBuffer(), len); } - - if (errorCode != kThreadError_None) - { - mSending = false; - } - - return errorCode; } extern "C" void otPlatUartSendDone(void) { - sNcpUart->SendDoneTask(); + sNcpUart->HandleUartSendDone(); } -void NcpUart::SendDoneTask(void) +void NcpUart::HandleUartSendDone(void) { - mSending = false; + mUartBuffer.Clear(); - super_t::HandleSendDone(); + mUartSendTask.Post(); } extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength) { - sNcpUart->ReceiveTask(aBuf, aBufLength); + sNcpUart->HandleUartReceiveDone(aBuf, aBufLength); } -void NcpUart::ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength) +void NcpUart::HandleUartReceiveDone(const uint8_t *aBuf, uint16_t aBufLength) { mFrameDecoder.Decode(aBuf, aBufLength); } @@ -195,4 +215,3 @@ void NcpUart::HandleFrame(uint8_t *aBuf, uint16_t aBufLength) } } // namespace Thread - diff --git a/src/ncp/ncp_uart.hpp b/src/ncp/ncp_uart.hpp index 99e598862..82e848067 100644 --- a/src/ncp/ncp_uart.hpp +++ b/src/ncp/ncp_uart.hpp @@ -27,7 +27,7 @@ /** * @file - * This file contains definitions for an FLEN/HDLC interface to the OpenThread stack. + * This file contains definitions for a UART based NCP interface to the OpenThread stack. */ #ifndef NCP_UART_HPP_ @@ -36,6 +36,7 @@ #include #include #include +#include namespace Thread { @@ -46,38 +47,114 @@ class NcpUart : public NcpBase public: NcpUart(); + /** + * This method is called to start a new outbound frame. + * + * @retval kThreadError_None Successfully started a new frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to start a new frame. + * + */ virtual ThreadError OutboundFrameBegin(void); - virtual uint16_t OutboundFrameGetRemaining(void); - virtual ThreadError OutboundFrameFeedData(const uint8_t *frame, uint16_t frameLength); - virtual ThreadError OutboundFrameFeedMessage(Message &message); + + /** + * This method adds data to the current outbound frame being written. + * + * If no buffer space is available, this method will discard and clear the frame before returning an error status. + * + * @param[in] aDataBuffer A pointer to data buffer. + * @param[in] aDataBufferLength The length of the data buffer. + * + * @retval kThreadError_None Successfully added new data to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add data. + * + */ + virtual ThreadError OutboundFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength); + + /** + * This method adds a message to the current outbound frame being written. + * + * If no buffer space is available, this method will discard and clear the frame before returning an error status. + * In case of success, the passed-in message @aMessage will be owned by outbound buffer and will be freed + * when either the the frame is successfully sent and removed or if the frame is discarded. + * + * @param[in] aMessage A reference to the message to be added to current frame. + * + * @retval kThreadError_None Successfully added the message to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add message. + * + */ + virtual ThreadError OutboundFrameFeedMessage(Message &aMessage); + + /** + * This method finalizes and sends the current outbound frame. + * + * If no buffer space is available, this method will discard and clear the frame before returning an error status. + * + * @retval kThreadError_None Successfully added the message to the frame. + * @retval kThreadError_NoBufs Insufficient buffer space available to add message. + * + */ virtual ThreadError OutboundFrameSend(void); - void SendDoneTask(void); - void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength); + /** + * This method is called when uart tx is finished. It prepares and sends the next data chunk (if any) to uart. + * + */ + void HandleUartSendDone(void); + + /** + * This method is called when uart received a data buffer. + * + */ + void HandleUartReceiveDone(const uint8_t *aBuf, uint16_t aBufLength); private: - static void HandleFrame(void *context, uint8_t *aBuf, uint16_t aBufLength); - void HandleFrame(uint8_t *aBuf, uint16_t aBufLength); - Hdlc::Encoder mFrameEncoder; - Hdlc::Decoder mFrameDecoder; + enum + { + kUartTxBufferSize = 128, // Uart tx buffer size. + kTxBufferSize = 512, // Tx Buffer size (used by mTxFrameBuffer). + kRxBufferSize = 1500, // Rx buffer size (should be large enough to fit one whole (decoded) received frame). + }; - class SendHdlcBuffer : public Hdlc::Encoder::BufferWriteIterator + enum UartTxState + { + kStartingFrame, // Starting a new frame. + kEncodingFrame, // In middle of encoding a frame. + kFinalizingFrame, // Finalizing a frame. + }; + + class UartTxBuffer : public Hdlc::Encoder::BufferWriteIterator { public: - SendHdlcBuffer(void); + UartTxBuffer(void); - void Reset(void); + void Clear(void); + bool IsEmpty(void) const; uint16_t GetLength(void) const; - uint16_t GetRemainingLength(void) const; const uint8_t *GetBuffer(void) const; private: - uint8_t mBuffer[1500]; + uint8_t mBuffer[kUartTxBufferSize]; }; - SendHdlcBuffer mSendFrame; - uint8_t mReceiveFrame[1500]; + void EncodeAndSendToUart(void); + void HandleFrame(uint8_t *aBuf, uint16_t aBufLength); + void TxFrameBufferHasData(void); + + static void EncodeAndSendToUart(void *aContext); + static void HandleFrame(void *context, uint8_t *aBuf, uint16_t aBufLength); + static void TxFrameBufferHasData(void *aContext, NcpFrameBuffer *aNcpFrameBuffer); + + Hdlc::Encoder mFrameEncoder; + Hdlc::Decoder mFrameDecoder; + UartTxBuffer mUartBuffer; + NcpFrameBuffer mTxFrameBuffer; + UartTxState mState; + uint8_t mByte; + uint8_t mTxBuffer[kTxBufferSize]; + uint8_t mRxBuffer[kRxBufferSize]; + Tasklet mUartSendTask; }; } // namespace Thread