Imported more library files

Not compiling currently
This commit is contained in:
2025-04-12 23:37:19 +01:00
parent 264a3462e0
commit 9d06f983af
2518 changed files with 1021900 additions and 52 deletions

View File

@@ -0,0 +1,95 @@
/*
* 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
* @brief
* This file defines the platform-specific functions needed by OpenThread's example applications.
*/
#ifndef OPENTHREAD_SYSTEM_H_
#define OPENTHREAD_SYSTEM_H_
#include <openthread/instance.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Performs all platform-specific initialization of OpenThread's drivers.
*
* @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
* when initialization of OpenThread's drivers is most appropriate.
*
* @param[in] argc Number of arguments in @p argv.
* @param[in] argv Argument vector.
*/
void otSysInit(int argc, char *argv[]);
/**
* Performs all platform-specific deinitialization for OpenThread's drivers.
*
* @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
* when deinitialization of OpenThread's drivers is most appropriate.
*/
void otSysDeinit(void);
/**
* Returns true if a pseudo-reset was requested.
*
* In such a case, the main loop should shut down and re-initialize the OpenThread instance.
*
* @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
* in the main loop to determine when to shut down and re-initialize the OpenThread instance.
*/
bool otSysPseudoResetWasRequested(void);
/**
* Performs all platform-specific processing for OpenThread's example applications.
*
* @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
* in the main loop when processing OpenThread's drivers is most appropriate.
*
* @param[in] aInstance The OpenThread instance structure.
*/
void otSysProcessDrivers(otInstance *aInstance);
/**
* Is called whenever platform drivers needs processing.
*
* @note This function is not handled by the OpenThread library. Instead, the system/RTOS should handle this function
* and schedule a call to `otSysProcessDrivers()`.
*/
extern void otSysEventSignalPending(void);
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // OPENTHREAD_SYSTEM_H_

View File

@@ -0,0 +1,81 @@
/*
* 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.
*/
/**
* @file
* This file includes macros for validating runtime conditions.
*/
#ifndef CODE_UTILS_H
#define CODE_UTILS_H
/**
* This checks for the specified condition, which is expected to
* commonly be true, and branches to the local label 'exit' if the
* condition is false.
*
* @param[in] aCondition A Boolean expression to be evaluated.
*/
#define otEXPECT(aCondition) \
do \
{ \
if (!(aCondition)) \
{ \
goto exit; \
} \
} while (0)
/**
* This checks for the specified condition, which is expected to
* commonly be true, and both executes @p anAction and branches to
* the local label 'exit' if the condition is false.
*
* @param[in] aCondition A Boolean expression to be evaluated.
* @param[in] aAction An expression or block to execute when the
* assertion fails.
*/
#define otEXPECT_ACTION(aCondition, aAction) \
do \
{ \
if (!(aCondition)) \
{ \
aAction; \
goto exit; \
} \
} while (0)
/**
* Calculates the number of elements in an array.
*
* @param[in] aArray Name of the array variable.
*
* @returns Number of elements in the array.
*/
#define otARRAY_LENGTH(aArray) (sizeof(aArray) / sizeof(aArray[0]))
#endif // CODE_UTILS_H

View File

@@ -0,0 +1,140 @@
/*
* 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 <stdarg.h>
#include <stdio.h>
#include <openthread/config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/debug_uart.h>
#include <openthread/platform/toolchain.h>
/*
* Implementation note:
* These are all "weak" so that a platform may if it chooses override the instance.
*/
OT_TOOL_WEAK
void otPlatDebugUart_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
otPlatDebugUart_vprintf(fmt, ap);
va_end(ap);
}
OT_TOOL_WEAK
void otPlatDebugUart_vprintf(const char *fmt, va_list ap)
{
char buf[128];
/* by standard ...
* vsnprintf() always null terminates
*/
vsnprintf(buf, sizeof(buf), fmt, ap);
/* however ... some platforms have bugs */
buf[sizeof(buf) - 1] = 0;
otPlatDebugUart_puts_no_nl(buf);
}
OT_TOOL_WEAK
void otPlatDebugUart_write_bytes(const uint8_t *pBytes, int nBytes)
{
while (nBytes > 0)
{
otPlatDebugUart_putchar((int)(*pBytes));
pBytes++;
nBytes--;
}
}
OT_TOOL_WEAK
void otPlatDebugUart_puts_no_nl(const char *s)
{
while (*s)
{
otPlatDebugUart_putchar(*s);
s++;
}
}
OT_TOOL_WEAK
void otPlatDebugUart_puts(const char *s)
{
otPlatDebugUart_puts_no_nl(s);
otPlatDebugUart_putchar('\n');
}
OT_TOOL_WEAK
void otPlatDebugUart_putchar(int c)
{
/* map lf to crlf as needed */
if (c == '\n')
{
otPlatDebugUart_putchar_raw('\r');
}
otPlatDebugUart_putchar_raw(c);
}
/* provide WEAK stubs for platforms that do not implement all functions */
OT_TOOL_WEAK
void otPlatDebugUart_putchar_raw(int c) { OT_UNUSED_VARIABLE(c); }
OT_TOOL_WEAK
int otPlatDebugUart_kbhit(void) { return 0; /* nothing */ }
OT_TOOL_WEAK
int otPlatDebugUart_getc(void) { return -1; /* nothing */ }
OT_TOOL_WEAK
otError otPlatDebugUart_logfile(const char *filename)
{
OT_UNUSED_VARIABLE(filename);
return OT_ERROR_FAILED;
}
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART)
/* this should not be a WEAK function */
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
OT_UNUSED_VARIABLE(aLogLevel);
OT_UNUSED_VARIABLE(aLogRegion);
va_list ap;
uint32_t now;
now = otPlatAlarmMilliGetNow();
otPlatDebugUart_printf("%3d.%03d | ", (int)(now / 1000), (int)(now % 1000));
va_start(ap, aFormat);
otPlatDebugUart_vprintf(aFormat, ap);
va_end(ap);
otPlatDebugUart_putchar('\n');
}
#endif

View File

