diff --git a/Android.mk b/Android.mk index df86c4238..480e6a602 100644 --- a/Android.mk +++ b/Android.mk @@ -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 \ diff --git a/configure.ac b/configure.ac index 5dbaf388d..a30c51ac6 100644 --- a/configure.ac +++ b/configure.ac @@ -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} diff --git a/examples/apps/cli/Makefile.am b/examples/apps/cli/Makefile.am index 9fbd003ae..28282e64e 100644 --- a/examples/apps/cli/Makefile.am +++ b/examples/apps/cli/Makefile.am @@ -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 \ diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c index f9ad5d9f6..312082c97 100644 --- a/examples/apps/cli/main.c +++ b/examples/apps/cli/main.c @@ -104,10 +104,6 @@ pseudo_reset: otCliUartInit(instance); -#if OPENTHREAD_ENABLE_DIAG - otDiagInit(instance); -#endif - while (!otSysPseudoResetWasRequested()) { otTaskletsProcess(instance); diff --git a/examples/apps/ncp/Makefile.am b/examples/apps/ncp/Makefile.am index 870dafe93..4881d06cf 100644 --- a/examples/apps/ncp/Makefile.am +++ b/examples/apps/ncp/Makefile.am @@ -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) \ diff --git a/examples/apps/ncp/main.c b/examples/apps/ncp/main.c index c51d4a0f7..b71aa49fa 100644 --- a/examples/apps/ncp/main.c +++ b/examples/apps/ncp/main.c @@ -103,10 +103,6 @@ pseudo_reset: otNcpInit(instance); -#if OPENTHREAD_ENABLE_DIAG - otDiagInit(instance); -#endif - while (!otSysPseudoResetWasRequested()) { otTaskletsProcess(instance); diff --git a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/Makefile.am b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/Makefile.am index a3f26c842..0fe2690ce 100644 --- a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/Makefile.am +++ b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/Makefile.am @@ -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 \ diff --git a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/main.c b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/main.c index 24aba9bc8..e7a792fed 100644 --- a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/main.c +++ b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/main.c @@ -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); diff --git a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/Makefile.am b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/Makefile.am index 2b976b861..c9f932587 100644 --- a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/Makefile.am +++ b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/Makefile.am @@ -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 \ diff --git a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/main.c b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/main.c index ab406fe59..f5d2378f3 100644 --- a/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/main.c +++ b/examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-mtd/main.c @@ -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); diff --git a/examples/platforms/nrf52811/Makefile.am b/examples/platforms/nrf52811/Makefile.am index aa04a067a..543db893e 100644 --- a/examples/platforms/nrf52811/Makefile.am +++ b/examples/platforms/nrf52811/Makefile.am @@ -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 = - diff --git a/examples/platforms/nrf52840/Makefile.am b/examples/platforms/nrf52840/Makefile.am index 078ec5a44..49dcbed5b 100644 --- a/examples/platforms/nrf52840/Makefile.am +++ b/examples/platforms/nrf52840/Makefile.am @@ -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 = - diff --git a/examples/platforms/qpg6095/Makefile.am b/examples/platforms/qpg6095/Makefile.am index ab114adbe..3b24ccafa 100644 --- a/examples/platforms/qpg6095/Makefile.am +++ b/examples/platforms/qpg6095/Makefile.am @@ -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 diff --git a/include/openthread/diag.h b/include/openthread/diag.h index 35ecc765e..f43d05078 100644 --- a/include/openthread/diag.h +++ b/include/openthread/diag.h @@ -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); /** * @} diff --git a/src/Makefile.am b/src/Makefile.am index 449b4f370..9107ec9b8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/cli/README.md b/src/cli/README.md index 186f30a3d..bf67225b7 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -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 diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 15da7d333..7ba0319a1 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -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(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 diff --git a/src/core/Makefile.am b/src/core/Makefile.am index c7bf08f8f..a37ad3fb2 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -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 \ diff --git a/src/core/api/diags_api.cpp b/src/core/api/diags_api.cpp new file mode 100644 index 000000000..280762eca --- /dev/null +++ b/src/core/api/diags_api.cpp @@ -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 + +#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(aInstance); + + instance.Get().ProcessLine(aString, aOutput, aOutputMaxLen); +} + +void otDiagProcessCmd(otInstance *aInstance, int aArgCount, char *aArgVector[], char *aOutput, size_t aOutputMaxLen) +{ + Instance &instance = *static_cast(aInstance); + + instance.Get().ProcessCmd(aArgCount, aArgVector, aOutput, aOutputMaxLen); +} + +bool otDiagIsEnabled(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().IsEnabled(); +} + +#endif // OPENTHREAD_ENABLE_DIAG diff --git a/src/core/api/link_raw_api.cpp b/src/core/api/link_raw_api.cpp index eacd2a091..504683586 100644 --- a/src/core/api/link_raw_api.cpp +++ b/src/core/api/link_raw_api.cpp @@ -260,98 +260,6 @@ uint16_t otLinkGetShortAddress(otInstance *aInstance) return static_cast(aInstance)->Get().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(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(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 diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index 13c5282e4..bccc8035e 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -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) { diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index 0d84d5a5d..f481c1b2a 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -44,6 +44,7 @@ #include #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 + /** * @} * diff --git a/src/diag/README.md b/src/core/diags/README.md similarity index 98% rename from src/diag/README.md rename to src/core/diags/README.md index 3e39f6250..084d45f15 100644 --- a/src/diag/README.md +++ b/src/core/diags/README.md @@ -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. diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp new file mode 100644 index 000000000..b7e8edcc5 --- /dev/null +++ b/src/core/diags/factory_diags.cpp @@ -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 +#include + +#include +#include + +#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(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(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(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(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(value); + + SuccessOrExit(error = ParseLong(aArgVector[1], value)); + VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); + mTxLen = static_cast(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(mTxLen), static_cast(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(value); + + SuccessOrExit(error = ParseLong(aArgVector[1], value)); + VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); + mTxLen = static_cast(value); + + snprintf(aOutput, aOutputMaxLen, "sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n", + static_cast(mTxPackets), static_cast(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(mStats.mReceivedPackets), static_cast(mStats.mSentPackets), + static_cast(mStats.mFirstRssi), static_cast(mStats.mFirstLqi), + static_cast(mStats.mLastRssi), static_cast(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(mStats.mReceivedPackets), static_cast(mStats.mSentPackets), + static_cast(mStats.mFirstRssi), static_cast(mStats.mFirstLqi), + static_cast(mStats.mLastRssi), static_cast(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(aInstance); + + instance->Get().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(aInstance); + + instance->Get().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(aInstance); + + instance->Get().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 diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp new file mode 100644 index 000000000..6fe0b9d48 --- /dev/null +++ b/src/core/diags/factory_diags.hpp @@ -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 + +#include +#include +#include + +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_ diff --git a/src/diag/Makefile.am b/src/diag/Makefile.am deleted file mode 100644 index 78717e80d..000000000 --- a/src/diag/Makefile.am +++ /dev/null @@ -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 diff --git a/src/diag/diag_process.cpp b/src/diag/diag_process.cpp deleted file mode 100644 index 5d3865590..000000000 --- a/src/diag/diag_process.cpp +++ /dev/null @@ -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 -#include - -#include -#include - -#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(sStats.mReceivedPackets), static_cast(sStats.mSentPackets), - static_cast(sStats.mFirstRssi), static_cast(sStats.mFirstLqi), - static_cast(sStats.mLastRssi), static_cast(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(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(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(value); - - SuccessOrExit(error = ParseLong(aArgVector[1], value)); - VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); - sTxLen = static_cast(value); - - snprintf(aOutput, aOutputMaxLen, "sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n", - static_cast(sTxPackets), static_cast(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(value); - - SuccessOrExit(error = ParseLong(aArgVector[1], value)); - VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); - sTxLen = static_cast(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(sTxLen), static_cast(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(sStats.mReceivedPackets), static_cast(sStats.mSentPackets), - static_cast(sStats.mFirstRssi), static_cast(sStats.mFirstLqi), - static_cast(sStats.mLastRssi), static_cast(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 diff --git a/src/diag/diag_process.hpp b/src/diag/diag_process.hpp deleted file mode 100644 index 83a7c1439..000000000 --- a/src/diag/diag_process.hpp +++ /dev/null @@ -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 - -#include -#include -#include - -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_ diff --git a/src/diag/openthread-diag.cpp b/src/diag/openthread-diag.cpp deleted file mode 100644 index 93397d7fc..000000000 --- a/src/diag/openthread-diag.cpp +++ /dev/null @@ -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 -#include -#include "utils/parse_cmdline.hpp" -#include "utils/wrap_string.h" - -#include - -#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(); -} diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index d45646727..ccf4982c9 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -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)); diff --git a/src/posix/Makefile.am b/src/posix/Makefile.am index b4e4009e4..49f6055f7 100644 --- a/src/posix/Makefile.am +++ b/src/posix/Makefile.am @@ -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) diff --git a/src/posix/main.c b/src/posix/main.c index b18c14ecb..18ca721ae 100644 --- a/src/posix/main.c +++ b/src/posix/main.c @@ -102,10 +102,6 @@ int main(int argc, char *argv[]) #endif #endif -#if OPENTHREAD_ENABLE_DIAG - otDiagInit(instance); -#endif - while (true) { otSysMainloopContext mainloop; diff --git a/tests/fuzz/fuzzer_platform.c b/tests/fuzz/fuzzer_platform.c index 2c730bef8..480e0f595 100644 --- a/tests/fuzz/fuzzer_platform.c +++ b/tests/fuzz/fuzzer_platform.c @@ -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); +} diff --git a/tests/scripts/thread-cert/Makefile.am b/tests/scripts/thread-cert/Makefile.am index 51e8ac269..c81963420 100644 --- a/tests/scripts/thread-cert/Makefile.am +++ b/tests/scripts/thread-cert/Makefile.am @@ -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)' \ diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index 07085d10a..5e700ead6 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -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 *) { }