mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 07:07:47 +00:00
[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:
+2
-2
@@ -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
@@ -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}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -104,10 +104,6 @@ pseudo_reset:
|
||||
|
||||
otCliUartInit(instance);
|
||||
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
otDiagInit(instance);
|
||||
#endif
|
||||
|
||||
while (!otSysPseudoResetWasRequested())
|
||||
{
|
||||
otTaskletsProcess(instance);
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = -
|
||||
|
||||
|
||||
@@ -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 = -
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -102,10 +102,6 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
otDiagInit(instance);
|
||||
#endif
|
||||
|
||||
while (true)
|
||||
{
|
||||
otSysMainloopContext mainloop;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)' \
|
||||
|
||||
@@ -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 *)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user