Skip to content

Commit

Permalink
net: openthread: Adding diag transmit command.
Browse files Browse the repository at this point in the history
Commit adds `diag transmit` used for transmission IEEE802154 packets
in specific amount and interval.

Signed-off-by: Przemyslaw Bida <[email protected]>
  • Loading branch information
canisLupus1313 committed Dec 16, 2024
1 parent 7c4abb1 commit 76df2ad
Showing 1 changed file with 169 additions and 12 deletions.
181 changes: 169 additions & 12 deletions modules/openthread/platform/diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,44 @@
#include <zephyr/drivers/gpio.h>

#include <openthread/error.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>

#include "platform-zephyr.h"
#include "zephyr/sys/util.h"

enum {
DIAG_TRANSMIT_MODE_IDLE,
DIAG_TRANSMIT_MODE_PACKETS,
DIAG_TRANSMIT_MODE_CARRIER,
DIAG_TRANSMIT_MODE_MODCARRIER

} diag_trasmit_mode;

/**
* Diagnostics mode variables.
*
*/

static bool sDiagMode;
static void *sDiagCallbackContext;
static otPlatDiagOutputCallback sDiagOutputCallback;
static uint8_t sTransmitMode = DIAG_TRANSMIT_MODE_IDLE;
static uint8_t sChannel = 20;
static uint32_t sTxPeriod = 1;
static int32_t sTxCount;
static int32_t sTxRequestedCount = 1;

static otError startModCarrier(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]);
static otError processTransmit(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]);

static otError parse_long(char *aArgs, long *aValue)
{
char *endptr;
*aValue = strtol(aArgs, &endptr, 0);
return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE;
}

