diff --git a/src/core/diags/README.md b/src/core/diags/README.md index f51008d82..7171cc932 100644 --- a/src/core/diags/README.md +++ b/src/core/diags/README.md @@ -365,6 +365,20 @@ Clear statistics during diagnostics mode. Done ``` +### diag sweep [async] \ + +Transmit a single radio frame of a given length for every supported channel. + +- async: Use the non-blocking mode. +- length: The length of packet. The valid range is [3, 127]. + +```bash +> diag sweep 100 +Done +> diag send async 100 +Done +``` + ### diag gpio get \ Get the gpio value. diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp index e26a74026..38e43e704 100644 --- a/src/core/diags/factory_diags.cpp +++ b/src/core/diags/factory_diags.cpp @@ -188,6 +188,7 @@ const struct Diags::Command Diags::sCommands[] = { {"stats", &Diags::ProcessStats}, {"stop", &Diags::ProcessStop}, {"stream", &Diags::ProcessStream}, + {"sweep", &Diags::ProcessSweep}, }; Diags::Diags(Instance &aInstance) @@ -202,6 +203,8 @@ Diags::Diags(Instance &aInstance) , mIsTxPacketSet(false) , mIsAsyncSend(false) , mDiagSendOn(false) + , mIsSleepOn(false) + , mIsAsyncSweep(false) , mOutputCallback(nullptr) , mOutputContext(nullptr) { @@ -554,6 +557,49 @@ Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[]) return kErrorNone; } +Error Diags::ProcessSweep(uint8_t aArgsLength, char *aArgs[]) +{ + Error error = kErrorNone; + uint8_t txLength; + + VerifyOrExit(aArgsLength >= 1, error = kErrorInvalidArgs); + VerifyOrExit(mCurTxCmd == kTxCmdNone, error = kErrorInvalidState); + + if (StringMatch(aArgs[0], "async")) + { + aArgs++; + aArgsLength--; + VerifyOrExit(aArgsLength >= 1, error = kErrorInvalidArgs); + mIsAsyncSweep = true; + } + else + { + mIsAsyncSweep = false; + } + + SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint8(aArgs[0], txLength)); + + VerifyOrExit(txLength <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs); + VerifyOrExit(txLength >= OT_RADIO_FRAME_MIN_SIZE, error = kErrorInvalidArgs); + + mTxLen = txLength; + mIsTxPacketSet = false; + + mChannel = Radio::kChannelMin; + otPlatDiagChannelSet(mChannel); + + SuccessOrExit(error = TransmitPacket()); + mCurTxCmd = kTxCmdSweep; + + if (!mIsAsyncSweep) + { + error = kErrorPending; + } + +exit: + return error; +} + Error Diags::TransmitPacket(void) { Error error = kErrorNone; @@ -878,9 +924,28 @@ void Diags::TransmitDone(Error aError) } UpdateTxStats(aError); - VerifyOrExit((mCurTxCmd == kTxCmdSend) && (mTxPackets > 0)); + VerifyOrExit(((mCurTxCmd == kTxCmdSend) && (mTxPackets > 0)) || (mCurTxCmd == kTxCmdSweep)); - if (mTxPackets > 1) + if (mCurTxCmd == kTxCmdSweep) + { + if (IsChannelValid(mChannel + 1)) + { + mChannel += 1; + otPlatDiagChannelSet(mChannel); + + IgnoreError(TransmitPacket()); + } + else + { + mCurTxCmd = kTxCmdNone; + + if (!mIsAsyncSweep) + { + Output("OT_ERROR_NONE"); + } + } + } + else if (mTxPackets > 1) { mTxPackets--; IgnoreError(TransmitPacket()); diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp index 04a7328a2..7dcae3048 100644 --- a/src/core/diags/factory_diags.hpp +++ b/src/core/diags/factory_diags.hpp @@ -225,6 +225,7 @@ private: Error ProcessStats(uint8_t aArgsLength, char *aArgs[]); Error ProcessStop(uint8_t aArgsLength, char *aArgs[]); Error ProcessStream(uint8_t aArgsLength, char *aArgs[]); + Error ProcessSweep(uint8_t aArgsLength, char *aArgs[]); #if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI Error ProcessEcho(uint8_t aArgsLength, char *aArgs[]); #endif @@ -252,6 +253,7 @@ private: kTxCmdNone, kTxCmdRepeat, kTxCmdSend, + kTxCmdSweep, }; Stats mStats; @@ -269,6 +271,7 @@ private: bool mIsAsyncSend : 1; bool mDiagSendOn : 1; bool mIsSleepOn : 1; + bool mIsAsyncSweep : 1; #endif ReceiveConfig mReceiveConfig;