Add diagnostics module in OpenThread (#343)

* Add diagnostics module in OpenThread

  - provide the same diagnostics interface for both CLI and NCP usage
  - implement common diagnostics features based on existing platform interface defined in 'include/platform/'
  - other more platform specific diagnostics features will be processed under platform layer
  - update CLI interface to support diagnostics feature
  - update both Posix and CC2538 platform to support diagnostics feature

* Add diagnostics module unit test

   - move platform.h from "examples/platform" to "include/platform"
   - add test_diag.cpp to test diagnostics module

* Add a configuration option that would enable/disable diagnostics module

Add --enable-diag configuration option to enable/disable diagnostics module when building OpenThread.
This commit is contained in:
Shu Chen
2016-08-11 10:26:51 -07:00
committed by Jonathan Hui
parent cefea1a3c6
commit 7130798123
38 changed files with 1476 additions and 16 deletions
+1
View File
@@ -33,6 +33,7 @@ AM_MAKEFLAGS = --no-print-directory
AM_DISTCHECK_CONFIGURE_FLAGS = \
--enable-cli \
--enable-ncp \
--enable-diag \
--with-examples=posix \
$(NULL)
+33
View File
@@ -428,6 +428,37 @@ AM_CONDITIONAL([OPENTHREAD_ENABLE_NCP], [test "${enable_ncp}" != "no"])
AM_CONDITIONAL([OPENTHREAD_ENABLE_NCP_SPI], [test "${enable_ncp}" = "spi"])
AM_CONDITIONAL([OPENTHREAD_ENABLE_NCP_UART], [test "${enable_ncp}" = "uart"])
#
# Diagnostics Library
#
AC_ARG_ENABLE(diag,
[AS_HELP_STRING([--enable-diag],[Enable diagnostics suport @<:@default=no@:>@.])],
[
case "${enableval}" in
no|yes)
enable_diag=${enableval}
;;
*)
AC_MSG_ERROR([Invalid value ${enable_diag} for --enable-diag])
;;
esac
],
[enable_diag=no])
if test "$enable_diag" = "yes"; then
OPENTHREAD_ENABLE_DIAG=1
else
OPENTHREAD_ENABLE_DIAG=0
fi
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])
#
# Examples
#
@@ -596,6 +627,7 @@ src/Makefile
src/cli/Makefile
src/ncp/Makefile
src/core/Makefile
src/diag/Makefile
third_party/Makefile
third_party/mbedtls/Makefile
examples/Makefile
@@ -670,6 +702,7 @@ AC_MSG_NOTICE([
Pretty check args : ${PRETTY_CHECK_ARGS:--}
OpenThread CLI support : ${enable_cli}
OpenThread NCP support : ${enable_ncp}
OpenThread Diagnostics support : ${enable_diag}
OpenThread examples : ${OPENTHREAD_EXAMPLES}
OpenThread platform information : ${PLATFORM_INFO}
+1
View File
@@ -44,6 +44,7 @@ BuildJobs ?= 99
configure_OPTIONS = \
--enable-cli \
--enable-ncp \
--enable-diag \
--with-examples=cc2538 \
--with-platform-info=CC2538 \
$(NULL)
+1
View File
@@ -89,6 +89,7 @@ TargetTuple = $(shell ${AbsTopSourceDir}/third_party/nlbuild
configure_OPTIONS = \
--enable-cli \
--enable-ncp \
--enable-diag \
--with-examples=posix \
--with-platform-info=POSIX \
$(NULL)
+6
View File
@@ -46,6 +46,12 @@ ot_cli_LDADD = \
ot_cli_LDFLAGS = \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
ot_cli_LDADD += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif
if OPENTHREAD_EXAMPLES_POSIX
ot_cli_LDADD += \
$(top_builddir)/examples/platforms/posix/libopenthread-posix.a \
+7 -1
View File
@@ -27,8 +27,10 @@
*/
#include <openthread.h>
#include <openthread-config.h>
#include <openthread-diag.h>
#include <cli/cli-uart.h>
#include <platform.h>
#include <platform/platform.h>
void otSignalTaskletPending(void)
{
@@ -40,6 +42,10 @@ int main(int argc, char *argv[])
otEnable();
otCliUartInit();
#if OPENTHREAD_ENABLE_DIAG
diagInit();
#endif
while (1)
{
otProcessNextTasklet();
+6
View File
@@ -46,6 +46,12 @@ ot_ncp_LDADD = \
ot_ncp_LDFLAGS = \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
ot_ncp_LDADD += \
$(top_builddir)/src/diag/libopenthread-diag.a \
$(NULL)
endif
if OPENTHREAD_EXAMPLES_POSIX
ot_ncp_LDADD += \
$(top_builddir)/examples/platforms/posix/libopenthread-posix.a \
+7 -1
View File
@@ -27,8 +27,10 @@
*/
#include <openthread.h>
#include <openthread-config.h>
#include <openthread-diag.h>
#include <ncp/ncp.h>
#include <platform.h>
#include <platform/platform.h>
void otSignalTaskletPending(void)
{
@@ -40,6 +42,10 @@ int main(int argc, char *argv[])
otEnable();
otNcpInit();
#if OPENTHREAD_ENABLE_DIAG
diagInit();
#endif
while (1)
{
otProcessNextTasklet();
-4
View File
@@ -45,10 +45,6 @@ if OPENTHREAD_EXAMPLES_CC2538
SUBDIRS = cc2538
endif
noinst_HEADERS = \
platform.h \
$(NULL)
# Always pretty (e.g. for 'make pretty') these subdirectories.
PRETTY_SUBDIRS = \
+6
View File
@@ -46,6 +46,12 @@ libopenthread_cc2538_a_SOURCES = \
startup-gcc.c \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
libopenthread_cc2538_a_SOURCES += \
diag.c \
$(NULL)
endif
noinst_HEADERS = \
cc2538-reg.h \
platform-cc2538.h \
+14 -1
View File
@@ -35,7 +35,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <openthread-config.h>
#include <platform/alarm.h>
#include <platform/diag.h>
#include "platform-cc2538.h"
enum
@@ -99,7 +101,18 @@ void cc2538AlarmProcess(void)
if (fire)
{
sIsRunning = false;
otPlatAlarmFired();
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagAlarmFired();
}
else
#endif
{
otPlatAlarmFired();
}
}
}
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <platform/alarm.h>
#include "platform-cc2538.h"
/**
* diagnostics mode flag.
*
*/
static bool sDiagMode = false;
void otPlatDiagProcess(int argc, char *argv[], char *aOutput)
{
// add more plarform specific diagnostics features here
sprintf(aOutput, "diag feature '%s' is not supported\r\n", argv[0]);
(void)argc;
}
void otPlatDiagModeSet(bool aMode)
{
sDiagMode = aMode;
}
bool otPlatDiagModeGet()
{
return sDiagMode;
}
+37 -3
View File
@@ -33,9 +33,11 @@
*/
#include <openthread-types.h>
#include <openthread-config.h>
#include <common/code_utils.hpp>
#include <platform/radio.h>
#include <platform/diag.h>
#include "platform-cc2538.h"
enum
@@ -371,7 +373,17 @@ void cc2538RadioProcess(void)
if ((sState == kStateReceive) && (sReceiveFrame.mLength > 0))
{
otPlatRadioReceiveDone(&sReceiveFrame, sReceiveError);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioReceiveDone(&sReceiveFrame, sReceiveError);
}
else
#endif
{
otPlatRadioReceiveDone(&sReceiveFrame, sReceiveError);
}
}
if (sState == kStateTransmit)
@@ -379,14 +391,36 @@ void cc2538RadioProcess(void)
if (sTransmitError != kThreadError_None || (sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
{
sState = kStateReceive;
otPlatRadioTransmitDone(false, sTransmitError);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioTransmitDone(false, sTransmitError);
}
else
#endif
{
otPlatRadioTransmitDone(false, sTransmitError);
}
}
else if (sReceiveFrame.mLength == IEEE802154_ACK_LENGTH &&
(sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK &&
(sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET]))
{
sState = kStateReceive;
otPlatRadioTransmitDone((sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, sTransmitError);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioTransmitDone((sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, sTransmitError);
}
else
#endif
{
otPlatRadioTransmitDone((sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, sTransmitError);
}
}
}
+6
View File
@@ -46,6 +46,12 @@ libopenthread_posix_a_SOURCES = \
uart.c \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
libopenthread_posix_a_SOURCES += \
diag.c \
$(NULL)
endif
if OPENTHREAD_ENABLE_NCP_SPI
libopenthread_posix_a_SOURCES += \
spi-stubs.c \
+14 -1
View File
@@ -31,7 +31,9 @@
#include <string.h>
#include <sys/time.h>
#include <openthread-config.h>
#include <platform/alarm.h>
#include <platform/diag.h>
#include "platform-posix.h"
static bool s_is_running = false;
@@ -106,7 +108,18 @@ void posixAlarmProcess(void)
if (remaining <= 0)
{
s_is_running = false;
otPlatAlarmFired();
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagAlarmFired();
}
else
#endif
{
otPlatAlarmFired();
}
}
}
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <platform/alarm.h>
#include "platform-posix.h"
/**
* diagnostics mode flag.
*
*/
static bool sDiagMode = false;
void otPlatDiagProcess(int argc, char *argv[], char *aOutput)
{
// no more diagnostics features for Posix platform
sprintf(aOutput, "diag feature '%s' is not supported\r\n", argv[0]);
(void)argc;
}
void otPlatDiagModeSet(bool aMode)
{
sDiagMode = aMode;
}
bool otPlatDiagModeGet()
{
return sDiagMode;
}
+38 -3
View File
@@ -39,7 +39,9 @@
#include <sys/stat.h>
#include <unistd.h>
#include <openthread-config.h>
#include <platform/radio.h>
#include <platform/diag.h>
#include <common/code_utils.hpp>
#include "platform-posix.h"
@@ -456,7 +458,18 @@ void radioReceive(void)
{
sState = kStateReceive;
sAckWait = false;
otPlatRadioTransmitDone(isFramePending(sReceiveFrame.mPsdu), kThreadError_None);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioTransmitDone(isFramePending(sReceiveFrame.mPsdu), kThreadError_None);
}
else
#endif
{
otPlatRadioTransmitDone(isFramePending(sReceiveFrame.mPsdu), kThreadError_None);
}
}
}
else if (sState == kStateReceive &&
@@ -478,7 +491,18 @@ void radioSendMessage(void)
if (!sAckWait)
{
sState = kStateReceive;
otPlatRadioTransmitDone(false, kThreadError_None);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioTransmitDone(false, kThreadError_None);
}
else
#endif
{
otPlatRadioTransmitDone(false, kThreadError_None);
}
}
}
@@ -609,5 +633,16 @@ void radioProcessFrame(void)
exit:
otPlatRadioReceiveDone(error == kThreadError_None ? &sReceiveFrame : NULL, error);
#if OPENTHREAD_ENABLE_DIAG
if (otPlatDiagModeGet())
{
otPlatDiagRadioReceiveDone(error == kThreadError_None ? &sReceiveFrame : NULL, error);
}
else
#endif
{
otPlatRadioReceiveDone(error == kThreadError_None ? &sReceiveFrame : NULL, error);
}
}
+1
View File
@@ -57,6 +57,7 @@ PRETTY_SUBDIRS = \
include_HEADERS = \
openthread.h \
openthread-diag.h \
openthread-types.h \
$(NULL)
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file defines the top-level functions for the OpenThread diagnostics library.
*/
#ifndef OPENTHREAD_DIAG_H_
#define OPENTHREAD_DIAG_H_
#ifdef __cplusplus
extern "C" {
#endif
void diagInit();
char *diagProcessCmd(int argc, char *argv[]);
bool isDiagEnabled();
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_DIAG_H_
+2
View File
@@ -30,8 +30,10 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
ot_platform_headers =\
alarm.h \
diag.h \
misc.h \
logging.h \
platform.h \
radio.h \
random.h \
uart.h \
+5
View File
@@ -77,6 +77,11 @@ uint32_t otPlatAlarmGetNow(void);
*/
extern void otPlatAlarmFired(void);
/**
* Signal diagnostics module that the alarm has fired.
*/
extern void otPlatDiagAlarmFired(void);
/**
* @}
*
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file defines the platform diag interface.
*
*/
#ifndef DIAG_H_
#define DIAG_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup diag Diag
* @ingroup platform
*
* @brief
* This module includes the platform abstraction for diagnostics features.
*
* @{
*
*/
/**
* Process the platform specific diagnostics features.
*
* @param[in] argc The argument counter of diagnostics command line.
* @param[in] argv The argument vector of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
*/
void otPlatDiagProcess(int argc, char *argv[], char *aOutput);
/**
* Set diagnostics mode.
*/
void otPlatDiagModeSet(bool aMode);
/**
* Get diagnostics mode.
*/
bool otPlatDiagModeGet(void);
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif
@@ -29,12 +29,17 @@
/**
* @file
* @brief
* This file includes the posix platform-specific initializers.
* This file defines the platform-specific initializers.
*/
#ifndef PLATFORM_H_
#define PLATFORM_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* This function performs all platform-specific initialization.
*
@@ -47,4 +52,8 @@ void PlatformInit(int argc, char *argv[]);
*/
void PlatformProcessDrivers(void);
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // PLATFORM_H_
+22
View File
@@ -298,6 +298,28 @@ bool otPlatRadioGetPromiscuous(void);
*/
void otPlatRadioSetPromiscuous(bool aEnable);
/**
* The radio driver calls this method to notify OpenThread diagnostics module that the transmission has completed.
*
* @param[in] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set.
* @param[in] aError ::kThreadError_None when the frame was transmitted, ::kThreadError_NoAck when the frame was
* transmitted but no ACK was received, ::kThreadError_ChannelAccessFailure when the transmission
* could not take place due to activity on the channel, ::kThreadError_Abort when transmission was
* aborted for other reasons.
*
*/
extern void otPlatDiagRadioTransmitDone(bool aFramePending, ThreadError aError);
/**
* The radio driver calls this method to notify OpenThread diagnostics module of a received packet.
*
* @param[in] aPacket A pointer to the received packet or NULL if the receive operation was aborted.
* @param[in] aError ::kThreadError_None when successfully received a frame, ::kThreadError_Abort when reception
* was aborted and a frame was not received.
*
*/
extern void otPlatDiagRadioReceiveDone(RadioPacket *aPacket, ThreadError aError);
/**
* @}
*
+5
View File
@@ -34,6 +34,7 @@ DIST_SUBDIRS = \
cli \
core \
ncp \
diag \
$(NULL)
# Always build (e.g. for 'make all') these subdirectories.
@@ -50,6 +51,10 @@ if OPENTHREAD_ENABLE_NCP
SUBDIRS += ncp
endif
if OPENTHREAD_ENABLE_DIAG
SUBDIRS += diag
endif
# Always pretty (e.g. for 'make pretty') these subdirectories.
PRETTY_SUBDIRS = \
+9
View File
@@ -38,6 +38,7 @@ OpenThread test scripts use the CLI to execute test cases.
* [thread](#thread)
* [version](#version)
* [whitelist](#whitelist)
* [diag](#diag)
## OpenThread Command Details
@@ -680,3 +681,11 @@ Remove an IEEE 802.15.4 Extended Address from the whitelist.
> whitelist remove dead00beef00cafe
Done
```
### diag
Diagnostics module is enabled only when building OpenThread with --enable-diag option.
Go [diagnostics module][1] for more information.
[1]:../diag/README.md
+17 -1
View File
@@ -36,7 +36,7 @@
#include <string.h>
#include <openthread.h>
#include <openthread-config.h>
#include <openthread-diag.h>
#include "cli.hpp"
#include "cli_dataset.hpp"
@@ -86,6 +86,9 @@ const struct Command Interpreter::sCommands[] =
{ "thread", &ProcessThread },
{ "version", &ProcessVersion },
{ "whitelist", &ProcessWhitelist },
#if OPENTHREAD_ENABLE_DIAG
{ "diag", &ProcessDiag },
#endif
};
otNetifAddress Interpreter::sAddress;
@@ -1477,6 +1480,14 @@ exit:
AppendResult(error);
}
#if OPENTHREAD_ENABLE_DIAG
void Interpreter::ProcessDiag(int argc, char *argv[])
{
// all diagnostics related features are processed within diagnostics module
sServer->OutputFormat("%s\r\n", diagProcessCmd(argc, argv));
}
#endif
void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer)
{
char *argv[kMaxArgs];
@@ -1504,6 +1515,11 @@ void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer)
cmd = aBuf;
#if OPENTHREAD_ENABLE_DIAG
VerifyOrExit((!isDiagEnabled() || (strcmp(cmd, "diag") == 0)),
sServer->OutputFormat("under diagnostics mode, execute 'diag stop' before running any other commands.\r\n"));
#endif
for (unsigned int i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++)
{
if (strcmp(cmd, sCommands[i].mName) == 0)
+5
View File
@@ -39,6 +39,7 @@
#include <cli/cli_server.hpp>
#include <net/icmp6.hpp>
#include <common/timer.hpp>
#include <openthread-config.h>
namespace Thread {
@@ -157,6 +158,10 @@ private:
static void ProcessVersion(int argc, char *argv[]);
static void ProcessWhitelist(int argc, char *argv[]);
#if OPENTHREAD_ENABLE_DIAG
static void ProcessDiag(int argc, char *argv[]);
#endif
static void HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandlePingTimer(void *aContext);
static void HandleActiveScanResult(otActiveScanResult *aResult);
+53
View File
@@ -0,0 +1,53 @@
#
# Copyright (c) 2016, Nest Labs, Inc.
# 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
+143
View File
@@ -0,0 +1,143 @@
# OpenThread 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.
The diagnostics module supports common diagnostics features that are listed below, and it also provides a mechanism for expanding platform specific diagnostics features.
## Common Diagnostics Command List
* [diag](#diag)
* [diag start](#diag start)
* [diag channel](#diag channel)
* [diag channel \<channel\>](#diag channel \<channel\>)
* [diag power](#diag power)
* [diag power \<power\>](#diag power \<power\>)
* [diag send \<packets\> \<length\>](#diag send \<packets\> \<length\>)
* [diag repeat \<delay\> \<length\>](#diag repeat \<delay\> \<length\>)
* [diag repeat stop](#diag repeat stop)
* [diag sleep](#diag sleep)
* [diag stats](#diag stats)
* [diag stop](#diag stop)
### diag
Show diagnostics mode status.
```bash
> diag
diagnostics mode is disabled
```
### diag start
Start diagnostics mode.
```bash
> diag start
start diagnostics mode
status 0x00
```
### diag channel
Get the IEEE 802.15.4 Channel value for diagnostics module.
```bash
> diag channel
channel: 11
```
### diag channel \<channel\>
Set the IEEE 802.15.4 Channel value for diagnostics module.
```bash
> diag channel 11
set channel to 11
status 0x00
```
### diag power
Get the tx power value(dBm) for diagnostics module.
```bash
> diag power
tx power: -10 dBm
```
### diag power \<power\>
Set the tx power value(dBm) for diagnostics module.
```bash
> diag power -10
set tx power to -10 dBm
status 0x00
```
### diag send \<packets\> \<length\>
Transmit a fixed number of packets with fixed length.
```bash
> diag send 20 100
sending 0x14 packet(s), length 0x64
status 0x00
```
### diag repeat \<delay\> \<length\>
Transmit packets repeatedly with a fixed interval.
```bash
> diag repeat 100 100
sending packets of length 0x64 at the delay of 0x64 ms
status 0x00
```
### diag repeat stop
Stop repeated packet transmission.
```bash
> diag repeat stop
repeated packet transmission is stopped
status 0x00
```
### diag sleep
Enter radio sleep mode.
```bash
> diag sleep
sleeping now...
```
### diag stats
Print statistics during diagnostics mode.
```bash
> diag stats
received packets: 10
sent packets: 10
first received packet: rssi=-65, lqi=101
```
### diag stop
Stop diagnostics mode and print statistics.
```bash
> diag stop
received packets: 10
sent packets: 10
first received packet: rssi=-65, lqi=101
stop diagnostics mode
status 0x00
```
+383
View File
@@ -0,0 +1,383 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <common/code_utils.hpp>
#include "diag_process.hpp"
namespace Thread {
namespace Diagnostics {
const struct Command Diag::sCommands[] =
{
{ "start", &ProcessStart },
{ "stop", &ProcessStop },
{ "channel", &ProcessChannel },
{ "power", &ProcessPower },
{ "send", &ProcessSend },
{ "repeat", &ProcessRepeat },
{ "sleep", &ProcessSleep },
{ "stats", &ProcessStats },
};
char Diag::sDiagOutput[MAX_DIAG_OUTPUT];
struct DiagStats Diag::sStats;
int8_t Diag::sTxPower;
uint8_t Diag::sChannel;
uint8_t Diag::sTxLen;
uint32_t Diag::sTxPeriod;
uint32_t Diag::sTxPackets;
void Diag::Init()
{
sChannel = 20;
sTxPower = 0;
sTxPeriod = 0;
sTxLen = 0;
sTxPackets = 0;
memset(&sStats, 0, sizeof(struct DiagStats));
}
char *Diag::ProcessCmd(int argc, char *argv[])
{
unsigned int i;
if (argc == 0)
{
sprintf(sDiagOutput, "diagnostics mode is %s\r\n", otPlatDiagModeGet() ? "enabled" : "disabled");
}
else
{
for (i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++)
{
if (strcmp(argv[0], sCommands[i].mName) == 0)
{
sCommands[i].mCommand(argc - 1, &argv[1], sDiagOutput);
break;
}
}
// more platform specific features will be processed under platform layer
if (i == sizeof(sCommands) / sizeof(sCommands[0]))
{
otPlatDiagProcess(argc, argv, sDiagOutput);
}
}
return sDiagOutput;
}
bool Diag::isEnabled()
{
return otPlatDiagModeGet();
}
void Diag::AppendErrorResult(ThreadError aError, char *aOutput)
{
if (aError != kThreadError_None)
{
sprintf(aOutput, "failed\r\nstatus %#x\r\n", aError);
}
}
void Diag::ProcessStart(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
// enable radio
otPlatRadioEnable();
// enable promiscuous mode
otPlatRadioSetPromiscuous(true);
// stop timer
otPlatAlarmStop();
// start to listen on the default channel
SuccessOrExit(error = otPlatRadioReceive(sChannel));
// enable diagnostics mode
otPlatDiagModeSet(true);
memset(&sStats, 0, sizeof(struct DiagStats));
sprintf(aOutput, "start diagnostics mode\r\nstatus 0x%02x\r\n", error);
exit:
(void)argc;
(void)argv;
AppendErrorResult(error, aOutput);
}
void Diag::ProcessStop(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
otPlatAlarmStop();
otPlatDiagModeSet(false);
otPlatRadioSetPromiscuous(false);
sprintf(aOutput, "received packets: %d\r\nsent packets: %d\r\nfirst received packet: rssi=%d, lqi=%d\r\n\nstop diagnostics mode\r\nstatus 0x%02x\r\n",
static_cast<int>(sStats.received_packets), static_cast<int>(sStats.sent_packets), static_cast<int>(sStats.first_rssi),
static_cast<int>(sStats.first_lqi), error);
exit:
(void)argc;
(void)argv;
AppendErrorResult(error, aOutput);
}
ThreadError Diag::ParseLong(char *argv, long &value)
{
char *endptr;
value = strtol(argv, &endptr, 0);
return (*endptr == '\0') ? kThreadError_None : kThreadError_Parse;
}
void Diag::TxPacket()
{
RadioPacket *packet = otPlatRadioGetTransmitBuffer();
if (sTxPackets > 0)
{
sTxPackets--;
}
packet->mLength = sTxLen;
packet->mChannel = sChannel;
packet->mPower = sTxPower;
for (uint8_t i = 0; i < sTxLen; i++)
{
packet->mPsdu[i] = i;
}
otPlatRadioTransmit();
}
void Diag::ProcessChannel(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
if (argc == 0)
{
sprintf(aOutput, "channel: %d\r\n", sChannel);
}
else
{
long value;
SuccessOrExit(error = ParseLong(argv[0], value));
VerifyOrExit(value >= kPhyMinChannel && value <= kPhyMaxChannel, error = kThreadError_InvalidArgs);
sChannel = static_cast<uint8_t>(value);
// listen on the set channel immediately
otPlatRadioReceive(sChannel);
sprintf(aOutput, "set channel to %d\r\nstatus 0x%02x\r\n", sChannel, error);
}
exit:
AppendErrorResult(error, aOutput);
}
void Diag::ProcessPower(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
if (argc == 0)
{
sprintf(aOutput, "tx power: %d dBm\r\n", sTxPower);
}
else
{
long value;
SuccessOrExit(error = ParseLong(argv[0], value));
sTxPower = static_cast<int8_t>(value);
sprintf(aOutput, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", sTxPower, error);
}
exit:
AppendErrorResult(error, aOutput);
}
void Diag::ProcessSend(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
long value;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs);
SuccessOrExit(error = ParseLong(argv[0], value));
sTxPackets = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(argv[1], value));
VerifyOrExit(value <= kMaxPHYPacketSize, error = kThreadError_InvalidArgs);
sTxLen = static_cast<uint8_t>(value);
sprintf(aOutput, "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);
}
void Diag::ProcessRepeat(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
VerifyOrExit(argc > 0, error = kThreadError_InvalidArgs);
if (strcmp(argv[0], "stop") == 0)
{
otPlatAlarmStop();
sprintf(aOutput, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
}
else
{
long value;
VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs);
SuccessOrExit(error = ParseLong(argv[0], value));
sTxPeriod = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(argv[1], value));
VerifyOrExit(value <= kMaxPHYPacketSize, error = kThreadError_InvalidArgs);
sTxLen = static_cast<uint8_t>(value);
uint32_t now = otPlatAlarmGetNow();
otPlatAlarmStartAt(now, sTxPeriod);
sprintf(aOutput, "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);
}
void Diag::ProcessSleep(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
otPlatRadioSleep();
sprintf(aOutput, "sleeping now...\r\n");
exit:
(void)argc;
(void)argv;
AppendErrorResult(error, aOutput);
}
void Diag::ProcessStats(int argc, char *argv[], char *aOutput)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
sprintf(aOutput, "received packets: %d\r\nsent packets: %d\r\nfirst received packet: rssi=%d, lqi=%d\r\n",
static_cast<int>(sStats.received_packets), static_cast<int>(sStats.sent_packets),
static_cast<int>(sStats.first_rssi), static_cast<int>(sStats.first_lqi));
exit:
(void)argc;
(void)argv;
AppendErrorResult(error, aOutput);
}
void Diag::DiagTransmitDone(bool aRxPending, ThreadError aError)
{
if (!aRxPending && aError == kThreadError_None)
{
sStats.sent_packets++;
if (sTxPackets > 0)
{
TxPacket();
}
}
}
void Diag::DiagReceiveDone(RadioPacket *aFrame, ThreadError aError)
{
if (aError == kThreadError_None)
{
// for sensitivity test, only record the rssi and lqi for the first packet
if (sStats.received_packets == 0)
{
sStats.first_rssi = aFrame->mPower;
sStats.first_lqi = aFrame->mLqi;
}
sStats.received_packets++;
}
}
void Diag::AlarmFired()
{
uint32_t now = otPlatAlarmGetNow();
TxPacket();
otPlatAlarmStartAt(now, sTxPeriod);
}
extern "C" void otPlatDiagAlarmFired()
{
Diag::AlarmFired();
}
extern "C" void otPlatDiagRadioTransmitDone(bool aRxPending, ThreadError aError)
{
Diag::DiagTransmitDone(aRxPending, aError);
}
extern "C" void otPlatDiagRadioReceiveDone(RadioPacket *aFrame, ThreadError aError)
{
Diag::DiagReceiveDone(aFrame, aError);
}
} // namespace Diagnostics
} // namespace Thread
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 <stdarg.h>
#include <platform/radio.h>
#include <platform/alarm.h>
#include <platform/diag.h>
namespace Thread {
namespace Diagnostics {
#define MAX_DIAG_OUTPUT 256
struct Command
{
const char *mName; ///< A pointer to the command string.
void (*mCommand)(int argc, char *argv[], char *aOutput); ///< A function pointer to process the command.
};
struct DiagStats
{
uint32_t received_packets;
uint32_t sent_packets;
int8_t first_rssi;
uint8_t first_lqi;
};
class Diag
{
public:
static void Init();
static char *ProcessCmd(int argc, char *argv[]);
static bool isEnabled();
static void DiagTransmitDone(bool aRxPending, ThreadError aError);
static void DiagReceiveDone(RadioPacket *aFrame, ThreadError aError);
static void AlarmFired();
private:
static void AppendErrorResult(ThreadError error, char *aOutput);
static void ProcessSleep(int argc, char *argv[], char *aOutput);
static void ProcessStart(int argc, char *argv[], char *aOutput);
static void ProcessStop(int argc, char *argv[], char *aOutput);
static void ProcessSend(int argc, char *argv[], char *aOutput);
static void ProcessRepeat(int argc, char *argv[], char *aOutput);
static void ProcessStats(int argc, char *argv[], char *aOutput);
static void ProcessChannel(int argc, char *argv[], char *aOutput);
static void ProcessPower(int argc, char *argv[], char *aOutput);
static void TxPacket();
static ThreadError ParseLong(char *aString, long &aLong);
static char sDiagOutput[];
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;
};
} // namespace Diagnostics
} // namespace Thread
#endif // CLI_HPP_
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openthread-diag.h>
#include <diag_process.hpp>
namespace Thread {
namespace Diagnostics {
#ifdef __cplusplus
extern "C" {
#endif
void diagInit()
{
Diag::Init();
}
char *diagProcessCmd(int argc, char *argv[])
{
return Diag::ProcessCmd(argc, argv);
}
bool isDiagEnabled()
{
return Diag::isEnabled();
}
#ifdef __cplusplus
} // extern "C"
#endif
} // namespace Diagnostics
} // namespace Thread
+13
View File
@@ -75,6 +75,12 @@ check_PROGRAMS = \
test-toolchain \
$(NULL)
if OPENTHREAD_ENABLE_DIAG
check_PROGRAMS += \
test-diag \
$(NULL)
endif
if OPENTHREAD_ENABLE_NCP
COMMON_LDADD += \
@@ -129,6 +135,13 @@ test_timer_SOURCES = test_timer.cpp
test_toolchain_LDADD = $(COMMON_LDADD)
test_toolchain_SOURCES = test_toolchain.cpp
if OPENTHREAD_ENABLE_DIAG
test_diag_LDADD = $(top_builddir)/src/diag/libopenthread-diag.a \
$(top_builddir)/examples/platforms/posix/libopenthread-posix.a \
$(NULL)
test_diag_SOURCES = test_diag.cpp
endif
endif # OPENTHREAD_BUILD_TESTS
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright (c) 2016, Nest Labs, Inc.
* 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 "test_util.h"
#include <string.h>
#include <openthread-diag.h>
#include <platform/platform.h>
#include <platform/radio.h>
extern "C" void otSignalTaskletPending(void)
{
}
extern "C" bool otAreTaskletsPending(void)
{
return false;
}
extern "C" void otPlatUartSendDone(void)
{
}
extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
{
(void)aBuf;
(void)aBufLength;
}
extern "C" void otPlatAlarmFired()
{
}
extern "C" void otPlatRadioTransmitDone(bool aRxPending, ThreadError aError)
{
(void)aRxPending;
(void)aError;
}
extern "C" void otPlatRadioReceiveDone(RadioPacket *aFrame, ThreadError aError)
{
(void)aFrame;
(void)aError;
}
/**
* diagnostics module tests
*/
void TestDiag()
{
static const struct
{
const char *command;
const char *output;
} tests[] =
{
{
"diag\n",
"diagnostics mode is disabled\r\n",
},
{
"diag send 10 100\n",
"failed\r\nstatus 0xe\r\n",
},
{
"diag start\n",
"start diagnostics mode\r\nstatus 0x00\r\n",
},
{
"diag\n",
"diagnostics mode is enabled\r\n",
},
{
"diag channel 10\n",
"failed\r\nstatus 0x7\r\n",
},
{
"diag channel 11\n",
"set channel to 11\r\nstatus 0x00\r\n",
},
{
"diag channel\n",
"channel: 11\r\n",
},
{
"diag power -10\n",
"set tx power to -10 dBm\r\nstatus 0x00\r\n",
},
{
"diag power\n",
"tx power: -10 dBm\r\n",
},
{
"diag stats\n",
"received packets: 0\r\nsent packets: 0\r\nfirst received packet: rssi=0, lqi=0\r\n",
},
{
"diag send 20 100\n",
"sending 0x14 packet(s), length 0x64\r\nstatus 0x00\r\n",
},
{
"diag repeat 100 100\n",
"sending packets of length 0x64 at the delay of 0x64 ms\r\nstatus 0x00\r\n"
},
{
"diag sleep\n",
"sleeping now...\r\n",
},
{
"diag stop\n",
"received packets: 0\r\nsent packets: 0\r\nfirst received packet: rssi=0, lqi=0\r\n\nstop diagnostics mode\r\nstatus 0x00\r\n",
},
{
"diag\n",
"diagnostics mode is disabled\r\n",
},
};
// initialize platform layer
int argc = 2;
char *argv[2] = {(char *)"test_diag", (char *)"1"};
PlatformInit(argc, argv);
// initialize diagnostics module
diagInit();
// test diagnostics commands
VerifyOrQuit(!isDiagEnabled(), "diagnostics mode shoud be disabled as default\n");
for (unsigned int i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
{
char string[50];
int length = strlen(tests[i].command);
char *cmd;
char *argv[8];
int argc = 0;
char *output = NULL;
memcpy(string, tests[i].command, length + 1);
for (cmd = string + 1; (cmd < string + length) && (cmd != NULL); ++cmd)
{
if (*cmd == ' ' || *cmd == '\r' || *cmd == '\n')
{
*cmd = '\0';
}
if (*(cmd - 1) == '\0' && *cmd != ' ')
{
argv[argc++] = cmd;
}
}
output = diagProcessCmd(argc, argv);
VerifyOrQuit(memcmp(output, tests[i].output, strlen(tests[i].output)) == 0,
"Test Diagnostics module failed\r\n");
}
}
int main(void)
{
TestDiag();
printf("All tests passed\n");
return 0;
}
+16
View File
@@ -59,6 +59,22 @@ extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
(void)aBufLength;
}
extern "C" void otPlatDiagAlarmFired()
{
}
extern "C" void otPlatDiagRadioTransmitDone(bool aRxPending, ThreadError aError)
{
(void)aRxPending;
(void)aError;
}
extern "C" void otPlatDiagRadioReceiveDone(RadioPacket *aFrame, ThreadError aError)
{
(void)aFrame;
(void)aError;
}
ThreadNetif sMockThreadNetif;
Lowpan::Lowpan sMockLowpan(sMockThreadNetif);
+4
View File
@@ -36,6 +36,10 @@ extern"C" void otSignalTaskletPending(void)
{
}
extern "C" void otPlatDiagAlarmFired()
{
}
void TestMessage(void)
{
Thread::Message *message;
+4
View File
@@ -40,6 +40,10 @@ extern"C" void otSignalTaskletPending(void)
{
}
extern "C" void otPlatDiagAlarmFired()
{
}
enum
{
kTestBufferSize = 101, // Size of backed buffer for NcpFrameBuffer.