[diag] add diag output callback (#10354)

The length of diag output messages is limited by the diag buffer size.
Developers have to change the diag buffer size to allow diag module to
output long messages. If diag output messages become longer and
longer, developers have to keep changing the diag buffer size.

This commit adds an output callback to diag module to output diag
messages.  Then the length of diag output messages won't be limited by
the diag buffer size.
This commit is contained in:
Zhanglong Xia
2024-06-19 20:27:35 -07:00
committed by GitHub
parent 31e512ac7b
commit 215c23f2a6
21 changed files with 505 additions and 269 deletions
+7
View File
@@ -58,6 +58,13 @@ static bool sGpioValue = false;
static uint8_t sRawPowerSetting[OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE];
static uint16_t sRawPowerSettingLength = 0;
void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aCallback);
OT_UNUSED_VARIABLE(aContext);
}
void otPlatDiagModeSet(bool aMode) { sDiagMode = aMode; }
bool otPlatDiagModeGet(void) { return sDiagMode; }
+16 -16
View File
@@ -36,6 +36,7 @@
#define OPENTHREAD_DIAG_H_
#include <openthread/instance.h>
#include <openthread/platform/diag.h>
#ifdef __cplusplus
extern "C" {
@@ -51,39 +52,38 @@ extern "C" {
*
*/
/* Represents the pointer to callback to output diag messages. */
typedef otPlatDiagOutputCallback otDiagOutputCallback;
/**
* Sets the diag output callback.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aCallback A pointer to a function that is called on outputting diag messages.
* @param[in] aContext A pointer to the user context.
*
*/
void otDiagSetOutputCallback(otInstance *aInstance, otDiagOutputCallback aCallback, void *aContext);
/**
* Processes a factory diagnostics command line.
*
* The output of this function (the content written to @p aOutput) MUST terminate with `\0` and the `\0` is within the
* output buffer.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aArgsLength The number of elements in @p aArgs.
* @param[in] aArgs An array of arguments.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval OT_ERROR_INVALID_ARGS The command is supported but invalid arguments provided.
* @retval OT_ERROR_NONE The command is successfully process.
* @retval OT_ERROR_NOT_IMPLEMENTED The command is not supported.
*
*/
otError otDiagProcessCmd(otInstance *aInstance,
uint8_t aArgsLength,
char *aArgs[],
char *aOutput,
size_t aOutputMaxLen);
otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]);
/**
* Processes a factory diagnostics command line.
*
* The output of this function (the content written to @p aOutput) MUST terminate with `\0` and the `\0` is within the
* output buffer.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aString A NULL-terminated input string.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval OT_ERROR_NONE The command is successfully process.
* @retval OT_ERROR_INVALID_ARGS The command is supported but invalid arguments provided.
@@ -91,7 +91,7 @@ otError otDiagProcessCmd(otInstance *aInstance,
* @retval OT_ERROR_NO_BUFS The command string is too long.
*
*/
otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen);
otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString);
/**
* Indicates whether or not the factory diagnostics mode is enabled.
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (422)
#define OPENTHREAD_API_VERSION (423)
/**
* @addtogroup api-instance
+21 -10
View File
@@ -67,27 +67,38 @@ typedef enum
} otGpioMode;
/**
* Processes a factory diagnostics command line.
* Pointer to callback to output platform diag messages.
*
* The output of this function (the content written to @p aOutput) MUST terminate with `\0` and the `\0` is within the
* output buffer.
* @param[in] aFormat The format string.
* @param[in] aArguments The format string arguments.
* @param[out] aContext A pointer to the user context.
*
*/
typedef void (*otPlatDiagOutputCallback)(const char *aFormat, va_list aArguments, void *aContext);
/**
* Sets the platform diag output callback.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aCallback A pointer to a function that is called on outputting diag messages.
* @param[in] aContext A pointer to the user context.
*
*/
void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext);
/**
* Processes a factory diagnostics command line.
*
* @param[in] aInstance The OpenThread instance for current request.
* @param[in] aArgsLength The number of arguments in @p aArgs.
* @param[in] aArgs The arguments of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval OT_ERROR_INVALID_ARGS The command is supported but invalid arguments provided.
* @retval OT_ERROR_NONE The command is successfully process.
* @retval OT_ERROR_INVALID_COMMAND The command is not valid or not supported.
*
*/
otError otPlatDiagProcess(otInstance *aInstance,
uint8_t aArgsLength,
char *aArgs[],
char *aOutput,
size_t aOutputMaxLen);
otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]);
/**
* Enables/disables the factory diagnostics mode.
+3 -1
View File
@@ -105,9 +105,11 @@ build_nrf52840()
case "$2" in
new)
local sha=${OT_SHA_NEW}
local clone_options=("clone")
;;
old)
local sha=${OT_SHA_OLD}
local clone_options=("clone" "no-depend")
;;
*)
exit 128
@@ -119,7 +121,7 @@ build_nrf52840()
local config_file="../examples/config/${config_name}"
mkdir -p "${OT_TMP_DIR}/${folder}"
script/git-tool clone https://github.com/openthread/ot-nrf528xx.git "${OT_TMP_DIR}/${folder}"
script/git-tool "${clone_options[@]}" https://github.com/openthread/ot-nrf528xx.git "${OT_TMP_DIR}/${folder}"
rm -rf "${OT_TMP_DIR}/${folder}/openthread/*" # replace openthread submodule with latest commit
git archive "${sha}" | tar x -C "${OT_TMP_DIR}/${folder}/openthread"
+8 -3
View File
@@ -80,10 +80,15 @@ try_clone()
{
local dest_dir
dest_dir="$(git clone "$@" 2>&1 | tee | cut -d\' -f2)"
if [[ $1 == no-depend ]]; then
shift
git clone "$@" 2>&1
else
dest_dir="$(git clone "$@" 2>&1 | tee | cut -d\' -f2)"
cd "${dest_dir}"
get_pr_body | apply_dependencies
cd "${dest_dir}"
get_pr_body | apply_dependencies
fi
}
print_help()
+13 -8
View File
@@ -169,6 +169,10 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
#if (OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK
otIp6SetReceiveCallback(GetInstancePtr(), &Interpreter::HandleIp6Receive, this);
#endif
#if OPENTHREAD_CONFIG_DIAG_ENABLE
otDiagSetOutputCallback(GetInstancePtr(), &Interpreter::HandleDiagOutput, this);
#endif
ClearAllBytes(mUserCommands);
OutputPrompt();
@@ -210,19 +214,20 @@ exit:
#if OPENTHREAD_CONFIG_DIAG_ENABLE
template <> otError Interpreter::Process<Cmd("diag")>(Arg aArgs[])
{
otError error;
char *args[kMaxArgs];
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
char *args[kMaxArgs];
// all diagnostics related features are processed within diagnostics module
Arg::CopyArgsToStringArray(aArgs, args);
error = otDiagProcessCmd(GetInstancePtr(), Arg::GetArgsLength(aArgs), args, output, sizeof(output));
OutputFormat("%s", output);
return error;
return otDiagProcessCmd(GetInstancePtr(), Arg::GetArgsLength(aArgs), args);
}
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext)
{
static_cast<Interpreter *>(aContext)->HandleDiagOutput(aFormat, aArguments);
}
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments) { OutputFormatV(aFormat, aArguments); }
#endif
template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
+5
View File
@@ -339,6 +339,11 @@ private:
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_DIAG_ENABLE
static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext);
void HandleDiagOutput(const char *aFormat, va_list aArguments);
#endif
void SetCommandTimeout(uint32_t aTimeoutMilli);
static void HandleTimer(Timer &aTimer);
+8 -4
View File
@@ -42,18 +42,22 @@
using namespace ot;
otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString)
{
AssertPointerIsNotNull(aString);
return AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessLine(aString, aOutput, aOutputMaxLen);
return AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessLine(aString);
}
otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
return AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessCmd(aArgsLength, aArgs, aOutput, aOutputMaxLen);
return AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessCmd(aArgsLength, aArgs);
}
bool otDiagIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get<FactoryDiags::Diags>().IsEnabled(); }
void otDiagSetOutputCallback(otInstance *aInstance, otDiagOutputCallback aCallback, void *aContext)
{
AsCoreType(aInstance).Get<FactoryDiags::Diags>().SetOutputCallback(aCallback, aContext);
}
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
+130 -129
View File
@@ -50,17 +50,11 @@
#include "utils/parse_cmdline.hpp"
OT_TOOL_WEAK
otError otPlatDiagProcess(otInstance *aInstance,
uint8_t aArgsLength,
char *aArgs[],
char *aOutput,
size_t aOutputMaxLen)
otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
return ot::kErrorInvalidCommand;
}
@@ -85,10 +79,12 @@ const struct Diags::Command Diags::sCommands[] = {
Diags::Diags(Instance &aInstance)
: InstanceLocator(aInstance)
, mOutputCallback(nullptr)
, mOutputContext(nullptr)
{
}
Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
long value;
@@ -101,11 +97,11 @@ Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, s
otPlatDiagChannelSet(static_cast<uint8_t>(value));
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
long value;
@@ -117,35 +113,39 @@ Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
otPlatDiagTxPowerSet(static_cast<int8_t>(value));
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessEcho(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
if (aArgsLength == 1)
{
snprintf(aOutput, aOutputMaxLen, "%s\r\n", aArgs[0]);
Output("%s\r\n", aArgs[0]);
}
else if ((aArgsLength == 2) && (strcmp(aArgs[0], "-n") == 0))
{
const uint8_t kReservedLen = 3; // 1 byte '\r', 1 byte '\n' and 1 byte '\0'
uint32_t outputMaxLen = static_cast<uint32_t>(aOutputMaxLen) - kReservedLen;
long value;
uint32_t i;
uint32_t number;
static constexpr uint8_t kReservedLen = 1; // 1 byte '\0'
static constexpr uint16_t kOutputLen = OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE;
static constexpr uint16_t kOutputMaxLen = kOutputLen - kReservedLen;
char output[kOutputLen];
long value;
uint32_t i;
uint32_t number;
SuccessOrExit(error = ParseLong(aArgs[1], value));
number = Min(static_cast<uint32_t>(value), outputMaxLen);
number = Min(static_cast<uint32_t>(value), static_cast<uint32_t>(kOutputMaxLen));
for (i = 0; i < number; i++)
{
aOutput[i] = '0' + i % 10;
output[i] = '0' + i % 10;
}
snprintf(&aOutput[i], aOutputMaxLen - i, "\r\n");
output[number] = '\0';
Output("%s\r\n", output);
}
else
{
@@ -153,28 +153,24 @@ Error Diags::ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
otPlatDiagModeSet(true);
return kErrorNone;
}
Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
otPlatDiagModeSet(false);
@@ -213,11 +209,13 @@ Diags::Diags(Instance &aInstance)
, mIsTxPacketSet(false)
, mRepeatActive(false)
, mDiagSendOn(false)
, mOutputCallback(nullptr)
, mOutputContext(nullptr)
{
mStats.Clear();
}
Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
uint16_t size = OT_RADIO_FRAME_MAX_SIZE;
@@ -231,11 +229,11 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
mIsTxPacketSet = true;
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
@@ -243,7 +241,7 @@ Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, s
if (aArgsLength == 0)
{
snprintf(aOutput, aOutputMaxLen, "channel: %d\r\n", mChannel);
Output("channel: %d\r\n", mChannel);
}
else
{
@@ -256,15 +254,15 @@ Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, s
IgnoreError(Get<Radio>().Receive(mChannel));
otPlatDiagChannelSet(mChannel);
snprintf(aOutput, aOutputMaxLen, "set channel to %d\r\nstatus 0x%02x\r\n", mChannel, error);
Output("set channel to %d\r\nstatus 0x%02x\r\n", mChannel, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
@@ -272,7 +270,7 @@ Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
if (aArgsLength == 0)
{
snprintf(aOutput, aOutputMaxLen, "tx power: %d dBm\r\n", mTxPower);
Output("tx power: %d dBm\r\n", mTxPower);
}
else
{
@@ -284,15 +282,15 @@ Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
otPlatDiagTxPowerSet(mTxPower);
snprintf(aOutput, aOutputMaxLen, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", mTxPower, error);
Output("set tx power to %d dBm\r\nstatus 0x%02x\r\n", mTxPower, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
@@ -303,7 +301,7 @@ Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, si
{
otPlatAlarmMilliStop(&GetInstance());
mRepeatActive = false;
snprintf(aOutput, aOutputMaxLen, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
Output("repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
}
else
{
@@ -335,16 +333,16 @@ Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, si
mRepeatActive = true;
uint32_t now = otPlatAlarmMilliGetNow();
otPlatAlarmMilliStartAt(&GetInstance(), now, mTxPeriod);
snprintf(aOutput, aOutputMaxLen, "sending packets of length %#x at the delay of %#x ms\r\nstatus 0x%02x\r\n",
static_cast<int>(mTxLen), static_cast<int>(mTxPeriod), error);
Output("sending packets of length %#x at the delay of %#x ms\r\nstatus 0x%02x\r\n", static_cast<int>(mTxLen),
static_cast<int>(mTxPeriod), error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
long value;
@@ -373,16 +371,16 @@ Error Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
VerifyOrExit(value >= OT_RADIO_FRAME_MIN_SIZE, error = kErrorInvalidArgs);
mTxLen = static_cast<uint8_t>(value);
snprintf(aOutput, aOutputMaxLen, "sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n",
static_cast<int>(mTxPackets), static_cast<int>(mTxLen), error);
Output("sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n", static_cast<int>(mTxPackets),
static_cast<int>(mTxLen), error);
TransmitPacket();
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
@@ -403,14 +401,14 @@ Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
otPlatDiagModeSet(true);
mStats.Clear();
snprintf(aOutput, aOutputMaxLen, "start diagnostics mode\r\nstatus 0x%02x\r\n", error);
Output("start diagnostics mode\r\nstatus 0x%02x\r\n", error);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStats(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
@@ -419,26 +417,25 @@ Error Diags::ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
if ((aArgsLength == 1) && (strcmp(aArgs[0], "clear") == 0))
{
mStats.Clear();
snprintf(aOutput, aOutputMaxLen, "stats cleared\r\n");
Output("stats cleared\r\n");
}
else
{
VerifyOrExit(aArgsLength == 0, error = kErrorInvalidArgs);
snprintf(aOutput, aOutputMaxLen,
"received packets: %d\r\nsent packets: %d\r\n"
"first received packet: rssi=%d, lqi=%d\r\n"
"last received packet: rssi=%d, lqi=%d\r\n",
static_cast<int>(mStats.mReceivedPackets), static_cast<int>(mStats.mSentPackets),
static_cast<int>(mStats.mFirstRssi), static_cast<int>(mStats.mFirstLqi),
static_cast<int>(mStats.mLastRssi), static_cast<int>(mStats.mLastLqi));
Output("received packets: %d\r\nsent packets: %d\r\n"
"first received packet: rssi=%d, lqi=%d\r\n"
"last received packet: rssi=%d, lqi=%d\r\n",
static_cast<int>(mStats.mReceivedPackets), static_cast<int>(mStats.mSentPackets),
static_cast<int>(mStats.mFirstRssi), static_cast<int>(mStats.mFirstLqi),
static_cast<int>(mStats.mLastRssi), static_cast<int>(mStats.mLastLqi));
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
@@ -451,17 +448,16 @@ Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
otPlatDiagModeSet(false);
Get<Radio>().SetPromiscuous(false);
snprintf(aOutput, aOutputMaxLen,
"received packets: %d\r\nsent packets: %d\r\n"
"first received packet: rssi=%d, lqi=%d\r\n"
"last received packet: rssi=%d, lqi=%d\r\n"
"\nstop diagnostics mode\r\nstatus 0x%02x\r\n",
static_cast<int>(mStats.mReceivedPackets), static_cast<int>(mStats.mSentPackets),
static_cast<int>(mStats.mFirstRssi), static_cast<int>(mStats.mFirstLqi),
static_cast<int>(mStats.mLastRssi), static_cast<int>(mStats.mLastLqi), error);
Output("received packets: %d\r\nsent packets: %d\r\n"
"first received packet: rssi=%d, lqi=%d\r\n"
"last received packet: rssi=%d, lqi=%d\r\n"
"\nstop diagnostics mode\r\nstatus 0x%02x\r\n",
static_cast<int>(mStats.mReceivedPackets), static_cast<int>(mStats.mSentPackets),
static_cast<int>(mStats.mFirstRssi), static_cast<int>(mStats.mFirstLqi), static_cast<int>(mStats.mLastRssi),
static_cast<int>(mStats.mLastLqi), error);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
@@ -483,7 +479,7 @@ void Diags::TransmitPacket(void)
IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
}
Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
@@ -493,7 +489,7 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
if (strcmp(aArgs[0], "sleep") == 0)
{
SuccessOrExit(error = Get<Radio>().Sleep());
snprintf(aOutput, aOutputMaxLen, "set radio from receive to sleep \r\nstatus 0x%02x\r\n", error);
Output("set radio from receive to sleep \r\nstatus 0x%02x\r\n", error);
}
else if (strcmp(aArgs[0], "receive") == 0)
{
@@ -502,8 +498,7 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);
snprintf(aOutput, aOutputMaxLen, "set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel,
error);
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
}
else if (strcmp(aArgs[0], "state") == 0)
{
@@ -514,29 +509,29 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, siz
switch (state)
{
case OT_RADIO_STATE_DISABLED:
snprintf(aOutput, aOutputMaxLen, "disabled\r\n");
Output("disabled\r\n");
break;
case OT_RADIO_STATE_SLEEP:
snprintf(aOutput, aOutputMaxLen, "sleep\r\n");
Output("sleep\r\n");
break;
case OT_RADIO_STATE_RECEIVE:
snprintf(aOutput, aOutputMaxLen, "receive\r\n");
Output("receive\r\n");
break;
case OT_RADIO_STATE_TRANSMIT:
snprintf(aOutput, aOutputMaxLen, "transmit\r\n");
Output("transmit\r\n");
break;
default:
snprintf(aOutput, aOutputMaxLen, "invalid\r\n");
Output("invalid\r\n");
break;
}
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
@@ -605,7 +600,7 @@ exit:
#endif // OPENTHREAD_RADIO
Error Diags::ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
@@ -622,11 +617,11 @@ Error Diags::ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOu
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessStream(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessStream(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
@@ -643,7 +638,7 @@ Error Diags::ProcessStream(uint8_t aArgsLength, char *aArgs[], char *aOutput, si
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
@@ -655,7 +650,7 @@ Error Diags::GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings)
&aPowerSettings.mRawPowerSetting.mLength);
}
Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
uint8_t channel;
@@ -668,14 +663,9 @@ Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOut
bool isPrePowerSettingsValid = false;
uint8_t preChannel = 0;
PowerSettings prePowerSettings;
int n;
n = snprintf(aOutput, aOutputMaxLen,
"| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |\r\n"
"+---------+-------+-------------+-------------+-----------------+\r\n");
VerifyOrExit((n > 0) && (n < static_cast<int>(aOutputMaxLen)), error = kErrorNoBufs);
aOutput += n;
aOutputMaxLen -= static_cast<size_t>(n);
Output("| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |\r\n"
"+---------+-------+-------------+-------------+-----------------+\r\n");
for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax + 1; channel++)
{
@@ -683,12 +673,8 @@ Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOut
if (isPrePowerSettingsValid && ((powerSettings != prePowerSettings) || (error != kErrorNone)))
{
n = snprintf(aOutput, aOutputMaxLen, "| %7u | %5u | %11d | %11d | %15s |\r\n", preChannel, channel - 1,
prePowerSettings.mTargetPower, prePowerSettings.mActualPower,
prePowerSettings.mRawPowerSetting.ToString().AsCString());
VerifyOrExit((n > 0) && (n < static_cast<int>(aOutputMaxLen)), error = kErrorNoBufs);
aOutput += n;
aOutputMaxLen -= static_cast<size_t>(n);
Output("| %7u | %5u | %11d | %11d | %15s |\r\n", preChannel, channel - 1, prePowerSettings.mTargetPower,
prePowerSettings.mActualPower, prePowerSettings.mRawPowerSetting.ToString().AsCString());
isPrePowerSettingsValid = false;
}
@@ -708,14 +694,13 @@ Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOut
VerifyOrExit(channel >= Radio::kChannelMin && channel <= Radio::kChannelMax, error = kErrorInvalidArgs);
SuccessOrExit(error = GetPowerSettings(channel, powerSettings));
snprintf(aOutput, aOutputMaxLen,
"TargetPower(0.01dBm): %d\r\nActualPower(0.01dBm): %d\r\nRawPowerSetting: %s\r\n",
powerSettings.mTargetPower, powerSettings.mActualPower,
powerSettings.mRawPowerSetting.ToString().AsCString());
Output("TargetPower(0.01dBm): %d\r\nActualPower(0.01dBm): %d\r\nRawPowerSetting: %s\r\n",
powerSettings.mTargetPower, powerSettings.mActualPower,
powerSettings.mRawPowerSetting.ToString().AsCString());
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
@@ -725,7 +710,7 @@ Error Diags::GetRawPowerSetting(RawPowerSetting &aRawPowerSetting)
return otPlatDiagRadioGetRawPowerSetting(&GetInstance(), aRawPowerSetting.mData, &aRawPowerSetting.mLength);
}
Error Diags::ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
RawPowerSetting setting;
@@ -735,7 +720,7 @@ Error Diags::ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aO
if (aArgsLength == 0)
{
SuccessOrExit(error = GetRawPowerSetting(setting));
snprintf(aOutput, aOutputMaxLen, "%s\r\n", setting.ToString().AsCString());
Output("%s\r\n", setting.ToString().AsCString());
}
else if (strcmp(aArgs[0], "enable") == 0)
{
@@ -753,11 +738,11 @@ Error Diags::ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aO
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
long value;
@@ -770,7 +755,7 @@ Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
SuccessOrExit(error = ParseLong(aArgs[1], value));
gpio = static_cast<uint32_t>(value);
SuccessOrExit(error = otPlatDiagGpioGet(gpio, &level));
snprintf(aOutput, aOutputMaxLen, "%d\r\n", level);
Output("%d\r\n", level);
}
else if ((aArgsLength == 3) && (strcmp(aArgs[0], "set") == 0))
{
@@ -789,11 +774,11 @@ Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
SuccessOrExit(error = otPlatDiagGpioGetMode(gpio, &mode));
if (mode == OT_GPIO_MODE_INPUT)
{
snprintf(aOutput, aOutputMaxLen, "in\r\n");
Output("in\r\n");
}
else if (mode == OT_GPIO_MODE_OUTPUT)
{
snprintf(aOutput, aOutputMaxLen, "out\r\n");
Output("out\r\n");
}
}
else if ((aArgsLength == 3) && (strcmp(aArgs[2], "in") == 0))
@@ -807,15 +792,15 @@ Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
AppendErrorResult(error);
return error;
}
void Diags::AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen)
void Diags::AppendErrorResult(Error aError)
{
if (aError != kErrorNone)
{
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
Output("failed\r\nstatus %#x\r\n", aError);
}
}
@@ -852,7 +837,7 @@ exit:
return error;
}
Error Diags::ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessLine(const char *aString)
{
constexpr uint16_t kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE;
@@ -871,27 +856,26 @@ exit:
switch (error)
{
case kErrorNone:
aOutput[0] = '\0'; // In case there is no output.
error = ProcessCmd(argCount, &args[0], aOutput, aOutputMaxLen);
error = ProcessCmd(argCount, &args[0]);
break;
case kErrorNoBufs:
snprintf(aOutput, aOutputMaxLen, "failed: command string too long\r\n");
Output("failed: command string too long\r\n");
break;
case kErrorInvalidArgs:
snprintf(aOutput, aOutputMaxLen, "failed: command string contains too many arguments\r\n");
Output("failed: command string contains too many arguments\r\n");
break;
default:
snprintf(aOutput, aOutputMaxLen, "failed to parse command string\r\n");
Output("failed to parse command string\r\n");
break;
}
return error;
}
Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorNone;
@@ -907,37 +891,54 @@ Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_
if (aArgsLength == 0)
{
snprintf(aOutput, aOutputMaxLen, "diagnostics mode is %s\r\n", otPlatDiagModeGet() ? "enabled" : "disabled");
Output("diagnostics mode is %s\r\n", otPlatDiagModeGet() ? "enabled" : "disabled");
ExitNow();
}
else
{
aOutput[0] = '\0';
}
for (const Command &command : sCommands)
{
if (strcmp(aArgs[0], command.mName) == 0)
{
error = (this->*command.mCommand)(aArgsLength - 1, (aArgsLength > 1) ? &aArgs[1] : nullptr, aOutput,
aOutputMaxLen);
error = (this->*command.mCommand)(aArgsLength - 1, (aArgsLength > 1) ? &aArgs[1] : nullptr);
ExitNow();
}
}
// more platform specific features will be processed under platform layer
error = otPlatDiagProcess(&GetInstance(), aArgsLength, aArgs, aOutput, aOutputMaxLen);
error = otPlatDiagProcess(&GetInstance(), aArgsLength, aArgs);
exit:
// Add more platform specific diagnostics features here.
if (error == kErrorInvalidCommand && aArgsLength > 1)
{
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", aArgs[0]);
Output("diag feature '%s' is not supported\r\n", aArgs[0]);
}
return error;
}
void Diags::SetOutputCallback(otDiagOutputCallback aCallback, void *aContext)
{
mOutputCallback = aCallback;
mOutputContext = aContext;
otPlatDiagSetOutputCallback(&GetInstance(), aCallback, aContext);
}
void Diags::Output(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
if (mOutputCallback != nullptr)
{
mOutputCallback(aFormat, args, mOutputContext);
}
va_end(args);
}
bool Diags::IsEnabled(void) { return otPlatDiagModeGet(); }
} // namespace FactoryDiags
+33 -23
View File
@@ -40,6 +40,7 @@
#include <string.h>
#include <openthread/diag.h>
#include <openthread/platform/radio.h>
#include "common/clearable.hpp"
@@ -66,26 +67,22 @@ public:
* Processes a factory diagnostics command line.
*
* @param[in] aString A null-terminated input string.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
*/
Error ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen);
Error ProcessLine(const char *aString);
/**
* Processes a factory diagnostics command line.
*
* @param[in] aArgsLength The number of args in @p aArgs.
* @param[in] aArgs The arguments of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval kErrorInvalidArgs The command is supported but invalid arguments provided.
* @retval kErrorNone The command is successfully process.
* @retval kErrorNotImplemented The command is not supported.
*
*/
Error ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessCmd(uint8_t aArgsLength, char *aArgs[]);
/**
* Indicates whether or not the factory diagnostics mode is enabled.
@@ -123,13 +120,22 @@ public:
*/
void TransmitDone(Error aError);
/**
* Sets the diag output callback.
*
* @param[in] aCallback A callback method called to output diag messages.
* @param[in] aContext A user context pointer.
*
*/
void SetOutputCallback(otDiagOutputCallback aCallback, void *aContext);
private:
static constexpr uint8_t kMaxArgs = OPENTHREAD_CONFIG_DIAG_CMD_LINE_ARGS_MAX;
struct Command
{
const char *mName;
Error (Diags::*mCommand)(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error (Diags::*mCommand)(uint8_t aArgsLength, char *aArgs[]);
};
struct Stats : public Clearable<Stats>
@@ -180,30 +186,31 @@ private:
};
Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessFrame(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStream(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
Error ProcessFrame(uint8_t aArgsLength, char *aArgs[]);
Error ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[]);
Error ProcessGpio(uint8_t aArgsLength, char *aArgs[]);
Error ProcessPower(uint8_t aArgsLength, char *aArgs[]);
Error ProcessRadio(uint8_t aArgsLength, char *aArgs[]);
Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[]);
Error ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[]);
Error ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[]);
Error ProcessSend(uint8_t aArgsLength, char *aArgs[]);
Error ProcessStart(uint8_t aArgsLength, char *aArgs[]);
Error ProcessStats(uint8_t aArgsLength, char *aArgs[]);
Error ProcessStop(uint8_t aArgsLength, char *aArgs[]);
Error ProcessStream(uint8_t aArgsLength, char *aArgs[]);
#if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
Error ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessEcho(uint8_t aArgsLength, char *aArgs[]);
#endif
Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting);
Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings);
void TransmitPacket(void);
void Output(const char *aFormat, ...);
void AppendErrorResult(Error aError);
static void AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen);
static Error ParseLong(char *aString, long &aLong);
static Error ParseBool(char *aString, bool &aBool);
@@ -222,6 +229,9 @@ private:
bool mRepeatActive;
bool mDiagSendOn;
#endif
otDiagOutputCallback mOutputCallback;
void *mOutputContext;
};
} // namespace FactoryDiags
+40 -17
View File
@@ -99,8 +99,8 @@ RadioSpinel::RadioSpinel(void)
#endif
#if OPENTHREAD_CONFIG_DIAG_ENABLE
, mDiagMode(false)
, mDiagOutput(nullptr)
, mDiagOutputMaxLen(0)
, mOutputCallback(nullptr)
, mOutputContext(nullptr)
#endif
, mTxRadioEndUs(UINT64_MAX)
, mRadioTimeRecalcStart(UINT64_MAX)
@@ -431,12 +431,13 @@ void RadioSpinel::HandleWaitingResponse(uint32_t aCommand,
else if (aKey == SPINEL_PROP_NEST_STREAM_MFG)
{
spinel_ssize_t unpacked;
const char *diagOutput;
mError = OT_ERROR_NONE;
EXPECT(mDiagOutput != nullptr, NO_ACTION);
unpacked =
spinel_datatype_unpack_in_place(aBuffer, aLength, SPINEL_DATATYPE_UTF8_S, mDiagOutput, &mDiagOutputMaxLen);
EXPECT(mOutputCallback != nullptr, NO_ACTION);
unpacked = spinel_datatype_unpack(aBuffer, aLength, SPINEL_DATATYPE_UTF8_S, &diagOutput);
EXPECT(unpacked > 0, mError = OT_ERROR_PARSE);
PlatDiagOutput("%s", diagOutput);
}
#endif
else if (aKey == mWaitingKey)
@@ -591,6 +592,17 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
break;
}
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
else if (aKey == SPINEL_PROP_NEST_STREAM_MFG)
{
const char *diagOutput;
EXPECT(mOutputCallback != nullptr, NO_ACTION);
unpacked = spinel_datatype_unpack(aBuffer, aLength, SPINEL_DATATYPE_UTF8_S, &diagOutput);
EXPECT(unpacked > 0, error = OT_ERROR_PARSE);
PlatDiagOutput("%s", diagOutput);
}
#endif
#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
else if (aKey >= SPINEL_PROP_VENDOR__BEGIN && aKey < SPINEL_PROP_VENDOR__END)
{
@@ -1753,20 +1765,31 @@ exit:
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
otError RadioSpinel::PlatDiagProcess(const char *aString, char *aOutput, size_t aOutputMaxLen)
void RadioSpinel::SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext)
{
otError error;
mDiagOutput = aOutput;
mDiagOutputMaxLen = aOutputMaxLen;
error = Set(SPINEL_PROP_NEST_STREAM_MFG, SPINEL_DATATYPE_UTF8_S, aString);
mDiagOutput = nullptr;
mDiagOutputMaxLen = 0;
return error;
mOutputCallback = aCallback;
mOutputContext = aContext;
}
otError RadioSpinel::PlatDiagProcess(const char *aString)
{
return Set(SPINEL_PROP_NEST_STREAM_MFG, SPINEL_DATATYPE_UTF8_S, aString);
}
void RadioSpinel::PlatDiagOutput(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
if (mOutputCallback != nullptr)
{
mOutputCallback(aFormat, args, mOutputContext);
}
va_end(args);
}
#endif
uint32_t RadioSpinel::GetRadioChannelMask(bool aPreferred)
+18 -6
View File
@@ -34,6 +34,7 @@
#ifndef RADIO_SPINEL_HPP_
#define RADIO_SPINEL_HPP_
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
#include "openthread-spinel-config.h"
@@ -678,15 +679,22 @@ public:
* Processes platform diagnostics commands.
*
* @param[in] aString A null-terminated input string.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval OT_ERROR_NONE Succeeded.
* @retval OT_ERROR_BUSY Failed due to another operation is on going.
* @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver.
*
*/
otError PlatDiagProcess(const char *aString, char *aOutput, size_t aOutputMaxLen);
otError PlatDiagProcess(const char *aString);
/**
* Sets the diag output callback.
*
* @param[in] aCallback A pointer to a function that is called on outputting diag messages.
* @param[in] aContext A pointer to the user context.
*
*/
void SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext);
#endif
/**
@@ -1194,6 +1202,10 @@ private:
static otError ReadMacKey(const otMacKeyMaterial &aKeyMaterial, otMacKey &aKey);
#endif
#if OPENTHREAD_CONFIG_DIAG_ENABLE
void PlatDiagOutput(const char *aFormat, ...);
#endif
otInstance *mInstance;
RadioSpinelCallbacks mCallbacks; ///< Callbacks for notifications of higher layer.
@@ -1281,9 +1293,9 @@ private:
#endif // OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
#if OPENTHREAD_CONFIG_DIAG_ENABLE
bool mDiagMode;
char *mDiagOutput;
size_t mDiagOutputMaxLen;
bool mDiagMode;
otPlatDiagOutputCallback mOutputCallback;
void *mOutputContext;
#endif
uint64_t mTxRadioEndUs;
+51 -5
View File
@@ -313,6 +313,10 @@ NcpBase::NcpBase(Instance *aInstance)
, mTxSpinelFrameCounter(0)
, mDidInitialUpdates(false)
, mLogTimestampBase(0)
#if OPENTHREAD_CONFIG_DIAG_ENABLE
, mDiagOutput(nullptr)
, mDiagOutputLen(0)
#endif
{
OT_ASSERT(mInstance != nullptr);
@@ -354,6 +358,9 @@ NcpBase::NcpBase(Instance *aInstance)
otSrpClientSetCallback(mInstance, HandleSrpClientCallback, this);
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_DIAG_ENABLE
otDiagSetOutputCallback(mInstance, &NcpBase::HandleDiagOutput_Jump, this);
#endif
mChangedPropsSet.AddLastStatus(SPINEL_STATUS_RESET_UNKNOWN);
mUpdateChangedPropsTask.Post();
@@ -1418,12 +1425,11 @@ exit:
// ----------------------------------------------------------------------------
#if OPENTHREAD_CONFIG_DIAG_ENABLE
otError NcpBase::HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)
{
const char *string = nullptr;
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
otError error = OT_ERROR_NONE;
const char *string = nullptr;
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE] = {0};
otError error = OT_ERROR_NONE;
error = mDecoder.ReadUtf8(string);
@@ -1438,7 +1444,10 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)
}
#endif
SuccessOrExit(error = otDiagProcessCmdLine(mInstance, string, output, sizeof(output)));
mDiagOutput = output;
mDiagOutputLen = sizeof(output);
SuccessOrExit(error = otDiagProcessCmdLine(mInstance, string));
// Prepare the response
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
@@ -1446,9 +1455,46 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)
SuccessOrExit(error = mEncoder.EndFrame());
exit:
mDiagOutput = nullptr;
mDiagOutputLen = 0;
return error;
}
void NcpBase::HandleDiagOutput_Jump(const char *aFormat, va_list aArguments, void *aContext)
{
static_cast<NcpBase *>(aContext)->HandleDiagOutput(aFormat, aArguments);
}
void NcpBase::HandleDiagOutput(const char *aFormat, va_list aArguments)
{
int charsWritten;
if (mDiagOutput != nullptr)
{
charsWritten = vsnprintf(mDiagOutput, mDiagOutputLen, aFormat, aArguments);
VerifyOrExit(charsWritten > 0);
charsWritten = (mDiagOutputLen <= charsWritten) ? mDiagOutputLen : charsWritten;
mDiagOutput += charsWritten;
mDiagOutputLen -= charsWritten;
}
else
{
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
charsWritten = vsnprintf(output, sizeof(output), aFormat, aArguments);
VerifyOrExit(charsWritten >= 0);
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
SuccessOrExit(mEncoder.WriteUtf8(output));
SuccessOrExit(mEncoder.EndFrame());
}
exit:
return;
}
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_ENABLED>(void)
+10
View File
@@ -549,6 +549,11 @@ protected:
static uint8_t ConvertLogLevel(otLogLevel aLogLevel);
static unsigned int ConvertLogRegion(otLogRegion aLogRegion);
#if OPENTHREAD_CONFIG_DIAG_ENABLE
static void HandleDiagOutput_Jump(const char *aFormat, va_list aArguments, void *aContext);
void HandleDiagOutput(const char *aFormat, va_list aArguments);
#endif
#if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
/**
* Defines a vendor "command handler" hook to process vendor-specific spinel commands.
@@ -734,6 +739,11 @@ protected:
bool mDidInitialUpdates;
uint64_t mLogTimestampBase; // Timestamp base used for logging
#if OPENTHREAD_CONFIG_DIAG_ENABLE
char *mDiagOutput;
uint16_t mDiagOutputLen;
#endif
};
} // namespace Ncp
+80 -20
View File
@@ -498,11 +498,55 @@ exit:
#endif
#if OPENTHREAD_CONFIG_DIAG_ENABLE
otError otPlatDiagProcess(otInstance *aInstance,
uint8_t aArgsLength,
char *aArgs[],
char *aOutput,
size_t aOutputMaxLen)
static otPlatDiagOutputCallback sDiagOutputCallback = nullptr;
static void *sDiagCallbackContext = nullptr;
static char *sDiagOutput = nullptr;
static uint16_t sDiagOutputLen = 0;
static void handleDiagOutput(const char *aFormat, va_list aArguments, void *aContext)
{
OT_UNUSED_VARIABLE(aContext);
int charsWritten;
VerifyOrExit((sDiagOutput != nullptr) && (sDiagOutputLen > 0));
charsWritten = vsnprintf(sDiagOutput, sDiagOutputLen, aFormat, aArguments);
VerifyOrExit(charsWritten > 0);
charsWritten = (sDiagOutputLen <= charsWritten) ? sDiagOutputLen : charsWritten;
sDiagOutput += charsWritten;
sDiagOutputLen -= charsWritten;
exit:
return;
}
static void setDiagOutput(char *aOutput, size_t aSize)
{
sDiagOutput = aOutput;
sDiagOutputLen = static_cast<uint16_t>(aSize);
GetRadioSpinel().SetDiagOutputCallback(handleDiagOutput, nullptr);
}
static void freeDiagOutput(void)
{
sDiagOutput = nullptr;
sDiagOutputLen = 0;
GetRadioSpinel().SetDiagOutputCallback(sDiagOutputCallback, sDiagCallbackContext);
}
void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
{
OT_UNUSED_VARIABLE(aInstance);
sDiagOutputCallback = aCallback;
sDiagCallbackContext = aContext;
GetRadioSpinel().SetDiagOutputCallback(aCallback, aContext);
#if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
GetRcpCapsDiag().SetDiagOutputCallback(aCallback, aContext);
#endif
}
otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
// deliver the platform specific diags commands to radio only ncp.
OT_UNUSED_VARIABLE(aInstance);
@@ -513,7 +557,7 @@ otError otPlatDiagProcess(otInstance *aInstance,
#if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
if (strcmp(aArgs[0], "rcpcaps") == 0)
{
return GetRcpCapsDiag().DiagProcess(aArgs, aArgsLength, aOutput, aOutputMaxLen);
return GetRcpCapsDiag().DiagProcess(aArgs, aArgsLength);
}
#endif
@@ -522,12 +566,12 @@ otError otPlatDiagProcess(otInstance *aInstance,
cur += snprintf(cur, static_cast<size_t>(end - cur), "%s ", aArgs[index]);
}
return GetRadioSpinel().PlatDiagProcess(cmd, aOutput, aOutputMaxLen);
return GetRadioSpinel().PlatDiagProcess(cmd);
}
void otPlatDiagModeSet(bool aMode)
{
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(aMode ? "start" : "stop", nullptr, 0));
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(aMode ? "start" : "stop"));
GetRadioSpinel().SetDiagEnabled(aMode);
exit:
@@ -541,7 +585,7 @@ void otPlatDiagTxPowerSet(int8_t aTxPower)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "power %d", aTxPower);
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return;
@@ -552,7 +596,7 @@ void otPlatDiagChannelSet(uint8_t aChannel)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "channel %d", aChannel);
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return;
@@ -564,7 +608,7 @@ otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "gpio set %d %d", aGpio, aValue);
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return error;
@@ -577,12 +621,16 @@ otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
char *str;
setDiagOutput(output, sizeof(output));
snprintf(cmd, sizeof(cmd), "gpio get %d", aGpio);
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, output, sizeof(output)));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
*aValue = static_cast<bool>(atoi(str));
exit:
freeDiagOutput();
return error;
}
@@ -592,7 +640,7 @@ otError otPlatDiagGpioSetMode(uint32_t aGpio, otGpioMode aMode)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "gpio mode %d %s", aGpio, aMode == OT_GPIO_MODE_INPUT ? "in" : "out");
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return error;
@@ -605,8 +653,10 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
char *str;
setDiagOutput(output, sizeof(output));
snprintf(cmd, sizeof(cmd), "gpio mode %d", aGpio);
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, output, sizeof(output)));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
if (strcmp(str, "in") == 0)
@@ -623,6 +673,8 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
}
exit:
freeDiagOutput();
return error;
}
@@ -648,8 +700,10 @@ otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
assert((aTargetPower != nullptr) && (aActualPower != nullptr) && (aRawPowerSetting != nullptr) &&
(aRawPowerSettingLength != nullptr));
setDiagOutput(output, sizeof(output));
snprintf(cmd, sizeof(cmd), "powersettings %d", aChannel);
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, output, sizeof(output)));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
snprintf(fmt, sizeof(fmt), "TargetPower(0.01dBm): %%d\r\nActualPower(0.01dBm): %%d\r\nRawPowerSetting: %%%us\r\n",
kRawPowerStringSize);
VerifyOrExit(sscanf(output, fmt, &targetPower, &actualPower, rawPowerSetting) == 3, error = OT_ERROR_FAILED);
@@ -659,6 +713,8 @@ otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
*aActualPower = static_cast<int16_t>(actualPower);
exit:
freeDiagOutput();
return error;
}
@@ -682,7 +738,7 @@ otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
VerifyOrExit(nbytes < static_cast<int>(sizeof(cmd)), error = OT_ERROR_INVALID_ARGS);
}
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return error;
@@ -700,12 +756,16 @@ otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
assert((aRawPowerSetting != nullptr) && (aRawPowerSettingLength != nullptr));
setDiagOutput(output, sizeof(output));
snprintf(cmd, sizeof(cmd), "rawpowersetting");
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, output, sizeof(output)));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
SuccessOrExit(error = ot::Utils::CmdLineParser::ParseAsHexString(str, *aRawPowerSettingLength, aRawPowerSetting));
exit:
freeDiagOutput();
return error;
}
@@ -717,7 +777,7 @@ otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "rawpowersetting %s", aEnable ? "enable" : "disable");
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return error;
@@ -731,7 +791,7 @@ otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "cw %s", aEnable ? "start" : "stop");
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0));
SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
exit:
return error;
@@ -744,7 +804,7 @@ otError otPlatDiagRadioTransmitStream(otInstance *aInstance, bool aEnable)
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "stream %s", aEnable ? "start" : "stop");
return GetRadioSpinel().PlatDiagProcess(cmd, nullptr, 0);
return GetRadioSpinel().PlatDiagProcess(cmd);
}
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+9 -9
View File
@@ -447,15 +447,12 @@ const struct RcpCapsDiag::SpinelEntry RcpCapsDiag::sSpinelEntries[] = {
SPINEL_ENTRY(kCategoryUtils, SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_RADIO_COEX_ENABLE),
};
otError RcpCapsDiag::DiagProcess(char *aArgs[], uint8_t aArgsLength, char *aOutput, size_t aOutputMaxLen)
otError RcpCapsDiag::DiagProcess(char *aArgs[], uint8_t aArgsLength)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
mOutputStart = aOutput;
mOutputEnd = aOutput + aOutputMaxLen;
if (strcmp(aArgs[1], "spinel") == 0)
{
ProcessSpinel();
@@ -465,9 +462,6 @@ otError RcpCapsDiag::DiagProcess(char *aArgs[], uint8_t aArgsLength, char *aOutp
error = OT_ERROR_INVALID_COMMAND;
}
mOutputStart = nullptr;
mOutputEnd = nullptr;
exit:
return error;
}
@@ -498,6 +492,12 @@ void RcpCapsDiag::TestSpinelCommands(Category aCategory)
}
}
void RcpCapsDiag::SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext)
{
mOutputCallback = aCallback;
mOutputContext = aContext;
}
void RcpCapsDiag::OutputResult(const SpinelEntry &aEntry, otError error)
{
static constexpr uint8_t kSpaceLength = 1;
@@ -522,9 +522,9 @@ void RcpCapsDiag::Output(const char *aFormat, ...)
va_start(args, aFormat);
if ((mOutputStart != nullptr) && (mOutputEnd != nullptr) && (mOutputStart < mOutputEnd))
if (mOutputCallback != nullptr)
{
mOutputStart += vsnprintf(mOutputStart, static_cast<size_t>(mOutputEnd - mOutputStart), aFormat, args);
mOutputCallback(aFormat, args, mOutputContext);
}
va_end(args);
+17 -8
View File
@@ -37,6 +37,8 @@
#include "platform-posix.h"
#if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
#include <openthread/platform/diag.h>
#include "lib/spinel/radio_spinel.hpp"
#include "lib/spinel/spinel.h"
@@ -58,8 +60,8 @@ public:
*/
explicit RcpCapsDiag(Spinel::RadioSpinel &aRadioSpinel)
: mRadioSpinel(aRadioSpinel)
, mOutputStart(nullptr)
, mOutputEnd(nullptr)
, mOutputCallback(nullptr)
, mOutputContext(nullptr)
{
}
@@ -68,15 +70,22 @@ public:
*
* @param[in] aArgs The arguments of diagnostics command line.
* @param[in] aArgsLength The number of arguments in @p aArgs.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
* @retval OT_ERROR_INVALID_ARGS The command is supported but invalid arguments provided.
* @retval OT_ERROR_NONE The command is successfully processed.
* @retval OT_ERROR_INVALID_COMMAND The command is not valid or not supported.
*
*/
otError DiagProcess(char *aArgs[], uint8_t aArgsLength, char *aOutput, size_t aOutputMaxLen);
otError DiagProcess(char *aArgs[], uint8_t aArgsLength);
/**
* Sets the diag output callback.
*
* @param[in] aCallback A pointer to a function that is called on outputting diag messages.
* @param[in] aContext A user context pointer.
*
*/
void SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext);
private:
template <uint32_t aCommand, spinel_prop_key_t aKey> otError HandleSpinelCommand(void);
@@ -108,9 +117,9 @@ private:
static const struct SpinelEntry sSpinelEntries[];
Spinel::RadioSpinel &mRadioSpinel;
char *mOutputStart;
char *mOutputEnd;
Spinel::RadioSpinel &mRadioSpinel;
otPlatDiagOutputCallback mOutputCallback;
void *mOutputContext;
};
} // namespace Posix
+8 -7
View File
@@ -488,17 +488,18 @@ otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
void otPlatSettingsWipe(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
otError otPlatDiagProcess(otInstance *aInstance,
uint8_t aArgsLength,
char *aArgs[],
char *aOutput,
size_t aOutputMaxLen)
void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aCallback);
OT_UNUSED_VARIABLE(aContext);
}
otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
return OT_ERROR_INVALID_COMMAND;
}
+26 -2
View File
@@ -99,6 +99,9 @@ void testFreeInstance(otInstance *aInstance)
bool sDiagMode = false;
static otPlatDiagOutputCallback sOutputCallback = nullptr;
static void *sOutputCallbackContext = nullptr;
extern "C" {
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
@@ -225,9 +228,30 @@ exit:
return error;
}
OT_TOOL_WEAK void otPlatDiagProcess(otInstance *, uint8_t, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
static void DiagOutput(const char *aFormat, ...)
{
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", aArgs[0]);
va_list args;
va_start(args, aFormat);
if (sOutputCallback != nullptr)
{
sOutputCallback(aFormat, args, sOutputCallbackContext);
}
va_end(args);
}
OT_TOOL_WEAK void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
{
sOutputCallback = aCallback;
sOutputCallbackContext = aContext;
}
OT_TOOL_WEAK otError otPlatDiagProcess(otInstance *, uint8_t, char *aArgs[])
{
DiagOutput("diag feature '%s' is not supported\r\n", aArgs[0]);
return OT_ERROR_NONE;
}
OT_TOOL_WEAK void otPlatDiagModeSet(bool aMode) { sDiagMode = aMode; }
+1
View File
@@ -33,6 +33,7 @@
#include <openthread/config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/dns.h>
#include <openthread/platform/dnssd.h>
#include <openthread/platform/dso_transport.h>