mirror of
https://github.com/espressif/openthread.git
synced 2026-07-19 02:24:06 +00:00
[channelmask] add radio supported and preferred channel mask (#3732)
Add new radio platform APIs: * otPlatRadioGetSupportedChannelMask(); // supported channel mask: the device is allowed to be on; * otPlatRadioGetPreferredChannelMask(); // preferred channel mask: the device prefers to form on. Implement some default radio platform APIs. Add spinel property `SPINEL_PROP_PHY_CHAN_PREFERRED` to retrieve Preferred ChannelMask.
This commit is contained in:
@@ -163,6 +163,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/net/ip6_routes.cpp \
|
||||
src/core/net/netif.cpp \
|
||||
src/core/net/udp6.cpp \
|
||||
src/core/phy/radio_weak.cpp \
|
||||
src/core/thread/address_resolver.cpp \
|
||||
src/core/thread/announce_begin_server.cpp \
|
||||
src/core/thread/announce_sender.cpp \
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
<ClCompile Include="..\..\src\core\net\ip6_routes.cpp" />
|
||||
<ClCompile Include="..\..\src\core\net\netif.cpp" />
|
||||
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
|
||||
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
|
||||
|
||||
@@ -213,6 +213,9 @@
|
||||
<ClCompile Include="..\..\src\core\net\netif.cpp">
|
||||
<Filter>Source Files\net</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp">
|
||||
<Filter>Source Files\phy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
<ClCompile Include="..\..\src\core\net\ip6_routes.cpp" />
|
||||
<ClCompile Include="..\..\src\core\net\netif.cpp" />
|
||||
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
|
||||
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
|
||||
|
||||
@@ -207,6 +207,9 @@
|
||||
<ClCompile Include="..\..\src\core\net\netif.cpp">
|
||||
<Filter>Source Files\net</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp">
|
||||
<Filter>Source Files\phy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -821,16 +821,6 @@ OTAPI uint8_t OTCALL otLinkGetPhyChannelMin(otInstance *aInstance);
|
||||
*/
|
||||
OTAPI uint8_t OTCALL otLinkGetPhyChannelMax(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function gets the supported channel mask of IEEE 802.15.4 physical layer.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The supported channel mask as `uint32_t` with bit 0 (lsb) mapping to channel 0, bit 1 to channel 1, so on.
|
||||
*
|
||||
*/
|
||||
OTAPI uint32_t OTCALL otLinkGetPhySupportedChannelMask(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -694,6 +694,26 @@ void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance);
|
||||
*/
|
||||
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Get the radio supported channel mask that the device is allowed to be on.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @returns The radio supported channel mask.
|
||||
*
|
||||
*/
|
||||
uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Get the radio preferred channel mask that the device prefers to form on.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance strucyyture.
|
||||
*
|
||||
* @returns The radio preferred channel mask.
|
||||
*
|
||||
*/
|
||||
uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -187,6 +187,7 @@ SOURCES_COMMON = \
|
||||
net/netif.cpp \
|
||||
net/sntp_client.cpp \
|
||||
net/udp6.cpp \
|
||||
phy/radio_weak.cpp \
|
||||
thread/address_resolver.cpp \
|
||||
thread/announce_begin_server.cpp \
|
||||
thread/announce_sender.cpp \
|
||||
@@ -244,6 +245,7 @@ libopenthread_radio_a_SOURCES = \
|
||||
mac/mac_frame.cpp \
|
||||
mac/sub_mac.cpp \
|
||||
mac/sub_mac_callbacks.cpp \
|
||||
phy/radio_weak.cpp \
|
||||
thread/link_quality.cpp \
|
||||
utils/missing_strlcat.c \
|
||||
utils/missing_strlcpy.c \
|
||||
|
||||
@@ -443,9 +443,3 @@ uint8_t otLinkGetPhyChannelMax(otInstance *aInstance)
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return Phy::kChannelMax;
|
||||
}
|
||||
|
||||
uint32_t otLinkGetPhySupportedChannelMask(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return Phy::kSupportedChannels;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ Mac::Mac(Instance &aInstance)
|
||||
, mPanChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
|
||||
, mRadioChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
|
||||
, mRadioChannelAcquisitionId(0)
|
||||
, mSupportedChannelMask(Phy::kSupportedChannels)
|
||||
, mSupportedChannelMask(otPlatRadioGetSupportedChannelMask(&aInstance))
|
||||
, mScanChannel(Phy::kChannelMin)
|
||||
, mScanDuration(0)
|
||||
, mScanChannelMask()
|
||||
@@ -166,7 +166,7 @@ void Mac::Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanD
|
||||
|
||||
if (aScanChannels == 0)
|
||||
{
|
||||
aScanChannels = Phy::kSupportedChannels;
|
||||
aScanChannels = GetSupportedChannelMask().GetMask();
|
||||
}
|
||||
|
||||
mScanChannelMask.SetMask(aScanChannels);
|
||||
@@ -425,7 +425,7 @@ void Mac::SetSupportedChannelMask(const ChannelMask &aMask)
|
||||
{
|
||||
ChannelMask newMask = aMask;
|
||||
|
||||
newMask.Intersect(ChannelMask(Phy::kSupportedChannels));
|
||||
newMask.Intersect(ChannelMask(otPlatRadioGetSupportedChannelMask(&GetInstance())));
|
||||
VerifyOrExit(newMask != mSupportedChannelMask, Get<Notifier>().SignalIfFirst(OT_CHANGED_SUPPORTED_CHANNEL_MASK));
|
||||
|
||||
mSupportedChannelMask = newMask;
|
||||
|
||||
@@ -227,7 +227,7 @@ otError DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
|
||||
VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0);
|
||||
|
||||
aChannelMask.SetMask(mask & Phy::kSupportedChannels);
|
||||
aChannelMask.SetMask(mask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
|
||||
|
||||
VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The OpenThread Authors.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the default radio platform APIs.
|
||||
*/
|
||||
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "phy/phy.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
OT_TOOL_WEAK uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return Phy::kSupportedChannels;
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
|
||||
{
|
||||
return otPlatRadioGetSupportedChannelMask(aInstance);
|
||||
}
|
||||
@@ -69,7 +69,7 @@ otError AnnounceSenderBase::SendAnnounce(Mac::ChannelMask aChannelMask,
|
||||
VerifyOrExit(aPeriod != 0, error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(aJitter < aPeriod, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
aChannelMask.Intersect(Mac::ChannelMask(Phy::kSupportedChannels));
|
||||
aChannelMask.Intersect(Get<Mac::Mac>().GetSupportedChannelMask());
|
||||
VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
mChannelMask = aChannelMask;
|
||||
|
||||
@@ -1153,9 +1153,10 @@ exit:
|
||||
void MeshForwarder::SetDiscoverParameters(const Mac::ChannelMask &aScanChannels)
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t supportedMask = Get<Mac::Mac>().GetSupportedChannelMask().GetMask();
|
||||
|
||||
mask = aScanChannels.IsEmpty() ? static_cast<uint32_t>(Phy::kSupportedChannels) : aScanChannels.GetMask();
|
||||
mScanChannels.SetMask(mask & Phy::kSupportedChannels);
|
||||
mask = aScanChannels.IsEmpty() ? supportedMask : aScanChannels.GetMask();
|
||||
mScanChannels.SetMask(mask & supportedMask);
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleDiscoverTimer(Timer &aTimer)
|
||||
|
||||
@@ -480,14 +480,14 @@ exit:
|
||||
|
||||
void ChannelManager::SetSupportedChannels(uint32_t aChannelMask)
|
||||
{
|
||||
mSupportedChannelMask.SetMask(aChannelMask & Phy::kSupportedChannels);
|
||||
mSupportedChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
|
||||
|
||||
otLogInfoUtil("ChannelManager: Supported channels: %s", mSupportedChannelMask.ToString().AsCString());
|
||||
}
|
||||
|
||||
void ChannelManager::SetFavoredChannels(uint32_t aChannelMask)
|
||||
{
|
||||
mFavoredChannelMask.SetMask(aChannelMask & Phy::kSupportedChannels);
|
||||
mFavoredChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
|
||||
|
||||
otLogInfoUtil("ChannelManager: Favored channels: %s", mFavoredChannelMask.ToString().AsCString());
|
||||
}
|
||||
|
||||
@@ -2173,6 +2173,20 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
|
||||
{
|
||||
#if OPENTHREAD_RADIO
|
||||
return EncodeChannelMask(otPlatRadioGetSupportedChannelMask(mInstance));
|
||||
#else
|
||||
return EncodeChannelMask(otLinkGetSupportedChannelMask(mInstance));
|
||||
#endif // OPENTHREAD_RADIO
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>(void)
|
||||
{
|
||||
return EncodeChannelMask(otPlatRadioGetPreferredChannelMask(mInstance));
|
||||
}
|
||||
|
||||
} // namespace Ncp
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -134,6 +134,12 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
|
||||
case SPINEL_PROP_VENDOR_ID:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_VENDOR_ID>;
|
||||
break;
|
||||
case SPINEL_PROP_PHY_CHAN_SUPPORTED:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>;
|
||||
break;
|
||||
case SPINEL_PROP_PHY_CHAN_PREFERRED:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>;
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// MTD (or FTD) Properties (Get Handler)
|
||||
@@ -171,9 +177,6 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
|
||||
case SPINEL_PROP_MSG_BUFFER_COUNTERS:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MSG_BUFFER_COUNTERS>;
|
||||
break;
|
||||
case SPINEL_PROP_PHY_CHAN_SUPPORTED:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>;
|
||||
break;
|
||||
case SPINEL_PROP_PHY_FREQ:
|
||||
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>;
|
||||
break;
|
||||
|
||||
@@ -207,11 +207,6 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>(void)
|
||||
return mEncoder.WriteUint32(freq_khz);
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
|
||||
{
|
||||
return EncodeChannelMask(otLinkGetPhySupportedChannelMask(mInstance));
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
|
||||
{
|
||||
uint32_t newMask = 0;
|
||||
|
||||
@@ -1295,6 +1295,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PHY_PCAP_ENABLED";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_PHY_CHAN_PREFERRED:
|
||||
ret = "PHY_CHAN_PREFERRED";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_JAM_DETECT_ENABLE:
|
||||
ret = "JAM_DETECT_ENABLE";
|
||||
break;
|
||||
|
||||
@@ -1198,6 +1198,7 @@ typedef enum
|
||||
SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c]
|
||||
SPINEL_PROP_PHY_RX_SENSITIVITY = SPINEL_PROP_PHY__BEGIN + 7, ///< dBm [c]
|
||||
SPINEL_PROP_PHY_PCAP_ENABLED = SPINEL_PROP_PHY__BEGIN + 8, ///< [b]
|
||||
SPINEL_PROP_PHY_CHAN_PREFERRED = SPINEL_PROP_PHY__BEGIN + 9, ///< [A(C)]
|
||||
SPINEL_PROP_PHY__END = 0x30,
|
||||
|
||||
SPINEL_PROP_PHY_EXT__BEGIN = 0x1200,
|
||||
|
||||
@@ -1361,6 +1361,36 @@ otError RadioSpinel::PlatDiagProcess(const char *aString, char *aOutput, size_t
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t RadioSpinel::GetRadioChannelMask(bool aPreferred)
|
||||
{
|
||||
uint8_t maskBuffer[kChannelMaskBufferSize];
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint32_t channelMask = 0;
|
||||
const uint8_t *maskData = maskBuffer;
|
||||
spinel_size_t maskLength = sizeof(maskBuffer);
|
||||
|
||||
SuccessOrExit(error = Get(aPreferred ? SPINEL_PROP_PHY_CHAN_PREFERRED : SPINEL_PROP_PHY_CHAN_SUPPORTED,
|
||||
SPINEL_DATATYPE_DATA_S, maskBuffer, &maskLength));
|
||||
|
||||
while (maskLength > 0)
|
||||
{
|
||||
uint8_t channel;
|
||||
spinel_ssize_t unpacked;
|
||||
|
||||
unpacked = spinel_datatype_unpack(maskData, maskLength, SPINEL_DATATYPE_UINT8_S, &channel);
|
||||
VerifyOrExit(unpacked > 0, error = OT_ERROR_FAILED);
|
||||
VerifyOrExit(channel < kChannelMaskBufferSize, error = OT_ERROR_PARSE);
|
||||
channelMask |= (1UL << channel);
|
||||
|
||||
maskData += unpacked;
|
||||
maskLength -= static_cast<spinel_size_t>(unpacked);
|
||||
}
|
||||
|
||||
exit:
|
||||
LogIfFail("Get radio channel mask failed", error);
|
||||
return channelMask;
|
||||
}
|
||||
|
||||
} // namespace PosixApp
|
||||
} // namespace ot
|
||||
|
||||
@@ -1695,3 +1725,15 @@ void otPlatDiagAlarmCallback(otInstance *aInstance)
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return sRadioSpinel.GetRadioChannelMask(false);
|
||||
}
|
||||
|
||||
uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return sRadioSpinel.GetRadioChannelMask(true);
|
||||
}
|
||||
|
||||
@@ -439,6 +439,18 @@ public:
|
||||
otError PlatDiagProcess(const char *aString, char *aOutput, size_t aOutputMaxLen);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method returns the radio channel mask.
|
||||
*
|
||||
* @param[in] aPreferred TRUE to get preferred channel mask, FALSE to get supported channel mask.
|
||||
*
|
||||
* @returns The radio channel mask according to @aPreferred:
|
||||
* The radio supported channel mask that the device is allowed to be on.
|
||||
* The radio preferred channel mask that the device prefers to form on.
|
||||
*
|
||||
*/
|
||||
uint32_t GetRadioChannelMask(bool aPreferred);
|
||||
|
||||
/**
|
||||
* This method processes a received Spinel frame.
|
||||
*
|
||||
@@ -449,10 +461,11 @@ public:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxSpinelFrame = HdlcInterface::kMaxFrameSize,
|
||||
kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds.
|
||||
kVersionStringSize = 128, ///< Max size of version string.
|
||||
kCapsBufferSize = 100, ///< Max buffer size used to store `SPINEL_PROP_CAPS` value.
|
||||
kMaxSpinelFrame = HdlcInterface::kMaxFrameSize,
|
||||
kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds.
|
||||
kVersionStringSize = 128, ///< Max size of version string.
|
||||
kCapsBufferSize = 100, ///< Max buffer size used to store `SPINEL_PROP_CAPS` value.
|
||||
kChannelMaskBufferSize = 32, ///< Max buffer size used to store `SPINEL_PROP_PHY_CHAN_SUPPORTED` value.
|
||||
};
|
||||
|
||||
enum State
|
||||
|
||||
Reference in New Issue
Block a user