From a091fcaaa7242ceea48897334e54afc3e1fb864d Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Tue, 31 May 2016 10:08:37 -0700 Subject: [PATCH] ncp: Miscellaneous updates (#88) * spinel: Rename `PROP_PHY_PROMISCUOUS_MODE` to `PROP_PHY_MODE`. `PROP_PHY_MODE` is now an enumeration of the following values: * `PHY_MODE_NORMAL`: Normal filtering is in place. * `PHY_MODE_PROMISCUOUS`: Only PANID filtering is in place. * `PHY_MODE_MONITOR`: All channel traffic is passed up from the PHY. * spinel: Add more status codes and related descriptions. * spinel: Add support for fetching the thread network data. * ncp: Add support for the `STREAM_NET_INSECURE` data stream. * ncp: Support returning LQI for scan results. * spinel: Add missing definition of `spinel_prop_key_to_cstr()`. * spinel: Add new thread properties. * `PROP_THREAD_ON_MESH_NETS` : For advertising this device as a border router with an on-mesh prefix. * `PROP_THREAD_LOCAL_ROUTES` : For advertising more specific routes that this node can provide. (Was previously `PROP_IPV6_EXT_ROUTE_TABLE`) * `PROP_THREAD_ASSISTING_PORTS` : A list of port numbers that are allowed to be passed via `PROP_STREAM_NET_INSECURE` when received without security. Empty when this device is not an assisting device. * ncp: Fix for `PROP_FREQ`. The 2.4GHz range was being computed incorrectly. We were also returning the value of the pointer to the frequency. instead of the frequency. * ncp: Code style update. * spinel: Rename `PROP_PHY_MODE` to `PROP_MAC_FILTER_MODE`. Per discussion in #88. Also renamed `SPINEL_PROP_PHY_RAW_STREAM_ENABLED` to `SPINEL_PROP_MAC_RAW_STREAM_ENABLED`, for consistency. --- src/ncp/PROTOCOL.md | 17 +- src/ncp/ncp_base.cpp | 557 +++++++++++++++++++++++++++++++++++++------ src/ncp/ncp_base.hpp | 87 +++++-- src/ncp/spinel.c | 28 ++- src/ncp/spinel.h | 121 ++++++---- 5 files changed, 660 insertions(+), 150 deletions(-) diff --git a/src/ncp/PROTOCOL.md b/src/ncp/PROTOCOL.md index 37b176c3f..18f8f5e01 100644 --- a/src/ncp/PROTOCOL.md +++ b/src/ncp/PROTOCOL.md @@ -1081,11 +1081,6 @@ for managing a thread NCP. * Packed-Encoding: `c` * Unit: dBm -#### D.1.7. PROP x: `PROP_PHY_RAW_STREAM_ENABLED` -* Type: Read-Write -* Packed-Encoding: `b` - -Set to true to enable raw frames to be emitted from `PROP_STREAM_RAW`. @@ -1137,9 +1132,21 @@ chan,rssi,(laddr,saddr,panid,lqi),(proto,flags,networkid,xpanid) [CcT(ESSC)T(iCU * Type: Read-Write * Packed-Encoding: `S` +#### D.2.7. PROP x: `PROP_MAC_RAW_STREAM_ENABLED` +* Type: Read-Write +* Packed-Encoding: `b` +Set to true to enable raw MAC frames to be emitted from `PROP_STREAM_RAW`. +#### D.2.8. PROP x: `PROP_MAC_FILTER_MODE` +* Type: Read-Write +* Packed-Encoding: `C` +Possible Values: + +* 0: `MAC_FILTER_MODE_NORMAL`: Normal MAC filtering is in place. +* 1: `MAC_FILTER_MODE_PROMISCUOUS`: All MAC packets matching network are passed up the stack. +* 2: `MAC_FILTER_MODE_MONITOR`: All decoded MAC packets are passed up the stack. ### D.3. NET Properties diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 8301116e7..33882c6a6 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -95,9 +95,11 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = { SPINEL_PROP_THREAD_LEADER_RID, &NcpBase::GetPropertyHandler_THREAD_LEADER_RID }, { SPINEL_PROP_THREAD_LEADER_WEIGHT, &NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT }, { SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, &NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT }, + { SPINEL_PROP_THREAD_NETWORK_DATA, &NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA }, { SPINEL_PROP_THREAD_NETWORK_DATA_VERSION, &NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION }, + { SPINEL_PROP_THREAD_STABLE_NETWORK_DATA, &NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA }, { SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION, &NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION }, - + { SPINEL_PROP_THREAD_LOCAL_ROUTES, &NcpBase::NcpBase::GetPropertyHandler_THREAD_LOCAL_ROUTES }, { SPINEL_PROP_IPV6_ML_PREFIX, &NcpBase::GetPropertyHandler_IPV6_ML_PREFIX }, { SPINEL_PROP_IPV6_ML_ADDR, &NcpBase::GetPropertyHandler_IPV6_ML_ADDR }, @@ -115,7 +117,7 @@ const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] = { SPINEL_PROP_PHY_ENABLED, &NcpBase::SetPropertyHandler_PHY_ENABLED }, { SPINEL_PROP_PHY_TX_POWER, &NcpBase::NcpBase::SetPropertyHandler_PHY_TX_POWER }, { SPINEL_PROP_PHY_CHAN, &NcpBase::NcpBase::SetPropertyHandler_PHY_CHAN }, - { SPINEL_PROP_PHY_PROMISCUOUS_MODE, &NcpBase::SetPropertyHandler_PHY_PROMISCUOUS_MODE }, + { SPINEL_PROP_MAC_FILTER_MODE, &NcpBase::SetPropertyHandler_MAC_FILTER_MODE }, { SPINEL_PROP_MAC_SCAN_MASK, &NcpBase::NcpBase::SetPropertyHandler_MAC_SCAN_MASK }, { SPINEL_PROP_MAC_SCAN_STATE, &NcpBase::NcpBase::SetPropertyHandler_MAC_SCAN_STATE }, @@ -141,11 +143,15 @@ const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] = const NcpBase::InsertPropertyHandlerEntry NcpBase::mInsertPropertyHandlerTable[] = { { SPINEL_PROP_IPV6_ADDRESS_TABLE, &NcpBase::NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE }, + { SPINEL_PROP_THREAD_LOCAL_ROUTES, &NcpBase::NcpBase::InsertPropertyHandler_THREAD_LOCAL_ROUTES }, + { SPINEL_PROP_THREAD_ON_MESH_NETS, &NcpBase::NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS }, }; const NcpBase::RemovePropertyHandlerEntry NcpBase::mRemovePropertyHandlerTable[] = { { SPINEL_PROP_IPV6_ADDRESS_TABLE, &NcpBase::NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE }, + { SPINEL_PROP_THREAD_LOCAL_ROUTES, &NcpBase::NcpBase::RemovePropertyHandler_THREAD_LOCAL_ROUTES }, + { SPINEL_PROP_THREAD_ON_MESH_NETS, &NcpBase::NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS }, }; // ---------------------------------------------------------------------------- @@ -194,6 +200,14 @@ static spinel_status_t ThreadErrorToSpinelStatus(ThreadError error) ret = SPINEL_STATUS_INVALID_STATE; break; + case kThreadError_NoAck: + ret = SPINEL_STATUS_NO_ACK; + break; + + case kThreadError_ChannelAccessFailure: + ret = SPINEL_STATUS_CCA_FAILURE; + break; + default: ret = SPINEL_STATUS_FAILURE; break; @@ -251,7 +265,9 @@ void NcpBase::HandleDatagramFromStack(Message &message) "CiiS", SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS, - SPINEL_PROP_STREAM_NET, + message.GetSecurityValid() + ? SPINEL_PROP_STREAM_NET + : SPINEL_PROP_STREAM_NET_INSECURE, message.GetLength() ); } @@ -319,17 +335,17 @@ void NcpBase::HandleActiveScanResult(otActiveScanResult *result) SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_INSERTED, SPINEL_PROP_MAC_SCAN_BEACON, - "CcT(ESSC)T(iCUD.).", - result->mChannel,//chan - result->mRssi,//rssi - result->mExtAddress.m8,// laddr - 0xFFFF, // saddr, Not given - result->mPanId,//panid - 0xFF,//lqi, not given - SPINEL_PROTOCOL_TYPE_THREAD,//proto + "CcT(ESSC.)T(iCUD.).", + result->mChannel, + result->mRssi, + result->mExtAddress.m8, // laddr + 0xFFFF, // saddr, Not given + result->mPanId, + result->mLqi, + SPINEL_PROTOCOL_TYPE_THREAD, flags, - result->mNetworkName,//networkid - result->mExtPanId, sizeof(result->mExtPanId) //xpanid + result->mNetworkName, + result->mExtPanId, sizeof(result->mExtPanId) ); } else @@ -429,7 +445,7 @@ void NcpBase::HandleCommand(uint8_t header, unsigned int command, const uint8_t // We only support IID zero for now. VerifyOrExit(SPINEL_HEADER_GET_IID(header) == 0, SendLastStatus(header, SPINEL_STATUS_INVALID_INTERFACE);); - for (i = 0; i < sizeof(mCommandHandlerTable)/sizeof(mCommandHandlerTable[0]); i++) + for (i = 0; i < sizeof(mCommandHandlerTable) / sizeof(mCommandHandlerTable[0]); i++) { if (mCommandHandlerTable[i].mCommand == command) { @@ -437,7 +453,7 @@ void NcpBase::HandleCommand(uint8_t header, unsigned int command, const uint8_t } } - if (i < sizeof(mCommandHandlerTable)/sizeof(mCommandHandlerTable[0])) + if (i < sizeof(mCommandHandlerTable) / sizeof(mCommandHandlerTable[0])) { (this->*mCommandHandlerTable[i].mHandler)(header, command, arg_ptr, arg_len); } @@ -468,7 +484,7 @@ void NcpBase::HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key) ExitNow(;); } - for (i = 0; i < sizeof(mGetPropertyHandlerTable)/sizeof(mGetPropertyHandlerTable[0]); i++) + for (i = 0; i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0]); i++) { if (mGetPropertyHandlerTable[i].mPropKey == key) { @@ -476,13 +492,13 @@ void NcpBase::HandleCommandPropertyGet(uint8_t header, spinel_prop_key_t key) } } - if (i < sizeof(mGetPropertyHandlerTable)/sizeof(mGetPropertyHandlerTable[0])) + if (i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0])) { (this->*mGetPropertyHandlerTable[i].mHandler)(header, key); } else { - SendLastStatus(header, SPINEL_STATUS_PROPERTY_NOT_FOUND); + SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } exit: @@ -509,7 +525,7 @@ void NcpBase::HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, co ExitNow(;); } - for (i = 0; i < sizeof(mSetPropertyHandlerTable)/sizeof(mSetPropertyHandlerTable[0]); i++) + for (i = 0; i < sizeof(mSetPropertyHandlerTable) / sizeof(mSetPropertyHandlerTable[0]); i++) { if (mSetPropertyHandlerTable[i].mPropKey == key) { @@ -517,13 +533,13 @@ void NcpBase::HandleCommandPropertySet(uint8_t header, spinel_prop_key_t key, co } } - if (i < sizeof(mSetPropertyHandlerTable)/sizeof(mSetPropertyHandlerTable[0])) + if (i < sizeof(mSetPropertyHandlerTable) / sizeof(mSetPropertyHandlerTable[0])) { (this->*mSetPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROPERTY_NOT_FOUND); + SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } exit: @@ -550,7 +566,7 @@ void NcpBase::HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, ExitNow(;); } - for (i = 0; i < sizeof(mInsertPropertyHandlerTable)/sizeof(mInsertPropertyHandlerTable[0]); i++) + for (i = 0; i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0]); i++) { if (mInsertPropertyHandlerTable[i].mPropKey == key) { @@ -558,13 +574,13 @@ void NcpBase::HandleCommandPropertyInsert(uint8_t header, spinel_prop_key_t key, } } - if (i < sizeof(mInsertPropertyHandlerTable)/sizeof(mInsertPropertyHandlerTable[0])) + if (i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0])) { (this->*mInsertPropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROPERTY_NOT_FOUND); + SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } exit: @@ -591,7 +607,7 @@ void NcpBase::HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, ExitNow(;); } - for (i = 0; i < sizeof(mRemovePropertyHandlerTable)/sizeof(mRemovePropertyHandlerTable[0]); i++) + for (i = 0; i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0]); i++) { if (mRemovePropertyHandlerTable[i].mPropKey == key) { @@ -599,13 +615,13 @@ void NcpBase::HandleCommandPropertyRemove(uint8_t header, spinel_prop_key_t key, } } - if (i < sizeof(mRemovePropertyHandlerTable)/sizeof(mRemovePropertyHandlerTable[0])) + if (i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0])) { (this->*mRemovePropertyHandlerTable[i].mHandler)(header, key, value_ptr, value_len); } else { - SendLastStatus(header, SPINEL_STATUS_PROPERTY_NOT_FOUND); + SendLastStatus(header, SPINEL_STATUS_PROP_NOT_FOUND); } exit: @@ -751,7 +767,8 @@ void NcpBase::CommandHandler_RESET(uint8_t header, unsigned int command, const u SendLastStatus(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) +void 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; @@ -768,7 +785,8 @@ void NcpBase::CommandHandler_PROP_VALUE_GET(uint8_t header, unsigned int command } } -void NcpBase::CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +void 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; @@ -787,7 +805,8 @@ void NcpBase::CommandHandler_PROP_VALUE_SET(uint8_t header, unsigned int command } } -void NcpBase::CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +void 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; @@ -806,7 +825,8 @@ void NcpBase::CommandHandler_PROP_VALUE_INSERT(uint8_t header, unsigned int comm } } -void NcpBase::CommandHandler_PROP_VALUE_REMOVE(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len) +void 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; @@ -970,7 +990,7 @@ void NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key) } else if (chan < 26) { - freq_khz = 2405 - (5000 * 11) + 5000 * (chan); + freq_khz = 2405000 - (5000 * 11) + 5000 * (chan); } SendPropteryUpdate( @@ -978,12 +998,14 @@ void NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t header, spinel_prop_key_t key) SPINEL_CMD_PROP_VALUE_IS, key, SPINEL_DATATYPE_UINT32_S, - &freq_khz + freq_khz ); } void NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t header, spinel_prop_key_t key) { + // TODO: This list should ideally come from the PHY layer + // because 802.15.4 doesn't just run on 2.4GHz. static const uint8_t supported_channels[] = { 11, 12, 13, 14, 15, 16, 17, 18, @@ -1065,13 +1087,15 @@ void NcpBase::GetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key); } - for (int i = 0; i < 32; i++) { + for (int i = 0; i < 32; i++) + { if (errorCode != kThreadError_None) { break; } - if (0 != (mChannelMask & (1 << i))) { + if (0 != (mChannelMask & (1 << i))) + { errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT8_S, i); } } @@ -1278,6 +1302,72 @@ void NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t head ); } +void NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) +{ + ThreadError errorCode(OutboundFrameBegin()); + 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) + { + sThreadNetif->GetNetworkDataLocal().GetNetworkData( + 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); + } +} + +void NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spinel_prop_key_t key) +{ + ThreadError errorCode(OutboundFrameBegin()); + 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) + { + sThreadNetif->GetNetworkDataLocal().GetNetworkData( + true, // 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); + } +} + void NcpBase::GetPropertyHandler_THREAD_LEADER_RID(uint8_t header, spinel_prop_key_t key) { SendPropteryUpdate( @@ -1344,7 +1434,7 @@ void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ memcpy(addr.m8, ml_prefix, 8); // Zero out the last 8 bytes. - memset(addr.m8+8, 0, 8); + memset(addr.m8 + 8, 0, 8); SendPropteryUpdate( header, @@ -1439,6 +1529,12 @@ void NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t header, spinel_prop_ke SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); } +void 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 NcpBase::GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key) { // TODO: Implement explicit data poll. @@ -1451,13 +1547,15 @@ void NcpBase::GetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke // 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) +void 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 NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1496,13 +1594,15 @@ void NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t header, spinel_prop_key_t k } } -void NcpBase::SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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 NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1534,22 +1634,66 @@ void NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key, } } -void NcpBase::SetPropertyHandler_PHY_PROMISCUOUS_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void NcpBase::SetPropertyHandler_MAC_FILTER_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) { - // TODO: Implement PHY_PROMISCUOUS_MODE, once the API becomes available. - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); + uint8_t i = 0; + spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + SPINEL_DATATYPE_UINT8_S, + &i + ); + + if (parsedLength > 0) + { + errorCode = kThreadError_NotImplemented; + + /* Uncomment when API is available. + switch (i) { + case SPINEL_MAC_FILTER_MODE_NORMAL: + errorCode = otPlatRadioSetPromiscuous(false); + break; + + case SPINEL_MAC_FILTER_MODE_PROMISCUOUS: + case SPINEL_MAC_FILTER_MODE_MONITOR: + errorCode = otPlatRadioSetPromiscuous(true); + break; + } + */ + + if (errorCode == kThreadError_None) + { + SendLastStatus(header, SPINEL_STATUS_OK); + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } } -void NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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) { + for (; value_len != 0; value_len--, value_ptr++) + { + if (value_ptr[0] > 31) + { errorCode = kThreadError_InvalidArgs; break; } + new_mask |= (1 << value_ptr[0]); } @@ -1564,7 +1708,8 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t header, spinel_prop_key_t } } -void NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1586,7 +1731,8 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t header, spinel_prop_key } } -void NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void NcpBase::SetPropertyHandler_MAC_SCAN_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; @@ -1610,10 +1756,10 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_ case SPINEL_SCAN_STATE_BEACON: gActiveScanContextHack = this; errorCode = otActiveScan( - (mChannelMask >> kPhyMinChannel), - mScanPeriod, - &HandleActiveScanResult_Jump - ); + (mChannelMask >> kPhyMinChannel), + mScanPeriod, + &HandleActiveScanResult_Jump + ); break; case SPINEL_SCAN_STATE_ENERGY: @@ -1641,7 +1787,8 @@ void NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_ } -void NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1673,7 +1820,8 @@ void NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_ } } -void NcpBase::SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1712,7 +1860,8 @@ void NcpBase::SetPropertyHandler_NET_ENABLED(uint8_t header, spinel_prop_key_t k } } -void NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1796,7 +1945,8 @@ void NcpBase::SetPropertyHandler_NET_STATE(uint8_t header, spinel_prop_key_t key } } -void NcpBase::SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1845,9 +1995,10 @@ void NcpBase::SetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key_t key, } } -void NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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); + const char *string(NULL); spinel_ssize_t parsedLength; ThreadError errorCode = kThreadError_None; @@ -1877,7 +2028,8 @@ void NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t header, spinel_prop_ke } } -void NcpBase::SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1902,7 +2054,8 @@ void NcpBase::SetPropertyHandler_NET_XPANID(uint8_t header, spinel_prop_key_t ke } } -void NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1936,7 +2089,8 @@ void NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t header, spinel_prop_key_ } } -void NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -1959,7 +2113,8 @@ void NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE(uint8_t header, spinel_prop_ke } } -void NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +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 errorCode = kThreadError_None; uint8_t value = 0; @@ -1993,12 +2148,8 @@ void NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t header, spin -void NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) -{ - SendLastStatus(header, SPINEL_STATUS_UNIMPLEMENTED); -} - -void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -2014,6 +2165,9 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke } else { + // STREAM_NET_INSECURE packets are not secured at layer 2. + message->SetSecurityValid(false); + parsedLength = spinel_datatype_unpack( value_ptr, value_len, @@ -2025,6 +2179,7 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke ); // We ignore metadata for now. + // May later include TX power, allow retransmits, etc... (void)meta_ptr; (void)meta_len; @@ -2051,7 +2206,66 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke } } -void NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; + const uint8_t *frame_ptr(NULL); + unsigned int frame_len(0); + const uint8_t *meta_ptr(NULL); + unsigned int meta_len(0); + Message *message(Ip6::Ip6::NewMessage(0)); + + if (message == NULL) + { + errorCode = kThreadError_NoBufs; + } + else + { + // STREAM_NET requires layer 2 security. + message->SetSecurityValid(true); + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + SPINEL_DATATYPE_DATA_S SPINEL_DATATYPE_DATA_S, + &frame_ptr, + &frame_len, + &meta_ptr, + &meta_len + ); + + // We ignore metadata for now. + // May later include TX power, allow retransmits, etc... + (void)meta_ptr; + (void)meta_len; + + errorCode = message->Append(frame_ptr, frame_len); + } + + if (errorCode == kThreadError_None) + { + errorCode = Ip6::Ip6::HandleDatagram(*message, NULL, sThreadNetif->GetInterfaceId(), NULL, true); + } + + if (errorCode == kThreadError_None) + { + if (SPINEL_HEADER_GET_TID(header) != 0) + { + // Only send a successful status update if + // there was a transaction id in the header. + SendLastStatus(header, SPINEL_STATUS_OK); + } + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(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 errorCode = kThreadError_None; @@ -2081,7 +2295,8 @@ void NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ // ---------------------------------------------------------------------------- -void NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -2124,13 +2339,128 @@ void NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_pr } } +void 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; + + spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; + + otExternalRouteConfig ext_route_config = {}; + otIp6Address *addr_ptr; + bool stable = false; + uint8_t flags = 0; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + "6CbC", + &addr_ptr, + &ext_route_config.mPrefix.mLength, + &stable, + &flags + ); + + if (parsedLength > 0) + { + ext_route_config.mPrefix.mPrefix = *addr_ptr; + ext_route_config.mStable = stable; + ext_route_config.mPreference = ((flags & kPreferenceMask) >> kPreferenceOffset); + errorCode = otAddExternalRoute(&ext_route_config); + + if (errorCode == kThreadError_None) + { + SendPropteryUpdate( + header, + SPINEL_CMD_PROP_VALUE_INSERTED, + key, + value_ptr, + value_len + ); + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } +} + +void 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; + const static int kPreferredFlag = 1 << 5; + const static int kValidFlag = 1 << 4; + const static int kDhcpFlag = 1 << 3; + const static int kConfigureFlag = 1 << 2; + const static int kDefaultRouteFlag = 1 << 1; + + spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; + + otBorderRouterConfig border_router_config = {}; + otIp6Address *addr_ptr; + bool stable = false; + uint8_t flags = 0; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + "6CbC", + &addr_ptr, + &border_router_config.mPrefix.mLength, + &stable, + &flags + ); + + if (parsedLength > 0) + { + border_router_config.mPrefix.mPrefix = *addr_ptr; + border_router_config.mStable = stable; + border_router_config.mPreference = ((flags & kPreferenceMask) >> kPreferenceOffset); + border_router_config.mSlaacPreferred = ((flags & kPreferredFlag) == kPreferredFlag); + border_router_config.mSlaacValid = ((flags & kValidFlag) == kValidFlag); + border_router_config.mDhcp = ((flags & kDhcpFlag) == kDhcpFlag); + border_router_config.mConfigure = ((flags & kConfigureFlag) == kConfigureFlag); + border_router_config.mDefaultRoute = ((flags & kDefaultRouteFlag) == kDefaultRouteFlag); + + errorCode = otAddBorderRouter(&border_router_config); + + if (errorCode == kThreadError_None) + { + SendPropteryUpdate( + header, + SPINEL_CMD_PROP_VALUE_INSERTED, + key, + value_ptr, + value_len + ); + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } +} // ---------------------------------------------------------------------------- // MARK: Individual Property Removers // ---------------------------------------------------------------------------- -void NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) +void 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; @@ -2174,6 +2504,91 @@ void NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_pr } } +void 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; + + otIp6Prefix ip6_prefix = {}; + otIp6Address *addr_ptr; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + "6C", + &addr_ptr, + &ip6_prefix.mLength + ); + + if (parsedLength > 0) + { + ip6_prefix.mPrefix = *addr_ptr; + errorCode = otRemoveExternalRoute(&ip6_prefix); + + if (errorCode == kThreadError_None) + { + SendPropteryUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } +} + +void 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; + + otIp6Prefix ip6_prefix = {}; + otIp6Address *addr_ptr; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + "6C", + &addr_ptr, + &ip6_prefix.mLength + ); + + if (parsedLength > 0) + { + ip6_prefix.mPrefix = *addr_ptr; + errorCode = otRemoveBorderRouter(&ip6_prefix); + + if (errorCode == kThreadError_None) + { + SendPropteryUpdate( + header, + SPINEL_CMD_PROP_VALUE_REMOVED, + key, + value_ptr, + value_len + ); + } + else + { + SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } +} } // namespace Thread diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 52644e636..253077d68 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -120,7 +120,8 @@ private: void SendLastStatus(uint8_t header, spinel_status_t lastStatus); - void SendPropteryUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + void SendPropteryUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); void SendPropteryUpdate(uint8_t header, uint8_t command, spinel_prop_key_t key, Message &message); @@ -128,33 +129,40 @@ private: private: - typedef void (NcpBase::*CommandHandlerType)(uint8_t header, unsigned int command, const uint8_t *arg_ptr, uint16_t arg_len); + typedef void (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 void (NcpBase::*SetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); + typedef void (NcpBase::*SetPropertyHandlerType)(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); - struct CommandHandlerEntry { + struct CommandHandlerEntry + { spinel_cid_t mCommand; CommandHandlerType mHandler; }; - struct GetPropertyHandlerEntry { + struct GetPropertyHandlerEntry + { spinel_prop_key_t mPropKey; GetPropertyHandlerType mHandler; }; - struct SetPropertyHandlerEntry { + struct SetPropertyHandlerEntry + { spinel_prop_key_t mPropKey; SetPropertyHandlerType mHandler; }; - struct InsertPropertyHandlerEntry { + struct InsertPropertyHandlerEntry + { spinel_prop_key_t mPropKey; SetPropertyHandlerType mHandler; }; - struct RemovePropertyHandlerEntry { + struct RemovePropertyHandlerEntry + { spinel_prop_key_t mPropKey; SetPropertyHandlerType mHandler; }; @@ -205,6 +213,7 @@ private: 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); @@ -212,32 +221,60 @@ private: 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 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_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_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_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, 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, + 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_PHY_PROMISCUOUS_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, uint16_t value_len); - void SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(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, + uint16_t value_len); + void SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(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 RemovePropertyHandler_IPV6_ADDRESS_TABLE(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 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); private: diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index dfcad8cd5..7f230bf37 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -882,12 +882,12 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_PHY_RSSI"; break; - case SPINEL_PROP_PHY_RAW_STREAM_ENABLED: - ret = "PROP_PHY_RAW_STREAM_ENABLED"; + case SPINEL_PROP_MAC_RAW_STREAM_ENABLED: + ret = "PROP_MAC_RAW_STREAM_ENABLED"; break; - case SPINEL_PROP_PHY_PROMISCUOUS_MODE: - ret = "PROP_PHY_PROMISCUOUS_MODE"; + case SPINEL_PROP_MAC_FILTER_MODE: + ret = "PROP_MAC_FILTER_MODE"; break; case SPINEL_PROP_MAC_SCAN_STATE: @@ -1006,8 +1006,24 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_IPV6_ROUTE_TABLE"; break; - case SPINEL_PROP_IPV6_EXT_ROUTE_TABLE: - ret = "PROP_IPV6_EXT_ROUTE_TABLE"; + case SPINEL_PROP_THREAD_PARENT: + ret = "SPINEL_PROP_THREAD_PARENT"; + break; + + case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA: + ret = "SPINEL_PROP_THREAD_STABLE_NETWORK_DATA"; + break; + + case SPINEL_PROP_THREAD_ON_MESH_NETS: + ret = "SPINEL_PROP_THREAD_ON_MESH_NETS"; + break; + + case SPINEL_PROP_THREAD_LOCAL_ROUTES: + ret = "PROP_THREAD_LOCAL_ROUTES"; + break; + + case SPINEL_PROP_THREAD_ASSISTING_PORTS: + ret = "PROP_THREAD_ASSISTING_PORTS"; break; default: diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 4bfbb5802..2f97314ca 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -69,23 +69,26 @@ __BEGIN_DECLS typedef enum { - SPINEL_STATUS_OK = 0, //!< Operation has completed successfully. - SPINEL_STATUS_FAILURE = 1, //!< Operation has failed for some undefined reason. + SPINEL_STATUS_OK = 0, ///< Operation has completed successfully. + SPINEL_STATUS_FAILURE = 1, ///< Operation has failed for some undefined reason. - SPINEL_STATUS_UNIMPLEMENTED = 2, - SPINEL_STATUS_INVALID_ARGUMENT = 3, - SPINEL_STATUS_INVALID_STATE = 4, - SPINEL_STATUS_INVALID_COMMAND = 5, - SPINEL_STATUS_INVALID_INTERFACE = 6, - SPINEL_STATUS_INTERNAL_ERROR = 7, - SPINEL_STATUS_SECURITY_ERROR = 8, - SPINEL_STATUS_PARSE_ERROR = 9, - SPINEL_STATUS_IN_PROGRESS = 10, - SPINEL_STATUS_NOMEM = 11, - SPINEL_STATUS_BUSY = 12, - SPINEL_STATUS_PROPERTY_NOT_FOUND = 12, - SPINEL_STATUS_DROPPED = 14, - SPINEL_STATUS_EMPTY = 15, + SPINEL_STATUS_UNIMPLEMENTED = 2, ///< Given operation has not been implemented. + SPINEL_STATUS_INVALID_ARGUMENT = 3, ///< An argument to the operation is invalid. + SPINEL_STATUS_INVALID_STATE = 4, ///< This operation is invalid for the current device state. + SPINEL_STATUS_INVALID_COMMAND = 5, ///< This command is not recognized. + SPINEL_STATUS_INVALID_INTERFACE = 6, ///< This interface is not supported. + SPINEL_STATUS_INTERNAL_ERROR = 7, ///< An internal runtime error has occured. + SPINEL_STATUS_SECURITY_ERROR = 8, ///< A security/authentication error has occured. + SPINEL_STATUS_PARSE_ERROR = 9, ///< A error has occured while parsing the command. + SPINEL_STATUS_IN_PROGRESS = 10, ///< This operation is in progress. + SPINEL_STATUS_NOMEM = 11, ///< Operation prevented due to memory pressure. + SPINEL_STATUS_BUSY = 12, ///< The device is currently performing an mutually exclusive operation + SPINEL_STATUS_PROP_NOT_FOUND = 12, ///< The given property is not recognized. + SPINEL_STATUS_DROPPED = 14, ///< A/The packet was dropped. + SPINEL_STATUS_EMPTY = 15, ///< The result of the operation is empty. + SPINEL_STATUS_CMD_TOO_BIG = 16, ///< The command was too large to fit in the internal buffer. + SPINEL_STATUS_NO_ACK = 17, ///< The packet was not acknowledged. + SPINEL_STATUS_CCA_FAILURE = 18, ///< The packet was not sent due to a CCA failure. SPINEL_STATUS_RESET__BEGIN = 112, SPINEL_STATUS_RESET_POWER_ON = SPINEL_STATUS_RESET__BEGIN + 0, @@ -144,6 +147,23 @@ enum SPINEL_PROTOCOL_TYPE_THREAD = 3, }; +enum +{ + SPINEL_MAC_FILTER_MODE_NORMAL = 0, ///< Normal MAC filtering is in place. + SPINEL_MAC_FILTER_MODE_PROMISCUOUS = 1, ///< All MAC packets matching network are passed up the stack. + SPINEL_MAC_FILTER_MODE_MONITOR = 2, ///< All decoded MAC packets are passed up the stack. + + /// 802.15.4's definition of "Promiscuous" mode. + /** 802.15.4 defines promiscuous mode to be what + * is generally considered to be "Monitor" mode. + * This definition will hopefully help people who + * are familiar with the 802.15.4 spec from being + * confused about what they need to set this + * property to in order to get the desired behavior. + */ + SPINEL_MAC_FILTER_MODE_15_4_PROMISCUOUS = SPINEL_MAC_FILTER_MODE_MONITOR, +}; + typedef struct { uint8_t bytes[8]; @@ -205,19 +225,19 @@ enum SPINEL_CAP_HBO = 3, SPINEL_CAP_POWER_SAVE = 4, - SPINEL_CAP_802_15_4__BEGIN = 16, - SPINEL_CAP_802_15_4_2003 = (SPINEL_CAP_802_15_4__BEGIN + 0), - SPINEL_CAP_802_15_4_2006 = (SPINEL_CAP_802_15_4__BEGIN + 1), - SPINEL_CAP_802_15_4_2011 = (SPINEL_CAP_802_15_4__BEGIN + 2), - SPINEL_CAP_802_15_4_PIB = (SPINEL_CAP_802_15_4__BEGIN + 5), + SPINEL_CAP_802_15_4__BEGIN = 16, + SPINEL_CAP_802_15_4_2003 = (SPINEL_CAP_802_15_4__BEGIN + 0), + SPINEL_CAP_802_15_4_2006 = (SPINEL_CAP_802_15_4__BEGIN + 1), + SPINEL_CAP_802_15_4_2011 = (SPINEL_CAP_802_15_4__BEGIN + 2), + SPINEL_CAP_802_15_4_PIB = (SPINEL_CAP_802_15_4__BEGIN + 5), SPINEL_CAP_802_15_4_2450MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 8), - SPINEL_CAP_802_15_4_915MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 9), - SPINEL_CAP_802_15_4_868MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 10), - SPINEL_CAP_802_15_4_915MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 11), - SPINEL_CAP_802_15_4_868MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 12), - SPINEL_CAP_802_15_4_915MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 13), - SPINEL_CAP_802_15_4_868MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 14), - SPINEL_CAP_802_15_4__END = 32, + SPINEL_CAP_802_15_4_915MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 9), + SPINEL_CAP_802_15_4_868MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 10), + SPINEL_CAP_802_15_4_915MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 11), + SPINEL_CAP_802_15_4_868MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 12), + SPINEL_CAP_802_15_4_915MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 13), + SPINEL_CAP_802_15_4_868MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 14), + SPINEL_CAP_802_15_4__END = 32, SPINEL_CAP_ROLE__BEGIN = 48, SPINEL_CAP_ROLE_ROUTER = (SPINEL_CAP_ROLE__BEGIN + 0), @@ -264,19 +284,19 @@ typedef enum SPINEL_PROP_PHY_CCA_THRESHOLD = SPINEL_PROP_PHY__BEGIN + 4, ///< dBm [c] SPINEL_PROP_PHY_TX_POWER = SPINEL_PROP_PHY__BEGIN + 5, ///< [c] SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c] - SPINEL_PROP_PHY_RAW_STREAM_ENABLED = SPINEL_PROP_PHY__BEGIN + 7, ///< [C] - SPINEL_PROP_PHY_PROMISCUOUS_MODE = SPINEL_PROP_PHY__BEGIN + 8, ///< [C] SPINEL_PROP_PHY__END = 0x30, - SPINEL_PROP_MAC__BEGIN = 0x30, - SPINEL_PROP_MAC_SCAN_STATE = SPINEL_PROP_MAC__BEGIN + 0, ///< [C] - SPINEL_PROP_MAC_SCAN_MASK = SPINEL_PROP_MAC__BEGIN + 1, ///< [A(C)] - SPINEL_PROP_MAC_SCAN_PERIOD = SPINEL_PROP_MAC__BEGIN + 2, ///< ms-per-channel [S] - SPINEL_PROP_MAC_SCAN_BEACON = SPINEL_PROP_MAC__BEGIN + 3, ///< chan,rssi,(laddr,saddr,panid,lqi),(proto,xtra) [CcT(ESSC)T(i).] - SPINEL_PROP_MAC_15_4_LADDR = SPINEL_PROP_MAC__BEGIN + 4, ///< [E] - SPINEL_PROP_MAC_15_4_SADDR = SPINEL_PROP_MAC__BEGIN + 5, ///< [S] - SPINEL_PROP_MAC_15_4_PANID = SPINEL_PROP_MAC__BEGIN + 6, ///< [S] - SPINEL_PROP_MAC__END = 0x40, + SPINEL_PROP_MAC__BEGIN = 0x30, + SPINEL_PROP_MAC_SCAN_STATE = SPINEL_PROP_MAC__BEGIN + 0, ///< [C] + SPINEL_PROP_MAC_SCAN_MASK = SPINEL_PROP_MAC__BEGIN + 1, ///< [A(C)] + SPINEL_PROP_MAC_SCAN_PERIOD = SPINEL_PROP_MAC__BEGIN + 2, ///< ms-per-channel [S] + SPINEL_PROP_MAC_SCAN_BEACON = SPINEL_PROP_MAC__BEGIN + 3, ///< chan,rssi,(laddr,saddr,panid,lqi),(proto,xtra) [CcT(ESSC.)T(i).] + SPINEL_PROP_MAC_15_4_LADDR = SPINEL_PROP_MAC__BEGIN + 4, ///< [E] + SPINEL_PROP_MAC_15_4_SADDR = SPINEL_PROP_MAC__BEGIN + 5, ///< [S] + SPINEL_PROP_MAC_15_4_PANID = SPINEL_PROP_MAC__BEGIN + 6, ///< [S] + SPINEL_PROP_MAC_RAW_STREAM_ENABLED = SPINEL_PROP_MAC__BEGIN + 7, ///< [C] + SPINEL_PROP_MAC_FILTER_MODE = SPINEL_PROP_MAC__BEGIN + 8, ///< [C] + SPINEL_PROP_MAC__END = 0x40, SPINEL_PROP_NET__BEGIN = 0x40, SPINEL_PROP_NET_SAVED = SPINEL_PROP_NET__BEGIN + 0, ///< [b] @@ -301,17 +321,21 @@ typedef enum SPINEL_PROP_THREAD_NETWORK_DATA = SPINEL_PROP_THREAD__BEGIN + 6, ///< [D] SPINEL_PROP_THREAD_NETWORK_DATA_VERSION = SPINEL_PROP_THREAD__BEGIN + 7, ///< [S] + SPINEL_PROP_THREAD_STABLE_NETWORK_DATA + = SPINEL_PROP_THREAD__BEGIN + 8, ///< [D] SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION - = SPINEL_PROP_THREAD__BEGIN + 8, ///< [S] + = SPINEL_PROP_THREAD__BEGIN + 9, ///< [S] + SPINEL_PROP_THREAD_ON_MESH_NETS = SPINEL_PROP_THREAD__BEGIN + 10, ///< array(ipv6prefix,prefixlen,stable,flags) [A(T(6CbC))] + SPINEL_PROP_THREAD_LOCAL_ROUTES = SPINEL_PROP_THREAD__BEGIN + 11, ///< array(ipv6prefix,prefixlen,stable,flags) [A(T(6CbC))] + SPINEL_PROP_THREAD_ASSISTING_PORTS = SPINEL_PROP_THREAD__BEGIN + 12, ///< array(portn) [A(S)] SPINEL_PROP_THREAD__END = 0x60, SPINEL_PROP_IPV6__BEGIN = 0x60, SPINEL_PROP_IPV6_LL_ADDR = SPINEL_PROP_IPV6__BEGIN + 0, ///< [6] SPINEL_PROP_IPV6_ML_ADDR = SPINEL_PROP_IPV6__BEGIN + 1, ///< [6C] SPINEL_PROP_IPV6_ML_PREFIX = SPINEL_PROP_IPV6__BEGIN + 2, ///< [6C] - SPINEL_PROP_IPV6_ADDRESS_TABLE = SPINEL_PROP_IPV6__BEGIN + 3, ///< array(ipv6addr,prefixlen,flags) [A(6CL)] - SPINEL_PROP_IPV6_ROUTE_TABLE = SPINEL_PROP_IPV6__BEGIN + 4, ///< array(ipv6prefix,prefixlen,iface,flags) [A(6CCL)] - SPINEL_PROP_IPV6_EXT_ROUTE_TABLE = SPINEL_PROP_IPV6__BEGIN + 5, ///< array(ipv6prefix,prefixlen,flags) [A(6CL)] + SPINEL_PROP_IPV6_ADDRESS_TABLE = SPINEL_PROP_IPV6__BEGIN + 3, ///< array(ipv6addr,prefixlen,flags) [A(T(6CL))] + SPINEL_PROP_IPV6_ROUTE_TABLE = SPINEL_PROP_IPV6__BEGIN + 4, ///< array(ipv6prefix,prefixlen,iface,flags) [A(T(6CCL))] SPINEL_PROP_IPV6__END = 0x70, SPINEL_PROP_STREAM__BEGIN = 0x70, @@ -326,6 +350,13 @@ typedef enum // Individual registers are fetched using // `SPINEL_PROP_15_4_PIB__BEGIN+[PIB_IDENTIFIER]` // Only supported if SPINEL_CAP_15_4_PIB is set. + // + // For brevity, the entire 802.15.4 PIB space is + // not defined here, but a few choice attributes + // are defined for illustration and convenience. + SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED = SPINEL_PROP_15_4_PIB__BEGIN + 0x01, ///< [A(L)] + SPINEL_PROP_15_4_PIB_MAC_PROMISCUOUS_MODE = SPINEL_PROP_15_4_PIB__BEGIN + 0x51, ///< [b] + SPINEL_PROP_15_4_PIB_MAC_SECURITY_ENABLED = SPINEL_PROP_15_4_PIB__BEGIN + 0x5d, ///< [b] SPINEL_PROP_15_4_PIB__END = 1280, SPINEL_PROP_NEST__BEGIN = 15296, @@ -424,6 +455,10 @@ SPINEL_API_EXTERN const char *spinel_next_packed_datatype(const char *pack_forma // ---------------------------------------------------------------------------- +SPINEL_API_EXTERN const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key); + +// ---------------------------------------------------------------------------- + __END_DECLS #endif /* defined(SPINEL_HEADER_INCLUDED) */