[posix-app] support platform energy scan in posix-app (#3038)

This commit is contained in:
Shu Chen
2018-09-06 20:57:38 -10:00
committed by Jonathan Hui
parent 045aa4f358
commit b795c729d3
7 changed files with 236 additions and 213 deletions
+183
View File
@@ -52,6 +52,25 @@ namespace Ncp {
// MARK: Utility Functions
// ----------------------------------------------------------------------------
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
static bool HasOnly1BitSet(uint32_t aValue)
{
return aValue != 0 && ((aValue & (aValue - 1)) == 0);
}
static uint8_t IndexOfMSB(uint32_t aValue)
{
uint8_t index = 0;
while (aValue >>= 1)
{
index++;
}
return index;
}
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
spinel_status_t NcpBase::ThreadErrorToSpinelStatus(otError aError)
{
spinel_status_t ret;
@@ -1475,6 +1494,170 @@ exit:
return error;
}
otError NcpBase::EncodeChannelMask(uint32_t aChannelMask)
{
otError error = OT_ERROR_NONE;
for (uint8_t i = 0; i < 32; i++)
{
if (0 != (aChannelMask & (1 << i)))
{
SuccessOrExit(error = mEncoder.WriteUint8(i));
}
}
exit:
return error;
}
otError NcpBase::DecodeChannelMask(uint32_t &aChannelMask)
{
otError error = OT_ERROR_NONE;
uint8_t channel;
aChannelMask = 0;
while (!mDecoder.IsAllReadInStruct())
{
SuccessOrExit(error = mDecoder.ReadUint8(channel));
VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
aChannelMask |= (1U << channel);
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>(void)
{
return EncodeChannelMask(mScanChannelMask);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>(void)
{
uint32_t newMask = 0;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = DecodeChannelMask(newMask));
mScanChannelMask = newMask;
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
{
return mEncoder.WriteUint16(mScanPeriod);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
{
return mDecoder.ReadUint16(mScanPeriod);
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>(void)
{
uint8_t scanState = SPINEL_SCAN_STATE_IDLE;
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
scanState = (mCurScanChannel == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE : SPINEL_SCAN_STATE_ENERGY;
}
else
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
if (otLinkIsActiveScanInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_BEACON;
}
else if (otLinkIsEnergyScanInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_ENERGY;
}
else if (otThreadIsDiscoverInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_DISCOVER;
}
else
{
scanState = SPINEL_SCAN_STATE_IDLE;
}
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
}
return mEncoder.WriteUint8(scanState);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
{
uint8_t state = 0;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mDecoder.ReadUint8(state));
switch (state)
{
case SPINEL_SCAN_STATE_IDLE:
error = OT_ERROR_NONE;
break;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
case SPINEL_SCAN_STATE_BEACON:
error = otLinkActiveScan(mInstance, mScanChannelMask, mScanPeriod, &HandleActiveScanResult_Jump, this);
SuccessOrExit(error);
break;
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
case SPINEL_SCAN_STATE_ENERGY:
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
uint8_t scanChannel;
// Make sure we aren't already scanning and that we have
// only 1 bit set for the channel mask.
VerifyOrExit(mCurScanChannel == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(HasOnly1BitSet(mScanChannelMask), error = OT_ERROR_INVALID_ARGS);
scanChannel = IndexOfMSB(mScanChannelMask);
mCurScanChannel = (int8_t)scanChannel;
error = otLinkRawEnergyScan(mInstance, scanChannel, mScanPeriod, LinkRawEnergyScanDone);
}
else
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
error = otLinkEnergyScan(mInstance, mScanChannelMask, mScanPeriod, &HandleEnergyScanResult_Jump, this);
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
}
SuccessOrExit(error);
break;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
case SPINEL_SCAN_STATE_DISCOVER:
error = otThreadDiscover(mInstance, mScanChannelMask, mDiscoveryScanPanId, mDiscoveryScanJoinerFlag,
mDiscoveryScanEnableFiltering, &HandleActiveScanResult_Jump, this);
SuccessOrExit(error);
break;
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
default:
error = OT_ERROR_NOT_IMPLEMENTED;
break;
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_UNSOL_UPDATE_FILTER>(void)
{
otError error = OT_ERROR_NONE;
+3 -2
View File
@@ -240,6 +240,9 @@ protected:
static void HandleRawFrame(const otRadioFrame *aFrame, void *aContext);
void HandleRawFrame(const otRadioFrame *aFrame);
otError EncodeChannelMask(uint32_t aChannelMask);
otError DecodeChannelMask(uint32_t &aChannelMask);
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
@@ -299,8 +302,6 @@ protected:
static void SendDoneTask(void *aContext);
void SendDoneTask(void);
otError EncodeChannelMask(uint32_t aChannelMask);
otError DecodeChannelMask(uint32_t &aChannelMask);
otError EncodeOperationalDataset(const otOperationalDataset &aDataset);
#if OPENTHREAD_FTD
+18 -18
View File
@@ -110,6 +110,15 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_MAC_PROMISCUOUS_MODE:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_PROMISCUOUS_MODE>;
break;
case SPINEL_PROP_MAC_SCAN_STATE:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>;
break;
case SPINEL_PROP_MAC_SCAN_MASK:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>;
break;
case SPINEL_PROP_MAC_SCAN_PERIOD:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_PERIOD>;
break;
case SPINEL_PROP_NCP_VERSION:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_NCP_VERSION>;
break;
@@ -133,15 +142,6 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_MAC_EXTENDED_ADDR:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_EXTENDED_ADDR>;
break;
case SPINEL_PROP_MAC_SCAN_STATE:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>;
break;
case SPINEL_PROP_MAC_SCAN_MASK:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>;
break;
case SPINEL_PROP_MAC_SCAN_PERIOD:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_PERIOD>;
break;
case SPINEL_PROP_MAC_CCA_FAILURE_RATE:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_CCA_FAILURE_RATE>;
break;
@@ -668,6 +668,15 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_MAC_RAW_STREAM_ENABLED:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RAW_STREAM_ENABLED>;
break;
case SPINEL_PROP_MAC_SCAN_MASK:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>;
break;
case SPINEL_PROP_MAC_SCAN_STATE:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>;
break;
case SPINEL_PROP_MAC_SCAN_PERIOD:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_PERIOD>;
break;
// --------------------------------------------------------------------------
// MTD (or FTD) Properties (Set Handler)
@@ -679,15 +688,6 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_MAC_DATA_POLL_PERIOD:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>;
break;
case SPINEL_PROP_MAC_SCAN_MASK:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>;
break;
case SPINEL_PROP_MAC_SCAN_STATE:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>;
break;
case SPINEL_PROP_MAC_SCAN_PERIOD:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_PERIOD>;
break;
case SPINEL_PROP_NET_IF_UP:
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_NET_IF_UP>;
break;
-187
View File
@@ -68,27 +68,6 @@
namespace ot {
namespace Ncp {
#if OPENTHREAD_ENABLE_RAW_LINK_API
static bool HasOnly1BitSet(uint32_t aValue)
{
return aValue != 0 && ((aValue & (aValue - 1)) == 0);
}
static uint8_t IndexOfMSB(uint32_t aValue)
{
uint8_t index = 0;
while (aValue >>= 1)
{
index++;
}
return index;
}
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
static uint8_t BorderRouterConfigToFlagByte(const otBorderRouterConfig &aConfig)
{
uint8_t flags(0);
@@ -2639,172 +2618,6 @@ exit:
}
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
otError NcpBase::EncodeChannelMask(uint32_t aChannelMask)
{
otError error = OT_ERROR_NONE;
for (uint8_t i = 0; i < 32; i++)
{
if (0 != (aChannelMask & (1 << i)))
{
SuccessOrExit(error = mEncoder.WriteUint8(i));
}
}
exit:
return error;
}
otError NcpBase::DecodeChannelMask(uint32_t &aChannelMask)
{
otError error = OT_ERROR_NONE;
uint8_t channel;
aChannelMask = 0;
while (!mDecoder.IsAllReadInStruct())
{
SuccessOrExit(error = mDecoder.ReadUint8(channel));
VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
aChannelMask |= (1U << channel);
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>(void)
{
return EncodeChannelMask(mScanChannelMask);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>(void)
{
uint32_t newMask = 0;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = DecodeChannelMask(newMask));
mScanChannelMask = newMask;
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
{
return mEncoder.WriteUint16(mScanPeriod);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_PERIOD>(void)
{
return mDecoder.ReadUint16(mScanPeriod);
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>(void)
{
uint8_t scanState = SPINEL_SCAN_STATE_IDLE;
#if OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
scanState = (mCurScanChannel == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE : SPINEL_SCAN_STATE_ENERGY;
}
else
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
{
if (otLinkIsActiveScanInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_BEACON;
}
else if (otLinkIsEnergyScanInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_ENERGY;
}
else if (otThreadIsDiscoverInProgress(mInstance))
{
scanState = SPINEL_SCAN_STATE_DISCOVER;
}
else
{
scanState = SPINEL_SCAN_STATE_IDLE;
}
}
return mEncoder.WriteUint8(scanState);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
{
uint8_t state = 0;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mDecoder.ReadUint8(state));
switch (state)
{
case SPINEL_SCAN_STATE_IDLE:
error = OT_ERROR_NONE;
break;
case SPINEL_SCAN_STATE_BEACON:
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
error = OT_ERROR_NOT_IMPLEMENTED;
}
else
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
{
error = otLinkActiveScan(mInstance, mScanChannelMask, mScanPeriod, &HandleActiveScanResult_Jump, this);
}
SuccessOrExit(error);
break;
case SPINEL_SCAN_STATE_ENERGY:
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
uint8_t scanChannel;
// Make sure we aren't already scanning and that we have
// only 1 bit set for the channel mask.
VerifyOrExit(mCurScanChannel == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(HasOnly1BitSet(mScanChannelMask), error = OT_ERROR_INVALID_ARGS);
scanChannel = IndexOfMSB(mScanChannelMask);
mCurScanChannel = (int8_t)scanChannel;
error = otLinkRawEnergyScan(mInstance, scanChannel, mScanPeriod, LinkRawEnergyScanDone);
}
else
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
{
error = otLinkEnergyScan(mInstance, mScanChannelMask, mScanPeriod, &HandleEnergyScanResult_Jump, this);
}
SuccessOrExit(error);
break;
case SPINEL_SCAN_STATE_DISCOVER:
error = otThreadDiscover(mInstance, mScanChannelMask, mDiscoveryScanPanId, mDiscoveryScanJoinerFlag,
mDiscoveryScanEnableFiltering, &HandleActiveScanResult_Jump, this);
SuccessOrExit(error);
break;
default:
error = OT_ERROR_INVALID_ARGS;
break;
}
exit:
return error;
}
void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext)
{
static_cast<NcpBase *>(aContext)->HandleActiveScanResult(aResult);
+13 -6
View File
@@ -618,9 +618,7 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
unpacked = spinel_datatype_unpack(aBuffer, aLength, "Cc", &scanChannel, &maxRssi);
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
#if !OPENTHREAD_ENABLE_DIAG
otPlatRadioEnergyScanDone(mInstance, maxRssi);
#endif
}
else if (aKey == SPINEL_PROP_STREAM_DEBUG)
{
@@ -927,6 +925,18 @@ otError RadioSpinel::SetTransmitPower(int8_t aPower)
return error;
}
otError RadioSpinel::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
otError error;
SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_DATA_S, &aScanChannel, sizeof(uint8_t)));
SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_PERIOD, SPINEL_DATATYPE_UINT16_S, aScanDuration));
SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_STATE, SPINEL_DATATYPE_UINT8_S, SPINEL_SCAN_STATE_ENERGY));
exit:
return error;
}
otError RadioSpinel::Get(spinel_prop_key_t aKey, const char *aFormat, ...)
{
otError error;
@@ -1607,10 +1617,7 @@ void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aScanChannel);
OT_UNUSED_VARIABLE(aScanDuration);
return OT_ERROR_NOT_IMPLEMENTED;
return sRadioSpinel.EnergyScan(aScanChannel, aScanDuration);
}
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
+13
View File
@@ -278,6 +278,19 @@ public:
*/
otError ClearSrcMatchExtEntries(void);
/**
* This method begins the energy scan sequence on the radio.
*
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
* @retval OT_ERROR_NONE Succeeded.
* @retval OT_ERROR_BUSY Failed due to another operation is on going.
* @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver.
*
*/
otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
/**
* This method switches the radio state from Receive to Transmit.
*
+6
View File
@@ -84,6 +84,12 @@ extern "C" void otPlatRadioTxStarted(otInstance *, otRadioFrame *aFrame)
(void)aFrame;
}
extern "C" void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi)
{
(void)aInstance;
(void)aEnergyScanMaxRssi;
}
/**
* Converts a given string replacing '\n', '\r', '\t', etc. with literal strings "\n", "\r", "\t", etc. to make it
* printable on console.