/* * 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 OpenThread Link API. */ #include "openthread-core-config.h" #include #include "common/as_core_type.hpp" #include "common/locator_getters.hpp" #include "mac/mac.hpp" #include "radio/radio.hpp" using namespace ot; uint8_t otLinkGetChannel(otInstance *aInstance) { Instance &instance = AsCoreType(aInstance); uint8_t channel; #if OPENTHREAD_CONFIG_LINK_RAW_ENABLE if (instance.Get().IsEnabled()) { channel = instance.Get().GetChannel(); } else #endif { channel = instance.Get().GetPanChannel(); } return channel; } otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel) { Error error; Instance &instance = AsCoreType(aInstance); #if OPENTHREAD_CONFIG_LINK_RAW_ENABLE if (instance.Get().IsEnabled()) { error = instance.Get().SetChannel(aChannel); ExitNow(); } #endif VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); SuccessOrExit(error = instance.Get().SetPanChannel(aChannel)); instance.Get().Clear(); instance.Get().Clear(); exit: return error; } uint32_t otLinkGetSupportedChannelMask(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetSupportedChannelMask().GetMask(); } otError otLinkSetSupportedChannelMask(otInstance *aInstance, uint32_t aChannelMask) { Error error = kErrorNone; Instance &instance = AsCoreType(aInstance); VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); instance.Get().SetSupportedChannelMask(Mac::ChannelMask(aChannelMask)); exit: return error; } const otExtAddress *otLinkGetExtendedAddress(otInstance *aInstance) { return &AsCoreType(aInstance).Get().GetExtAddress(); } otError otLinkSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress) { Error error = kErrorNone; Instance &instance = AsCoreType(aInstance); VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); instance.Get().SetExtAddress(AsCoreType(aExtAddress)); instance.Get().UpdateLinkLocalAddress(); exit: return error; } void otLinkGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64) { AsCoreType(aInstance).Get().GetIeeeEui64(AsCoreType(aEui64)); } otPanId otLinkGetPanId(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetPanId(); } otError otLinkSetPanId(otInstance *aInstance, otPanId aPanId) { Error error = kErrorNone; Instance &instance = AsCoreType(aInstance); VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); instance.Get().SetPanId(aPanId); instance.Get().Clear(); instance.Get().Clear(); exit: return error; } uint32_t otLinkGetPollPeriod(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetKeepAlivePollPeriod(); } otError otLinkSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod) { return AsCoreType(aInstance).Get().SetExternalPollPeriod(aPollPeriod); } otError otLinkSendDataRequest(otInstance *aInstance) { return AsCoreType(aInstance).Get().SendDataPoll(); } otShortAddress otLinkGetShortAddress(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetShortAddress(); } uint8_t otLinkGetMaxFrameRetriesDirect(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetMaxFrameRetriesDirect(); } void otLinkSetMaxFrameRetriesDirect(otInstance *aInstance, uint8_t aMaxFrameRetriesDirect) { AsCoreType(aInstance).Get().SetMaxFrameRetriesDirect(aMaxFrameRetriesDirect); } #if OPENTHREAD_FTD uint8_t otLinkGetMaxFrameRetriesIndirect(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetMaxFrameRetriesIndirect(); } void otLinkSetMaxFrameRetriesIndirect(otInstance *aInstance, uint8_t aMaxFrameRetriesIndirect) { AsCoreType(aInstance).Get().SetMaxFrameRetriesIndirect(aMaxFrameRetriesIndirect); } #endif // OPENTHREAD_FTD #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE otMacFilterAddressMode otLinkFilterGetAddressMode(otInstance *aInstance) { return MapEnum(AsCoreType(aInstance).Get().GetMode()); } void otLinkFilterSetAddressMode(otInstance *aInstance, otMacFilterAddressMode aMode) { AsCoreType(aInstance).Get().SetMode(MapEnum(aMode)); } otError otLinkFilterAddAddress(otInstance *aInstance, const otExtAddress *aExtAddress) { return AsCoreType(aInstance).Get().AddAddress(AsCoreType(aExtAddress)); } void otLinkFilterRemoveAddress(otInstance *aInstance, const otExtAddress *aExtAddress) { AsCoreType(aInstance).Get().RemoveAddress(AsCoreType(aExtAddress)); } void otLinkFilterClearAddresses(otInstance *aInstance) { return AsCoreType(aInstance).Get().ClearAddresses(); } otError otLinkFilterGetNextAddress(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry) { AssertPointerIsNotNull(aIterator); AssertPointerIsNotNull(aEntry); return AsCoreType(aInstance).Get().GetNextAddress(*aIterator, *aEntry); } otError otLinkFilterAddRssIn(otInstance *aInstance, const otExtAddress *aExtAddress, int8_t aRss) { return AsCoreType(aInstance).Get().AddRssIn(AsCoreType(aExtAddress), aRss); } void otLinkFilterRemoveRssIn(otInstance *aInstance, const otExtAddress *aExtAddress) { AsCoreType(aInstance).Get().RemoveRssIn(AsCoreType(aExtAddress)); } void otLinkFilterSetDefaultRssIn(otInstance *aInstance, int8_t aRss) { AsCoreType(aInstance).Get().SetDefaultRssIn(aRss); } void otLinkFilterClearDefaultRssIn(otInstance *aInstance) { AsCoreType(aInstance).Get().ClearDefaultRssIn(); } void otLinkFilterClearAllRssIn(otInstance *aInstance) { AsCoreType(aInstance).Get().ClearAllRssIn(); } otError otLinkFilterGetNextRssIn(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry) { AssertPointerIsNotNull(aIterator); AssertPointerIsNotNull(aEntry); return AsCoreType(aInstance).Get().GetNextRssIn(*aIterator, *aEntry); } #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE void otLinkSetRadioFilterEnabled(otInstance *aInstance, bool aFilterEnabled) { return AsCoreType(aInstance).Get().SetRadioFilterEnabled(aFilterEnabled); } bool otLinkIsRadioFilterEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsRadioFilterEnabled(); } #endif #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE uint8_t otLinkConvertRssToLinkQuality(otInstance *aInstance, int8_t aRss) { return LinkQualityForLinkMargin(AsCoreType(aInstance).Get().ComputeLinkMargin(aRss)); } int8_t otLinkConvertLinkQualityToRss(otInstance *aInstance, uint8_t aLinkQuality) { return GetTypicalRssForLinkQuality(AsCoreType(aInstance).Get().GetNoiseFloor(), static_cast(aLinkQuality)); } #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE const uint32_t *otLinkGetTxDirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries) { AssertPointerIsNotNull(aNumberOfEntries); return AsCoreType(aInstance).Get().GetDirectRetrySuccessHistogram(*aNumberOfEntries); } const uint32_t *otLinkGetTxIndirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries) { const uint32_t *histogram = nullptr; AssertPointerIsNotNull(aNumberOfEntries); #if OPENTHREAD_FTD histogram = AsCoreType(aInstance).Get().GetIndirectRetrySuccessHistogram(*aNumberOfEntries); #else OT_UNUSED_VARIABLE(aInstance); *aNumberOfEntries = 0; #endif return histogram; } void otLinkResetTxRetrySuccessHistogram(otInstance *aInstance) { AsCoreType(aInstance).Get().ResetRetrySuccessHistogram(); } #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE void otLinkSetPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext) { AsCoreType(aInstance).Get().SetPcapCallback(aPcapCallback, aCallbackContext); } bool otLinkIsPromiscuous(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsPromiscuous(); } otError otLinkSetPromiscuous(otInstance *aInstance, bool aPromiscuous) { Error error = kErrorNone; Instance &instance = AsCoreType(aInstance); // cannot enable IEEE 802.15.4 promiscuous mode if the Thread interface is enabled VerifyOrExit(!instance.Get().IsUp(), error = kErrorInvalidState); instance.Get().SetPromiscuous(aPromiscuous); exit: return error; } otError otLinkSetEnabled(otInstance *aInstance, bool aEnable) { Error error = kErrorNone; Instance &instance = AsCoreType(aInstance); // cannot disable the link layer if the Thread interface is enabled VerifyOrExit(!instance.Get().IsUp(), error = kErrorInvalidState); instance.Get().SetEnabled(aEnable); exit: return error; } bool otLinkIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsEnabled(); } const otMacCounters *otLinkGetCounters(otInstance *aInstance) { return &AsCoreType(aInstance).Get().GetCounters(); } void otLinkResetCounters(otInstance *aInstance) { AsCoreType(aInstance).Get().ResetCounters(); } otError otLinkActiveScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration, otHandleActiveScanResult aCallback, void *aCallbackContext) { return AsCoreType(aInstance).Get().ActiveScan(aScanChannels, aScanDuration, aCallback, aCallbackContext); } bool otLinkIsActiveScanInProgress(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsActiveScanInProgress(); } otError otLinkEnergyScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration, otHandleEnergyScanResult aCallback, void *aCallbackContext) { return AsCoreType(aInstance).Get().EnergyScan(aScanChannels, aScanDuration, aCallback, aCallbackContext); } bool otLinkIsEnergyScanInProgress(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsEnergyScanInProgress(); } bool otLinkIsInTransmitState(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsInTransmitState(); } uint16_t otLinkGetCcaFailureRate(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCcaFailureRate(); } #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE bool otLinkIsCslEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslEnabled(); } bool otLinkIsCslSupported(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslSupported(); } uint8_t otLinkGetCslChannel(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslChannel(); } otError otLinkSetCslChannel(otInstance *aInstance, uint8_t aChannel) { Error error = kErrorNone; VerifyOrExit(Radio::IsCslChannelValid(aChannel), error = kErrorInvalidArgs); AsCoreType(aInstance).Get().SetCslChannel(aChannel); exit: return error; } uint32_t otLinkGetCslPeriod(otInstance *aInstance) { return Mac::Mac::CslPeriodToUsec(AsCoreType(aInstance).Get().GetCslPeriod()); } otError otLinkSetCslPeriod(otInstance *aInstance, uint32_t aPeriod) { Error error = kErrorNone; uint16_t periodInTenSymbolsUnit; if (aPeriod == 0) { periodInTenSymbolsUnit = 0; } else { VerifyOrExit((aPeriod % kUsPerTenSymbols) == 0, error = kErrorInvalidArgs); periodInTenSymbolsUnit = ClampToUint16(aPeriod / kUsPerTenSymbols); VerifyOrExit(periodInTenSymbolsUnit >= kMinCslPeriod, error = kErrorInvalidArgs); } AsCoreType(aInstance).Get().SetCslPeriod(periodInTenSymbolsUnit); exit: return error; } uint32_t otLinkGetCslTimeout(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslTimeout(); } otError otLinkSetCslTimeout(otInstance *aInstance, uint32_t aTimeout) { Error error = kErrorNone; VerifyOrExit(kMaxCslTimeout >= aTimeout, error = kErrorInvalidArgs); AsCoreType(aInstance).Get().SetCslTimeout(aTimeout); exit: return error; } #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE otError otLinkSendEmptyData(otInstance *aInstance) { return AsCoreType(aInstance).Get().SendEmptyMessage(); } #endif