[diag] move factory diags into core (#4010)

- Simplifies make files by not having to deal with separate library.
- Combine factory diags source into single source file.
This commit is contained in:
Jonathan Hui
2019-07-23 08:47:16 -07:00
committed by GitHub
parent a5124493d9
commit e87bc42184
35 changed files with 900 additions and 920 deletions
+2 -2
View File
@@ -112,6 +112,7 @@ LOCAL_SRC_FILES := \
src/core/api/crypto_api.cpp \
src/core/api/dataset_api.cpp \
src/core/api/dataset_ftd_api.cpp \
src/core/api/diags_api.cpp \
src/core/api/dns_api.cpp \
src/core/api/icmp6_api.cpp \
src/core/api/instance_api.cpp \
@@ -151,6 +152,7 @@ LOCAL_SRC_FILES := \
src/core/crypto/mbedtls.cpp \
src/core/crypto/pbkdf2_cmac.cpp \
src/core/crypto/sha256.cpp \
src/core/diags/factory_diags.cpp \
src/core/mac/channel_mask.cpp \
src/core/mac/data_poll_handler.cpp \
src/core/mac/data_poll_sender.cpp \
@@ -221,8 +223,6 @@ LOCAL_SRC_FILES := \
src/core/utils/missing_strnlen.c \
src/core/utils/parse_cmdline.cpp \
src/core/utils/slaac_address.cpp \
src/diag/diag_process.cpp \
src/diag/openthread-diag.cpp \
src/ncp/hdlc.cpp \
src/ncp/spinel.c \
src/ncp/spinel_decoder.cpp \
+3 -4
View File
@@ -1161,7 +1161,7 @@ AM_CONDITIONAL([OPENTHREAD_ENABLE_MAC_FILTER], [test "${enable_mac_filter}" = "y
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_MAC_FILTER],[${OPENTHREAD_ENABLE_MAC_FILTER}],[Define to 1 if you want to use MAC filter feature])
#
# Diagnostics Library
# Factory Diagnostics
#
AC_ARG_ENABLE(diag,
@@ -1190,7 +1190,7 @@ AC_MSG_CHECKING([whether to enable diag])
AC_MSG_RESULT(${enable_diag})
AC_SUBST(OPENTHREAD_ENABLE_DIAG)
AM_CONDITIONAL([OPENTHREAD_ENABLE_DIAG], [test "${enable_diag}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DIAG],[${OPENTHREAD_ENABLE_DIAG}],[Define to 1 if you want to use diagnostics module])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DIAG],[${OPENTHREAD_ENABLE_DIAG}],[Define to 1 if you want to enable factory diagnostics feature])
#
# Vendor Extension - Specify a C++ source file which will be built as part of OpenThread core library.
@@ -1928,7 +1928,6 @@ src/Makefile
src/cli/Makefile
src/ncp/Makefile
src/core/Makefile
src/diag/Makefile
src/posix/Makefile
src/posix/platform/Makefile
third_party/Makefile
@@ -2048,7 +2047,7 @@ AC_MSG_NOTICE([
OpenThread Channel Monitor support : ${enable_channel_monitor}
OpenThread Channel Manager support : ${enable_channel_manager}
OpenThread MAC Filter support : ${enable_mac_filter}
OpenThread Diagnostics support : ${enable_diag}
OpenThread Factory Diagnostics support : ${enable_diag}
OpenThread Child Supervision support : ${enable_child_supervision}
OpenThread Legacy network support : ${enable_legacy}
OpenThread DHCPv6 Server support : ${enable_dhcp6_server}
-6
View File
@@ -57,12 +57,6 @@ LDADD_COMMON += \
$(NULL)
endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
if OPENTHREAD_ENABLE_DIAG
LDADD_COMMON += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif # OPENTHREAD_ENABLE_DIAG
if OPENTHREAD_ENABLE_FTD
bin_PROGRAMS += \
ot-cli-ftd \
-4
View File
@@ -104,10 +104,6 @@ pseudo_reset:
otCliUartInit(instance);
#if OPENTHREAD_ENABLE_DIAG
otDiagInit(instance);
#endif
while (!otSysPseudoResetWasRequested())
{
otTaskletsProcess(instance);
-6
View File
@@ -63,12 +63,6 @@ LDADD_MBEDTLS += \
$(NULL)
endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
if OPENTHREAD_ENABLE_DIAG
LDADD_DIAG += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif
if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
LDADD_COMMON += \
$(OPENTHREAD_NCP_SPINEL_ENCRYPTER_LIBS) \
-4
View File
@@ -103,10 +103,6 @@ pseudo_reset:
otNcpInit(instance);
#if OPENTHREAD_ENABLE_DIAG
otDiagInit(instance);
#endif
while (!otSysPseudoResetWasRequested())
{
otTaskletsProcess(instance);
@@ -111,12 +111,6 @@ LDADD_COMMON += \
$(NULL)
endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
if OPENTHREAD_ENABLE_DIAG
LDADD_COMMON += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif # OPENTHREAD_ENABLE_DIAG
if OPENTHREAD_ENABLE_EXECUTABLE
bin_PROGRAMS += \
sleepy-demo-ftd \
@@ -104,10 +104,6 @@ int main(int argc, char *argv[])
otIp6SetEnabled(instance, true);
otThreadSetEnabled(instance, true);
#if OPENTHREAD_ENABLE_DIAG
otDiagInit(instance);
#endif
while (!otSysPseudoResetWasRequested())
{
otTaskletsProcess(instance);
@@ -111,12 +111,6 @@ LDADD_COMMON += \
$(NULL)
endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
if OPENTHREAD_ENABLE_DIAG
LDADD_COMMON += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif # OPENTHREAD_ENABLE_DIAG
if OPENTHREAD_ENABLE_EXECUTABLE
bin_PROGRAMS += \
sleepy-demo-mtd \
@@ -115,10 +115,6 @@ int main(int argc, char *argv[])
otThreadSetEnabled(instance, true);
efr32SetSleepCallback(sleepCb);
#if OPENTHREAD_ENABLE_DIAG
otDiagInit(instance);
#endif
while (!otSysPseudoResetWasRequested())
{
otTaskletsProcess(instance);
+1 -11
View File
@@ -72,6 +72,7 @@ COMMONCPPFLAGS
PLATFORM_COMMON_SOURCES = \
alarm.c \
diag.c \
entropy.c \
fem.c \
flash.c \
@@ -97,20 +98,10 @@ SINGLEPHY_CPPFLAGS
-DRAAL_SINGLE_PHY=1 \
$(NULL)
PLATFORM_DIAG_SOURCES = \
diag.c \
$(NULL)
PLATFORM_SOURCES = \
$(PLATFORM_COMMON_SOURCES) \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
PLATFORM_SOURCES += \
$(PLATFORM_DIAG_SOURCES) \
$(NULL)
endif
libopenthread_nrf52811_a_CPPFLAGS = \
$(COMMONCPPFLAGS) \
$(SINGLEPHY_CPPFLAGS) \
@@ -133,7 +124,6 @@ libopenthread_nrf52811_sdk_a_SOURCES
PRETTY_FILES = \
$(PLATFORM_COMMON_SOURCES) \
$(PLATFORM_DIAG_SOURCES) \
$(NULL)
Dash = -
+1 -11
View File
@@ -80,6 +80,7 @@ COMMONCPPFLAGS
PLATFORM_COMMON_SOURCES = \
alarm.c \
diag.c \
entropy.c \
fem.c \
flash.c \
@@ -126,20 +127,10 @@ HWCRYPTO_SOURCES
@top_builddir@/third_party/NordicSemiconductor/libraries/crypto/sha256_alt_cc310.c \
$(NULL)
PLATFORM_DIAG_SOURCES = \
diag.c \
$(NULL)
PLATFORM_SOURCES = \
$(PLATFORM_COMMON_SOURCES) \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
PLATFORM_SOURCES += \
$(PLATFORM_DIAG_SOURCES) \
$(NULL)
endif
libopenthread_nrf52840_a_CPPFLAGS = \
$(COMMONCPPFLAGS) \
$(SINGLEPHY_CPPFLAGS) \
@@ -175,7 +166,6 @@ libopenthread_nrf52840_softdevice_sdk_a_SOURCES
PRETTY_FILES = \
$(PLATFORM_COMMON_SOURCES) \
$(PLATFORM_DIAG_SOURCES) \
$(NULL)
Dash = -
+1 -6
View File
@@ -44,6 +44,7 @@ CLEANFILES =
libopenthread_qpg6095_a_SOURCES = \
alarm.c \
alarm_qorvo.h \
diag.c \
entropy.c \
logging.c \
misc.c \
@@ -64,12 +65,6 @@ libopenthread_qpg6095_a_SOURCES = \
libopenthread_qpg6095_a_LIBADD = \
$(top_builddir)/examples/platforms/utils/libopenthread_platform_utils_a-settings_ram.o
if OPENTHREAD_ENABLE_DIAG
libopenthread_qpg6095_a_SOURCES += \
diag.c \
$(NULL)
endif
if OPENTHREAD_BUILD_COVERAGE
CLEANFILES += $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE
+10 -13
View File
@@ -29,7 +29,7 @@
/**
* @file
* @brief
* This file defines the top-level functions for the OpenThread diagnostics library.
* This file includes the OpenThread API for Factory Diagnostics.
*/
#ifndef OPENTHREAD_DIAG_H_
@@ -51,42 +51,39 @@ extern "C" {
*
*/
/**
* Initialize the diagnostics module.
*
* @param[in] aInstance A pointer to the OpenThread instance.
*
*/
void otDiagInit(otInstance *aInstance);
/**
* This function processes a factory diagnostics command line.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aArgCount The argument counter of diagnostics command line.
* @param[in] aArgVector The argument vector of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
*/
void otDiagProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void otDiagProcessCmd(otInstance *aInstance, int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
/**
* This function processes a factory diagnostics command line.
*
* @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.
*
*/
void otDiagProcessCmdLine(const char *aString, char *aOutput, size_t aOutputMaxLen);
void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen);
/**
* This function indicates whether or not the factory diagnostics mode is enabled.
*
* @returns TRUE if factory diagnostics mode is enabled, FALSE otherwise.
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval TRUE if factory diagnostics mode is enabled
* @retval FALSE if factory diagnostics mode is disabled.
*
*/
bool otDiagIsEnabled(void);
bool otDiagIsEnabled(otInstance *aInstance);
/**
* @}
-6
View File
@@ -34,7 +34,6 @@ DIST_SUBDIRS = \
core \
cli \
ncp \
diag \
posix \
$(NULL)
@@ -52,10 +51,6 @@ if OPENTHREAD_ENABLE_NCP
SUBDIRS += ncp
endif
if OPENTHREAD_ENABLE_DIAG
SUBDIRS += diag
endif
if OPENTHREAD_PLATFORM_POSIX_APP
SUBDIRS += posix
endif
@@ -65,7 +60,6 @@ endif
PRETTY_SUBDIRS = \
cli \
core \
diag \
ncp \
posix \
$(NULL)
+1 -1
View File
@@ -1500,7 +1500,7 @@ Done
### diag
Diagnostics module is enabled only when building OpenThread with --enable-diag option.
Factory Diagnostics module is enabled only when building OpenThread with --enable-diag option.
Go [diagnostics module][1] for more information.
### service
+2 -2
View File
@@ -3413,7 +3413,7 @@ void Interpreter::ProcessDiag(int argc, char *argv[])
// all diagnostics related features are processed within diagnostics module
output[sizeof(output) - 1] = '\0';
otDiagProcessCmd(argc, argv, output, sizeof(output) - 1);
otDiagProcessCmd(mInstance, argc, argv, output, sizeof(output) - 1);
mServer->Output(output, static_cast<uint16_t>(strlen(output)));
}
#endif
@@ -3436,7 +3436,7 @@ void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer)
#if OPENTHREAD_ENABLE_DIAG
VerifyOrExit(
(!otDiagIsEnabled() || (strcmp(cmd, "diag") == 0)),
(!otDiagIsEnabled(mInstance) || (strcmp(cmd, "diag") == 0)),
mServer->OutputFormat("under diagnostics mode, execute 'diag stop' before running any other commands.\r\n"));
#endif
+5
View File
@@ -112,6 +112,7 @@ SOURCES_COMMON = \
api/crypto_api.cpp \
api/dataset_api.cpp \
api/dataset_ftd_api.cpp \
api/diags_api.cpp \
api/dns_api.cpp \
api/entropy_api.cpp \
api/icmp6_api.cpp \
@@ -155,6 +156,7 @@ SOURCES_COMMON = \
crypto/mbedtls.cpp \
crypto/pbkdf2_cmac.cpp \
crypto/sha256.cpp \
diags/factory_diags.cpp \
mac/channel_mask.cpp \
mac/data_poll_handler.cpp \
mac/data_poll_sender.cpp \
@@ -235,6 +237,7 @@ EXTRA_DIST = \
$(NULL)
libopenthread_radio_a_SOURCES = \
api/diags_api.cpp \
api/instance_api.cpp \
api/link_raw_api.cpp \
api/logging_api.cpp \
@@ -246,6 +249,7 @@ libopenthread_radio_a_SOURCES = \
common/string.cpp \
common/tasklet.cpp \
common/timer.cpp \
diags/factory_diags.cpp \
mac/link_raw.cpp \
mac/mac_frame.cpp \
mac/sub_mac.cpp \
@@ -322,6 +326,7 @@ HEADERS_COMMON = \
crypto/mbedtls.hpp \
crypto/pbkdf2_cmac.h \
crypto/sha256.hpp \
diags/factory_diags.hpp \
mac/channel_mask.hpp \
mac/data_poll_handler.hpp \
mac/data_poll_sender.hpp \
+66
View File
@@ -0,0 +1,66 @@
/*
* 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 implements the OpenThread Factory Diagnostics API.
*/
#include "openthread-core-config.h"
#include <openthread/diag.h>
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
using namespace ot;
#if OPENTHREAD_ENABLE_DIAG
void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
{
Instance &instance = *static_cast<Instance *>(aInstance);
instance.Get<FactoryDiags::Diags>().ProcessLine(aString, aOutput, aOutputMaxLen);
}
void otDiagProcessCmd(otInstance *aInstance, int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
Instance &instance = *static_cast<Instance *>(aInstance);
instance.Get<FactoryDiags::Diags>().ProcessCmd(aArgCount, aArgVector, aOutput, aOutputMaxLen);
}
bool otDiagIsEnabled(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<FactoryDiags::Diags>().IsEnabled();
}
#endif // OPENTHREAD_ENABLE_DIAG
-92
View File
@@ -260,98 +260,6 @@ uint16_t otLinkGetShortAddress(otInstance *aInstance)
return static_cast<Instance *>(aInstance)->Get<Mac::LinkRaw>().GetShortAddress();
}
#if OPENTHREAD_ENABLE_DIAG
static otInstance *sDiagInstance;
void otDiagInit(otInstance *aInstance)
{
sDiagInstance = aInstance;
}
void otDiagProcessCmdLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
{
enum
{
kMaxArgs = OPENTHREAD_CONFIG_DIAG_CMD_LINE_ARGS_MAX,
kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE,
};
otError error = OT_ERROR_NONE;
char buffer[kMaxCommandBuffer];
char * argVector[kMaxArgs];
uint8_t argCount = 0;
VerifyOrExit(strnlen(aString, kMaxCommandBuffer) < kMaxCommandBuffer, error = OT_ERROR_NO_BUFS);
strcpy(buffer, aString);
SuccessOrExit(error = Utils::CmdLineParser::ParseCmd(buffer, argCount, argVector, kMaxArgs));
VerifyOrExit(argCount >= 1, error = OT_ERROR_INVALID_ARGS);
if (strcmp(argVector[0], "power") == 0)
{
char * endptr;
int8_t power;
VerifyOrExit(argCount == 2, error = OT_ERROR_INVALID_ARGS);
power = static_cast<int8_t>(strtol(argVector[1], &endptr, 0));
VerifyOrExit(*endptr == '\0', error = OT_ERROR_INVALID_ARGS);
otPlatDiagTxPowerSet(power);
}
else if (strcmp(argVector[0], "channel") == 0)
{
char * endptr;
uint8_t channel;
VerifyOrExit(argCount == 2, error = OT_ERROR_INVALID_ARGS);
channel = static_cast<uint8_t>(strtol(argVector[1], &endptr, 0));
VerifyOrExit(*endptr == '\0', error = OT_ERROR_INVALID_ARGS);
otPlatDiagChannelSet(channel);
}
else if (strcmp(argVector[0], "start") == 0)
{
otPlatDiagModeSet(true);
}
else if (strcmp(argVector[0], "stop") == 0)
{
otPlatDiagModeSet(false);
}
else
{
otPlatDiagProcess(sDiagInstance, argCount, argVector, aOutput, aOutputMaxLen);
}
exit:
switch (error)
{
case OT_ERROR_NONE:
break;
default:
snprintf(aOutput, aOutputMaxLen, "failed: invalid command: %s\r\n", otThreadErrorToString(error));
break;
}
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
{
otPlatDiagAlarmCallback(aInstance);
}
extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
// notify OpenThread Diags module on host side
otPlatRadioTxDone(aInstance, aFrame, NULL, aError);
}
extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
// notify OpenThread Diags module on host side
otPlatRadioReceiveDone(aInstance, aFrame, aError);
}
#endif // OPENTHREAD_ENABLE_DIAG
#endif // OPENTHREAD_RADIO
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
+3
View File
@@ -95,6 +95,9 @@ Instance::Instance(void)
#endif
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
, mExtension(Extension::ExtensionBase::Init(*this))
#endif
#if OPENTHREAD_ENABLE_DIAG
, mDiags(*this)
#endif
, mIsInitialized(false)
{
+11
View File
@@ -44,6 +44,7 @@
#include <openthread/platform/logging.h>
#include "common/random_manager.hpp"
#include "diags/factory_diags.hpp"
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
#include "common/message.hpp"
@@ -368,6 +369,9 @@ private:
#endif
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
Extension::ExtensionBase &mExtension;
#endif
#if OPENTHREAD_ENABLE_DIAG
FactoryDiags::Diags mDiags;
#endif
bool mIsInitialized;
};
@@ -713,6 +717,13 @@ template <> inline Extension::ExtensionBase &Instance::Get(void)
}
#endif
#if OPENTHREAD_ENABLE_DIAG
template <> inline FactoryDiags::Diags &Instance::Get(void)
{
return mDiags;
}
#endif
/**
* @}
*
@@ -1,4 +1,4 @@
# OpenThread Diagnostics Module Reference
# OpenThread Factory Diagnostics Module Reference
The OpenThread diagnostics module is a tool for debugging platform hardware manually, and it will also be used during manufacturing process, to verify platform hardware performance.
+563
View File
@@ -0,0 +1,563 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements the diagnostics module.
*/
#include "factory_diags.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <openthread/instance.h>
#include <openthread/link.h>
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "phy/phy.hpp"
#include "utils/parse_cmdline.hpp"
#include "utils/wrap_string.h"
namespace ot {
namespace FactoryDiags {
#if OPENTHREAD_ENABLE_DIAG
#if OPENTHREAD_RADIO
const struct Diags::Command Diags::sCommands[] = {
{"channel", &Diags::ProcessChannel},
{"power", &Diags::ProcessPower},
{"start", &Diags::ProcessStart},
{"stop", &Diags::ProcessStop},
};
Diags::Diags(otInstance &aInstance)
{
mInstance = &aInstance;
}
void Diags::ProcessChannel(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
long value;
VerifyOrExit(aArgCount == 1, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
VerifyOrExit(value >= Phy::kChannelMin && value <= Phy::kChannelMax, error = OT_ERROR_INVALID_ARGS);
mChannel = static_cast<uint8_t>(value);
otPlatDiagChannelSet(mChannel);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessPower(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
long value;
VerifyOrExit(aArgCount == 1, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
mTxPower = static_cast<int8_t>(value);
otPlatDiagTxPowerSet(mTxPower);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessStart(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
otPlatDiagModeSet(true);
}
void Diags::ProcessStop(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
otPlatDiagModeSet(false);
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
{
otPlatDiagAlarmCallback(aInstance);
}
extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
// notify OpenThread Diags module on host side
otPlatRadioTxDone(aInstance, aFrame, NULL, aError);
}
extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
// notify OpenThread Diags module on host side
otPlatRadioReceiveDone(aInstance, aFrame, aError);
}
#else // OPENTHREAD_RADIO
const struct Diags::Command Diags::sCommands[] = {
{"channel", &Diags::ProcessChannel}, {"power", &Diags::ProcessPower}, {"radio", &Diags::ProcessRadio},
{"repeat", &Diags::ProcessRepeat}, {"send", &Diags::ProcessSend}, {"start", &Diags::ProcessStart},
{"stats", &Diags::ProcessStats}, {"stop", &Diags::ProcessStop},
};
Diags::Diags(otInstance &aInstance)
{
mInstance = &aInstance;
mChannel = 20;
mTxPower = 0;
mTxPeriod = 0;
mTxLen = 0;
mTxPackets = 0;
mRepeatActive = false;
memset(&mStats, 0, sizeof(mStats));
mTxPacket = otPlatRadioGetTransmitBuffer(mInstance);
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);
}
void Diags::ProcessChannel(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "channel: %d\r\n", mChannel);
}
else
{
long value;
SuccessOrExit(error = ParseLong(aArgVector[0], value));
VerifyOrExit(value >= Phy::kChannelMin && value <= Phy::kChannelMax, error = OT_ERROR_INVALID_ARGS);
mChannel = static_cast<uint8_t>(value);
otPlatRadioReceive(mInstance, mChannel);
otPlatDiagChannelSet(mChannel);
snprintf(aOutput, aOutputMaxLen, "set channel to %d\r\nstatus 0x%02x\r\n", mChannel, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessPower(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "tx power: %d dBm\r\n", mTxPower);
}
else
{
long value;
SuccessOrExit(error = ParseLong(aArgVector[0], value));
mTxPower = static_cast<int8_t>(value);
SuccessOrExit(error = otPlatRadioSetTransmitPower(mInstance, mTxPower));
otPlatDiagTxPowerSet(mTxPower);
snprintf(aOutput, aOutputMaxLen, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", mTxPower, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessRepeat(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount > 0, error = OT_ERROR_INVALID_ARGS);
if (strcmp(aArgVector[0], "stop") == 0)
{
otPlatAlarmMilliStop(mInstance);
mRepeatActive = false;
snprintf(aOutput, aOutputMaxLen, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
}
else
{
long value;
VerifyOrExit(aArgCount == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
mTxPeriod = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgVector[1], value));
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
mTxLen = static_cast<uint8_t>(value);
mRepeatActive = true;
uint32_t now = otPlatAlarmMilliGetNow();
otPlatAlarmMilliStartAt(mInstance, 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);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessSend(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
long value;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
mTxPackets = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgVector[1], value));
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
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);
TransmitPacket();
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessStart(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
otError error = OT_ERROR_NONE;
otPlatRadioEnable(mInstance);
otPlatRadioSetPromiscuous(mInstance, true);
otPlatAlarmMilliStop(mInstance);
SuccessOrExit(error = otPlatRadioReceive(mInstance, mChannel));
SuccessOrExit(error = otPlatRadioSetTransmitPower(mInstance, mTxPower));
otPlatDiagModeSet(true);
memset(&mStats, 0, sizeof(mStats));
snprintf(aOutput, aOutputMaxLen, "start diagnostics mode\r\nstatus 0x%02x\r\n", error);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessStats(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if ((aArgCount == 1) && (strcmp(aArgVector[0], "clear") == 0))
{
memset(&mStats, 0, sizeof(mStats));
snprintf(aOutput, aOutputMaxLen, "stats cleared\r\n");
}
else
{
VerifyOrExit(aArgCount == 0, error = OT_ERROR_INVALID_ARGS);
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));
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::ProcessStop(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
otPlatAlarmMilliStop(mInstance);
otPlatDiagModeSet(false);
otPlatRadioSetPromiscuous(mInstance, 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);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diags::TransmitPacket(void)
{
mTxPacket->mLength = mTxLen;
mTxPacket->mChannel = mChannel;
for (uint8_t i = 0; i < mTxLen; i++)
{
mTxPacket->mPsdu[i] = i;
}
otPlatRadioTransmit(mInstance, mTxPacket);
}
void Diags::ProcessRadio(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_INVALID_ARGS;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount > 0, error = OT_ERROR_INVALID_ARGS);
if (strcmp(aArgVector[0], "sleep") == 0)
{
SuccessOrExit(error = otPlatRadioSleep(mInstance));
snprintf(aOutput, aOutputMaxLen, "set radio from receive to sleep \r\nstatus 0x%02x\r\n", error);
}
else if (strcmp(aArgVector[0], "receive") == 0)
{
SuccessOrExit(error = otPlatRadioReceive(mInstance, mChannel));
SuccessOrExit(error = otPlatRadioSetTransmitPower(mInstance, mTxPower));
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);
snprintf(aOutput, aOutputMaxLen, "set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel,
error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
{
Instance *instance = static_cast<Instance *>(aInstance);
instance->Get<Diags>().AlarmFired();
}
void Diags::AlarmFired(void)
{
if (mRepeatActive)
{
uint32_t now = otPlatAlarmMilliGetNow();
TransmitPacket();
otPlatAlarmMilliStartAt(mInstance, now, mTxPeriod);
}
else
{
otPlatDiagAlarmCallback(mInstance);
}
}
extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
Instance *instance = static_cast<Instance *>(aInstance);
instance->Get<Diags>().ReceiveDone(aFrame, aError);
}
void Diags::ReceiveDone(otRadioFrame *aFrame, otError aError)
{
if (aError == OT_ERROR_NONE)
{
// for sensitivity test, only record the rssi and lqi for the first and last packet
if (mStats.mReceivedPackets == 0)
{
mStats.mFirstRssi = aFrame->mInfo.mRxInfo.mRssi;
mStats.mFirstLqi = aFrame->mInfo.mRxInfo.mLqi;
}
mStats.mLastRssi = aFrame->mInfo.mRxInfo.mRssi;
mStats.mLastLqi = aFrame->mInfo.mRxInfo.mLqi;
mStats.mReceivedPackets++;
}
otPlatDiagRadioReceived(mInstance, aFrame, aError);
}
extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
OT_UNUSED_VARIABLE(aFrame);
Instance *instance = static_cast<Instance *>(aInstance);
instance->Get<Diags>().TransmitDone(aError);
}
void Diags::TransmitDone(otError aError)
{
if (aError == OT_ERROR_NONE)
{
mStats.mSentPackets++;
if (mTxPackets > 1)
{
mTxPackets--;
TransmitPacket();
}
}
else
{
TransmitPacket();
}
}
#endif // OPENTHREAD_RADIO
void Diags::AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen)
{
if (aError != OT_ERROR_NONE)
{
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
}
}
otError Diags::ParseLong(char *aString, long &aLong)
{
char *endptr;
aLong = strtol(aString, &endptr, 0);
return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE;
}
void Diags::ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
{
enum
{
kMaxArgs = OPENTHREAD_CONFIG_DIAG_CMD_LINE_ARGS_MAX,
kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE,
};
otError error = OT_ERROR_NONE;
char buffer[kMaxCommandBuffer];
char * argVector[kMaxArgs];
uint8_t argCount = 0;
VerifyOrExit(strnlen(aString, kMaxCommandBuffer) < kMaxCommandBuffer, error = OT_ERROR_NO_BUFS);
strcpy(buffer, aString);
error = ot::Utils::CmdLineParser::ParseCmd(buffer, argCount, argVector, kMaxArgs);
exit:
switch (error)
{
case OT_ERROR_NONE:
if (argCount >= 1)
{
ProcessCmd(argCount - 1, (argCount == 1) ? NULL : &argVector[1], aOutput, aOutputMaxLen);
}
else
{
ProcessCmd(0, NULL, aOutput, aOutputMaxLen);
}
break;
case OT_ERROR_NO_BUFS:
snprintf(aOutput, aOutputMaxLen, "failed: command string too long\r\n");
break;
case OT_ERROR_INVALID_ARGS:
snprintf(aOutput, aOutputMaxLen, "failed: command string contains too many arguments\r\n");
break;
default:
snprintf(aOutput, aOutputMaxLen, "failed to parse command string\r\n");
break;
}
}
void Diags::ProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "diagnostics mode is %s\r\n", otPlatDiagModeGet() ? "enabled" : "disabled");
ExitNow();
}
for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
{
if (strcmp(aArgVector[0], sCommands[i].mName) == 0)
{
(this->*sCommands[i].mCommand)(aArgCount - 1, (aArgCount > 1) ? &aArgVector[1] : NULL, aOutput,
aOutputMaxLen);
ExitNow();
}
}
// more platform specific features will be processed under platform layer
otPlatDiagProcess(mInstance, aArgCount, aArgVector, aOutput, aOutputMaxLen);
exit:
return;
}
bool Diags::IsEnabled(void)
{
return otPlatDiagModeGet();
}
#endif // OPENTHREAD_ENABLE_DIAG
} // namespace FactoryDiags
} // namespace ot
+170
View File
@@ -0,0 +1,170 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file contains definitions for the diagnostics module.
*/
#ifndef FACTORY_DIAGS_HPP_
#define FACTORY_DIAGS_HPP_
#include "openthread-core-config.h"
#include <stdarg.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
namespace ot {
namespace FactoryDiags {
#if OPENTHREAD_ENABLE_DIAG
class Diags
{
public:
/**
* Constructor.
*
* @param[in] aInstance The OpenThread instance.
*
*/
explicit Diags(otInstance &aInstance);
/**
* This function processes a factory diagnostics command line.
*
* @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.
*
*/
void ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen);
/**
* This function processes a factory diagnostics command line.
*
* @param[in] aArgCount The argument counter of diagnostics command line.
* @param[in] aArgVector The argument vector of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
*/
void ProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
/**
* This function indicates whether or not the factory diagnostics mode is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval TRUE if factory diagnostics mode is enabled
* @retval FALSE if factory diagnostics mode is disabled.
*
*/
bool IsEnabled(void);
/**
* The platform driver calls this method to notify OpenThread diagnostics module that the alarm has fired.
*
*/
void AlarmFired(void);
/**
* The radio driver calls this method to notify OpenThread diagnostics module of a received frame.
*
* @param[in] aFrame A pointer to the received frame or NULL if the receive operation failed.
* @param[in] aError OT_ERROR_NONE when successfully received a frame,
* OT_ERROR_ABORT when reception was aborted and a frame was not received,
* OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
*
*/
void ReceiveDone(otRadioFrame *aFrame, otError aError);
/**
* The radio driver calls this method to notify OpenThread diagnostics module that the transmission has completed.
*
* @param[in] aError OT_ERROR_NONE when the frame was transmitted,
* OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on channel,
* OT_ERROR_ABORT when transmission was aborted for other reasons.
*
*/
void TransmitDone(otError aError);
private:
struct Command
{
const char *mName;
void (Diags::*mCommand)(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
};
struct Stats
{
uint32_t mReceivedPackets;
uint32_t mSentPackets;
int8_t mFirstRssi;
uint8_t mFirstLqi;
int8_t mLastRssi;
uint8_t mLastLqi;
};
void ProcessChannel(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessPower(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessRadio(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessRepeat(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessSend(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessStart(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessStats(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void ProcessStop(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
void TransmitPacket(void);
static void AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen);
static otError ParseLong(char *aString, long &aLong);
static const struct Command sCommands[];
struct Stats mStats;
int8_t mTxPower;
uint8_t mChannel;
uint8_t mTxLen;
uint32_t mTxPeriod;
uint32_t mTxPackets;
otRadioFrame *mTxPacket;
otInstance * mInstance;
bool mRepeatActive;
};
#endif // #if OPENTHREAD_ENABLE_DIAG
} // namespace FactoryDiags
} // namespace ot
#endif // FACTORY_DIAGS_HPP_
-53
View File
@@ -1,53 +0,0 @@
#
# 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.
#
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
lib_LIBRARIES = libopenthread-diag.a
libopenthread_diag_a_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
$(OPENTHREAD_TARGET_DEFINES) \
$(NULL)
libopenthread_diag_a_SOURCES = \
openthread-diag.cpp \
diag_process.cpp \
$(NULL)
noinst_HEADERS = \
diag_process.hpp \
$(NULL)
if OPENTHREAD_BUILD_COVERAGE
CLEANFILES = $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
-438
View File
@@ -1,438 +0,0 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements the diagnostics module.
*/
#include "diag_process.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <openthread/instance.h>
#include <openthread/link.h>
#include "common/code_utils.hpp"
#include "phy/phy.hpp"
#include "utils/wrap_string.h"
namespace ot {
namespace Diagnostics {
const struct Diag::Command Diag::sCommands[] = {
{"start", &ProcessStart}, {"stop", &ProcessStop}, {"channel", &ProcessChannel}, {"power", &ProcessPower},
{"send", &ProcessSend}, {"repeat", &ProcessRepeat}, {"stats", &ProcessStats}, {"radio", &ProcessRadio},
};
struct Diag::DiagStats Diag::sStats;
int8_t Diag::sTxPower;
uint8_t Diag::sChannel;
uint8_t Diag::sTxLen;
uint32_t Diag::sTxPeriod;
uint32_t Diag::sTxPackets;
otRadioFrame *Diag::sTxPacket;
bool Diag::sRepeatActive;
otInstance * Diag::sInstance;
void Diag::Init(otInstance *aInstance)
{
sInstance = aInstance;
sChannel = 20;
sTxPower = 0;
sTxPeriod = 0;
sTxLen = 0;
sTxPackets = 0;
sRepeatActive = false;
memset(&sStats, 0, sizeof(struct DiagStats));
sTxPacket = otPlatRadioGetTransmitBuffer(sInstance);
otPlatDiagChannelSet(sChannel);
otPlatDiagTxPowerSet(sTxPower);
}
void Diag::ProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "diagnostics mode is %s\r\n", otPlatDiagModeGet() ? "enabled" : "disabled");
ExitNow();
}
for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
{
if (strcmp(aArgVector[0], sCommands[i].mName) == 0)
{
sCommands[i].mHandler(aArgCount - 1, (aArgCount > 1) ? &aArgVector[1] : NULL, aOutput, aOutputMaxLen);
ExitNow();
}
}
// more platform specific features will be processed under platform layer
otPlatDiagProcess(sInstance, aArgCount, aArgVector, aOutput, aOutputMaxLen);
exit:
return;
}
bool Diag::IsEnabled(void)
{
return otPlatDiagModeGet();
}
void Diag::AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen)
{
if (aError != OT_ERROR_NONE)
{
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
}
}
void Diag::ProcessStart(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
otError error = OT_ERROR_NONE;
otPlatRadioEnable(sInstance);
otPlatRadioSetPromiscuous(sInstance, true);
otPlatAlarmMilliStop(sInstance);
SuccessOrExit(error = otPlatRadioReceive(sInstance, sChannel));
SuccessOrExit(error = otPlatRadioSetTransmitPower(sInstance, sTxPower));
otPlatDiagModeSet(true);
memset(&sStats, 0, sizeof(struct DiagStats));
snprintf(aOutput, aOutputMaxLen, "start diagnostics mode\r\nstatus 0x%02x\r\n", error);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessStop(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
otPlatAlarmMilliStop(sInstance);
otPlatDiagModeSet(false);
otPlatRadioSetPromiscuous(sInstance, 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>(sStats.mReceivedPackets), static_cast<int>(sStats.mSentPackets),
static_cast<int>(sStats.mFirstRssi), static_cast<int>(sStats.mFirstLqi),
static_cast<int>(sStats.mLastRssi), static_cast<int>(sStats.mLastLqi), error);
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
otError Diag::ParseLong(char *aString, long &aLong)
{
char *endptr;
aLong = strtol(aString, &endptr, 0);
return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE;
}
void Diag::TxPacket(void)
{
sTxPacket->mLength = sTxLen;
sTxPacket->mChannel = sChannel;
for (uint8_t i = 0; i < sTxLen; i++)
{
sTxPacket->mPsdu[i] = i;
}
otPlatRadioTransmit(sInstance, sTxPacket);
}
void Diag::ProcessChannel(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "channel: %d\r\n", sChannel);
}
else
{
long value;
SuccessOrExit(error = ParseLong(aArgVector[0], value));
VerifyOrExit(value >= Phy::kChannelMin && value <= Phy::kChannelMax, error = OT_ERROR_INVALID_ARGS);
sChannel = static_cast<uint8_t>(value);
otPlatRadioReceive(sInstance, sChannel);
otPlatDiagChannelSet(sChannel);
snprintf(aOutput, aOutputMaxLen, "set channel to %d\r\nstatus 0x%02x\r\n", sChannel, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessPower(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if (aArgCount == 0)
{
snprintf(aOutput, aOutputMaxLen, "tx power: %d dBm\r\n", sTxPower);
}
else
{
long value;
SuccessOrExit(error = ParseLong(aArgVector[0], value));
sTxPower = static_cast<int8_t>(value);
SuccessOrExit(error = otPlatRadioSetTransmitPower(sInstance, sTxPower));
otPlatDiagTxPowerSet(sTxPower);
snprintf(aOutput, aOutputMaxLen, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", sTxPower, error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessSend(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
long value;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
sTxPackets = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgVector[1], value));
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
sTxLen = static_cast<uint8_t>(value);
snprintf(aOutput, aOutputMaxLen, "sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n",
static_cast<int>(sTxPackets), static_cast<int>(sTxLen), error);
TxPacket();
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessRepeat(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount > 0, error = OT_ERROR_INVALID_ARGS);
if (strcmp(aArgVector[0], "stop") == 0)
{
otPlatAlarmMilliStop(sInstance);
sRepeatActive = false;
snprintf(aOutput, aOutputMaxLen, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
}
else
{
long value;
VerifyOrExit(aArgCount == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseLong(aArgVector[0], value));
sTxPeriod = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgVector[1], value));
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
sTxLen = static_cast<uint8_t>(value);
sRepeatActive = true;
uint32_t now = otPlatAlarmMilliGetNow();
otPlatAlarmMilliStartAt(sInstance, now, sTxPeriod);
snprintf(aOutput, aOutputMaxLen, "sending packets of length %#x at the delay of %#x ms\r\nstatus 0x%02x\r\n",
static_cast<int>(sTxLen), static_cast<int>(sTxPeriod), error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessStats(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
if ((aArgCount == 1) && (strcmp(aArgVector[0], "clear") == 0))
{
memset(&sStats, 0, sizeof(struct DiagStats));
snprintf(aOutput, aOutputMaxLen, "stats cleared\r\n");
}
else
{
VerifyOrExit(aArgCount == 0, error = OT_ERROR_INVALID_ARGS);
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>(sStats.mReceivedPackets), static_cast<int>(sStats.mSentPackets),
static_cast<int>(sStats.mFirstRssi), static_cast<int>(sStats.mFirstLqi),
static_cast<int>(sStats.mLastRssi), static_cast<int>(sStats.mLastLqi));
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::ProcessRadio(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
otError error = OT_ERROR_INVALID_ARGS;
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aArgCount > 0, error = OT_ERROR_INVALID_ARGS);
if (strcmp(aArgVector[0], "sleep") == 0)
{
SuccessOrExit(error = otPlatRadioSleep(sInstance));
snprintf(aOutput, aOutputMaxLen, "set radio from receive to sleep \r\nstatus 0x%02x\r\n", error);
}
else if (strcmp(aArgVector[0], "receive") == 0)
{
SuccessOrExit(error = otPlatRadioReceive(sInstance, sChannel));
SuccessOrExit(error = otPlatRadioSetTransmitPower(sInstance, sTxPower));
otPlatDiagChannelSet(sChannel);
otPlatDiagTxPowerSet(sTxPower);
snprintf(aOutput, aOutputMaxLen, "set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", sChannel,
error);
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
}
void Diag::DiagTransmitDone(otInstance *aInstance, otError aError)
{
VerifyOrExit(aInstance == sInstance);
if (aError == OT_ERROR_NONE)
{
sStats.mSentPackets++;
if (sTxPackets > 1)
{
sTxPackets--;
TxPacket();
}
}
else
{
TxPacket();
}
exit:
return;
}
void Diag::DiagReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
VerifyOrExit(aInstance == sInstance);
if (aError == OT_ERROR_NONE)
{
// for sensitivity test, only record the rssi and lqi for the first and last packet
if (sStats.mReceivedPackets == 0)
{
sStats.mFirstRssi = aFrame->mInfo.mRxInfo.mRssi;
sStats.mFirstLqi = aFrame->mInfo.mRxInfo.mLqi;
}
sStats.mLastRssi = aFrame->mInfo.mRxInfo.mRssi;
sStats.mLastLqi = aFrame->mInfo.mRxInfo.mLqi;
sStats.mReceivedPackets++;
}
otPlatDiagRadioReceived(aInstance, aFrame, aError);
exit:
return;
}
void Diag::AlarmFired(otInstance *aInstance)
{
VerifyOrExit(aInstance == sInstance);
if (sRepeatActive)
{
uint32_t now = otPlatAlarmMilliGetNow();
TxPacket();
otPlatAlarmMilliStartAt(aInstance, now, sTxPeriod);
}
else
{
otPlatDiagAlarmCallback(aInstance);
}
exit:
return;
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
{
Diag::AlarmFired(aInstance);
}
extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
OT_UNUSED_VARIABLE(aFrame);
Diag::DiagTransmitDone(aInstance, aError);
}
extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
Diag::DiagReceiveDone(aInstance, aFrame, aError);
}
} // namespace Diagnostics
} // namespace ot
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file contains definitions for the diagnostics module.
*/
#ifndef DIAG_PROCESS_HPP_
#define DIAG_PROCESS_HPP_
#include "openthread-core-config.h"
#include <stdarg.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
namespace ot {
namespace Diagnostics {
class Diag
{
public:
static void Init(otInstance *aInstance);
static void ProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static bool IsEnabled(void);
static void DiagTransmitDone(otInstance *aInstance, otError aError);
static void DiagReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
static void AlarmFired(otInstance *aInstance);
private:
struct DiagStats
{
uint32_t mReceivedPackets;
uint32_t mSentPackets;
int8_t mFirstRssi;
uint8_t mFirstLqi;
int8_t mLastRssi;
uint8_t mLastLqi;
};
struct Command
{
const char *mName;
void (*mHandler)(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
};
static void AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen);
static void ProcessStart(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessStop(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessSend(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessRepeat(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessStats(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessRadio(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessChannel(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void ProcessPower(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen);
static void TxPacket(void);
static otError ParseLong(char *aString, long &aLong);
static const struct Command sCommands[];
static struct DiagStats sStats;
static int8_t sTxPower;
static uint8_t sChannel;
static uint8_t sTxLen;
static uint32_t sTxPeriod;
static uint32_t sTxPackets;
static otRadioFrame *sTxPacket;
static otInstance * sInstance;
static bool sRepeatActive;
};
} // namespace Diagnostics
} // namespace ot
#endif // CLI_HPP_
-110
View File
@@ -1,110 +0,0 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements the top-level interface to diagnostics module.
*/
#include "openthread-core-config.h"
#include <stdio.h>
#include <stdlib.h>
#include "utils/parse_cmdline.hpp"
#include "utils/wrap_string.h"
#include <openthread/diag.h>
#include "diag_process.hpp"
#include "common/code_utils.hpp"
using namespace ot::Diagnostics;
void otDiagInit(otInstance *aInstance)
{
Diag::Init(aInstance);
}
void otDiagProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
Diag::ProcessCmd(aArgCount, aArgVector, aOutput, aOutputMaxLen);
}
void otDiagProcessCmdLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
{
enum
{
kMaxArgs = OPENTHREAD_CONFIG_DIAG_CMD_LINE_ARGS_MAX,
kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE,
};
otError error = OT_ERROR_NONE;
char buffer[kMaxCommandBuffer];
char * argVector[kMaxArgs];
uint8_t argCount = 0;
VerifyOrExit(strnlen(aString, kMaxCommandBuffer) < kMaxCommandBuffer, error = OT_ERROR_NO_BUFS);
strcpy(buffer, aString);
error = ot::Utils::CmdLineParser::ParseCmd(buffer, argCount, argVector, kMaxArgs);
exit:
switch (error)
{
case OT_ERROR_NONE:
if (argCount >= 1)
{
Diag::ProcessCmd(argCount - 1, (argCount == 1) ? NULL : &argVector[1], aOutput, aOutputMaxLen);
}
else
{
Diag::ProcessCmd(0, NULL, aOutput, aOutputMaxLen);
}
break;
case OT_ERROR_NO_BUFS:
snprintf(aOutput, aOutputMaxLen, "failed: command string too long\r\n");
break;
case OT_ERROR_INVALID_ARGS:
snprintf(aOutput, aOutputMaxLen, "failed: command string contains too many arguments\r\n");
break;
default:
snprintf(aOutput, aOutputMaxLen, "failed to parse command string\r\n");
break;
}
}
bool otDiagIsEnabled(void)
{
return Diag::IsEnabled();
}
+1 -1
View File
@@ -1286,7 +1286,7 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader)
VerifyOrExit(error == OT_ERROR_NONE, error = WriteLastStatusFrame(aHeader, ThreadErrorToSpinelStatus(error)));
output[sizeof(output) - 1] = '\0';
otDiagProcessCmdLine(string, output, sizeof(output) - 1);
otDiagProcessCmdLine(mInstance, string, output, sizeof(output) - 1);
// Prepare the response
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
-6
View File
@@ -67,12 +67,6 @@ LDADD_COMMON += \
$(NULL)
endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
if OPENTHREAD_ENABLE_DIAG
LDADD_COMMON += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif # OPENTHREAD_ENABLE_DIAG
bin_PROGRAMS = \
$(NULL)
-4
View File
@@ -102,10 +102,6 @@ int main(int argc, char *argv[])
#endif
#endif
#if OPENTHREAD_ENABLE_DIAG
otDiagInit(instance);
#endif
while (true)
{
otSysMainloopContext mainloop;
+48 -3
View File
@@ -132,21 +132,25 @@ void otPlatAlarmMicroStop(otInstance *aInstance)
sAlarmMicro.isRunning = false;
}
bool otDiagIsEnabled(void)
bool otDiagIsEnabled(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return false;
}
void otDiagProcessCmd(int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
void otDiagProcessCmd(otInstance *aInstance, int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aArgCount);
OT_UNUSED_VARIABLE(aArgVector);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
}
void otDiagProcessCmdLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aString);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
@@ -415,3 +419,44 @@ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
OT_UNUSED_VARIABLE(aBufLength);
return OT_ERROR_NONE;
}
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(argc);
OT_UNUSED_VARIABLE(argv);
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
}
void otPlatDiagModeSet(bool aMode)
{
OT_UNUSED_VARIABLE(aMode);
}
bool otPlatDiagModeGet(void)
{
return false;
}
void otPlatDiagChannelSet(uint8_t aChannel)
{
OT_UNUSED_VARIABLE(aChannel);
}
void otPlatDiagTxPowerSet(int8_t aTxPower)
{
OT_UNUSED_VARIABLE(aTxPower);
}
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aFrame);
OT_UNUSED_VARIABLE(aError);
}
void otPlatDiagAlarmCallback(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
}
+1 -6
View File
@@ -165,6 +165,7 @@ check_SCRIPTS = \
test_coaps.py \
test_common.py \
test_crypto.py \
test_diag.py \
test_ipv6.py \
test_lowpan.py \
test_mac802154.py \
@@ -266,12 +267,6 @@ check_SCRIPTS = \
Cert_9_2_18_RollBackActiveTimestamp.py \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
check_SCRIPTS += \
test_diag.py \
$(NULL)
endif
TESTS_ENVIRONMENT = \
export \
top_builddir='$(top_builddir)' \
+10 -4
View File
@@ -417,9 +417,11 @@ exit:
// Diag
//
void otPlatDiagProcess(int argc, char *argv[], char *aOutput)
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(argc);
OT_UNUSED_VARIABLE(aOutputMaxLen);
// no more diagnostics features for Posix platform
sprintf(aOutput, "diag feature '%s' is not supported\r\n", argv[0]);
@@ -435,15 +437,19 @@ bool otPlatDiagModeGet()
return sDiagMode;
}
void otPlatDiagAlarmFired(otInstance *)
void otPlatDiagChannelSet(uint8_t)
{
}
void otPlatDiagRadioTransmitDone(otInstance *, otRadioFrame *, otError)
void otPlatDiagTxPowerSet(int8_t)
{
}
void otPlatDiagRadioReceiveDone(otInstance *, otRadioFrame *, otError)
void otPlatDiagRadioReceived(otInstance *, otRadioFrame *, otError)
{
}
void otPlatDiagAlarmCallback(otInstance *)
{
}