@@ -0,0 +1,265 @@
/*
* Copyright (c) 2020, 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 "link_metrics.h"
#include <openthread/link_metrics.h>
#include "common/clearable.hpp"
#include "common/linked_list.hpp"
#include "common/pool.hpp"
#include "thread/link_quality.hpp"
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
using namespace ot;
static int8_t sNoiseFloor; ///< The noise floor used by Link Metrics. It should be set to the platform's
///< noise floor (measured noise floor, receiver sensitivity or a constant).
class LinkMetricsDataInfo : public LinkedListEntry<LinkMetricsDataInfo>, public Clearable<LinkMetricsDataInfo>
{
friend class LinkedList<LinkMetricsDataInfo>;
friend class LinkedListEntry<LinkMetricsDataInfo>;
public:
/**
* Constructor.
*/
LinkMetricsDataInfo(void) { Clear(); };
/**
* Set the information for this object.
*
* @param[in] aLinkMetrics Flags specifying what metrics to query.
* @param[in] aShortAddress Short Address of the Probing Initiator tracked by this object.
* @param[in] aExtAddress A reference to the Extended Address of the Probing Initiator tracked by this
* object.
*/
void Set(otLinkMetrics aLinkMetrics, otShortAddress aShortAddress, const otExtAddress &aExtAddress)
{
mLinkMetrics = aLinkMetrics;
mShortAddress = aShortAddress;
memcpy(mExtAddress.m8, aExtAddress.m8, sizeof(aExtAddress));
}
/**
* Gets Link Metrics data stored in this object.
*
* TODO: Currently the order of Link Metircs data is fixed. Will update it to follow the order specified in TLV.
*
* @param[in] aLqi LQI value of the acknowledeged frame.
* @param[in] aRssi RSSI value of the acknowledged frame.
* @param[out] aData A pointer to the output buffer. @p aData MUST NOT be `nullptr`. The buffer must have
* at least 2 bytes (per spec 4.11.3.4.4.6). Otherwise the behavior would be undefined.
*
* @returns The number of bytes written. `0` on failure.
*/
uint8_t GetEnhAckData(uint8_t aLqi, int8_t aRssi, uint8_t *aData) const
{
enum
{
kEnhAckProbingDataMaxLen = 2,
};
uint8_t bytes = 0;
VerifyOrExit(aData != nullptr);
if (mLinkMetrics.mLqi)
{
aData[bytes++] = aLqi;
}
if (mLinkMetrics.mLinkMargin)
{
aData[bytes++] = static_cast<uint8_t>(GetLinkMargin(aRssi) * 255 /
130); // Linear scale Link Margin from [0, 130] to [0, 255]
}
if (bytes < kEnhAckProbingDataMaxLen && mLinkMetrics.mRssi)
{
aData[bytes++] =
static_cast<uint8_t>((aRssi + 130) * 255 / 130); // Linear scale RSSI from [-130, 0] to [0, 255]
}
exit:
return bytes;
}
/**
* Gets the length of Link Metrics Data.
*
* @returns The number of bytes for the data.
*/
uint8_t GetEnhAckDataLen() const
{
return static_cast<uint8_t>(mLinkMetrics.mLqi) + static_cast<uint8_t>(mLinkMetrics.mLinkMargin) +
static_cast<uint8_t>(mLinkMetrics.mRssi);
}
/**
* Gets the metrics configured for the Enhanced-ACK Based Probing.
*
* @returns The metrics configured.
*/
otLinkMetrics GetLinkMetrics(void) const { return mLinkMetrics; }
private:
uint8_t GetLinkMargin(int8_t aRssi) const { return ComputeLinkMargin(sNoiseFloor, aRssi); }
bool Matches(const otShortAddress &aShortAddress) const { return mShortAddress == aShortAddress; };
bool Matches(const otExtAddress &aExtAddress) const
{
return memcmp(&mExtAddress, &aExtAddress, sizeof(otExtAddress)) == 0;
};
LinkMetricsDataInfo *mNext;
otLinkMetrics mLinkMetrics;
otShortAddress mShortAddress;
otExtAddress mExtAddress;
};
enum
{
kMaxEnhAckProbingInitiator = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED,
};
typedef Pool<LinkMetricsDataInfo, kMaxEnhAckProbingInitiator> LinkMetricsDataInfoPool;
typedef LinkedList<LinkMetricsDataInfo> LinkMetricsDataInfoList;
static LinkMetricsDataInfoPool &GetLinkMetricsDataInfoPool(void)
{
static LinkMetricsDataInfoPool sDataInfoPool;
return sDataInfoPool;
}
static LinkMetricsDataInfoList &GetLinkMetricsDataInfoActiveList(void)
{
static LinkMetricsDataInfoList sDataInfoActiveList;
return sDataInfoActiveList;
}
static inline bool IsLinkMetricsClear(otLinkMetrics aLinkMetrics)
{
return !aLinkMetrics.mPduCount && !aLinkMetrics.mLqi && !aLinkMetrics.mLinkMargin && !aLinkMetrics.mRssi;
}
void otLinkMetricsInit(int8_t aNoiseFloor)
{
sNoiseFloor = aNoiseFloor;
otLinkMetricsResetEnhAckProbing();
}
otError otLinkMetricsConfigureEnhAckProbing(otShortAddress aShortAddress,
const otExtAddress *aExtAddress,
otLinkMetrics aLinkMetrics)
{
otError error = OT_ERROR_NONE;
LinkMetricsDataInfo *dataInfo = nullptr;
VerifyOrExit(aExtAddress != nullptr, error = OT_ERROR_INVALID_ARGS);
if (IsLinkMetricsClear(aLinkMetrics)) ///< Remove the entry
{
dataInfo = GetLinkMetricsDataInfoActiveList().RemoveMatching(aShortAddress);
VerifyOrExit(dataInfo != nullptr, error = OT_ERROR_NOT_FOUND);
GetLinkMetricsDataInfoPool().Free(*dataInfo);
}
else
{
dataInfo = GetLinkMetricsDataInfoActiveList().FindMatching(aShortAddress);
if (dataInfo == nullptr)
{
dataInfo = GetLinkMetricsDataInfoPool().Allocate();
VerifyOrExit(dataInfo != nullptr, error = OT_ERROR_NO_BUFS);
dataInfo->Clear();
GetLinkMetricsDataInfoActiveList().Push(*dataInfo);
}
// Overwrite the previous configuration if it already existed.
dataInfo->Set(aLinkMetrics, aShortAddress, *aExtAddress);
}
exit:
return error;
}
LinkMetricsDataInfo *GetLinkMetricsInfoByMacAddress(const otMacAddress *aMacAddress)
{
LinkMetricsDataInfo *dataInfo = nullptr;
VerifyOrExit(aMacAddress != nullptr);
if (aMacAddress->mType == OT_MAC_ADDRESS_TYPE_SHORT)
{
dataInfo = GetLinkMetricsDataInfoActiveList().FindMatching(aMacAddress->mAddress.mShortAddress);
}
else if (aMacAddress->mType == OT_MAC_ADDRESS_TYPE_EXTENDED)
{
dataInfo = GetLinkMetricsDataInfoActiveList().FindMatching(aMacAddress->mAddress.mExtAddress);
}
exit:
return dataInfo;
}
uint8_t otLinkMetricsEnhAckGenData(const otMacAddress *aMacAddress, uint8_t aLqi, int8_t aRssi, uint8_t *aData)
{
uint8_t bytes = 0;
LinkMetricsDataInfo *dataInfo = GetLinkMetricsInfoByMacAddress(aMacAddress);
VerifyOrExit(dataInfo != nullptr);
bytes = dataInfo->GetEnhAckData(aLqi, aRssi, aData);
exit:
return bytes;
}
uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress)
{
uint8_t len = 0;
LinkMetricsDataInfo *dataInfo = GetLinkMetricsInfoByMacAddress(aMacAddress);
VerifyOrExit(dataInfo != nullptr);
len = dataInfo->GetEnhAckDataLen();
exit:
return len;
}
void otLinkMetricsResetEnhAckProbing(void)
{
GetLinkMetricsDataInfoActiveList().Clear();
GetLinkMetricsDataInfoPool().FreeAll();
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2020, 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
* @brief
* This file defines the link metrics interface for OpenThread platform radio drivers.
*
* APIs defined in this module could be used by a platform to implement Enhanced-ACK Based Probing feature
* (Probing Subject side) in its radio driver.
*/
#ifndef OPENTHREAD_UTILS_LINK_METRICS_H
#define OPENTHREAD_UTILS_LINK_METRICS_H
#include <openthread/link_metrics.h>
#include "mac_frame.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initializes the Link Metrics util module.
*
* @param[in] aNoiseFloor The noise floor used by Link Metrics. It should be set to the platform's
* noise floor (measured noise floor, receiver sensitivity or a constant).
*/
void otLinkMetricsInit(int8_t aNoiseFloor);
/**
* Sets/clears Enhanced-ACK Based Probing for a specific Initiator.
*
* Can start/stop Enhanced-ACK Based Probing for a neighbor that has the address @p aShortAddress and
* @p aExtAddress. Once the Probing is started, the device would record the Link Metrics data of link layer frames
* sent from that neighbor and include the data into header IE in Enhanced-ACK sent to that neighbor.
*
* @param[in] aShortAddress The short address of the Initiator.
* @param[in] aExtAddress A pointer to the extended address of the Initiator.
* @param[in] aLinkMetrics Flags specifying what metrics to query (Pdu Count would be omitted). When
* @p aLinkMetrics is equal to `0`, this method clears the Initiator.
*
* @retval OT_ERROR_NONE Successfully configured the Enhanced-ACK Based Probing.
* @retval OT_ERROR_INVALID_ARGS @p aExtAddress is `nullptr`.
* @retval OT_ERROR_NOT_FOUND The Initiator indicated by @p aShortAddress is not found when trying to clear.
* @retval OT_ERROR_NO_BUFS No more Initiator can be supported.
*/
otError otLinkMetricsConfigureEnhAckProbing(otShortAddress aShortAddress,
const otExtAddress *aExtAddress,
otLinkMetrics aLinkMetrics);
/**
* Generates the Link Metrics data (assessed for the acknowledged frame) bytes that would be included in
* Vendor-Specific IE.
*
* First checks what Link Metrics are specified by the Initiator indicated by @p aMacAddress. And then
* write the values to @p aData.
*
* @param[in] aMacAddress The Mac address of the Initiator.
* @param[in] aLqi LQI value of the acknowledged frame.
* @param[in] aRssi RSSI value of the acknowledged frame.
* @param[out] aData A pointer to the buffer where the data would be written to. The caller should make
* sure that the size of the buffer is not less than the size of Link Metrics data
* configured before.
*
* @returns The size of data read. Would be `0` if the Initiator is not found or @p aData is invalid.
*/
uint8_t otLinkMetricsEnhAckGenData(const otMacAddress *aMacAddress, uint8_t aLqi, int8_t aRssi, uint8_t *aData);
/**
* Returns the data length of Enhanced-ACK Based Probing for a specific Initiator.
*
* @param[in] aMacAddress The Mac address of the Initiator.
*
* @returns The size of data. `0` if it's not configured for the Initiator.
*/
uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress);
/**
* This method resets Enhanced-ACK Based Probing data.
*/
void otLinkMetricsResetEnhAckProbing(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_UTILS_LINK_METRICS_H

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2018, 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
* @brief
* This file defines the logging rtt interfaces and default constants used by logging_rtt.c.
*/
#ifndef UTILS_LOGGING_RTT_H
#define UTILS_LOGGING_RTT_H
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include "openthread-core-config.h"
#include <openthread/config.h>
#include <openthread/platform/logging.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @def LOG_RTT_BUFFER_INDEX
*
* RTT's buffer index.
*/
#ifndef LOG_RTT_BUFFER_INDEX
#define LOG_RTT_BUFFER_INDEX 0
#endif
/**
* @def LOG_RTT_BUFFER_NAME
*
* RTT's name. Only used if LOG_RTT_BUFFER_INDEX is not 0. Otherwise,
* the buffer name is fixed to "Terminal".
*/
#ifndef LOG_RTT_BUFFER_NAME
#define LOG_RTT_BUFFER_NAME "Terminal"
#endif
/**
* @def LOG_RTT_BUFFER_SIZE
*
* LOG RTT's buffer size. Only used if LOG_RTT_BUFFER_INDEX is not 0. To
* configure buffer #0 size, check the BUFFER_SIZE_UP definition in
* SEGGER_RTT_Conf.h
*/
#ifndef LOG_RTT_BUFFER_SIZE
#define LOG_RTT_BUFFER_SIZE 256
#endif
/**
* @def LOG_RTT_COLOR_ENABLE
*
* Enable colors on RTT Viewer.
*/
#ifndef LOG_RTT_COLOR_ENABLE
#define LOG_RTT_COLOR_ENABLE 1
#endif
/**
* @def LOG_PARSE_BUFFER_SIZE
*
* LOG buffer used to parse print format. It will be locally allocated on the
* stack.
*/
#ifndef LOG_PARSE_BUFFER_SIZE
#define LOG_PARSE_BUFFER_SIZE \
(19 /* Timestamp */ + 8 /* RTT color code */ + OPENTHREAD_CONFIG_LOG_MAX_SIZE + 1 /* \n */)
#endif
/**
* @def LOG_TIMESTAMP_ENABLE
*
* Enable timestamp in the logs.
*/
#ifndef LOG_TIMESTAMP_ENABLE
#define LOG_TIMESTAMP_ENABLE 1
#endif
/**
* Initialization of Logger driver.
*/
void utilsLogRttInit(void);
/**
* Deinitialization of Logger driver.
*/
void utilsLogRttDeinit(void);
/**
* Outputs logs to SEGGER RTT.
*
* @param[in] aLogLevel The log level.
* @param[in] aLogRegion The log region.
* @param[in] aFormat A pointer to the format string.
* @param[in] ap va_list matching information for aFormat
*/
void utilsLogRttOutput(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, va_list ap);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // UTILS_LOGGING_RTT_H

View File

@@ -0,0 +1,397 @@
/*
* Copyright (c) 2019, 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 "mac_frame.h"
#include <assert.h>
#include <openthread/platform/radio.h>
#include "common/code_utils.hpp"
#include "mac/mac_frame.hpp"
using namespace ot;
bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
otPanId aPanId,
otShortAddress aShortAddress,
const otExtAddress *aExtAddress)
{
return otMacFrameDoesAddrMatchAny(aFrame, aPanId, aShortAddress, Mac::kShortAddrInvalid, aExtAddress);
}
bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
otPanId aPanId,
otShortAddress aShortAddress,
otShortAddress aAltShortAddress,
const otExtAddress *aExtAddress)
{
const Mac::Frame &frame = *static_cast<const Mac::Frame *>(aFrame);
bool rval = true;
Mac::Address dst;
Mac::PanId panid;
VerifyOrExit(frame.GetDstAddr(dst) == kErrorNone, rval = false);
switch (dst.GetType())
{
case Mac::Address::kTypeShort:
VerifyOrExit(dst.GetShort() == Mac::kShortAddrBroadcast || dst.GetShort() == aShortAddress ||
(aAltShortAddress != Mac::kShortAddrInvalid && dst.GetShort() == aAltShortAddress),
rval = false);
break;
case Mac::Address::kTypeExtended:
VerifyOrExit(dst.GetExtended() == *static_cast<const Mac::ExtAddress *>(aExtAddress), rval = false);
break;
case Mac::Address::kTypeNone:
break;
}
SuccessOrExit(frame.GetDstPanId(panid));
VerifyOrExit(panid == Mac::kPanIdBroadcast || panid == aPanId, rval = false);
exit:
return rval;
}
bool otMacFrameIsAck(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeAck;
}
bool otMacFrameIsData(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeData;
}
bool otMacFrameIsCommand(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeMacCmd;
}
bool otMacFrameIsDataRequest(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->IsDataRequestCommand();
}
bool otMacFrameIsAckRequested(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetAckRequest();
}
static void GetOtMacAddress(const Mac::Address &aInAddress, otMacAddress *aOutAddress)
{
switch (aInAddress.GetType())
{
case Mac::Address::kTypeNone:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
break;
case Mac::Address::kTypeShort:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_SHORT;
aOutAddress->mAddress.mShortAddress = aInAddress.GetShort();
break;
case Mac::Address::kTypeExtended:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_EXTENDED;
aOutAddress->mAddress.mExtAddress = aInAddress.GetExtended();
break;
}
}
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
{
otError error;
Mac::Address address;
error = static_cast<const Mac::Frame *>(aFrame)->GetSrcAddr(address);
SuccessOrExit(error);
GetOtMacAddress(address, aMacAddress);
exit:
return error;
}
otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
{
otError error;
Mac::Address address;
error = static_cast<const Mac::Frame *>(aFrame)->GetDstAddr(address);
SuccessOrExit(error);
GetOtMacAddress(address, aMacAddress);
exit:
return error;
}
otError otMacFrameGetSequence(const otRadioFrame *aFrame, uint8_t *aSequence)
{
otError error;
if (static_cast<const Mac::Frame *>(aFrame)->IsSequencePresent())
{
*aSequence = static_cast<const Mac::Frame *>(aFrame)->GetSequence();
error = kErrorNone;
}
else
{
error = kErrorParse;
}
return error;
}
void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress)
{
static_cast<Mac::TxFrame *>(aFrame)->ProcessTransmitAesCcm(*static_cast<const Mac::ExtAddress *>(aExtAddress));
}
bool otMacFrameIsVersion2015(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->IsVersion2015();
}
void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame)
{
assert(aFrame != nullptr && aAckFrame != nullptr);
static_cast<Mac::TxFrame *>(aAckFrame)->GenerateImmAck(*static_cast<const Mac::RxFrame *>(aFrame), aIsFramePending);
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
bool aIsFramePending,
const uint8_t *aIeData,
uint8_t aIeLength,
otRadioFrame *aAckFrame)
{
assert(aFrame != nullptr && aAckFrame != nullptr);
return static_cast<Mac::TxFrame *>(aAckFrame)->GenerateEnhAck(*static_cast<const Mac::RxFrame *>(aFrame),
aIsFramePending, aIeData, aIeLength);
}
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase)
{
static_cast<Mac::Frame *>(aFrame)->SetCslIe(aCslPeriod, aCslPhase);
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetSecurityEnabled();
}
bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame)
{
uint8_t keyIdMode;
otError error;
error = static_cast<const Mac::Frame *>(aFrame)->GetKeyIdMode(keyIdMode);
return (error == OT_ERROR_NONE) ? (keyIdMode == Mac::Frame::kKeyIdMode1) : false;
}
uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame)
{
uint8_t keyId = 0;
IgnoreError(static_cast<const Mac::Frame *>(aFrame)->GetKeyId(keyId));
return keyId;
}
void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId) { static_cast<Mac::Frame *>(aFrame)->SetKeyId(aKeyId); }
uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame)
{
uint32_t frameCounter = UINT32_MAX;
IgnoreError(static_cast<Mac::Frame *>(aFrame)->GetFrameCounter(frameCounter));
return frameCounter;
}
void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter)
{
static_cast<Mac::Frame *>(aFrame)->SetFrameCounter(aFrameCounter);
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest)
{
assert(aDest != nullptr);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::CslIe::kHeaderIeId);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(sizeof(Mac::CslIe));
return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData, uint8_t aIeDataLength)
{
uint8_t len = sizeof(Mac::VendorIeHeader) + aIeDataLength;
assert(aDest != nullptr);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::ThreadIe::kHeaderIeId);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(len);
aDest += sizeof(Mac::HeaderIe);
reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetVendorOui(Mac::ThreadIe::kVendorOuiThreadCompanyId);
reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetSubType(Mac::ThreadIe::kEnhAckProbingIe);
if (aIeData != nullptr)
{
aDest += sizeof(Mac::VendorIeHeader);
memcpy(aDest, aIeData, aIeDataLength);
}
return sizeof(Mac::HeaderIe) + len;
}
void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen)
{
assert(aFrame != nullptr && aData != nullptr);
reinterpret_cast<Mac::Frame *>(aFrame)->SetEnhAckProbingIe(aData, aDataLen);
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static uint16_t ComputeCslPhase(uint32_t aRadioTime, otRadioContext *aRadioContext)
{
return (aRadioContext->mCslSampleTime - aRadioTime) % (aRadioContext->mCslPeriod * OT_US_PER_TEN_SYMBOLS) /
OT_US_PER_TEN_SYMBOLS;
}
#endif
otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext)
{
otError error = OT_ERROR_NONE;
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
otMacKeyMaterial *key = nullptr;
uint8_t keyId;
uint32_t frameCounter;
VerifyOrExit(otMacFrameIsSecurityEnabled(aFrame) && otMacFrameIsKeyIdMode1(aFrame) &&
!aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
if (otMacFrameIsAck(aFrame))
{
keyId = otMacFrameGetKeyId(aFrame);
VerifyOrExit(keyId != 0, error = OT_ERROR_FAILED);
if (keyId == aRadioContext->mKeyId)
{
key = &aRadioContext->mCurrKey;
frameCounter = aRadioContext->mMacFrameCounter++;
}
else if (keyId == aRadioContext->mKeyId - 1)
{
key = &aRadioContext->mPrevKey;
frameCounter = aRadioContext->mPrevMacFrameCounter++;
}
else if (keyId == aRadioContext->mKeyId + 1)
{
key = &aRadioContext->mNextKey;
frameCounter = 0;
}
else
{
ExitNow(error = OT_ERROR_SECURITY);
}
}
else if (!aFrame->mInfo.mTxInfo.mIsHeaderUpdated)
{
key = &aRadioContext->mCurrKey;
keyId = aRadioContext->mKeyId;
frameCounter = aRadioContext->mMacFrameCounter++;
}
if (key != nullptr)
{
aFrame->mInfo.mTxInfo.mAesKey = key;
otMacFrameSetKeyId(aFrame, keyId);
otMacFrameSetFrameCounter(aFrame, frameCounter);
aFrame->mInfo.mTxInfo.mIsHeaderUpdated = true;
}
#else
VerifyOrExit(!aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
otMacFrameProcessTransmitAesCcm(aFrame, &aRadioContext->mExtAddress);
exit:
return error;
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
void otMacFrameUpdateTimeIe(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
{
if (aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
{
uint8_t *timeIe = aFrame->mPsdu + aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
uint64_t time = aRadioTime + aFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
*timeIe = aFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
*(++timeIe) = static_cast<uint8_t>(time & 0xff);
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
{
time = time >> 8;
*(++timeIe) = static_cast<uint8_t>(time & 0xff);
}
}
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
{
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (aRadioContext->mCslPeriod > 0) // CSL IE should be filled for every transmit attempt
{
otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext));
}
#endif
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otMacFrameUpdateTimeIe(aFrame, aRadioTime, aRadioContext);
#endif
aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime;
return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext);
}

View File

@@ -0,0 +1,383 @@
/*
* Copyright (c) 2019, 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
* @brief
* This file defines the mac frame interface for OpenThread platform radio drivers.
*/
#ifndef OPENTHREAD_UTILS_MAC_FRAME_H
#define OPENTHREAD_UTILS_MAC_FRAME_H
#include <openthread/platform/radio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Specifies the IEEE 802.15.4 Address type.
*/
typedef enum
{
OT_MAC_ADDRESS_TYPE_NONE, ///< No address.
OT_MAC_ADDRESS_TYPE_SHORT, ///< IEEE 802.15.4 Short Address.
OT_MAC_ADDRESS_TYPE_EXTENDED, ///< IEEE 802.15.4 Extended Address.
} otMacAddressType;
/**
* Represents an IEEE 802.15.4 short or extended Address.
*/
typedef struct otMacAddress
{
union
{
otShortAddress mShortAddress; ///< The IEEE 802.15.4 Short Address.
otExtAddress mExtAddress; ///< The IEEE 802.15.4 Extended Address.
} mAddress;
otMacAddressType mType; ///< The address type (short, extended, or none).
} otMacAddress;
/**
* Check if @p aFrame is an Ack frame.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It is an ACK frame.
* @retval false It is not an ACK frame.
*/
bool otMacFrameIsAck(const otRadioFrame *aFrame);
/**
* Check if @p aFrame is a Data frame.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It is a Data frame.
* @retval false It is not a Data frame.
*/
bool otMacFrameIsData(const otRadioFrame *aFrame);
/**
* Check if @p aFrame is a Command frame.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It is a Command frame.
* @retval false It is not a Command frame.
*/
bool otMacFrameIsCommand(const otRadioFrame *aFrame);
/**
* Check if @p aFrame is a Data Request Command.
*
* @param[in] aFrame A pointer to the frame. For 802.15.4-2015 and above frame,
* the frame should be already decrypted.
*
* @retval true It is a Data Request Command frame.
* @retval false It is not a Data Request Command frame.
*/
bool otMacFrameIsDataRequest(const otRadioFrame *aFrame);
/**
* Check if @p aFrame requests ACK.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It requests ACK.
* @retval false It does not request ACK.
*/
bool otMacFrameIsAckRequested(const otRadioFrame *aFrame);
/**
* Check if @p aFrame matches the @p aPandId and @p aShortAddress or @p aExtAddress.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aPanId The PAN id to match with.
* @param[in] aShortAddress The short address to match with.
* @param[in] aExtAddress The extended address to match with.
*
* @retval true It is a broadcast or matches with the PAN id and one of the addresses.
* @retval false It doesn't match.
*/
bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
otPanId aPanId,
otShortAddress aShortAddress,
const otExtAddress *aExtAddress);
/**
* Check if @p aFrame matches the @p aPandId and @p aShortAddress, or @p aAltShortAddress or @p aExtAddress.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aPanId The PAN id to match with.
* @param[in] aShortAddress The short address to match with.
* @param[in] aAltShortAddress The alternate short address to match with. Can be `OT_RADIO_INVALID_SHORT_ADDR` if
* there is no alternate address.
* @param[in] aExtAddress The extended address to match with.
*
* @retval true It is a broadcast or matches with the PAN id and one of the addresses.
* @retval false It doesn't match.
*/
bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
otPanId aPanId,
otShortAddress aShortAddress,
otShortAddress aAltShortAddress,
const otExtAddress *aExtAddress);
/**
* Get source MAC address.
*
* @param[in] aFrame A pointer to the frame.
* @param[out] aMacAddress A pointer to MAC address.
*
* @retval OT_ERROR_NONE Successfully got the source MAC address.
* @retval OT_ERROR_PARSE Failed to parse the source MAC address.
*/
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
/**
* Get destination MAC address.
*
* @param[in] aFrame A pointer to the frame.
* @param[out] aMacAddress A pointer to MAC address.
*
* @retval OT_ERROR_NONE Successfully got the destination MAC address.
* @retval OT_ERROR_PARSE Failed to parse the destination MAC address.
*/
otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
/**
* Get the sequence of @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
* @param[out] aSequence A pointer to the sequence.
*
* @retval OT_ERROR_NONE Successfully got the sequence.
* @retval OT_ERROR_PARSE Failed to parse the sequence.
*/
otError otMacFrameGetSequence(const otRadioFrame *aFrame, uint8_t *aSequence);
/**
* Performs AES CCM on the frame which is going to be sent.
*
* @param[in] aFrame A pointer to the MAC frame buffer that is going to be sent.
* @param[in] aExtAddress A pointer to the extended address, which will be used to generate nonce
* for AES CCM computation.
*/
void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress);
/**
* Tell if the version of @p aFrame is 2015.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It is a version 2015 frame.
* @retval false It is not a version 2015 frame.
*/
bool otMacFrameIsVersion2015(const otRadioFrame *aFrame);
/**
* Generate Imm-Ack for @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
* @param[out] aAckFrame A pointer to the ack frame to be generated.
*/
void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame);
/**
* Generate Enh-Ack for @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
* @param[in] aIeData A pointer to the IE data portion of the ACK to be sent.
* @param[in] aIeLength The length of IE data portion of the ACK to be sent.
* @param[out] aAckFrame A pointer to the ack frame to be generated.
*
* @retval OT_ERROR_NONE Successfully generated Enh Ack in @p aAckFrame.
* @retval OT_ERROR_PARSE @p aFrame has incorrect format.
*/
otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
bool aIsFramePending,
const uint8_t *aIeData,
uint8_t aIeLength,
otRadioFrame *aAckFrame);
/**
* Set CSL IE content into the frame.
*
* @param[in,out] aFrame A pointer to the frame to be modified.
* @param[in] aCslPeriod CSL Period in CSL IE.
* @param[in] aCslPhase CSL Phase in CSL IE.
*/
void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase);
/**
* Tell if the security of @p aFrame is enabled.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true The frame has security enabled.
* @retval false The frame does not have security enabled.
*/
bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame);
/**
* Tell if the key ID mode of @p aFrame is 1.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true The frame key ID mode is 1.
* @retval false The frame security is not enabled or key ID mode is not 1.
*/
bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame);
/**
* Get the key ID of @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
*
* @returns The key ID of the frame with key ID mode 1. Returns 0 if failed.
*/
uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame);
/**
* Set key ID to @p aFrame with key ID mode 1.
*
* @param[in,out] aFrame A pointer to the frame to be modified.
* @param[in] aKeyId Key ID to be set to the frame.
*/
void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId);
/**
* Get the frame counter of @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
*
* @returns The frame counter of the frame. Returns UINT32_MAX if failed.
*/
uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame);
/**
* Set frame counter to @p aFrame.
*
* @param[in,out] aFrame A pointer to the frame to be modified.
* @param[in] aFrameCounter Frame counter to be set to the frame.
*/
void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter);
/**
* Write CSL IE to a buffer (without setting IE value).
*
* @param[out] aDest A pointer to the output buffer.
*
* @returns The total count of bytes (total length of CSL IE) written to the buffer.
*/
uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest);
/**
* Write Enh-ACK Probing IE (Vendor IE with THREAD OUI) to a buffer.
*
* @p aIeData could be `NULL`. If @p aIeData is `NULL`, this method generates the IE with the data unset. This allows
* users to generate the pattern first and update value later. (For example, using `otMacFrameSetEnhAckProbingIe`)
*
* @param[out] aDest A pointer to the output buffer.
* @param[in] aIeData A pointer to the Link Metrics data.
* @param[in] aIeDataLength The length of Link Metrics data value. Should be `1` or `2`. (Per spec 4.11.3.4.4.6)
*
* @returns The total count of bytes (total length of the Vendor IE) written to the buffer.
*/
uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData, uint8_t aIeDataLength);
/**
* Sets the data value of Enh-ACK Probing IE (Vendor IE with THREAD OUI) in a frame.
*
* If no Enh-ACK Probing IE is found in @p aFrame, nothing would be done.
*
* @param[in] aFrame The target frame that contains the IE. MUST NOT be `NULL`.
* @param[in] aData A pointer to the data value. MUST NOT be `NULL`.
* @param[in] aDataLen The length of @p aData.
*/
void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen);
/**
* Represents the context for radio layer.
*/
typedef struct otRadioContext
{
otExtAddress mExtAddress; ///< In little-endian byte order.
uint32_t mMacFrameCounter;
uint32_t mPrevMacFrameCounter;
uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer.
uint16_t mCslPeriod; ///< In unit of 10 symbols.
otShortAddress mShortAddress;
otShortAddress mAlternateShortAddress;
otRadioKeyType mKeyType;
uint8_t mKeyId;
otMacKeyMaterial mPrevKey;
otMacKeyMaterial mCurrKey;
otMacKeyMaterial mNextKey;
} otRadioContext;
/**
* Perform processing of SFD callback from ISR.
*
* This function may do multiple tasks as follows.
*
* - CSL IE will be populated (if present)
* - Time IE will be populated (if present)
* - Tx timestamp will be populated
* - Tx security will be performed (including assignment of security frame counter and key id if not assigned)
*
* @param[in,out] aFrame The target frame. MUST NOT be `NULL`.
* @param[in] aRadioTime The radio time when the SFD was at the antenna.
* @param[in,out] aRadioContext The radio context accessible in ISR.
*
* @returns the error processing the callback. The caller should abort transmission on failures.
*/
otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext);
/**
* Process frame tx security.
*
* @param[in,out] aFrame The target frame. MUST NOT be `NULL`.
* @param[in,out] aRadioContext The radio context accessible in ISR.
*
* @retval OT_ERROR_NONE Successfully processed security.
* @retval OT_ERROR_FAILED Failed to processed security.
* @retval OT_ERROR_SECURITY Failed to processed security for missing key.
*/
otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_UTILS_MAC_FRAME_H

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2020, 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 defines the configuration options for platform abstraction of non-volatile storage of settings.
*/
#ifndef UTILS_SETTINGS_H_
#define UTILS_SETTINGS_H_
#include <openthread-core-config.h>
/**
* @def OPENTHREAD_SETTINGS_RAM
*
* Define as 1 to enable saving the settings in RAM instead of flash.
*/
#ifndef OPENTHREAD_SETTINGS_RAM
#define OPENTHREAD_SETTINGS_RAM 0
#endif
#endif // UTILS_SETTINGS_H_

