mirror of
https://github.com/espressif/openthread.git
synced 2026-07-08 21:30:24 +00:00
834c8cbc8e
This feature allows the RCP to support multiple host stacks on different PANs by making use of the spinel Interface ID. Created unit tests for testing multipan feature with multiple ot-instance support. Based on Si-Labs PR #8914 by @parag-silabs, but a little different approach. Instead of handling everything by a single sub-mac instance, multiple OpenThread instances are created on RCP side that map to different IID. Thanks to this there are separate data kept for each interface. Platform is able to determine interface by ot instance pointer passed as an argument to most of the API functions. Tx/scan queue was removed as it is possible to request transmission in parallel, it is up to the platform to decide if it should fail or queue second tx or it has two radios available. NOTE: Platform needs to provide different otRadioFrame of each instance and the processing needs to take into account the instance being used. Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
518 lines
14 KiB
C++
518 lines
14 KiB
C++
/*
|
|
* Copyright (c) 2017, 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.
|
|
*/
|
|
|
|
#include "openthread-core-config.h"
|
|
|
|
#include "fuzzer_platform.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <openthread/platform/alarm-micro.h>
|
|
#include <openthread/platform/alarm-milli.h>
|
|
#include <openthread/platform/diag.h>
|
|
#include <openthread/platform/entropy.h>
|
|
#include <openthread/platform/logging.h>
|
|
#include <openthread/platform/misc.h>
|
|
#include <openthread/platform/multipan.h>
|
|
#include <openthread/platform/radio.h>
|
|
#include <openthread/platform/settings.h>
|
|
|
|
#include "mac/mac_frame.hpp"
|
|
|
|
using namespace ot;
|
|
|
|
typedef struct AlarmState
|
|
{
|
|
uint32_t fire;
|
|
bool isRunning;
|
|
} AlarmState;
|
|
|
|
enum
|
|
{
|
|
IEEE802154_ACK_LENGTH = 5,
|
|
|
|
IEEE802154_FRAME_TYPE_ACK = 2 << 0,
|
|
};
|
|
|
|
static uint32_t sAlarmNow;
|
|
static AlarmState sAlarmMilli;
|
|
static AlarmState sAlarmMicro;
|
|
static uint32_t sRandomState = 1;
|
|
static uint8_t sRadioTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE];
|
|
static otRadioFrame sRadioTransmitFrame;
|
|
static uint8_t sRadioAckPsdu[OT_RADIO_FRAME_MAX_SIZE];
|
|
static otRadioFrame sRadioAckFrame;
|
|
static bool sResetWasRequested = false;
|
|
static otRadioState sRadioState = OT_RADIO_STATE_DISABLED;
|
|
|
|
bool otMacFrameIsAckRequested(const otRadioFrame *aFrame)
|
|
{
|
|
return static_cast<const Mac::Frame *>(aFrame)->GetAckRequest();
|
|
}
|
|
|
|
uint8_t otMacFrameGetSequence(const otRadioFrame *aFrame)
|
|
{
|
|
return static_cast<const Mac::Frame *>(aFrame)->GetSequence();
|
|
}
|
|
|
|
void FuzzerPlatformInit(void)
|
|
{
|
|
sRandomState = 1;
|
|
sAlarmNow = 0;
|
|
memset(&sAlarmMilli, 0, sizeof(sAlarmMilli));
|
|
memset(&sAlarmMicro, 0, sizeof(sAlarmMicro));
|
|
|
|
sRadioTransmitFrame.mPsdu = sRadioTransmitPsdu;
|
|
sRadioAckFrame.mPsdu = sRadioAckPsdu;
|
|
}
|
|
|
|
void FuzzerPlatformProcess(otInstance *aInstance)
|
|
{
|
|
if (sRadioState == OT_RADIO_STATE_TRANSMIT)
|
|
{
|
|
sRadioState = OT_RADIO_STATE_RECEIVE;
|
|
|
|
if (otMacFrameIsAckRequested(&sRadioTransmitFrame))
|
|
{
|
|
sRadioAckFrame.mLength = IEEE802154_ACK_LENGTH;
|
|
sRadioAckFrame.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
|
sRadioAckFrame.mPsdu[1] = 0;
|
|
sRadioAckFrame.mPsdu[2] = otMacFrameGetSequence(&sRadioTransmitFrame);
|
|
sRadioAckFrame.mChannel = sRadioTransmitFrame.mChannel;
|
|
|
|
otPlatRadioTxDone(aInstance, &sRadioTransmitFrame, &sRadioAckFrame, OT_ERROR_NONE);
|
|
}
|
|
else
|
|
{
|
|
otPlatRadioTxDone(aInstance, &sRadioTransmitFrame, nullptr, OT_ERROR_NONE);
|
|
}
|
|
}
|
|
|
|
if (sAlarmMilli.isRunning || sAlarmMicro.isRunning)
|
|
{
|
|
uint32_t fire = UINT32_MAX;
|
|
|
|
if (sAlarmMilli.isRunning && fire > sAlarmMilli.fire)
|
|
{
|
|
fire = sAlarmMilli.fire;
|
|
}
|
|
|
|
if (sAlarmMicro.isRunning && fire > sAlarmMicro.fire)
|
|
{
|
|
fire = sAlarmMicro.fire;
|
|
}
|
|
|
|
sAlarmNow = fire;
|
|
|
|
if (sAlarmMilli.isRunning && sAlarmNow >= sAlarmMilli.fire)
|
|
{
|
|
sAlarmMilli.isRunning = false;
|
|
otPlatAlarmMilliFired(aInstance);
|
|
}
|
|
|
|
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
|
if (sAlarmMicro.isRunning && sAlarmNow >= sAlarmMicro.fire)
|
|
{
|
|
sAlarmMicro.isRunning = false;
|
|
otPlatAlarmMicroFired(aInstance);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
bool FuzzerPlatformResetWasRequested(void) { return sResetWasRequested; }
|
|
|
|
uint32_t otPlatAlarmMilliGetNow(void) { return sAlarmNow / 1000; }
|
|
|
|
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sAlarmMilli.fire = (aT0 + aDt) * 1000;
|
|
sAlarmMilli.isRunning = true;
|
|
}
|
|
|
|
void otPlatAlarmMilliStop(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sAlarmMilli.isRunning = false;
|
|
}
|
|
|
|
uint32_t otPlatAlarmMicroGetNow(void) { return sAlarmNow; }
|
|
|
|
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sAlarmMicro.fire = aT0 + aDt;
|
|
sAlarmMicro.isRunning = true;
|
|
}
|
|
|
|
void otPlatAlarmMicroStop(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sAlarmMicro.isRunning = false;
|
|
}
|
|
|
|
bool otDiagIsEnabled(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
return false;
|
|
}
|
|
|
|
otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aArgsLength);
|
|
OT_UNUSED_VARIABLE(aArgs);
|
|
OT_UNUSED_VARIABLE(aOutput);
|
|
OT_UNUSED_VARIABLE(aOutputMaxLen);
|
|
|
|
return OT_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aString);
|
|
OT_UNUSED_VARIABLE(aOutput);
|
|
OT_UNUSED_VARIABLE(aOutputMaxLen);
|
|
|
|
return OT_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
void otPlatReset(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sResetWasRequested = true;
|
|
}
|
|
|
|
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return OT_PLAT_RESET_REASON_POWER_ON;
|
|
}
|
|
|
|
OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
|
{
|
|
OT_UNUSED_VARIABLE(aLogLevel);
|
|
OT_UNUSED_VARIABLE(aLogRegion);
|
|
OT_UNUSED_VARIABLE(aFormat);
|
|
}
|
|
|
|
void otPlatWakeHost(void) {}
|
|
|
|
otError otPlatMultipanGetActiveInstance(otInstance **) { return OT_ERROR_NOT_IMPLEMENTED; }
|
|
|
|
otError otPlatMultipanSetActiveInstance(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
|
|
|
|
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aIeeeEui64);
|
|
}
|
|
|
|
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aPanId);
|
|
}
|
|
|
|
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddr)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aExtAddr);
|
|
}
|
|
|
|
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aShortAddress);
|
|
}
|
|
|
|
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnabled)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aEnabled);
|
|
}
|
|
|
|
void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnabled)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aEnabled);
|
|
}
|
|
|
|
bool otPlatRadioIsEnabled(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return true;
|
|
}
|
|
|
|
otError otPlatRadioEnable(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sRadioState = OT_RADIO_STATE_SLEEP;
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioDisable(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sRadioState = OT_RADIO_STATE_DISABLED;
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioSleep(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
sRadioState = OT_RADIO_STATE_SLEEP;
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aChannel);
|
|
|
|
sRadioState = OT_RADIO_STATE_RECEIVE;
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
|
|
{
|
|
sRadioState = OT_RADIO_STATE_TRANSMIT;
|
|
|
|
otPlatRadioTxStarted(aInstance, aFrame);
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aPower);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return &sRadioTransmitFrame;
|
|
}
|
|
|
|
int8_t otPlatRadioGetRssi(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return 0;
|
|
}
|
|
|
|
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return OT_RADIO_CAPS_NONE;
|
|
}
|
|
|
|
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return false;
|
|
}
|
|
|
|
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aEnable);
|
|
}
|
|
|
|
otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aShortAddress);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aExtAddress);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aShortAddress);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aExtAddress);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
|
|
|
|
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) { OT_UNUSED_VARIABLE(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;
|
|
}
|
|
|
|
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aPower);
|
|
return OT_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aThreshold);
|
|
return OT_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aThreshold);
|
|
return OT_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
return 0;
|
|
}
|
|
|
|
otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
|
|
{
|
|
for (uint16_t length = 0; length < aOutputLength; length++)
|
|
{
|
|
aOutput[length] = (uint8_t)rand();
|
|
}
|
|
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aSensitiveKeys);
|
|
OT_UNUSED_VARIABLE(aSensitiveKeysLength);
|
|
}
|
|
|
|
void otPlatSettingsDeinit(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
|
|
|
|
otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aKey);
|
|
OT_UNUSED_VARIABLE(aIndex);
|
|
OT_UNUSED_VARIABLE(aValue);
|
|
OT_UNUSED_VARIABLE(aValueLength);
|
|
return OT_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aKey);
|
|
OT_UNUSED_VARIABLE(aValue);
|
|
OT_UNUSED_VARIABLE(aValueLength);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aKey);
|
|
OT_UNUSED_VARIABLE(aValue);
|
|
OT_UNUSED_VARIABLE(aValueLength);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aKey);
|
|
OT_UNUSED_VARIABLE(aIndex);
|
|
return OT_ERROR_NONE;
|
|
}
|
|
|
|
void otPlatSettingsWipe(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
|
|
|
|
otError otPlatDiagProcess(otInstance *aInstance,
|
|
uint8_t aArgsLength,
|
|
char *aArgs[],
|
|
char *aOutput,
|
|
size_t aOutputMaxLen)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aArgsLength);
|
|
OT_UNUSED_VARIABLE(aArgs);
|
|
OT_UNUSED_VARIABLE(aOutput);
|
|
OT_UNUSED_VARIABLE(aOutputMaxLen);
|
|
|
|
return OT_ERROR_INVALID_COMMAND;
|
|
}
|
|
|
|
void otPlatDiagModeSet(bool aMode) { OT_UNUSED_VARIABLE(aMode); }
|
|
|
|
bool otPlatDiagModeGet(void) { return false; }
|
|
|
|
void otPlatDiagChannelSet(uint8_t aChannel) { OT_UNUSED_VARIABLE(aChannel); }
|
|
|
|
void otPlatDiagTxPowerSet(int8_t aTxPower) { OT_UNUSED_VARIABLE(aTxPower); }
|
|
|
|
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
OT_UNUSED_VARIABLE(aFrame);
|
|
OT_UNUSED_VARIABLE(aError);
|
|
}
|
|
|
|
void otPlatDiagAlarmCallback(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
|