static void diag_output(const char *aFormat, ...)
{
Expand All @@ -48,15 +72,16 @@ void otPlatDiagSetOutputCallback(otInstance *aInstance,

otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
ARG_UNUSED(aInstance);
ARG_UNUSED(aArgsLength);

#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS)
if (strcmp(aArgs[0], "modcarrier") == 0) {
return startModCarrier(aInstance, aArgsLength - 1, aArgs + 1);
}
#endif

if (strcmp(aArgs[0], "transmit") == 0) {
return processTransmit(aInstance, aArgsLength - 1, aArgs + 1);
}

/* Add more platform specific diagnostics features here. */
diag_output("diag feature '%s' is not supported\r\n", aArgs[0]);

Expand All @@ -80,6 +105,7 @@ bool otPlatDiagModeGet(void)
void otPlatDiagChannelSet(uint8_t aChannel)
{
ARG_UNUSED(aChannel);
sChannel = aChannel;
}

void otPlatDiagTxPowerSet(int8_t aTxPower)
Expand All @@ -99,19 +125,21 @@ void otPlatDiagRadioReceived(otInstance *aInstance,
#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS)
otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
{
if (!otPlatDiagModeGet()) {
if (!otPlatDiagModeGet() || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
sTransmitMode != DIAG_TRANSMIT_MODE_CARRIER)) {
return OT_ERROR_INVALID_STATE;
}

if (aEnable) {
sTransmitMode = DIAG_TRANSMIT_MODE_CARRIER;
} else {
sTransmitMode = DIAG_TRANSMIT_MODE_IDLE;
}

return platformRadioTransmitCarrier(aInstance, aEnable);
}
#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */

void otPlatDiagAlarmCallback(otInstance *aInstance)
{
ARG_UNUSED(aInstance);
}

/*
* To enable gpio diag commands, in Devicetree create `openthread` node in `/options/` path
* with `compatible = "openthread,config"` property and `diag-gpios` property,
Expand Down Expand Up @@ -291,25 +319,154 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)

static otError startModCarrier(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
ARG_UNUSED(aInstance);
ARG_UNUSED(aArgsLength);

bool enable = true;
uint8_t data[OT_RADIO_FRAME_MAX_SIZE + 1];

if (aArgsLength <= 0) {
return OT_ERROR_INVALID_ARGS;
}

if (!otPlatDiagModeGet() || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
sTransmitMode != DIAG_TRANSMIT_MODE_MODCARRIER)) {
return OT_ERROR_INVALID_STATE;
}

if (strcmp(aArgs[0], "stop") == 0) {
enable = false;
sTransmitMode = DIAG_TRANSMIT_MODE_IDLE;
} else {
if (hex2bin(aArgs[0], strlen(aArgs[0]), data, ARRAY_SIZE(data)) == 0) {
return OT_ERROR_INVALID_ARGS;
}
sTransmitMode = DIAG_TRANSMIT_MODE_MODCARRIER;
}

return platformRadioTransmitModulatedCarrier(aInstance, enable, data);
}

#endif

void otPlatDiagAlarmCallback(otInstance *aInstance)
{
uint32_t now;
otRadioFrame *txPacket;
const uint16_t diag_packet_len = 30;

if (sTransmitMode == DIAG_TRANSMIT_MODE_PACKETS) {
if ((sTxCount > 0) || (sTxCount == -1)) {
txPacket = otPlatRadioGetTransmitBuffer(aInstance);

txPacket->mInfo.mTxInfo.mTxDelayBaseTime = 0;
txPacket->mInfo.mTxInfo.mTxDelay = 0;
txPacket->mInfo.mTxInfo.mMaxCsmaBackoffs = 0;
txPacket->mInfo.mTxInfo.mMaxFrameRetries = 0;
txPacket->mInfo.mTxInfo.mRxChannelAfterTxDone = sChannel;
txPacket->mInfo.mTxInfo.mTxPower = OT_RADIO_POWER_INVALID;
txPacket->mInfo.mTxInfo.mIsHeaderUpdated = false;
txPacket->mInfo.mTxInfo.mIsARetx = false;
txPacket->mInfo.mTxInfo.mCsmaCaEnabled = false;
txPacket->mInfo.mTxInfo.mCslPresent = false;
txPacket->mInfo.mTxInfo.mIsSecurityProcessed = false;

txPacket->mLength = diag_packet_len;

for (uint8_t i = 0; i < diag_packet_len; i++) {
txPacket->mPsdu[i] = i;
}

otPlatRadioTransmit(aInstance, txPacket);

if (sTxCount != -1) {
sTxCount--;
}

now = otPlatAlarmMilliGetNow();
otPlatAlarmMilliStartAt(aInstance, now, sTxPeriod);
} else {
sTransmitMode = DIAG_TRANSMIT_MODE_IDLE;
otPlatAlarmMilliStop(aInstance);
otPlatLog(OT_LOG_LEVEL_DEBG, OT_LOG_REGION_PLATFORM, "Transmit done");
}
}
}

static otError processTransmit(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
long value;
uint32_t now;

if (!otPlatDiagModeGet()) {
return OT_ERROR_INVALID_STATE;
}

if (aArgsLength == 0) {
diag_output("transmit will send %" PRId32 " diagnostic messages with %" PRIu32
" ms interval\r\n",
sTxRequestedCount, sTxPeriod);

} else if (strcmp(aArgs[0], "stop") == 0) {
if (sTransmitMode == DIAG_TRANSMIT_MODE_IDLE) {
return OT_ERROR_INVALID_STATE;
}

otPlatAlarmMilliStop(aInstance);
diag_output("diagnostic message transmission is stopped\r\n");
sTransmitMode = DIAG_TRANSMIT_MODE_IDLE;
otPlatRadioReceive(aInstance, sChannel);

} else if (strcmp(aArgs[0], "start") == 0) {
if (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE) {
return OT_ERROR_INVALID_STATE;
}

otPlatAlarmMilliStop(aInstance);
sTransmitMode = DIAG_TRANSMIT_MODE_PACKETS;
sTxCount = sTxRequestedCount;
now = otPlatAlarmMilliGetNow();
otPlatAlarmMilliStartAt(aInstance, now, sTxPeriod);
diag_output("sending %" PRId32 " diagnostic messages with %" PRIu32
" ms interval\r\n",
sTxRequestedCount, sTxPeriod);
} else if (strcmp(aArgs[0], "interval") == 0) {

if (aArgsLength != 2) {
return OT_ERROR_INVALID_ARGS;
}

error = parse_long(aArgs[1], &value);
if (error != OT_ERROR_NONE) {
return error;
}

if (value <= 0) {
return OT_ERROR_INVALID_ARGS;
}
sTxPeriod = (uint32_t)(value);
diag_output("set diagnostic messages interval to %" PRIu32
" ms\r\n", sTxPeriod);

} else if (strcmp(aArgs[0], "count") == 0) {

if (aArgsLength != 2) {
return OT_ERROR_INVALID_ARGS;
}

error = parse_long(aArgs[1], &value);
if (error != OT_ERROR_NONE) {
return error;
}

if ((value <= 0) && (value != -1)) {
return OT_ERROR_INVALID_ARGS;
}

sTxRequestedCount = (uint32_t)(value);
diag_output("set diagnostic messages count to %" PRId32 "\r\n",
sTxRequestedCount);
} else {
return OT_ERROR_INVALID_ARGS;
}

return error;
}

0 comments on commit 76df2ad

Please sign in to comment.