View File

@@ -0,0 +1,230 @@
/*
* Copyright (c) 2019, 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 OpenThread platform abstraction for storage of settings in RAM.
*/
#include "settings.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <openthread/instance.h>
#include <openthread/platform/settings.h>
#define SETTINGS_BUFFER_SIZE 1024
#if OPENTHREAD_SETTINGS_RAM
static uint8_t sSettingsBuf[SETTINGS_BUFFER_SIZE];
static uint16_t sSettingsBufLength;
OT_TOOL_PACKED_BEGIN
struct settingsBlock
{
uint16_t key;
uint16_t length;
} OT_TOOL_PACKED_END;
// settings API
void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aSensitiveKeys);
OT_UNUSED_VARIABLE(aSensitiveKeysLength);
sSettingsBufLength = 0;
}
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);
uint16_t i = 0;
uint16_t valueLength = 0;
uint16_t readLength;
int currentIndex = 0;
const struct settingsBlock *currentBlock;
otError error = OT_ERROR_NOT_FOUND;
while (i < sSettingsBufLength)
{
currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
if (aKey == currentBlock->key)
{
if (currentIndex == aIndex)
{
readLength = currentBlock->length;
// Perform read only if an input buffer was passed in
if (aValue != NULL && aValueLength != NULL)
{
// Adjust read length if input buffer size is smaller
if (readLength > *aValueLength)
{
readLength = *aValueLength;
}
memcpy(aValue, &sSettingsBuf[i + sizeof(struct settingsBlock)], readLength);
}
valueLength = currentBlock->length;
error = OT_ERROR_NONE;
break;
}
currentIndex++;
}
i += sizeof(struct settingsBlock) + currentBlock->length;
}
if (aValueLength != NULL)
{
*aValueLength = valueLength;
}
return error;
}
otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
uint16_t i = 0;
uint16_t currentBlockLength;
uint16_t nextBlockStart;
const struct settingsBlock *currentBlock;
// Delete all entries of aKey
while (i < sSettingsBufLength)
{
currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
if (aKey == currentBlock->key)
{
nextBlockStart = i + currentBlockLength;
if (nextBlockStart < sSettingsBufLength)
{
memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
}
assert(sSettingsBufLength >= currentBlockLength);
sSettingsBufLength -= currentBlockLength;
}
else
{
i += currentBlockLength;
}
}
return otPlatSettingsAdd(aInstance, aKey, aValue, aValueLength);
}
otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
OT_UNUSED_VARIABLE(aInstance);
otError error;
struct settingsBlock *currentBlock;
const uint16_t newBlockLength = sizeof(struct settingsBlock) + aValueLength;
if (sSettingsBufLength + newBlockLength <= sizeof(sSettingsBuf))
{
currentBlock = (struct settingsBlock *)&sSettingsBuf[sSettingsBufLength];
currentBlock->key = aKey;
currentBlock->length = aValueLength;
memcpy(&sSettingsBuf[sSettingsBufLength + sizeof(struct settingsBlock)], aValue, aValueLength);
sSettingsBufLength += newBlockLength;
error = OT_ERROR_NONE;
}
else
{
error = OT_ERROR_NO_BUFS;
}
return error;
}
otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
{
OT_UNUSED_VARIABLE(aInstance);
uint16_t i = 0;
int currentIndex = 0;
uint16_t nextBlockStart;
uint16_t currentBlockLength;
const struct settingsBlock *currentBlock;
otError error = OT_ERROR_NOT_FOUND;
while (i < sSettingsBufLength)
{
currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
if (aKey == currentBlock->key)
{
if (currentIndex == aIndex)
{
nextBlockStart = i + currentBlockLength;
if (nextBlockStart < sSettingsBufLength)
{
memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
}
assert(sSettingsBufLength >= currentBlockLength);
sSettingsBufLength -= currentBlockLength;
error = OT_ERROR_NONE;
break;
}
else
{
currentIndex++;
}
}
i += currentBlockLength;
}
return error;
}
void otPlatSettingsWipe(otInstance *aInstance) { otPlatSettingsInit(aInstance, NULL, 0); }
#endif // OPENTHREAD_SETTINGS_RAM

