diff --git a/examples/drivers/windows/otCli/main.cpp b/examples/drivers/windows/otCli/main.cpp index 6c869c24b..c30b2c815 100644 --- a/examples/drivers/windows/otCli/main.cpp +++ b/examples/drivers/windows/otCli/main.cpp @@ -32,6 +32,7 @@ #include #include #include +#include bool skipNextLine = false; @@ -83,3 +84,8 @@ EXTERN_C ThreadError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) return error; } + +EXTERN_C void otPlatWakeHost(void) +{ + +} diff --git a/examples/platforms/cc2538/misc.c b/examples/platforms/cc2538/misc.c index 528c23376..3f32f7c58 100644 --- a/examples/platforms/cc2538/misc.c +++ b/examples/platforms/cc2538/misc.c @@ -43,3 +43,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) // TODO: Write me! return kPlatResetReason_PowerOn; } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/cc2650/misc.c b/examples/platforms/cc2650/misc.c index 16a269a37..0665413b0 100644 --- a/examples/platforms/cc2650/misc.c +++ b/examples/platforms/cc2650/misc.c @@ -69,3 +69,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) return kPlatResetReason_Unknown; } } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/da15000/misc.c b/examples/platforms/da15000/misc.c old mode 100755 new mode 100644 index 270667ea1..9d9ce80cd --- a/examples/platforms/da15000/misc.c +++ b/examples/platforms/da15000/misc.c @@ -43,3 +43,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) (void)aInstance; return kPlatResetReason_PowerOn; } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/efr32/misc.c b/examples/platforms/efr32/misc.c index 8f84222c5..d3b105720 100644 --- a/examples/platforms/efr32/misc.c +++ b/examples/platforms/efr32/misc.c @@ -93,3 +93,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) return reason; } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/nrf52840/misc.c b/examples/platforms/nrf52840/misc.c index bd026d72c..a3987cc1f 100644 --- a/examples/platforms/nrf52840/misc.c +++ b/examples/platforms/nrf52840/misc.c @@ -99,3 +99,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) return reason; } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/posix/misc.c b/examples/platforms/posix/misc.c index 8e14f744c..2b833bb55 100644 --- a/examples/platforms/posix/misc.c +++ b/examples/platforms/posix/misc.c @@ -42,3 +42,8 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) (void)aInstance; return kPlatResetReason_PowerOn; } + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/include/openthread/platform/misc.h b/include/openthread/platform/misc.h index e22b5d238..d1e7b5e97 100644 --- a/include/openthread/platform/misc.h +++ b/include/openthread/platform/misc.h @@ -99,6 +99,13 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance); */ void otPlatAssertFail(const char *aFilename, int aLineNumber); +/** + * This function performs a platform specific operation to wake the host MCU. + * This is used only for NCP configurations. + * + */ +void otPlatWakeHost(void); + /** * @} * diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index f54850e3b..917b724aa 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -119,6 +119,7 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = { SPINEL_PROP_POWER_STATE, &NcpBase::GetPropertyHandler_POWER_STATE }, { SPINEL_PROP_HWADDR, &NcpBase::GetPropertyHandler_HWADDR }, { SPINEL_PROP_LOCK, &NcpBase::GetPropertyHandler_LOCK }, + { SPINEL_PROP_HOST_POWER_STATE, &NcpBase::GetPropertyHandler_HOST_POWER_STATE }, { SPINEL_PROP_PHY_ENABLED, &NcpBase::GetPropertyHandler_PHY_ENABLED }, { SPINEL_PROP_PHY_FREQ, &NcpBase::GetPropertyHandler_PHY_FREQ }, @@ -270,6 +271,7 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] = { { SPINEL_PROP_POWER_STATE, &NcpBase::SetPropertyHandler_POWER_STATE }, + { SPINEL_PROP_HOST_POWER_STATE, &NcpBase::SetPropertyHandler_HOST_POWER_STATE }, #if OPENTHREAD_ENABLE_RAW_LINK_API { SPINEL_PROP_PHY_ENABLED, &NcpBase::SetPropertyHandler_PHY_ENABLED }, @@ -566,6 +568,9 @@ NcpBase::NcpBase(otInstance *aInstance): mUpdateChangedPropsTask(aInstance->mIp6.mTaskletScheduler, &NcpBase::UpdateChangedProps, this), mChangedFlags(NCP_PLAT_RESET_REASON), mShouldSignalEndOfScan(false), + mHostPowerState(SPINEL_HOST_POWER_STATE_ONLINE), + mHostPowerStateInProgress(false), + mHostPowerStateHeader(0), #if OPENTHREAD_ENABLE_JAM_DETECTION mShouldSignalJamStateChange(false), #endif @@ -1240,6 +1245,19 @@ exit: // MARK: Serial Traffic Glue // ---------------------------------------------------------------------------- +void NcpBase::HandleFrameTransmitDone(void *aContext, ThreadError aError) +{ + NcpBase *obj = static_cast(aContext); + obj->HandleFrameTransmitDone(aError); +} + +void NcpBase::HandleFrameTransmitDone(ThreadError aError) +{ + (void) aError; + + mHostPowerStateInProgress = false; +} + ThreadError NcpBase::OutboundFrameSend(void) { ThreadError errorCode; @@ -1265,6 +1283,11 @@ void NcpBase::HandleReceive(const uint8_t *buf, uint16_t bufLength) parsedLength = spinel_datatype_unpack(buf, bufLength, SPINEL_DATATYPE_COMMAND_S SPINEL_DATATYPE_DATA_S, &header, &command, &arg_ptr, &arg_len); tid = SPINEL_HEADER_GET_TID(header); + // Receiving any message from the host has the side effect of transitioning the host power state to online. + mHostPowerState = SPINEL_HOST_POWER_STATE_ONLINE; + mHostPowerStateInProgress = false; + mTxFrameBuffer.SetFrameTransmitCallback(NULL, NULL); + if (parsedLength == bufLength) { errorCode = HandleCommand(header, command, arg_ptr, static_cast(arg_len)); @@ -1367,12 +1390,39 @@ void NcpBase::HandleSpaceAvailableInTxBuffer(void) } #endif // OPENTHREAD_ENABLE_JAM_DETECTION + if (mHostPowerStateHeader) + { + SuccessOrExit( + GetPropertyHandler_HOST_POWER_STATE( + mHostPowerStateHeader, + SPINEL_PROP_HOST_POWER_STATE + )); + + mHostPowerStateHeader = 0; + + if (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE) + { + mTxFrameBuffer.SetFrameTransmitCallback(&NcpBase::HandleFrameTransmitDone, this); + mHostPowerStateInProgress = true; + } + } + UpdateChangedProps(); exit: return; } +bool NcpBase::ShouldWakeHost(void) +{ + return (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE && !mHostPowerStateInProgress); +} + +bool NcpBase::ShouldDeferHostSend(void) +{ + return (mHostPowerState == SPINEL_HOST_POWER_STATE_DEEP_SLEEP && !mHostPowerStateInProgress); +} + void NcpBase::IncrementFrameErrorCounter(void) { mFramingErrorCounter++; @@ -1952,6 +2002,17 @@ ThreadError NcpBase::GetPropertyHandler_LOCK(uint8_t header, spinel_prop_key_t k return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } +ThreadError NcpBase::GetPropertyHandler_HOST_POWER_STATE(uint8_t header, spinel_prop_key_t key) +{ + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_UINT8_S, + mHostPowerState + ); +} + ThreadError NcpBase::GetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key) { return SendPropertyUpdate( @@ -3657,6 +3718,77 @@ ThreadError NcpBase::SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_ return SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } +ThreadError NcpBase::SetPropertyHandler_HOST_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) +{ + uint8_t value; + spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + SPINEL_DATATYPE_UINT8_S, + &value + ); + + if (parsedLength > 0) + { + switch (value) + { + case SPINEL_HOST_POWER_STATE_OFFLINE: + case SPINEL_HOST_POWER_STATE_DEEP_SLEEP: + case SPINEL_HOST_POWER_STATE_LOW_POWER: + case SPINEL_HOST_POWER_STATE_ONLINE: + // Adopt the requested power state. + mHostPowerState = static_cast(value); + break; + + case SPINEL_HOST_POWER_STATE_RESERVED: + // Per the specification, treat this as synonymous with SPINEL_HOST_POWER_STATE_DEEP_SLEEP. + mHostPowerState = SPINEL_HOST_POWER_STATE_DEEP_SLEEP; + break; + + default: + // Per the specification, treat unrecognized values as synonymous with SPINEL_HOST_POWER_STATE_LOW_POWER. + mHostPowerState = SPINEL_HOST_POWER_STATE_LOW_POWER; + break; + } + } + else + { + errorCode = kThreadError_Parse; + } + + if (errorCode == kThreadError_None) + { + mHostPowerStateHeader = 0; + + errorCode = HandleCommandPropertyGet(header, key); + + if (mHostPowerState != SPINEL_HOST_POWER_STATE_ONLINE) + { + if (errorCode == kThreadError_None) + { + mTxFrameBuffer.SetFrameTransmitCallback(&NcpBase::HandleFrameTransmitDone, this); + } + + mHostPowerStateInProgress = true; + } + + if (errorCode != kThreadError_None) + { + mHostPowerStateHeader = header; + } + } + else + { + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + + return errorCode; +} + #if OPENTHREAD_ENABLE_RAW_LINK_API ThreadError NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 716110c66..d4d7a6554 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -140,6 +140,16 @@ protected: */ void HandleSpaceAvailableInTxBuffer(void); + /** + * Called by the subclass to learn when the host wake operation must be issued. + */ + bool ShouldWakeHost(void); + + /** + * Called by the subclass to learn when the transfer to the host should be deferred. + */ + bool ShouldDeferHostSend(void); + private: ThreadError OutboundFrameSend(void); @@ -230,6 +240,10 @@ private: static void HandleNetifStateChanged(uint32_t flags, void *context); + static void HandleFrameTransmitDone(void *aContext, ThreadError aError); + + void HandleFrameTransmitDone(ThreadError aError); + private: ThreadError OutboundFrameFeedPacked(const char *pack_format, ...); @@ -336,6 +350,7 @@ private: 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_HOST_POWER_STATE(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); @@ -436,6 +451,8 @@ private: ThreadError SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + ThreadError SetPropertyHandler_HOST_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); ThreadError SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, @@ -660,6 +677,9 @@ private: Tasklet mUpdateChangedPropsTask; uint32_t mChangedFlags; bool mShouldSignalEndOfScan; + spinel_host_power_state_t mHostPowerState; + bool mHostPowerStateInProgress; + uint8_t mHostPowerStateHeader; #if OPENTHREAD_ENABLE_JAM_DETECTION bool mShouldSignalJamStateChange; diff --git a/src/ncp/ncp_buffer.cpp b/src/ncp/ncp_buffer.cpp index b17376b57..9c393940c 100644 --- a/src/ncp/ncp_buffer.cpp +++ b/src/ncp/ncp_buffer.cpp @@ -52,6 +52,7 @@ NcpFrameBuffer::NcpFrameBuffer(uint8_t *aBuffer, uint16_t aBufferLen) : otMessageQueueInit(&mMessageQueue); otMessageQueueInit(&mWriteFrameMessageQueue); SetCallbacks(NULL, NULL, NULL); + SetFrameTransmitCallback(NULL, NULL); Clear(); } @@ -102,7 +103,17 @@ void NcpFrameBuffer::Clear(void) { if (mEmptyBufferCallback != NULL) { - mEmptyBufferCallback(mCallbackContext, this); + mEmptyBufferCallback(mEmptyBufferCallbackContext, this); + } + } + + if (mFrameTransmitMark == mReadFrameStart) + { + if (mFrameTransmitCallback != NULL) + { + mFrameTransmitCallback(mFrameTransmitContext, kThreadError_Abort); + mFrameTransmitCallback = NULL; + mFrameTransmitMark = NULL; } } } @@ -112,7 +123,29 @@ void NcpFrameBuffer::SetCallbacks(BufferCallback aEmptyBufferCallback, BufferCal { mEmptyBufferCallback = aEmptyBufferCallback; mNonEmptyBufferCallback = aNonEmptyBufferCallback; - mCallbackContext = aContext; + mEmptyBufferCallbackContext = aContext; +} + +ThreadError NcpFrameBuffer::SetFrameTransmitCallback(FrameTransmitCallback aFrameTransmitCallback, void *aContext) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(mFrameTransmitCallback == NULL || aFrameTransmitCallback == NULL, error = kThreadError_Busy); + + mFrameTransmitCallback = aFrameTransmitCallback; + mFrameTransmitContext = aContext; + + if (mFrameTransmitCallback != NULL) + { + mFrameTransmitMark = mWriteFrameStart; + } + else + { + mFrameTransmitMark = NULL; + } + +exit: + return error; } // Returns the next buffer pointer addressing the wrap-around at the end of buffer. @@ -329,7 +362,7 @@ ThreadError NcpFrameBuffer::InFrameEnd(void) { if (mNonEmptyBufferCallback != NULL) { - mNonEmptyBufferCallback(mCallbackContext, this); + mNonEmptyBufferCallback(mEmptyBufferCallbackContext, this); } } @@ -603,7 +636,17 @@ ThreadError NcpFrameBuffer::OutFrameRemove(void) { if (mEmptyBufferCallback != NULL) { - mEmptyBufferCallback(mCallbackContext, this); + mEmptyBufferCallback(mEmptyBufferCallbackContext, this); + } + } + + if (mFrameTransmitMark == mReadFrameStart) + { + if (mFrameTransmitCallback != NULL) + { + mFrameTransmitCallback(mFrameTransmitContext, kThreadError_None); + mFrameTransmitCallback = NULL; + mFrameTransmitMark = NULL; } } diff --git a/src/ncp/ncp_buffer.hpp b/src/ncp/ncp_buffer.hpp index 340456380..f5aa0ed71 100644 --- a/src/ncp/ncp_buffer.hpp +++ b/src/ncp/ncp_buffer.hpp @@ -51,6 +51,15 @@ public: */ typedef void (*BufferCallback)(void *aContext, NcpFrameBuffer *aNcpFrameBuffer); + /** + * Defines a function pointer callback which is invoked to inform that a pre-tagged frame has transmitted. + * + * @param[in] aContext A pointer to arbitrary context information. + * @param[in] aError An error value representing the success or failure of the frame transmit attempt. + * + */ + typedef void (*FrameTransmitCallback)(void *aContext, ThreadError aError); + /** * This constructor creates an NCP frame buffer. * @@ -234,6 +243,19 @@ public: */ uint16_t OutFrameGetLength(void); + /** + * This method provides a callback to NcpBuffer that it will use when the last successfully written + * frame is removed from the buffer. + * + * @param[in] aFrameTransmitCallback Callback invoked when NcpBuffer transmits the current last frame. + * @param[in] aContex A pointer to arbitrary context information. + * + * @retval kThreadError_None Successfully accepted the callback. + * @retval kThreadError_Busy The feature is already in use and busy. + * + */ + ThreadError SetFrameTransmitCallback(FrameTransmitCallback aFrameTransmitCallback, void *aContext); + private: /* @@ -324,34 +346,38 @@ private: // Instance variables - uint8_t * const mBuffer; // Pointer to the buffer used to store the data. - uint8_t * const mBufferEnd; // Points to after the end of buffer. - const uint16_t mBufferLength; // Length of the the buffer. + uint8_t * const mBuffer; // Pointer to the buffer used to store the data. + uint8_t * const mBufferEnd; // Points to after the end of buffer. + const uint16_t mBufferLength; // Length of the the buffer. - BufferCallback mEmptyBufferCallback; // Callback to signal when buffer becomes empty. - BufferCallback mNonEmptyBufferCallback; // Callback to signal when buffer becomes non-empty. - void * mCallbackContext; // Context passed to callbacks. + BufferCallback mEmptyBufferCallback; // Callback to signal when buffer becomes empty. + BufferCallback mNonEmptyBufferCallback; // Callback to signal when buffer becomes non-empty. + void * mEmptyBufferCallbackContext;// Context passed to callbacks. - otMessageQueue mMessageQueue; // Main message queue. + FrameTransmitCallback mFrameTransmitCallback; // Callback to signal when a particular frame has been transmitted. + void * mFrameTransmitContext; // Context passed to mFrameTransmitCallback; + uint8_t * mFrameTransmitMark; // The end position of the desired frame in the frame buffer. - otMessageQueue mWriteFrameMessageQueue; // Message queue for the current frame being written. - uint8_t * mWriteFrameStart; // Pointer to start of current frame being written. - uint8_t * mWriteSegmentHead; // Pointer to start of current segment in the frame being written. - uint8_t * mWriteSegmentTail; // Pointer to end of current segment in the frame being written. + otMessageQueue mMessageQueue; // Main message queue. - ReadState mReadState; // Read state. - uint16_t mReadFrameLength; // Length of current frame being read. + otMessageQueue mWriteFrameMessageQueue; // Message queue for the current frame being written. + uint8_t * mWriteFrameStart; // Pointer to start of current frame being written. + uint8_t * mWriteSegmentHead; // Pointer to start of current segment in the frame being written. + uint8_t * mWriteSegmentTail; // Pointer to end of current segment in the frame being written. - uint8_t * mReadFrameStart; // Pointer to start of current frame being read. - uint8_t * mReadSegmentHead; // Pointer to start of current segment in the frame being read. - uint8_t * mReadSegmentTail; // Pointer to end of current segment in the frame being read. - uint8_t * mReadPointer; // Pointer to next byte to read (either in segment or in msg buffer). + ReadState mReadState; // Read state. + uint16_t mReadFrameLength; // Length of current frame being read. - otMessage * mReadMessage; // Current Message in the frame being read. - uint16_t mReadMessageOffset; // Offset within current message being read. + uint8_t * mReadFrameStart; // Pointer to start of current frame being read. + uint8_t * mReadSegmentHead; // Pointer to start of current segment in the frame being read. + uint8_t * mReadSegmentTail; // Pointer to end of current segment in the frame being read. + uint8_t * mReadPointer; // Pointer to next byte to read (either in segment or in msg buffer). - uint8_t mMessageBuffer[kMessageReadBufferSize]; // Buffer to hold part of current message being read. - uint8_t * mReadMessageTail; // Pointer to end of current part in mMessageBuffer. + otMessage * mReadMessage; // Current Message in the frame being read. + uint16_t mReadMessageOffset; // Offset within current message being read. + + uint8_t mMessageBuffer[kMessageReadBufferSize]; // Buffer to hold part of current message being read. + uint8_t * mReadMessageTail; // Pointer to end of current part in mMessageBuffer. }; } // namespace ot diff --git a/src/ncp/ncp_spi.cpp b/src/ncp/ncp_spi.cpp index d331f2e4a..560d6855f 100644 --- a/src/ncp/ncp_spi.cpp +++ b/src/ncp/ncp_spi.cpp @@ -40,6 +40,7 @@ #include #include +#include #include "openthread-core-config.h" #include "openthread-instance.h" @@ -239,6 +240,11 @@ ThreadError NcpSpi::PrepareNextSpiSendFrame(void) VerifyOrExit(!mTxFrameBuffer.IsEmpty()); + if (super_t::ShouldWakeHost()) + { + otPlatWakeHost(); + } + SuccessOrExit(errorCode = mTxFrameBuffer.OutFrameBegin()); frameLength = mTxFrameBuffer.OutFrameGetLength(); diff --git a/src/ncp/ncp_uart.cpp b/src/ncp/ncp_uart.cpp index 7ddfdd91a..3a9768630 100644 --- a/src/ncp/ncp_uart.cpp +++ b/src/ncp/ncp_uart.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "openthread-core-config.h" #include "openthread-instance.h" @@ -143,6 +144,12 @@ void NcpUart::EncodeAndSendToUart(void) { case kStartingFrame: + if (super_t::ShouldWakeHost()) + { + otPlatWakeHost(); + } + + VerifyOrExit(super_t::ShouldDeferHostSend() == false); SuccessOrExit(mFrameEncoder.Init(mUartBuffer)); mTxFrameBuffer.OutFrameBegin(); diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index ce66bc318..a0cc06ea5 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -940,6 +940,10 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_HBO_BLOCK_MAX"; break; + case SPINEL_PROP_HOST_POWER_STATE: + ret = "PROP_HOST_POWER_STATE"; + break; + case SPINEL_PROP_STREAM_DEBUG: ret = "PROP_STREAM_DEBUG"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 731770da1..7a98d9468 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -190,6 +190,15 @@ typedef enum SPINEL_POWER_STATE_ONLINE = 4, } spinel_power_state_t; +typedef enum +{ + SPINEL_HOST_POWER_STATE_OFFLINE = 0, + SPINEL_HOST_POWER_STATE_DEEP_SLEEP = 1, + SPINEL_HOST_POWER_STATE_RESERVED = 2, + SPINEL_HOST_POWER_STATE_LOW_POWER = 3, + SPINEL_HOST_POWER_STATE_ONLINE = 4, +} spinel_host_power_state_t; + enum { SPINEL_NET_FLAG_ON_MESH = (1 << 0), @@ -399,6 +408,7 @@ typedef enum SPINEL_PROP_LOCK = 9, ///< PropLock [b] SPINEL_PROP_HBO_MEM_MAX = 10, ///< Max offload mem [S] SPINEL_PROP_HBO_BLOCK_MAX = 11, ///< Max offload block [S] + SPINEL_PROP_HOST_POWER_STATE = 12, ///< Host MCU power state [C] SPINEL_PROP_BASE_EXT__BEGIN = 0x1000,