diff --git a/src/core/diags/README.md b/src/core/diags/README.md
index 2ddb658ac..ee447b3f9 100644
--- a/src/core/diags/README.md
+++ b/src/core/diags/README.md
@@ -77,6 +77,15 @@ Stop transmitting continuous carrier wave.
Done
```
+### diag frame \
+
+Set the frame (hex encoded) to be used by `diag send` and `diag repeat`. The frame may be overwritten by `diag send` and `diag repeat`.
+
+```bash
+> diag frame 11223344
+Done
+```
+
### diag stream start
Start transmitting a stream of characters.
@@ -143,11 +152,11 @@ RawPowerSetting: 223344
Done
```
-### diag send \ \
+### diag send \ [length]
-Transmit a fixed number of packets with fixed length.
+Transmit a fixed number of packets.
-Length parameter has to be in range [3, 127].
+Send the frame set by `diag frame` if length is omitted. Otherwise overwrite the frame set by `diag frame` and send a frame of the given length(MUST be in range [3, 127]).
```bash
> diag send 20 100
@@ -155,11 +164,11 @@ sending 0x14 packet(s), length 0x64
status 0x00
```
-### diag repeat \ \
+### diag repeat \ [length]
Transmit packets repeatedly with a fixed interval.
-Length parameter has to be in range [3, 127].
+Send the frame set by `diag frame` if length is omitted. Otherwise overwrite the frame set by `diag frame` and send a frame of the given length (MUST be in range [3, 127]).
```bash
> diag repeat 100 100
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 78845f1aa..03ce33d72 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -32,6 +32,7 @@
*/
#include "factory_diags.hpp"
+#include "common/error.hpp"
#if OPENTHREAD_CONFIG_DIAG_ENABLE
@@ -187,6 +188,7 @@ extern "C" void otPlatDiagAlarmFired(otInstance *aInstance) { otPlatDiagAlarmCal
const struct Diags::Command Diags::sCommands[] = {
{"channel", &Diags::ProcessChannel},
{"cw", &Diags::ProcessContinuousWave},
+ {"frame", &Diags::ProcessFrame},
{"gpio", &Diags::ProcessGpio},
{"power", &Diags::ProcessPower},
{"powersettings", &Diags::ProcessPowerSettings},
@@ -208,12 +210,31 @@ Diags::Diags(Instance &aInstance)
, mChannel(20)
, mTxPower(0)
, mTxLen(0)
+ , mIsTxPacketSet(false)
, mRepeatActive(false)
, mDiagSendOn(false)
{
mStats.Clear();
}
+Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+{
+ Error error = kErrorNone;
+ uint16_t size = OT_RADIO_FRAME_MAX_SIZE;
+
+ VerifyOrExit(aArgsLength == 1, error = kErrorInvalidArgs);
+
+ SuccessOrExit(error = Utils::CmdLineParser::ParseAsHexString(aArgs[0], size, mTxPacket->mPsdu));
+ VerifyOrExit(size <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs);
+ VerifyOrExit(size >= OT_RADIO_FRAME_MIN_SIZE, error = kErrorInvalidArgs);
+ mTxPacket->mLength = size;
+ mIsTxPacketSet = true;
+
+exit:
+ AppendErrorResult(error, aOutput, aOutputMaxLen);
+ return error;
+}
+
Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
Error error = kErrorNone;
@@ -288,12 +309,25 @@ Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, si
{
long value;
- VerifyOrExit(aArgsLength == 2, error = kErrorInvalidArgs);
+ VerifyOrExit(aArgsLength >= 1, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
mTxPeriod = static_cast(value);
- SuccessOrExit(error = ParseLong(aArgs[1], value));
+ if (aArgsLength >= 2)
+ {
+ SuccessOrExit(error = ParseLong(aArgs[1], value));
+ mIsTxPacketSet = false;
+ }
+ else if (mIsTxPacketSet)
+ {
+ value = mTxPacket->mLength;
+ }
+ else
+ {
+ ExitNow(error = kErrorInvalidArgs);
+ }
+
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs);
VerifyOrExit(value >= OT_RADIO_FRAME_MIN_SIZE, error = kErrorInvalidArgs);
mTxLen = static_cast(value);
@@ -316,12 +350,25 @@ Error Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size
long value;
VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
- VerifyOrExit(aArgsLength == 2, error = kErrorInvalidArgs);
+ VerifyOrExit(aArgsLength >= 1, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
mTxPackets = static_cast(value);
- SuccessOrExit(error = ParseLong(aArgs[1], value));
+ if (aArgsLength >= 2)
+ {
+ SuccessOrExit(ParseLong(aArgs[1], value));
+ mIsTxPacketSet = false;
+ }
+ else if (mIsTxPacketSet)
+ {
+ value = mTxPacket->mLength;
+ }
+ else
+ {
+ ExitNow(error = kErrorInvalidArgs);
+ }
+
VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs);
VerifyOrExit(value >= OT_RADIO_FRAME_MIN_SIZE, error = kErrorInvalidArgs);
mTxLen = static_cast(value);
@@ -420,12 +467,16 @@ exit:
void Diags::TransmitPacket(void)
{
- mTxPacket->mLength = mTxLen;
mTxPacket->mChannel = mChannel;
- for (uint8_t i = 0; i < mTxLen; i++)
+ if (!mIsTxPacketSet)
{
- mTxPacket->mPsdu[i] = i;
+ mTxPacket->mLength = mTxLen;
+
+ for (uint8_t i = 0; i < mTxLen; i++)
+ {
+ mTxPacket->mPsdu[i] = i;
+ }
}
mDiagSendOn = true;
@@ -986,4 +1037,5 @@ OT_TOOL_WEAK otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
return OT_ERROR_NOT_IMPLEMENTED;
}
+
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp
index 1b72a1563..cb1c7b95b 100644
--- a/src/core/diags/factory_diags.hpp
+++ b/src/core/diags/factory_diags.hpp
@@ -181,6 +181,7 @@ private:
Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessFrame(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
@@ -217,6 +218,7 @@ private:
uint8_t mChannel;
int8_t mTxPower;
uint8_t mTxLen;
+ bool mIsTxPacketSet;
bool mRepeatActive;
bool mDiagSendOn;
#endif
diff --git a/tests/scripts/expect/cli-diags.exp b/tests/scripts/expect/cli-diags.exp
index e5d2fbfab..b9ab58071 100755
--- a/tests/scripts/expect/cli-diags.exp
+++ b/tests/scripts/expect/cli-diags.exp
@@ -126,6 +126,35 @@ expect "start diagnostics mode"
expect "status 0x00"
expect_line "Done"
+send_user "input too short test\n"
+send "diag frame 11\n"
+expect "Error"
+
+send_user "input too long test\n"
+send "diag frame 11223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900\n"
+expect "Error"
+
+send_user "input odd length test\n"
+send "diag frame 123\n"
+expect "Error"
+
+send_user "shortest frame test\n"
+send "diag frame 112233\n"
+expect "Done"
+send "diag send 1\n"
+expect "length 0x3"
+expect "Done"
+
+send_user "longest frame test\n"
+send "diag frame 11223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677\n"
+expect "Done"
+send "diag repeat 1\n"
+expect "length 0x7f"
+expect "Done"
+
+send "diag repeat stop\n"
+expect "Done"
+
send "diag channel 11\n"
expect "set channel to 11"
expect "status 0x00"