View File

@@ -0,0 +1,116 @@
/*
* 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
* @brief
* This file includes the platform abstraction for UART communication.
*/
#ifndef OPENTHREAD_PLATFORM_UART_H_
#define OPENTHREAD_PLATFORM_UART_H_
#include <stdint.h>
#include <openthread/error.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup plat-uart
*
* @brief
* This module includes the platform abstraction for UART communication.
*
* @{
*/
/**
* Enable the UART.
*
* @retval OT_ERROR_NONE Successfully enabled the UART.
* @retval OT_ERROR_FAILED Failed to enabled the UART.
*/
otError otPlatUartEnable(void);
/**
* Disable the UART.
*
* @retval OT_ERROR_NONE Successfully disabled the UART.
* @retval OT_ERROR_FAILED Failed to disable the UART.
*/
otError otPlatUartDisable(void);
/**
* Send bytes over the UART.
*
* @param[in] aBuf A pointer to the data buffer.
* @param[in] aBufLength Number of bytes to transmit.
*
* @retval OT_ERROR_NONE Successfully started transmission.
* @retval OT_ERROR_FAILED Failed to start the transmission.
*/
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength);
/**
* Flush the outgoing transmit buffer and wait for the data to be sent.
* This is called when the CLI UART interface has a full buffer but still
* wishes to send more data.
*
* @retval OT_ERROR_NONE Flush succeeded, we can proceed to write more
* data to the buffer.
*
* @retval OT_ERROR_NOT_IMPLEMENTED Driver does not support synchronous flush.
* @retval OT_ERROR_INVALID_STATE Driver has no data to flush.
*/
otError otPlatUartFlush(void);
/**
* The UART driver calls this method to notify OpenThread that the requested bytes have been sent.
*/
extern void otPlatUartSendDone(void);
/**
* The UART driver calls this method to notify OpenThread that bytes have been received.
*
* @param[in] aBuf A pointer to the received bytes.
* @param[in] aBufLength The number of bytes received.
*/
extern void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength);
/**
* @}
*/
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_PLATFORM_UART_H_

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2023, 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 RTT implementation of the uart API.
*/
#include <stdint.h>
#include <openthread-core-config.h>
#include <openthread/config.h>
#include <utils/code_utils.h>
#include <openthread/error.h>
#if OPENTHREAD_UART_RTT_ENABLE
#include "SEGGER_RTT.h"
#include "uart.h"
#include "uart_rtt.h"
static bool sUartInitialized = false;
static bool sUartPendingUp = false;
#if UART_RTT_BUFFER_INDEX != 0
static uint8_t sUartUpBuffer[UART_RTT_UP_BUFFER_SIZE];
static uint8_t sUartDownBuffer[UART_RTT_DOWN_BUFFER_SIZE];
#endif
otError otPlatUartEnable(void)
{
otError error = OT_ERROR_FAILED;
#if UART_RTT_BUFFER_INDEX != 0
int resUp = SEGGER_RTT_ConfigUpBuffer(UART_RTT_BUFFER_INDEX, UART_RTT_BUFFER_NAME, sUartUpBuffer,
UART_RTT_UP_BUFFER_SIZE, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
int resDown = SEGGER_RTT_ConfigDownBuffer(UART_RTT_BUFFER_INDEX, UART_RTT_BUFFER_NAME, sUartDownBuffer,
UART_RTT_DOWN_BUFFER_SIZE, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
#else
int resUp = SEGGER_RTT_SetFlagsUpBuffer(UART_RTT_BUFFER_INDEX, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
int resDown = SEGGER_RTT_SetFlagsDownBuffer(UART_RTT_BUFFER_INDEX, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
#endif
otEXPECT(resUp >= 0 && resDown >= 0);
sUartInitialized = true;
sUartPendingUp = false;
error = OT_ERROR_NONE;
exit:
return error;
}
otError otPlatUartDisable(void)
{
sUartInitialized = false;
return OT_ERROR_NONE;
}
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
otError error = OT_ERROR_NONE;
otEXPECT_ACTION(SEGGER_RTT_Write(UART_RTT_BUFFER_INDEX, aBuf, aBufLength) != 0, error = OT_ERROR_FAILED);
sUartPendingUp = true;
exit:
return error;
}
otError otPlatUartFlush(void)
{
otError error = OT_ERROR_NONE;
otEXPECT_ACTION(sUartPendingUp, error = OT_ERROR_INVALID_STATE);
while (SEGGER_RTT_HasDataUp(UART_RTT_BUFFER_INDEX) != 0)
{
}
exit:
return error;
}
void utilsUartRttProcess(void)
{
uint8_t buf[UART_RTT_READ_BUFFER_SIZE];
unsigned count;
otEXPECT(sUartInitialized);
if (sUartPendingUp && SEGGER_RTT_HasDataUp(UART_RTT_BUFFER_INDEX) == 0)
{
sUartPendingUp = false;
otPlatUartSendDone();
}
count = SEGGER_RTT_Read(UART_RTT_BUFFER_INDEX, &buf, sizeof(buf));
if (count > 0)
{
otPlatUartReceived((const uint8_t *)&buf, count);
}
exit:
return;
}
#endif // OPENTHREAD_UART_RTT_ENABLE

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2023, 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 defines the RTT implementation of the uart API and default constants used by uart_rtt.c.
*/
#ifndef UTILS_UART_RTT_H
#define UTILS_UART_RTT_H
#include "openthread-core-config.h"
#include <openthread/config.h>
#include "logging_rtt.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @def UART_RTT_BUFFER_INDEX
*
* RTT buffer index used for the uart.
*/
#ifndef UART_RTT_BUFFER_INDEX
#define UART_RTT_BUFFER_INDEX 1
#endif
#if OPENTHREAD_UART_RTT_ENABLE && (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) && \
(LOG_RTT_BUFFER_INDEX == UART_RTT_BUFFER_INDEX)
#error "Log buffer index matches uart buffer index"
#endif
/**
* @def UART_RTT_BUFFER_NAME
*
* RTT name used for the uart. Only used if UART_RTT_BUFFER_INDEX is not 0.
* Otherwise, the buffer name is fixed to "Terminal".
*/
#ifndef UART_RTT_BUFFER_NAME
#define UART_RTT_BUFFER_NAME "Terminal"
#endif
/**
* @def UART_RTT_UP_BUFFER_SIZE
*
* RTT up buffer size used for the uart. Only used if UART_RTT_BUFFER_INDEX
* is not 0. To configure buffer #0 size, check the BUFFER_SIZE_UP definition
* in SEGGER_RTT_Conf.h
*/
#ifndef UART_RTT_UP_BUFFER_SIZE
#define UART_RTT_UP_BUFFER_SIZE 256
#endif
/**
* @def UART_RTT_DOWN_BUFFER_SIZE
*
* RTT down buffer size used for the uart. Only used if UART_RTT_BUFFER_INDEX
* is not 0. To configure buffer #0 size, check the BUFFER_SIZE_DOWN definition
* in SEGGER_RTT_Conf.h
*/
#ifndef UART_RTT_DOWN_BUFFER_SIZE
#define UART_RTT_DOWN_BUFFER_SIZE 16
#endif
/**
* @def UART_RTT_READ_BUFFER_SIZE
*
* Size of the temporary buffer used when reading from the RTT channel. It will be
* locally allocated on the stack.
*/
#ifndef UART_RTT_READ_BUFFER_SIZE
#define UART_RTT_READ_BUFFER_SIZE 16
#endif
/**
* Updates the rtt uart. Must be called frequently to process receive and send done.
*/
void utilsUartRttProcess(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // UTILS_UART_RTT_H