#include "instance.hpp"
#include <openthread/platform/misc.h>
#include "common/logging.hpp"
#include "common/new.hpp"
namespace ot {
#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
otHeapFreeFn ot::Instance::mFree = NULL;
otHeapCAllocFn ot::Instance::mCAlloc = NULL;
#endif
#endif
Instance::Instance(void)
: mTaskletScheduler()
, mTimerMilliScheduler(*this)
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
, mTimerMicroScheduler(*this)
#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
, mHeap()
#endif
, mMbedTls()
#endif , mRandomManager()
, mRadio(*this)
#if OPENTHREAD_MTD || OPENTHREAD_FTD
, mNotifier(*this)
, mSettings(*this)
, mSettingsDriver(*this)
, mMessagePool(*this)
, mIp6(*this)
, mThreadNetif(*this)
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
, mApplicationCoap(*this)
#endif
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
, mApplicationCoapSecure(*this, true)
#endif
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
, mChannelMonitor(*this)
#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
, mChannelManager(*this)
#endif
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
, mAnnounceSender(*this)
#endif
#if OPENTHREAD_CONFIG_OTNS_ENABLE
, mOtns(*this)
#endif
#endif #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
, mLinkRaw(*this)
#endif
#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
, mLogLevel(static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT))
#endif
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
, mExtension(Extension::ExtensionBase::Init(*this))
#endif
#if OPENTHREAD_CONFIG_DIAG_ENABLE
, mDiags(*this)
#endif
, mIsInitialized(false)
{
}
#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
Instance &Instance::InitSingle(void)
{
Instance *instance = &Get();
VerifyOrExit(!instance->mIsInitialized, OT_NOOP);
instance = new (&gInstanceRaw) Instance();
instance->AfterInit();
exit:
return *instance;
}
Instance &Instance::Get(void)
{
void *instance = &gInstanceRaw;
return *static_cast<Instance *>(instance);
}
#else
Instance *Instance::Init(void *aBuffer, size_t *aBufferSize)
{
Instance *instance = NULL;
VerifyOrExit(aBufferSize != NULL, OT_NOOP);
VerifyOrExit(sizeof(Instance) <= *aBufferSize, *aBufferSize = sizeof(Instance));
VerifyOrExit(aBuffer != NULL, OT_NOOP);
instance = new (aBuffer) Instance();
instance->AfterInit();
exit:
return instance;
}
#endif
void Instance::Reset(void)
{
otPlatReset(this);
}
void Instance::AfterInit(void)
{
mIsInitialized = true;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
Get<Settings>().Init();
IgnoreError(Get<Mle::MleRouter>().Restore());
#endif
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
Get<Extension::ExtensionBase>().SignalInstanceInit();
#endif
}
void Instance::Finalize(void)
{
VerifyOrExit(mIsInitialized, OT_NOOP);
mIsInitialized = false;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
IgnoreError(otThreadSetEnabled(this, false));
IgnoreError(otIp6SetEnabled(this, false));
IgnoreError(otLinkSetEnabled(this, false));
Get<Settings>().Deinit();
#endif
IgnoreError(Get<Mac::SubMac>().Disable());
#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
this->~Instance();
#endif
exit:
return;
}
#if OPENTHREAD_MTD || OPENTHREAD_FTD
void Instance::FactoryReset(void)
{
Get<Settings>().Wipe();
otPlatReset(this);
}
otError Instance::ErasePersistentInfo(void)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
Get<Settings>().Wipe();
exit:
return error;
}
#endif
}