blob: f7fb0527e8ed05b0ccad35342e4df860355bee40 [file] [log] [blame]
/*
* Copyright (c) 2016, 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 top-level interface to the OpenThread stack.
*/
#define WPP_NAME "openthread.tmh"
#ifdef OPENTHREAD_CONFIG_FILE
#include OPENTHREAD_CONFIG_FILE
#else
#include <openthread-config.h>
#endif
#include <openthread.h>
#if OPENTHREAD_ENABLE_JAM_DETECTION
#include <openthread-jam-detection.h>
#endif
#include <common/code_utils.hpp>
#include <common/debug.hpp>
#include <common/logging.hpp>
#include <common/message.hpp>
#include <common/new.hpp>
#include <common/tasklet.hpp>
#include <common/timer.hpp>
#include <crypto/mbedtls.hpp>
#include <net/icmp6.hpp>
#include <net/ip6.hpp>
#include <platform/settings.h>
#include <platform/radio.h>
#include <platform/random.h>
#include <platform/misc.h>
#include <thread/thread_netif.hpp>
#include <thread/thread_uris.hpp>
#include <utils/slaac_address.hpp>
#include <openthread-instance.h>
#include <openthread-coap.h>
#include <coap/coap_header.hpp>
#include <coap/coap_client.hpp>
#include <coap/coap_server.hpp>
using namespace Thread;
#ifndef OPENTHREAD_MULTIPLE_INSTANCE
static otDEFINE_ALIGNED_VAR(sInstanceRaw, sizeof(otInstance), uint64_t);
otInstance *sInstance = NULL;
#endif
otInstance::otInstance(void) :
mReceiveIp6DatagramCallback(NULL),
mReceiveIp6DatagramCallbackContext(NULL),
mActiveScanCallback(NULL),
mActiveScanCallbackContext(NULL),
mEnergyScanCallback(NULL),
mEnergyScanCallbackContext(NULL),
mThreadNetif(mIp6)
#if OPENTHREAD_ENABLE_RAW_LINK_API
, mLinkRaw(*this)
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
#if OPENTHREAD_ENABLE_APPLICATION_COAP
, mApplicationCoapServer(mIp6.mUdp, OT_DEFAULT_COAP_PORT)
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
{
}
#ifdef __cplusplus
extern "C" {
#endif
static void HandleActiveScanResult(void *aContext, Mac::Frame *aFrame);
static void HandleEnergyScanResult(void *aContext, otEnergyScanResult *aResult);
void otProcessQueuedTasklets(otInstance *aInstance)
{
otLogFuncEntry();
aInstance->mIp6.mTaskletScheduler.ProcessQueuedTasklets();
otLogFuncExit();
}
bool otAreTaskletsPending(otInstance *aInstance)
{
return aInstance->mIp6.mTaskletScheduler.AreTaskletsPending();
}
uint8_t otGetChannel(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetChannel();
}
ThreadError otSetChannel(otInstance *aInstance, uint8_t aChannel)
{
return aInstance->mThreadNetif.GetMac().SetChannel(aChannel);
}
ThreadError otSetDelayTimerMinimal(otInstance *aInstance, uint32_t aDelayTimerMinimal)
{
return aInstance->mThreadNetif.GetLeader().SetDelayTimerMinimal(aDelayTimerMinimal);
}
uint32_t otGetDelayTimerMinimal(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetLeader().GetDelayTimerMinimal();
}
uint8_t otGetMaxAllowedChildren(otInstance *aInstance)
{
uint8_t aNumChildren;
(void)aInstance->mThreadNetif.GetMle().GetChildren(&aNumChildren);
return aNumChildren;
}
ThreadError otSetMaxAllowedChildren(otInstance *aInstance, uint8_t aMaxChildren)
{
return aInstance->mThreadNetif.GetMle().SetMaxAllowedChildren(aMaxChildren);
}
uint32_t otGetChildTimeout(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetTimeout();
}
void otSetChildTimeout(otInstance *aInstance, uint32_t aTimeout)
{
aInstance->mThreadNetif.GetMle().SetTimeout(aTimeout);
}
const uint8_t *otGetExtendedAddress(otInstance *aInstance)
{
return reinterpret_cast<const uint8_t *>(aInstance->mThreadNetif.GetMac().GetExtAddress());
}
ThreadError otSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aExtAddress != NULL, error = kThreadError_InvalidArgs);
aInstance->mThreadNetif.GetMac().SetExtAddress(*static_cast<const Mac::ExtAddress *>(aExtAddress));
SuccessOrExit(error = aInstance->mThreadNetif.GetMle().UpdateLinkLocalAddress());
exit:
return error;
}
const uint8_t *otGetExtendedPanId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetExtendedPanId();
}
void otSetExtendedPanId(otInstance *aInstance, const uint8_t *aExtendedPanId)
{
uint8_t mlPrefix[8];
aInstance->mThreadNetif.GetMac().SetExtendedPanId(aExtendedPanId);
mlPrefix[0] = 0xfd;
memcpy(mlPrefix + 1, aExtendedPanId, 5);
mlPrefix[6] = 0x00;
mlPrefix[7] = 0x00;
aInstance->mThreadNetif.GetMle().SetMeshLocalPrefix(mlPrefix);
}
void otGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64)
{
otPlatRadioGetIeeeEui64(aInstance, aEui64->m8);
}
void otGetHashMacAddress(otInstance *aInstance, otExtAddress *aHashMacAddress)
{
aInstance->mThreadNetif.GetMac().GetHashMacAddress(static_cast<Mac::ExtAddress *>(aHashMacAddress));
}
ThreadError otGetLeaderRloc(otInstance *aInstance, otIp6Address *aAddress)
{
ThreadError error;
VerifyOrExit(aAddress != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetLeaderAddress(*static_cast<Ip6::Address *>(aAddress));
exit:
return error;
}
otLinkModeConfig otGetLinkMode(otInstance *aInstance)
{
otLinkModeConfig config;
uint8_t mode = aInstance->mThreadNetif.GetMle().GetDeviceMode();
memset(&config, 0, sizeof(otLinkModeConfig));
if (mode & Mle::ModeTlv::kModeRxOnWhenIdle)
{
config.mRxOnWhenIdle = 1;
}
if (mode & Mle::ModeTlv::kModeSecureDataRequest)
{
config.mSecureDataRequests = 1;
}
if (mode & Mle::ModeTlv::kModeFFD)
{
config.mDeviceType = 1;
}
if (mode & Mle::ModeTlv::kModeFullNetworkData)
{
config.mNetworkData = 1;
}
return config;
}
ThreadError otSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig)
{
uint8_t mode = 0;
if (aConfig.mRxOnWhenIdle)
{
mode |= Mle::ModeTlv::kModeRxOnWhenIdle;
}
if (aConfig.mSecureDataRequests)
{
mode |= Mle::ModeTlv::kModeSecureDataRequest;
}
if (aConfig.mDeviceType)
{
mode |= Mle::ModeTlv::kModeFFD;
}
if (aConfig.mNetworkData)
{
mode |= Mle::ModeTlv::kModeFullNetworkData;
}
return aInstance->mThreadNetif.GetMle().SetDeviceMode(mode);
}
const uint8_t *otGetMasterKey(otInstance *aInstance, uint8_t *aKeyLength)
{
return aInstance->mThreadNetif.GetKeyManager().GetMasterKey(aKeyLength);
}
ThreadError otSetMasterKey(otInstance *aInstance, const uint8_t *aKey, uint8_t aKeyLength)
{
return aInstance->mThreadNetif.GetKeyManager().SetMasterKey(aKey, aKeyLength);
}
int8_t otGetMaxTransmitPower(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetMaxTransmitPower();
}
void otSetMaxTransmitPower(otInstance *aInstance, int8_t aPower)
{
aInstance->mThreadNetif.GetMac().SetMaxTransmitPower(aPower);
}
const otIp6Address *otGetMeshLocalEid(otInstance *aInstance)
{
return &aInstance->mThreadNetif.GetMle().GetMeshLocal64();
}
const uint8_t *otGetMeshLocalPrefix(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetMeshLocalPrefix();
}
ThreadError otSetMeshLocalPrefix(otInstance *aInstance, const uint8_t *aMeshLocalPrefix)
{
return aInstance->mThreadNetif.GetMle().SetMeshLocalPrefix(aMeshLocalPrefix);
}
ThreadError otGetNetworkDataLeader(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs);
aInstance->mThreadNetif.GetNetworkDataLeader().GetNetworkData(aStable, aData, *aDataLength);
exit:
return error;
}
ThreadError otGetNetworkDataLocal(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs);
aInstance->mThreadNetif.GetNetworkDataLocal().GetNetworkData(aStable, aData, *aDataLength);
exit:
return error;
}
const char *otGetNetworkName(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetNetworkName();
}
ThreadError otSetNetworkName(otInstance *aInstance, const char *aNetworkName)
{
return aInstance->mThreadNetif.GetMac().SetNetworkName(aNetworkName);
}
otPanId otGetPanId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetPanId();
}
ThreadError otSetPanId(otInstance *aInstance, otPanId aPanId)
{
ThreadError error = kThreadError_None;
// do not allow setting PAN ID to broadcast if Thread is running
VerifyOrExit(aPanId != Mac::kPanIdBroadcast ||
aInstance->mThreadNetif.GetMle().GetDeviceState() != Mle::kDeviceStateDisabled,
error = kThreadError_InvalidState);
error = aInstance->mThreadNetif.GetMac().SetPanId(aPanId);
exit:
return error;
}
bool otIsRouterRoleEnabled(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().IsRouterRoleEnabled();
}
void otSetRouterRoleEnabled(otInstance *aInstance, bool aEnabled)
{
aInstance->mThreadNetif.GetMle().SetRouterRoleEnabled(aEnabled);
}
otShortAddress otGetShortAddress(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetShortAddress();
}
uint8_t otGetLocalLeaderWeight(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderWeight();
}
void otSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight)
{
aInstance->mThreadNetif.GetMle().SetLeaderWeight(aWeight);
}
uint32_t otGetLocalLeaderPartitionId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderPartitionId();
}
void otSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId)
{
return aInstance->mThreadNetif.GetMle().SetLeaderPartitionId(aPartitionId);
}
uint16_t otGetJoinerUdpPort(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJoinerRouter().GetJoinerUdpPort();
}
ThreadError otSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort)
{
return aInstance->mThreadNetif.GetJoinerRouter().SetJoinerUdpPort(aJoinerUdpPort);
}
ThreadError otAddBorderRouter(otInstance *aInstance, const otBorderRouterConfig *aConfig)
{
uint8_t flags = 0;
if (aConfig->mPreferred)
{
flags |= NetworkData::BorderRouterEntry::kPreferredFlag;
}
if (aConfig->mSlaac)
{
flags |= NetworkData::BorderRouterEntry::kSlaacFlag;
}
if (aConfig->mDhcp)
{
flags |= NetworkData::BorderRouterEntry::kDhcpFlag;
}
if (aConfig->mConfigure)
{
flags |= NetworkData::BorderRouterEntry::kConfigureFlag;
}
if (aConfig->mDefaultRoute)
{
flags |= NetworkData::BorderRouterEntry::kDefaultRouteFlag;
}
if (aConfig->mOnMesh)
{
flags |= NetworkData::BorderRouterEntry::kOnMeshFlag;
}
return aInstance->mThreadNetif.GetNetworkDataLocal().AddOnMeshPrefix(aConfig->mPrefix.mPrefix.mFields.m8,
aConfig->mPrefix.mLength,
aConfig->mPreference, flags, aConfig->mStable);
}
ThreadError otRemoveBorderRouter(otInstance *aInstance, const otIp6Prefix *aPrefix)
{
return aInstance->mThreadNetif.GetNetworkDataLocal().RemoveOnMeshPrefix(aPrefix->mPrefix.mFields.m8, aPrefix->mLength);
}
ThreadError otGetNextOnMeshPrefix(otInstance *aInstance, bool aLocal, otNetworkDataIterator *aIterator,
otBorderRouterConfig *aConfig)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aIterator && aConfig, error = kThreadError_InvalidArgs);
if (aLocal)
{
error = aInstance->mThreadNetif.GetNetworkDataLocal().GetNextOnMeshPrefix(aIterator, aConfig);
}
else
{
error = aInstance->mThreadNetif.GetNetworkDataLeader().GetNextOnMeshPrefix(aIterator, aConfig);
}
exit:
return error;
}
ThreadError otAddExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig)
{
return aInstance->mThreadNetif.GetNetworkDataLocal().AddHasRoutePrefix(aConfig->mPrefix.mPrefix.mFields.m8,
aConfig->mPrefix.mLength,
aConfig->mPreference, aConfig->mStable);
}
ThreadError otRemoveExternalRoute(otInstance *aInstance, const otIp6Prefix *aPrefix)
{
return aInstance->mThreadNetif.GetNetworkDataLocal().RemoveHasRoutePrefix(aPrefix->mPrefix.mFields.m8,
aPrefix->mLength);
}
ThreadError otSendServerData(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetNetworkDataLocal().SendServerDataNotification();
}
ThreadError otAddUnsecurePort(otInstance *aInstance, uint16_t aPort)
{
return aInstance->mThreadNetif.GetIp6Filter().AddUnsecurePort(aPort);
}
ThreadError otRemoveUnsecurePort(otInstance *aInstance, uint16_t aPort)
{
return aInstance->mThreadNetif.GetIp6Filter().RemoveUnsecurePort(aPort);
}
const uint16_t *otGetUnsecurePorts(otInstance *aInstance, uint8_t *aNumEntries)
{
return aInstance->mThreadNetif.GetIp6Filter().GetUnsecurePorts(*aNumEntries);
}
uint32_t otGetContextIdReuseDelay(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetNetworkDataLeader().GetContextIdReuseDelay();
}
void otSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay)
{
aInstance->mThreadNetif.GetNetworkDataLeader().SetContextIdReuseDelay(aDelay);
}
uint32_t otGetKeySequenceCounter(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetKeyManager().GetCurrentKeySequence();
}
void otSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter)
{
aInstance->mThreadNetif.GetKeyManager().SetCurrentKeySequence(aKeySequenceCounter);
}
uint32_t otGetKeySwitchGuardTime(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetKeyManager().GetKeySwitchGuardTime();
}
void otSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime)
{
aInstance->mThreadNetif.GetKeyManager().SetKeySwitchGuardTime(aKeySwitchGuardTime);
}
uint8_t otGetNetworkIdTimeout(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetNetworkIdTimeout();
}
void otSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout)
{
aInstance->mThreadNetif.GetMle().SetNetworkIdTimeout((uint8_t)aTimeout);
}
uint8_t otGetRouterUpgradeThreshold(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetRouterUpgradeThreshold();
}
void otSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold)
{
aInstance->mThreadNetif.GetMle().SetRouterUpgradeThreshold(aThreshold);
}
ThreadError otReleaseRouterId(otInstance *aInstance, uint8_t aRouterId)
{
return aInstance->mThreadNetif.GetMle().ReleaseRouterId(aRouterId);
}
ThreadError otAddMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr)
{
ThreadError error = kThreadError_None;
if (aInstance->mThreadNetif.GetMac().GetWhitelist().Add(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr)) == NULL)
{
error = kThreadError_NoBufs;
}
return error;
}
ThreadError otAddMacWhitelistRssi(otInstance *aInstance, const uint8_t *aExtAddr, int8_t aRssi)
{
ThreadError error = kThreadError_None;
otMacWhitelistEntry *entry;
entry = aInstance->mThreadNetif.GetMac().GetWhitelist().Add(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr));
VerifyOrExit(entry != NULL, error = kThreadError_NoBufs);
aInstance->mThreadNetif.GetMac().GetWhitelist().SetFixedRssi(*entry, aRssi);
exit:
return error;
}
void otRemoveMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr)
{
aInstance->mThreadNetif.GetMac().GetWhitelist().Remove(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr));
}
void otClearMacWhitelist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetWhitelist().Clear();
}
ThreadError otGetMacWhitelistEntry(otInstance *aInstance, uint8_t aIndex, otMacWhitelistEntry *aEntry)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aEntry != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMac().GetWhitelist().GetEntry(aIndex, *aEntry);
exit:
return error;
}
void otDisableMacWhitelist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetWhitelist().Disable();
}
void otEnableMacWhitelist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetWhitelist().Enable();
}
bool otIsMacWhitelistEnabled(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetWhitelist().IsEnabled();
}
ThreadError otBecomeDetached(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().BecomeDetached();
}
ThreadError otBecomeChild(otInstance *aInstance, otMleAttachFilter aFilter)
{
return aInstance->mThreadNetif.GetMle().BecomeChild(aFilter);
}
ThreadError otBecomeRouter(otInstance *aInstance)
{
ThreadError error = kThreadError_InvalidState;
switch (aInstance->mThreadNetif.GetMle().GetDeviceState())
{
case Mle::kDeviceStateDisabled:
case Mle::kDeviceStateDetached:
break;
case Mle::kDeviceStateChild:
error = aInstance->mThreadNetif.GetMle().BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest);
break;
case Mle::kDeviceStateRouter:
case Mle::kDeviceStateLeader:
error = kThreadError_None;
break;
}
return error;
}
ThreadError otBecomeLeader(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().BecomeLeader();
}
ThreadError otAddMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr)
{
ThreadError error = kThreadError_None;
if (aInstance->mThreadNetif.GetMac().GetBlacklist().Add(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr)) == NULL)
{
error = kThreadError_NoBufs;
}
return error;
}
void otRemoveMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr)
{
aInstance->mThreadNetif.GetMac().GetBlacklist().Remove(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr));
}
void otClearMacBlacklist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetBlacklist().Clear();
}
ThreadError otGetMacBlacklistEntry(otInstance *aInstance, uint8_t aIndex, otMacBlacklistEntry *aEntry)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aEntry != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMac().GetBlacklist().GetEntry(aIndex, *aEntry);
exit:
return error;
}
void otDisableMacBlacklist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetBlacklist().Disable();
}
void otEnableMacBlacklist(otInstance *aInstance)
{
aInstance->mThreadNetif.GetMac().GetBlacklist().Enable();
}
bool otIsMacBlacklistEnabled(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().GetBlacklist().IsEnabled();
}
ThreadError otGetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t *aLinkQuality)
{
Mac::ExtAddress extAddress;
memset(&extAddress, 0, sizeof(extAddress));
memcpy(extAddress.m8, aExtAddr, OT_EXT_ADDRESS_SIZE);
return aInstance->mThreadNetif.GetMle().GetAssignLinkQuality(extAddress, *aLinkQuality);
}
void otSetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t aLinkQuality)
{
Mac::ExtAddress extAddress;
memset(&extAddress, 0, sizeof(extAddress));
memcpy(extAddress.m8, aExtAddr, OT_EXT_ADDRESS_SIZE);
aInstance->mThreadNetif.GetMle().SetAssignLinkQuality(extAddress, aLinkQuality);
}
void otPlatformReset(otInstance *aInstance)
{
otPlatReset(aInstance);
}
void otFactoryReset(otInstance *aInstance)
{
otPlatSettingsWipe(aInstance);
otPlatReset(aInstance);
}
ThreadError otPersistentInfoErase(otInstance *aInstance)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otGetDeviceRole(aInstance) == kDeviceRoleDisabled, error = kThreadError_InvalidState);
otPlatSettingsWipe(aInstance);
exit:
return error;
}
uint8_t otGetRouterDowngradeThreshold(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetRouterDowngradeThreshold();
}
void otSetRouterDowngradeThreshold(otInstance *aInstance, uint8_t aThreshold)
{
aInstance->mThreadNetif.GetMle().SetRouterDowngradeThreshold(aThreshold);
}
uint8_t otGetRouterSelectionJitter(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetRouterSelectionJitter();
}
void otSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter)
{
aInstance->mThreadNetif.GetMle().SetRouterSelectionJitter(aRouterJitter);
}
ThreadError otGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aChildInfo != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetChildInfoById(aChildId, *aChildInfo);
exit:
return error;
}
ThreadError otGetChildInfoByIndex(otInstance *aInstance, uint8_t aChildIndex, otChildInfo *aChildInfo)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aChildInfo != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetChildInfoByIndex(aChildIndex, *aChildInfo);
exit:
return error;
}
ThreadError otGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator *aIterator, otNeighborInfo *aInfo)
{
ThreadError error = kThreadError_None;
VerifyOrExit((aInfo != NULL) && (aIterator != NULL), error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetNextNeighborInfo(*aIterator, *aInfo);
exit:
return error;
}
otDeviceRole otGetDeviceRole(otInstance *aInstance)
{
otDeviceRole rval = kDeviceRoleDisabled;
switch (aInstance->mThreadNetif.GetMle().GetDeviceState())
{
case Mle::kDeviceStateDisabled:
rval = kDeviceRoleDisabled;
break;
case Mle::kDeviceStateDetached:
rval = kDeviceRoleDetached;
break;
case Mle::kDeviceStateChild:
rval = kDeviceRoleChild;
break;
case Mle::kDeviceStateRouter:
rval = kDeviceRoleRouter;
break;
case Mle::kDeviceStateLeader:
rval = kDeviceRoleLeader;
break;
}
return rval;
}
ThreadError otGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCacheEntry *aEntry)
{
ThreadError error;
VerifyOrExit(aEntry != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetAddressResolver().GetEntry(aIndex, *aEntry);
exit:
return error;
}
ThreadError otGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData)
{
ThreadError error;
VerifyOrExit(aLeaderData != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetLeaderData(*aLeaderData);
exit:
return error;
}
uint8_t otGetLeaderRouterId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderDataTlv().GetLeaderRouterId();
}
uint8_t otGetLeaderWeight(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderDataTlv().GetWeighting();
}
uint8_t otGetNetworkDataVersion(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderDataTlv().GetDataVersion();
}
uint32_t otGetPartitionId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderDataTlv().GetPartitionId();
}
uint16_t otGetRloc16(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetRloc16();
}
uint8_t otGetRouterIdSequence(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetRouterIdSequence();
}
ThreadError otGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aRouterInfo != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetMle().GetRouterInfo(aRouterId, *aRouterInfo);
exit:
return error;
}
ThreadError otGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
{
ThreadError error = kThreadError_None;
Router *parent;
VerifyOrExit(aParentInfo != NULL, error = kThreadError_InvalidArgs);
parent = aInstance->mThreadNetif.GetMle().GetParent();
memcpy(aParentInfo->mExtAddress.m8, parent->mMacAddr.m8, OT_EXT_ADDRESS_SIZE);
aParentInfo->mRloc16 = parent->mValid.mRloc16;
exit:
return error;
}
uint8_t otGetStableNetworkDataVersion(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().GetLeaderDataTlv().GetStableDataVersion();
}
void otSetLinkPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext)
{
aInstance->mThreadNetif.GetMac().SetPcapCallback(aPcapCallback, aCallbackContext);
}
bool otIsLinkPromiscuous(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().IsPromiscuous();
}
ThreadError otSetLinkPromiscuous(otInstance *aInstance, bool aPromiscuous)
{
ThreadError error = kThreadError_None;
// cannot enable IEEE 802.15.4 promiscuous mode if the Thread interface is enabled
VerifyOrExit(aInstance->mThreadNetif.IsUp() == false, error = kThreadError_InvalidState);
aInstance->mThreadNetif.GetMac().SetPromiscuous(aPromiscuous);
exit:
return error;
}
const otMacCounters *otGetMacCounters(otInstance *aInstance)
{
return &aInstance->mThreadNetif.GetMac().GetCounters();
}
void otGetMessageBufferInfo(otInstance *aInstance, otBufferInfo *aBufferInfo)
{
aBufferInfo->mTotalBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS;
aBufferInfo->mFreeBuffers = aInstance->mThreadNetif.GetIp6().mMessagePool.GetFreeBufferCount();
aInstance->mThreadNetif.GetMeshForwarder().GetSendQueue().GetInfo(aBufferInfo->m6loSendMessages,
aBufferInfo->m6loSendBuffers);
aInstance->mThreadNetif.GetMeshForwarder().GetReassemblyQueue().GetInfo(aBufferInfo->m6loReassemblyMessages,
aBufferInfo->m6loReassemblyBuffers);
aInstance->mThreadNetif.GetMeshForwarder().GetResolvingQueue().GetInfo(aBufferInfo->mArpMessages,
aBufferInfo->mArpBuffers);
aInstance->mThreadNetif.GetIp6().GetSendQueue().GetInfo(aBufferInfo->mIp6Messages,
aBufferInfo->mIp6Buffers);
aInstance->mThreadNetif.GetIp6().mMpl.GetBufferedMessageSet().GetInfo(aBufferInfo->mMplMessages,
aBufferInfo->mMplBuffers);
aInstance->mThreadNetif.GetMle().GetMessageQueue().GetInfo(aBufferInfo->mMleMessages,
aBufferInfo->mMleBuffers);
aInstance->mThreadNetif.GetCoapClient().GetRequestMessages().GetInfo(aBufferInfo->mCoapClientMessages,
aBufferInfo->mCoapClientBuffers);
}
#if OPENTHREAD_ENABLE_JAM_DETECTION
ThreadError otSetJamDetectionRssiThreshold(otInstance *aInstance, int8_t aRssiThreshold)
{
return aInstance->mThreadNetif.GetJamDetector().SetRssiThreshold(aRssiThreshold);
}
int8_t otGetJamDetectionRssiThreshold(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().GetRssiThreshold();
}
ThreadError otSetJamDetectionWindow(otInstance *aInstance, uint8_t aWindow)
{
return aInstance->mThreadNetif.GetJamDetector().SetWindow(aWindow);
}
uint8_t otGetJamDetectionWindow(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().GetWindow();
}
ThreadError otSetJamDetectionBusyPeriod(otInstance *aInstance, uint8_t aBusyPeriod)
{
return aInstance->mThreadNetif.GetJamDetector().SetBusyPeriod(aBusyPeriod);
}
uint8_t otGetJamDetectionBusyPeriod(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().GetBusyPeriod();
}
ThreadError otStartJamDetection(otInstance *aInstance, otJamDetectionCallback aCallback, void *aContext)
{
return aInstance->mThreadNetif.GetJamDetector().Start(aCallback, aContext);
}
ThreadError otStopJamDetection(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().Stop();
}
bool otIsJamDetectionEnabled(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().IsEnabled();
}
bool otGetJamDetectionState(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().GetState();
}
uint64_t otGetJamDetectionHistoryBitmap(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJamDetector().GetHistoryBitmap();
}
#endif // OPENTHREAD_ENABLE_JAM_DETECTION
bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b)
{
return *static_cast<const Ip6::Address *>(a) == *static_cast<const Ip6::Address *>(b);
}
ThreadError otIp6AddressFromString(const char *str, otIp6Address *address)
{
return static_cast<Ip6::Address *>(address)->FromString(str);
}
const otNetifAddress *otGetUnicastAddresses(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetUnicastAddresses();
}
ThreadError otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *address)
{
return aInstance->mThreadNetif.AddExternalUnicastAddress(*static_cast<const Ip6::NetifUnicastAddress *>(address));
}
ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *address)
{
return aInstance->mThreadNetif.RemoveExternalUnicastAddress(*static_cast<const Ip6::Address *>(address));
}
#if OPENTHREAD_ENABLE_DHCP6_SERVER
void otDhcp6ServerUpdate(otInstance *aInstance)
{
aInstance->mThreadNetif.GetDhcp6Server().UpdateService();
}
#endif // OPENTHREAD_ENABLE_DHCP6_SERVER
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
void otDhcp6ClientUpdate(otInstance *aInstance, otDhcpAddress *aAddresses, uint32_t aNumAddresses, void *aContext)
{
aInstance->mThreadNetif.GetDhcp6Client().UpdateAddresses(aInstance, aAddresses, aNumAddresses, aContext);
}
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
const otNetifMulticastAddress *otGetMulticastAddresses(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMulticastAddresses();
}
ThreadError otSubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress)
{
return aInstance->mThreadNetif.SubscribeExternalMulticast(*static_cast<const Ip6::Address *>(aAddress));
}
ThreadError otUnsubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress)
{
return aInstance->mThreadNetif.UnsubscribeExternalMulticast(*static_cast<const Ip6::Address *>(aAddress));
}
bool otIsMulticastPromiscuousModeEnabled(otInstance *aInstance)
{
return aInstance->mThreadNetif.IsMulticastPromiscuousModeEnabled();
}
void otEnableMulticastPromiscuousMode(otInstance *aInstance)
{
aInstance->mThreadNetif.EnableMulticastPromiscuousMode();
}
void otDisableMulticastPromiscuousMode(otInstance *aInstance)
{
aInstance->mThreadNetif.DisableMulticastPromiscuousMode();
}
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
otSlaacIidCreate aIidCreate, void *aContext)
{
Utils::Slaac::UpdateAddresses(aInstance, aAddresses, aNumAddresses, aIidCreate, aContext);
}
ThreadError otCreateRandomIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext)
{
return Utils::Slaac::CreateRandomIid(aInstance, aAddress, aContext);
}
ThreadError otCreateMacIid(otInstance *aInstance, otNetifAddress *aAddress, void *)
{
memcpy(&aAddress->mAddress.mFields.m8[OT_IP6_ADDRESS_SIZE - OT_IP6_IID_SIZE],
aInstance->mThreadNetif.GetMac().GetExtAddress(), OT_IP6_IID_SIZE);
aAddress->mAddress.mFields.m8[OT_IP6_ADDRESS_SIZE - OT_IP6_IID_SIZE] ^= 0x02;
return kThreadError_None;
}
ThreadError otCreateSemanticallyOpaqueIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext)
{
return static_cast<Utils::SemanticallyOpaqueIidGenerator *>(aContext)->CreateIid(aInstance, aAddress);
}
ThreadError otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aCallbackContext)
{
ThreadError error = kThreadError_NoBufs;
for (size_t i = 0; i < OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS; i++)
{
if (aInstance->mNetifCallback[i].IsFree())
{
aInstance->mNetifCallback[i].Set(aCallback, aCallbackContext);
error = aInstance->mThreadNetif.RegisterCallback(aInstance->mNetifCallback[i]);
break;
}
}
return error;
}
void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aCallbackContext)
{
for (size_t i = 0; i < OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS; i++)
{
if (aInstance->mNetifCallback[i].IsServing(aCallback, aCallbackContext))
{
aInstance->mThreadNetif.RemoveCallback(aInstance->mNetifCallback[i]);
aInstance->mNetifCallback[i].Free();
break;
}
}
}
const char *otGetVersionString(void)
{
/**
* PLATFORM_VERSION_ATTR_PREFIX and PLATFORM_VERSION_ATTR_SUFFIX are
* intended to be used to specify compiler directives to indicate
* what linker section the platform version string should be stored.
*
* This is useful for specifying an exact locaiton of where the version
* string will be located so that it can be easily retrieved from the
* raw firmware image.
*
* If PLATFORM_VERSION_ATTR_PREFIX is unspecified, the keyword `static`
* is used instead.
*
* If both are unspecified, the location of the string in the firmware
* image will be undefined and may change.
*/
#ifdef PLATFORM_VERSION_ATTR_PREFIX
PLATFORM_VERSION_ATTR_PREFIX
#else
static
#endif
const char sVersion[] =
PACKAGE_NAME "/" PACKAGE_VERSION
#ifdef PLATFORM_INFO
"; " PLATFORM_INFO
#endif
#if defined(__DATE__)
"; " __DATE__ " " __TIME__
#endif
#ifdef PLATFORM_VERSION_ATTR_SUFFIX
PLATFORM_VERSION_ATTR_SUFFIX
#endif
; // Trailing semicolon to end statement.
return sVersion;
}
uint32_t otGetPollPeriod(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMeshForwarder().GetAssignPollPeriod();
}
void otSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod)
{
aInstance->mThreadNetif.GetMeshForwarder().SetAssignPollPeriod(aPollPeriod);
}
ThreadError otSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId)
{
return aInstance->mThreadNetif.GetMle().SetPreferredRouterId(aRouterId);
}
#ifdef OPENTHREAD_MULTIPLE_INSTANCE
otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize)
{
otInstance *aInstance = NULL;
otLogFuncEntry();
otLogInfoApi("otInstanceInit");
VerifyOrExit(aInstanceBufferSize != NULL, ;);
// Make sure the input buffer is big enough
VerifyOrExit(sizeof(otInstance) <= *aInstanceBufferSize, *aInstanceBufferSize = sizeof(otInstance));
VerifyOrExit(aInstanceBuffer != NULL, ;);
// Construct the context
aInstance = new(aInstanceBuffer)otInstance();
// restore datasets and network information
otPlatSettingsInit(aInstance);
aInstance->mThreadNetif.GetMle().Restore();
exit:
otLogFuncExit();
return aInstance;
}
#else
otInstance *otInstanceInit()
{
otLogFuncEntry();
otLogInfoApi("otInstanceInit");
VerifyOrExit(sInstance == NULL, ;);
// Construct the context
sInstance = new(&sInstanceRaw)otInstance();
// restore datasets and network information
otPlatSettingsInit(sInstance);
sInstance->mThreadNetif.GetMle().Restore();
exit:
otLogFuncExit();
return sInstance;
}
#endif
void otSetReceiveDiagnosticGetCallback(otInstance *aInstance, otReceiveDiagnosticGetCallback aCallback,
void *aCallbackContext)
{
aInstance->mThreadNetif.GetNetworkDiagnostic().SetReceiveDiagnosticGetCallback(aCallback, aCallbackContext);
}
ThreadError otSendDiagnosticGet(otInstance *aInstance, const otIp6Address *aDestination, const uint8_t aTlvTypes[],
uint8_t aCount)
{
return aInstance->mThreadNetif.GetNetworkDiagnostic().SendDiagnosticGet(*static_cast<const Ip6::Address *>
(aDestination),
aTlvTypes,
aCount);
}
ThreadError otSendDiagnosticReset(otInstance *aInstance, const otIp6Address *aDestination, const uint8_t aTlvTypes[],
uint8_t aCount)
{
return aInstance->mThreadNetif.GetNetworkDiagnostic().SendDiagnosticReset(*static_cast<const Ip6::Address *>
(aDestination),
aTlvTypes,
aCount);
}
void otInstanceFinalize(otInstance *aInstance)
{
otLogFuncEntry();
// Ensure we are disabled
(void)otThreadStop(aInstance);
(void)otInterfaceDown(aInstance);
#ifndef OPENTHREAD_MULTIPLE_INSTANCE
sInstance = NULL;
#endif
otLogFuncExit();
}
ThreadError otInterfaceUp(otInstance *aInstance)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
#if OPENTHREAD_ENABLE_RAW_LINK_API
VerifyOrExit(!aInstance->mLinkRaw.IsEnabled(), error = kThreadError_InvalidState);
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
error = aInstance->mThreadNetif.Up();
#if OPENTHREAD_ENABLE_RAW_LINK_API
exit:
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
otLogFuncExitErr(error);
return error;
}
ThreadError otInterfaceDown(otInstance *aInstance)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
#if OPENTHREAD_ENABLE_RAW_LINK_API
VerifyOrExit(!aInstance->mLinkRaw.IsEnabled(), error = kThreadError_InvalidState);
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
error = aInstance->mThreadNetif.Down();
#if OPENTHREAD_ENABLE_RAW_LINK_API
exit:
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
otLogFuncExitErr(error);
return error;
}
bool otIsInterfaceUp(otInstance *aInstance)
{
return aInstance->mThreadNetif.IsUp();
}
ThreadError otThreadStart(otInstance *aInstance)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
VerifyOrExit(aInstance->mThreadNetif.GetMac().GetPanId() != Mac::kPanIdBroadcast, error = kThreadError_InvalidState);
error = aInstance->mThreadNetif.GetMle().Start(true);
exit:
otLogFuncExitErr(error);
return error;
}
ThreadError otThreadStop(otInstance *aInstance)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
error = aInstance->mThreadNetif.GetMle().Stop(true);
otLogFuncExitErr(error);
return error;
}
bool otIsSingleton(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().IsSingleton();
}
ThreadError otActiveScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
otHandleActiveScanResult aCallback, void *aCallbackContext)
{
aInstance->mActiveScanCallback = aCallback;
aInstance->mActiveScanCallbackContext = aCallbackContext;
return aInstance->mThreadNetif.GetMac().ActiveScan(aScanChannels, aScanDuration, &HandleActiveScanResult, aInstance);
}
bool otIsActiveScanInProgress(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().IsActiveScanInProgress();
}
void HandleActiveScanResult(void *aContext, Mac::Frame *aFrame)
{
otInstance *aInstance = static_cast<otInstance *>(aContext);
otActiveScanResult result;
Mac::Address address;
Mac::Beacon *beacon;
uint8_t payloadLength;
memset(&result, 0, sizeof(otActiveScanResult));
if (aFrame == NULL)
{
aInstance->mActiveScanCallback(NULL, aInstance->mActiveScanCallbackContext);
ExitNow();
}
SuccessOrExit(aFrame->GetSrcAddr(address));
VerifyOrExit(address.mLength == sizeof(address.mExtAddress), ;);
memcpy(&result.mExtAddress, &address.mExtAddress, sizeof(result.mExtAddress));
aFrame->GetSrcPanId(result.mPanId);
result.mChannel = aFrame->GetChannel();
result.mRssi = aFrame->GetPower();
result.mLqi = aFrame->GetLqi();
payloadLength = aFrame->GetPayloadLength();
beacon = reinterpret_cast<Mac::Beacon *>(aFrame->GetPayload());
if (payloadLength >= sizeof(*beacon) && beacon->IsValid())
{
result.mVersion = beacon->GetProtocolVersion();
result.mIsJoinable = beacon->IsJoiningPermitted();
result.mIsNative = beacon->IsNative();
memcpy(&result.mNetworkName, beacon->GetNetworkName(), sizeof(result.mNetworkName));
memcpy(&result.mExtendedPanId, beacon->GetExtendedPanId(), sizeof(result.mExtendedPanId));
}
aInstance->mActiveScanCallback(&result, aInstance->mActiveScanCallbackContext);
exit:
return;
}
ThreadError otEnergyScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
otHandleEnergyScanResult aCallback, void *aCallbackContext)
{
aInstance->mEnergyScanCallback = aCallback;
aInstance->mEnergyScanCallbackContext = aCallbackContext;
return aInstance->mThreadNetif.GetMac().EnergyScan(aScanChannels, aScanDuration, &HandleEnergyScanResult, aInstance);
}
void HandleEnergyScanResult(void *aContext, otEnergyScanResult *aResult)
{
otInstance *aInstance = static_cast<otInstance *>(aContext);
aInstance->mEnergyScanCallback(aResult, aInstance->mEnergyScanCallbackContext);
}
bool otIsEnergyScanInProgress(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMac().IsEnergyScanInProgress();
}
ThreadError otDiscover(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanId,
otHandleActiveScanResult aCallback, void *aCallbackContext)
{
return aInstance->mThreadNetif.GetMle().Discover(aScanChannels, aScanDuration, aPanId, false, aCallback,
aCallbackContext);
}
bool otIsDiscoverInProgress(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMle().IsDiscoverInProgress();
}
ThreadError otSendMacDataRequest(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetMeshForwarder().SendMacDataRequest();
}
void otSetReceiveIp6DatagramCallback(otInstance *aInstance, otReceiveIp6DatagramCallback aCallback,
void *aCallbackContext)
{
aInstance->mIp6.SetReceiveDatagramCallback(aCallback, aCallbackContext);
}
bool otIsReceiveIp6DatagramFilterEnabled(otInstance *aInstance)
{
return aInstance->mIp6.IsReceiveIp6FilterEnabled();
}
void otSetReceiveIp6DatagramFilterEnabled(otInstance *aInstance, bool aEnabled)
{
aInstance->mIp6.SetReceiveIp6FilterEnabled(aEnabled);
}
ThreadError otSendIp6Datagram(otInstance *aInstance, otMessage aMessage)
{
ThreadError error;
otLogFuncEntry();
error = aInstance->mIp6.HandleDatagram(*static_cast<Message *>(aMessage), NULL,
aInstance->mThreadNetif.GetInterfaceId(), NULL, true);
otLogFuncExitErr(error);
return error;
}
otMessage otNewUdpMessage(otInstance *aInstance, bool aLinkSecurityEnabled)
{
Message *message = aInstance->mIp6.mUdp.NewMessage(0);
if (message)
{
message->SetLinkSecurityEnabled(aLinkSecurityEnabled);
}
return message;
}
otMessage otNewIp6Message(otInstance *aInstance, bool aLinkSecurityEnabled)
{
Message *message = aInstance->mIp6.mMessagePool.New(Message::kTypeIp6, 0);
if (message)
{
message->SetLinkSecurityEnabled(aLinkSecurityEnabled);
}
return message;
}
ThreadError otFreeMessage(otMessage aMessage)
{
return static_cast<Message *>(aMessage)->Free();
}
uint16_t otGetMessageLength(otMessage aMessage)
{
Message *message = static_cast<Message *>(aMessage);
return message->GetLength();
}
ThreadError otSetMessageLength(otMessage aMessage, uint16_t aLength)
{
Message *message = static_cast<Message *>(aMessage);
return message->SetLength(aLength);
}
uint16_t otGetMessageOffset(otMessage aMessage)
{
Message *message = static_cast<Message *>(aMessage);
return message->GetOffset();
}
ThreadError otSetMessageOffset(otMessage aMessage, uint16_t aOffset)
{
Message *message = static_cast<Message *>(aMessage);
return message->SetOffset(aOffset);
}
bool otIsMessageLinkSecurityEnabled(otMessage aMessage)
{
Message *message = static_cast<Message *>(aMessage);
return message->IsLinkSecurityEnabled();
}
void otMessageSetDirectTransmission(otMessage aMessage, bool aEnabled)
{
Message *message = static_cast<Message *>(aMessage);
if (aEnabled)
{
message->SetDirectTransmission();
}
else
{
message->ClearDirectTransmission();
}
}
ThreadError otAppendMessage(otMessage aMessage, const void *aBuf, uint16_t aLength)
{
Message *message = static_cast<Message *>(aMessage);
return message->Append(aBuf, aLength);
}
int otReadMessage(otMessage aMessage, uint16_t aOffset, void *aBuf, uint16_t aLength)
{
Message *message = static_cast<Message *>(aMessage);
return message->Read(aOffset, aLength, aBuf);
}
int otWriteMessage(otMessage aMessage, uint16_t aOffset, const void *aBuf, uint16_t aLength)
{
Message *message = static_cast<Message *>(aMessage);
return message->Write(aOffset, aLength, aBuf);
}
void otMessageQueueInit(otMessageQueue *aQueue)
{
aQueue->mData = NULL;
}
ThreadError otMessageQueueEnqueue(otMessageQueue *aQueue, otMessage aMessage)
{
Message *message = static_cast<Message *>(aMessage);
MessageQueue *queue = static_cast<MessageQueue *>(aQueue);
return queue->Enqueue(*message);
}
ThreadError otMessageQueueDequeue(otMessageQueue *aQueue, otMessage aMessage)
{
Message *message = static_cast<Message *>(aMessage);
MessageQueue *queue = static_cast<MessageQueue *>(aQueue);
return queue->Dequeue(*message);
}
otMessage otMessageQueueGetHead(otMessageQueue *aQueue)
{
MessageQueue *queue = static_cast<MessageQueue *>(aQueue);
return queue->GetHead();
}
otMessage otMessageQueueGetNext(otMessageQueue *aQueue, otMessage aMessage)
{
Message *next;
Message *message = static_cast<Message *>(aMessage);
MessageQueue *queue = static_cast<MessageQueue *>(aQueue);
VerifyOrExit(message != NULL, next = NULL);
VerifyOrExit(message->GetMessageQueue() == queue, next = NULL);
next = message->GetNext();
exit:
return next;
}
ThreadError otOpenUdpSocket(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aCallbackContext)
{
ThreadError error = kThreadError_InvalidArgs;
Ip6::UdpSocket *socket = static_cast<Ip6::UdpSocket *>(aSocket);
if (socket->mTransport == NULL)
{
socket->mTransport = &aInstance->mIp6.mUdp;
error = socket->Open(aCallback, aCallbackContext);
}
return error;
}
ThreadError otCloseUdpSocket(otUdpSocket *aSocket)
{
ThreadError error = kThreadError_InvalidState;
Ip6::UdpSocket *socket = static_cast<Ip6::UdpSocket *>(aSocket);
if (socket->mTransport != NULL)
{
error = socket->Close();
if (error == kThreadError_None)
{
socket->mTransport = NULL;
}
}
return error;
}
ThreadError otBindUdpSocket(otUdpSocket *aSocket, otSockAddr *aSockName)
{
Ip6::UdpSocket *socket = static_cast<Ip6::UdpSocket *>(aSocket);
return socket->Bind(*static_cast<const Ip6::SockAddr *>(aSockName));
}
ThreadError otSendUdp(otUdpSocket *aSocket, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
Ip6::UdpSocket *socket = static_cast<Ip6::UdpSocket *>(aSocket);
return socket->SendTo(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
bool otIsIcmpEchoEnabled(otInstance *aInstance)
{
return aInstance->mIp6.mIcmp.IsEchoEnabled();
}
void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled)
{
aInstance->mIp6.mIcmp.SetEchoEnabled(aEnabled);
}
uint8_t otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond)
{
uint8_t rval;
VerifyOrExit(aFirst != NULL && aSecond != NULL, rval = 0);
rval = static_cast<const Ip6::Address *>(aFirst)->PrefixMatch(*static_cast<const Ip6::Address *>(aSecond));
exit:
return rval;
}
ThreadError otGetActiveDataset(otInstance *aInstance, otOperationalDataset *aDataset)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aDataset != NULL, error = kThreadError_InvalidArgs);
aInstance->mThreadNetif.GetActiveDataset().GetLocal().Get(*aDataset);
exit:
return error;
}
ThreadError otSetActiveDataset(otInstance *aInstance, const otOperationalDataset *aDataset)
{
ThreadError error;
VerifyOrExit(aDataset != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetActiveDataset().Set(*aDataset);
exit:
return error;
}
bool otIsNodeCommissioned(otInstance *aInstance)
{
otOperationalDataset dataset;
otGetActiveDataset(aInstance, &dataset);
if ((dataset.mIsMasterKeySet) && (dataset.mIsNetworkNameSet) &&
(dataset.mIsExtendedPanIdSet) && (dataset.mIsPanIdSet) && (dataset.mIsChannelSet))
{
return true;
}
return false;
}
ThreadError otGetPendingDataset(otInstance *aInstance, otOperationalDataset *aDataset)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aDataset != NULL, error = kThreadError_InvalidArgs);
aInstance->mThreadNetif.GetPendingDataset().GetLocal().Get(*aDataset);
exit:
return error;
}
ThreadError otSetPendingDataset(otInstance *aInstance, const otOperationalDataset *aDataset)
{
ThreadError error;
VerifyOrExit(aDataset != NULL, error = kThreadError_InvalidArgs);
error = aInstance->mThreadNetif.GetPendingDataset().Set(*aDataset);
exit:
return error;
}
ThreadError otSendActiveGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
const otIp6Address *aAddress)
{
return aInstance->mThreadNetif.GetActiveDataset().SendGetRequest(aTlvTypes, aLength, aAddress);
}
ThreadError otSendActiveSet(otInstance *aInstance, const otOperationalDataset *aDataset, const uint8_t *aTlvs,
uint8_t aLength)
{
return aInstance->mThreadNetif.GetActiveDataset().SendSetRequest(*aDataset, aTlvs, aLength);
}
ThreadError otSendPendingGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
const otIp6Address *aAddress)
{
return aInstance->mThreadNetif.GetPendingDataset().SendGetRequest(aTlvTypes, aLength, aAddress);
}
ThreadError otSendPendingSet(otInstance *aInstance, const otOperationalDataset *aDataset, const uint8_t *aTlvs,
uint8_t aLength)
{
return aInstance->mThreadNetif.GetPendingDataset().SendSetRequest(*aDataset, aTlvs, aLength);
}
#if OPENTHREAD_ENABLE_COMMISSIONER
#include <commissioning/commissioner.h>
ThreadError otCommissionerStart(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetCommissioner().Start();
}
ThreadError otCommissionerStop(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetCommissioner().Stop();
}
ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress, const char *aPSKd)
{
return aInstance->mThreadNetif.GetCommissioner().AddJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress), aPSKd);
}
ThreadError otCommissionerRemoveJoiner(otInstance *aInstance, const otExtAddress *aExtAddress)
{
return aInstance->mThreadNetif.GetCommissioner().RemoveJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress));
}
ThreadError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl)
{
return aInstance->mThreadNetif.GetCommissioner().SetProvisioningUrl(aProvisioningUrl);
}
ThreadError otCommissionerAnnounceBegin(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
const otIp6Address *aAddress)
{
return aInstance->mThreadNetif.GetCommissioner().mAnnounceBegin.SendRequest(aChannelMask, aCount, aPeriod,
*static_cast<const Ip6::Address *>(aAddress));
}
ThreadError otCommissionerEnergyScan(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
uint16_t aScanDuration, const otIp6Address *aAddress,
otCommissionerEnergyReportCallback aCallback, void *aContext)
{
return aInstance->mThreadNetif.GetCommissioner().mEnergyScan.SendQuery(aChannelMask, aCount, aPeriod, aScanDuration,
*static_cast<const Ip6::Address *>(aAddress),
aCallback, aContext);
}
ThreadError otCommissionerPanIdQuery(otInstance *aInstance, uint16_t aPanId, uint32_t aChannelMask,
const otIp6Address *aAddress,
otCommissionerPanIdConflictCallback aCallback, void *aContext)
{
return aInstance->mThreadNetif.GetCommissioner().mPanIdQuery.SendQuery(
aPanId, aChannelMask, *static_cast<const Ip6::Address *>(aAddress), aCallback, aContext);
}
ThreadError otSendMgmtCommissionerGet(otInstance *aInstance, const uint8_t *aTlvs, uint8_t aLength)
{
return aInstance->mThreadNetif.GetCommissioner().SendMgmtCommissionerGetRequest(aTlvs, aLength);
}
ThreadError otSendMgmtCommissionerSet(otInstance *aInstance, const otCommissioningDataset *aDataset,
const uint8_t *aTlvs, uint8_t aLength)
{
return aInstance->mThreadNetif.GetCommissioner().SendMgmtCommissionerSetRequest(*aDataset, aTlvs, aLength);
}
uint16_t otCommissionerGetSessionId(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetCommissioner().GetSessionId();
}
ThreadError otCommissionerGeneratePSKc(otInstance *aInstance, const char *aPassPhrase, const char *aNetworkName,
const uint8_t *aExtPanId, uint8_t *aPSKc)
{
return aInstance->mThreadNetif.GetCommissioner().GeneratePSKc(aPassPhrase, aNetworkName, aExtPanId, aPSKc);
}
#endif // OPENTHREAD_ENABLE_COMMISSIONER
#if OPENTHREAD_ENABLE_JOINER
ThreadError otJoinerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl,
const char *aVendorName, const char *aVendorModel,
const char *aVendorSwVersion, const char *aVendorData,
otJoinerCallback aCallback, void *aContext)
{
return aInstance->mThreadNetif.GetJoiner().Start(aPSKd, aProvisioningUrl,
aVendorName, aVendorModel, aVendorSwVersion, aVendorData,
aCallback, aContext);
}
ThreadError otJoinerStop(otInstance *aInstance)
{
return aInstance->mThreadNetif.GetJoiner().Stop();
}
#endif // OPENTHREAD_ENABLE_JOINER
#if OPENTHREAD_ENABLE_APPLICATION_COAP
void otCoapHeaderInit(otCoapHeader *aHeader, otCoapType aType, otCoapCode aCode)
{
Coap::Header *header = static_cast<Coap::Header *>(aHeader);
header->Init(aType, aCode);
}
void otCoapHeaderSetToken(otCoapHeader *aHeader, const uint8_t *aToken, uint8_t aTokenLength)
{
static_cast<Coap::Header *>(aHeader)->SetToken(aToken, aTokenLength);
}
void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength)
{
static_cast<Coap::Header *>(aHeader)->SetToken(aTokenLength);
}
ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption)
{
return static_cast<Coap::Header *>(aHeader)->AppendOption(*static_cast<const Coap::Header::Option *>(aOption));
}
ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath)
{
return static_cast<Coap::Header *>(aHeader)->AppendUriPathOptions(aUriPath);
}
void otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader)
{
static_cast<Coap::Header *>(aHeader)->SetPayloadMarker();
}
void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId)
{
return static_cast<Coap::Header *>(aHeader)->SetMessageId(aMessageId);
}
otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader)
{
return static_cast<const Coap::Header *>(aHeader)->GetType();
}
otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader)
{
return static_cast<const Coap::Header *>(aHeader)->GetCode();
}
uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader)
{
return static_cast<const Coap::Header *>(aHeader)->GetMessageId();
}
uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader)
{
return static_cast<const Coap::Header *>(aHeader)->GetTokenLength();
}
const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader)
{
return static_cast<const Coap::Header *>(aHeader)->GetToken();
}
const otCoapOption *otCoapHeaderGetCurrentOption(const otCoapHeader *aHeader)
{
return static_cast<const otCoapOption *>(static_cast<const Coap::Header *>(aHeader)->GetCurrentOption());
}
const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader)
{
return static_cast<const otCoapOption *>(static_cast<Coap::Header *>(aHeader)->GetNextOption());
}
otMessage otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader)
{
return aInstance->mThreadNetif.GetCoapClient().NewMessage(*(static_cast<const Coap::Header *>(aHeader)));
}
ThreadError otCoapSendRequest(otInstance *aInstance, otMessage aMessage, const otMessageInfo *aMessageInfo,
otCoapResponseHandler aHandler, void *aContext)
{
return aInstance->mThreadNetif.GetCoapClient().SendMessage(
*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
aHandler, aContext);
}
ThreadError otCoapServerStart(otInstance *aInstance)
{
return aInstance->mApplicationCoapServer.Start();
}
ThreadError otCoapServerStop(otInstance *aInstance)
{
return aInstance->mApplicationCoapServer.Stop();
}
ThreadError otCoapServerSetPort(otInstance *aInstance, uint16_t aPort)
{
return aInstance->mApplicationCoapServer.SetPort(aPort);
}
ThreadError otCoapServerAddResource(otInstance *aInstance, otCoapResource *aResource)
{
return aInstance->mApplicationCoapServer.AddResource(*static_cast<Coap::Resource *>(aResource));
}
void otCoapServerRemoveResource(otInstance *aInstance, otCoapResource *aResource)
{
aInstance->mApplicationCoapServer.RemoveResource(*static_cast<Coap::Resource *>(aResource));
}
ThreadError otCoapSendResponse(otInstance *aInstance, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
return aInstance->mApplicationCoapServer.SendMessage(
*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
#ifdef __cplusplus
} // extern "C"
#endif