diff --git a/examples/platforms/cc2538/diag.c b/examples/platforms/cc2538/diag.c index 2379c7b99..ab93e3dde 100644 --- a/examples/platforms/cc2538/diag.c +++ b/examples/platforms/cc2538/diag.c @@ -35,20 +35,21 @@ #include #include +#include #include "platform-cc2538.h" /** - * diagnostics mode flag. + * Diagnostics mode variables. * */ static bool sDiagMode = false; -void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) { - // add more plarform specific diagnostics features here - + // Add more plarform specific diagnostics features here. snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); - (void)argc; + (void) argc; + (void) aInstance; } void otPlatDiagModeSet(bool aMode) @@ -60,3 +61,25 @@ bool otPlatDiagModeGet() { return sDiagMode; } + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + (void) aChannel; +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + (void) aTxPower; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError) +{ + (void) aInstance; + (void) aFrame; + (void) aError; +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + (void) aInstance; +} diff --git a/examples/platforms/nrf52840/diag.c b/examples/platforms/nrf52840/diag.c index 29322f8b7..60ece6868 100644 --- a/examples/platforms/nrf52840/diag.c +++ b/examples/platforms/nrf52840/diag.c @@ -28,21 +28,194 @@ #include #include +#include #include +#include #include +#include +#include + +#include +#include + +struct PlatformDiagCommand +{ + const char *mName; + void (*mCommand)(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen); +}; + +struct PlatformDiagMessage +{ + const char mMessageDescriptor[11]; + uint8_t mChannel; + int16_t mID; + uint32_t mCnt; +}; /** - * Diagnostics mode flag. + * Diagnostics mode variables. * */ static bool sDiagMode = false; +static bool sListen = false; +static bool sTransmitActive = false; +static uint8_t sChannel = 20; +static int8_t sTxPower = 0; +static uint32_t sTxPeriod = 1; +static int32_t sTxCount = 0; +static int32_t sTxRequestedCount = 1; +static int16_t sID = -1; +static struct PlatformDiagMessage sDiagMessage = {.mMessageDescriptor = "DiagMessage", .mChannel = 0, .mID = 0, .mCnt = 0}; -void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +static ThreadError parseLong(char *argv, long *aValue) { - // Add more plarform specific diagnostics features here. - snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); - (void)argc; + char *endptr; + *aValue = strtol(argv, &endptr, 0); + return (*endptr == '\0') ? kThreadError_None : kThreadError_Parse; +} + +static void appendErrorResult(ThreadError aError, char *aOutput, size_t aOutputMaxLen) +{ + if (aError != kThreadError_None) + { + snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError); + } +} + +static void processListen(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + (void) aInstance; + ThreadError error = kThreadError_None; + + VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState); + + if (argc == 0) + { + snprintf(aOutput, aOutputMaxLen, "listen: %s\r\n", sListen == true ? "yes" : "no"); + } + else + { + long value; + + SuccessOrExit(error = parseLong(argv[0], &value)); + sListen = (bool)(value); + snprintf(aOutput, aOutputMaxLen, "set listen to %s\r\nstatus 0x%02x\r\n", sListen == true ? "yes" : "no", error); + } + +exit: + appendErrorResult(error, aOutput, aOutputMaxLen); +} + +static void processID(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + (void) aInstance; + + ThreadError error = kThreadError_None; + + VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState); + + if (argc == 0) + { + snprintf(aOutput, aOutputMaxLen, "ID: %" PRId16 "\r\n", sID); + } + else + { + long value; + + SuccessOrExit(error = parseLong(argv[0], &value)); + VerifyOrExit(value >= 0, error = kThreadError_InvalidArgs); + sID = (int16_t)(value); + snprintf(aOutput, aOutputMaxLen, "set ID to %" PRId16 "\r\nstatus 0x%02x\r\n", sID, error); + } + +exit: + appendErrorResult(error, aOutput, aOutputMaxLen); +} + +static void processTransmit(otInstance *aInstance, int argc, char *argv[], char *aOutput, + size_t aOutputMaxLen) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState); + + if (argc == 0) + { + snprintf(aOutput, aOutputMaxLen, "transmit will send %" PRId32 " diagnostic messages with %" PRIu32 + " ms interval\r\nstatus 0x%02x\r\n", + sTxRequestedCount, sTxPeriod, error); + } + else if (strcmp(argv[0], "stop") == 0) + { + otPlatAlarmStop(aInstance); + snprintf(aOutput, aOutputMaxLen, "diagnostic message transmission is stopped\r\nstatus 0x%02x\r\n", error); + sTransmitActive = false; + } + else if (strcmp(argv[0], "start") == 0) + { + otPlatAlarmStop(aInstance); + sTransmitActive = true; + sTxCount = sTxRequestedCount; + uint32_t now = otPlatAlarmGetNow(); + otPlatAlarmStartAt(aInstance, now, sTxPeriod); + snprintf(aOutput, aOutputMaxLen, "sending %" PRId32 " diagnostic messages with %" PRIu32 + " ms interval\r\nstatus 0x%02x\r\n", + sTxRequestedCount, sTxPeriod, error); + } + else if (strcmp(argv[0], "interval") == 0) + { + long value; + + VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs); + + SuccessOrExit(error = parseLong(argv[1], &value)); + VerifyOrExit(value > 0, error = kThreadError_InvalidArgs); + sTxPeriod = (uint32_t)(value); + snprintf(aOutput, aOutputMaxLen, "set diagnostic messages interval to %" PRIu32 " ms\r\nstatus 0x%02x\r\n", sTxPeriod, + error); + } + else if (strcmp(argv[0], "count") == 0) + { + long value; + + VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs); + + SuccessOrExit(error = parseLong(argv[1], &value)); + VerifyOrExit((value > 0) || (value == -1), error = kThreadError_InvalidArgs); + sTxRequestedCount = (uint32_t)(value); + snprintf(aOutput, aOutputMaxLen, "set diagnostic messages count to %" PRId32 "\r\nstatus 0x%02x\r\n", sTxRequestedCount, + error); + } + +exit: + appendErrorResult(error, aOutput, aOutputMaxLen); +} + +const struct PlatformDiagCommand sCommands[] = +{ + {"listen", &processListen }, + {"transmit", &processTransmit }, + {"id", &processID } +}; + +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + uint32_t i; + + for (i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++) + { + if (strcmp(argv[0], sCommands[i].mName) == 0) + { + sCommands[i].mCommand(aInstance, argc - 1, argc > 1 ? &argv[1] : NULL, aOutput, aOutputMaxLen); + break; + } + } + + if (i == sizeof(sCommands) / sizeof(sCommands[0])) + { + snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); + } } void otPlatDiagModeSet(bool aMode) @@ -54,3 +227,83 @@ bool otPlatDiagModeGet() { return sDiagMode; } + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + sChannel = aChannel; +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + sTxPower = aTxPower; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError) +{ + (void) aInstance; + + if (sListen && (aError == kThreadError_None)) + { + if (aFrame->mLength == sizeof(struct PlatformDiagMessage)) + { + struct PlatformDiagMessage *message = (struct PlatformDiagMessage *)aFrame->mPsdu; + + if (strncmp(message->mMessageDescriptor, "DiagMessage", 11) == 0) + { + otPlatLog(kLogLevelDebg, kLogRegionPlatform, + "{\"Frame\":{" + "\"LocalChannel\":%u ," + "\"RemoteChannel\":%u," + "\"CNT\":%" PRIu32 "," + "\"LocalID\":%" PRId16 "," + "\"RemoteID\":%" PRId16 "," + "\"RSSI\":%d" + "}}\r\n", + aFrame->mChannel, + message->mChannel, + message->mCnt, + sID, + message->mID, + aFrame->mPower + ); + } + } + } +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + if (sTransmitActive) + { + if ((sTxCount > 0) || (sTxCount == -1)) + { + RadioPacket *sTxPacket = otPlatRadioGetTransmitBuffer(aInstance); + + sTxPacket->mLength = sizeof(struct PlatformDiagMessage); + sTxPacket->mChannel = sChannel; + sTxPacket->mPower = sTxPower; + + sDiagMessage.mChannel = sTxPacket->mChannel; + sDiagMessage.mID = sID; + + memcpy(sTxPacket->mPsdu, &sDiagMessage, sizeof(struct PlatformDiagMessage)); + otPlatRadioTransmit(aInstance, sTxPacket); + + sDiagMessage.mCnt++; + + if (sTxCount != -1) + { + sTxCount--; + } + + uint32_t now = otPlatAlarmGetNow(); + otPlatAlarmStartAt(aInstance, now, sTxPeriod); + } + else + { + sTransmitActive = false; + otPlatAlarmStop(aInstance); + otPlatLog(kLogLevelDebg, kLogRegionPlatform, "Transmit done"); + } + } +} diff --git a/examples/platforms/posix/diag.c b/examples/platforms/posix/diag.c index 93239879b..ad7bd908b 100644 --- a/examples/platforms/posix/diag.c +++ b/examples/platforms/posix/diag.c @@ -37,18 +37,20 @@ #include #include +#include /** - * diagnostics mode flag. + * Diagnostics mode variables. * */ static bool sDiagMode = false; -void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) { - // no more diagnostics features for Posix platform + // Add more plarform specific diagnostics features here. snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); - (void)argc; + (void) argc; + (void) aInstance; } void otPlatDiagModeSet(bool aMode) @@ -60,3 +62,25 @@ bool otPlatDiagModeGet() { return sDiagMode; } + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + (void) aChannel; +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + (void) aTxPower; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError) +{ + (void) aInstance; + (void) aFrame; + (void) aError; +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + (void) aInstance; +} diff --git a/include/platform/diag.h b/include/platform/diag.h index 03666b840..f2cafa636 100644 --- a/include/platform/diag.h +++ b/include/platform/diag.h @@ -39,6 +39,10 @@ #include #include +#include + +#include + #ifdef __cplusplus extern "C" { #endif @@ -57,15 +61,16 @@ extern "C" { /** * 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. - * @param[in] aOutputMaxLen The output buffer size. + * @param[in] aInstance The OpenThread instance for current request. + * @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. + * @param[in] aOutputMaxLen The output buffer size. */ -void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen); +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen); /** - * Set diagnostics mode. + * Set diagnostics mode. */ void otPlatDiagModeSet(bool aMode); @@ -74,6 +79,32 @@ void otPlatDiagModeSet(bool aMode); */ bool otPlatDiagModeGet(void); +/** + * Set diagnostics channel. + */ +void otPlatDiagChannelSet(uint8_t aChannel); + +/** + * Set diagnostics tx power. + */ +void otPlatDiagTxPowerSet(int8_t aTxPower); + +/** + * Process the platform specific received frame parsing. + * + * @param[in] aInstance The OpenThread instance for current request. + * @param[in] aFrame The received radio frame. + * @param[in] aError The received radio frame status. + */ +void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError); + +/** + * Process the platform specific alarm callback. + * + * @param[in] aInstance The OpenThread instance for current request. + */ +void otPlatDiagAlarmCallback(otInstance *aInstance); + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/src/diag/diag_process.cpp b/src/diag/diag_process.cpp index 44e04a6bc..8d13957b2 100644 --- a/src/diag/diag_process.cpp +++ b/src/diag/diag_process.cpp @@ -62,6 +62,7 @@ uint8_t Diag::sTxLen; uint32_t Diag::sTxPeriod; uint32_t Diag::sTxPackets; RadioPacket * Diag::sTxPacket; +bool Diag::sRepeatActive; otInstance *Diag::sContext; @@ -73,8 +74,11 @@ void Diag::Init(otInstance *aInstance) sTxPeriod = 0; sTxLen = 0; sTxPackets = 0; + sRepeatActive = false; memset(&sStats, 0, sizeof(struct DiagStats)); sTxPacket = otPlatRadioGetTransmitBuffer(sContext); + otPlatDiagChannelSet(sChannel); + otPlatDiagTxPowerSet(sTxPower); } char *Diag::ProcessCmd(int argc, char *argv[]) @@ -99,7 +103,7 @@ char *Diag::ProcessCmd(int argc, char *argv[]) // more platform specific features will be processed under platform layer if (i == sizeof(sCommands) / sizeof(sCommands[0])) { - otPlatDiagProcess(argc, argv, sDiagOutput, sizeof(sDiagOutput)); + otPlatDiagProcess(sContext, argc, argv, sDiagOutput, sizeof(sDiagOutput)); } } @@ -190,7 +194,6 @@ void Diag::TxPacket() { sTxPacket->mPsdu[i] = i; } - otPlatRadioTransmit(sContext, sTxPacket); } @@ -214,6 +217,7 @@ void Diag::ProcessChannel(int argc, char *argv[], char *aOutput, size_t aOutputM // listen on the set channel immediately otPlatRadioReceive(sContext, sChannel); + otPlatDiagChannelSet(sChannel); snprintf(aOutput, aOutputMaxLen, "set channel to %d\r\nstatus 0x%02x\r\n", sChannel, error); } @@ -237,6 +241,7 @@ void Diag::ProcessPower(int argc, char *argv[], char *aOutput, size_t aOutputMax SuccessOrExit(error = ParseLong(argv[0], value)); sTxPower = static_cast(value); + otPlatDiagTxPowerSet(sTxPower); snprintf(aOutput, aOutputMaxLen, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", sTxPower, error); } @@ -276,6 +281,7 @@ void Diag::ProcessRepeat(int argc, char *argv[], char *aOutput, size_t aOutputMa if (strcmp(argv[0], "stop") == 0) { otPlatAlarmStop(sContext); + sRepeatActive = false; snprintf(aOutput, aOutputMaxLen, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error); } else @@ -291,6 +297,7 @@ void Diag::ProcessRepeat(int argc, char *argv[], char *aOutput, size_t aOutputMa VerifyOrExit(value <= kMaxPHYPacketSize, error = kThreadError_InvalidArgs); sTxLen = static_cast(value); + sRepeatActive = true; uint32_t now = otPlatAlarmGetNow(); otPlatAlarmStartAt(sContext, 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); @@ -359,16 +366,23 @@ void Diag::DiagReceiveDone(otInstance *aInstance, RadioPacket *aFrame, ThreadErr sStats.received_packets++; } - + otPlatDiagRadioReceived(aInstance, aFrame, aError); otPlatRadioReceive(aInstance, sChannel); } void Diag::AlarmFired(otInstance *aInstance) { - uint32_t now = otPlatAlarmGetNow(); + if(sRepeatActive) + { + uint32_t now = otPlatAlarmGetNow(); - TxPacket(); - otPlatAlarmStartAt(aInstance, now, sTxPeriod); + TxPacket(); + otPlatAlarmStartAt(aInstance, now, sTxPeriod); + } + else + { + otPlatDiagAlarmCallback(aInstance); + } } extern "C" void otPlatDiagAlarmFired(otInstance *aInstance) diff --git a/src/diag/diag_process.hpp b/src/diag/diag_process.hpp index ea0a10cec..460d228eb 100644 --- a/src/diag/diag_process.hpp +++ b/src/diag/diag_process.hpp @@ -94,6 +94,7 @@ private: static uint32_t sTxPackets; static RadioPacket *sTxPacket; static otInstance *sContext; + static bool sRepeatActive; }; } // namespace Diagnostics