88#include <zephyr/drivers/gpio.h>
99
1010#include <openthread/error.h>
11+ #include <openthread/platform/alarm-milli.h>
1112#include <openthread/platform/diag.h>
13+ #include <openthread/platform/radio.h>
1214
1315#include "platform-zephyr.h"
1416#include "zephyr/sys/util.h"
1517
18+ enum {
19+ DIAG_TRANSMIT_MODE_IDLE ,
20+ DIAG_TRANSMIT_MODE_PACKETS ,
21+ DIAG_TRANSMIT_MODE_CARRIER ,
22+ DIAG_TRANSMIT_MODE_MODCARRIER
23+
24+ } diag_trasmit_mode ;
25+
1626/**
1727 * Diagnostics mode variables.
1828 *
1929 */
30+
2031static bool sDiagMode ;
2132static void * sDiagCallbackContext ;
2233static otPlatDiagOutputCallback sDiagOutputCallback ;
34+ static uint8_t sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
35+ static uint8_t sChannel = 20 ;
36+ static uint32_t sTxPeriod = 1 ;
37+ static int32_t sTxCount ;
38+ static int32_t sTxRequestedCount = 1 ;
2339
2440static otError startModCarrier (otInstance * aInstance , uint8_t aArgsLength , char * aArgs []);
41+ static otError processTransmit (otInstance * aInstance , uint8_t aArgsLength , char * aArgs []);
42+
43+ static otError parse_long (char * aArgs , long * aValue )
44+ {
45+ char * endptr ;
46+ * aValue = strtol (aArgs , & endptr , 0 );
47+ return (* endptr == '\0' ) ? OT_ERROR_NONE : OT_ERROR_PARSE ;
48+ }
2549
2650static void diag_output (const char * aFormat , ...)
2751{
@@ -48,15 +72,16 @@ void otPlatDiagSetOutputCallback(otInstance *aInstance,
4872
4973otError otPlatDiagProcess (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
5074{
51- ARG_UNUSED (aInstance );
52- ARG_UNUSED (aArgsLength );
53-
5475#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS )
5576 if (strcmp (aArgs [0 ], "modcarrier" ) == 0 ) {
5677 return startModCarrier (aInstance , aArgsLength - 1 , aArgs + 1 );
5778 }
5879#endif
5980
81+ if (strcmp (aArgs [0 ], "transmit" ) == 0 ) {
82+ return processTransmit (aInstance , aArgsLength - 1 , aArgs + 1 );
83+ }
84+
6085 /* Add more platform specific diagnostics features here. */
6186 diag_output ("diag feature '%s' is not supported\r\n" , aArgs [0 ]);
6287
@@ -80,6 +105,7 @@ bool otPlatDiagModeGet(void)
80105void otPlatDiagChannelSet (uint8_t aChannel )
81106{
82107 ARG_UNUSED (aChannel );
108+ sChannel = aChannel ;
83109}
84110
85111void otPlatDiagTxPowerSet (int8_t aTxPower )
@@ -99,19 +125,21 @@ void otPlatDiagRadioReceived(otInstance *aInstance,
99125#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS )
100126otError otPlatDiagRadioTransmitCarrier (otInstance * aInstance , bool aEnable )
101127{
102- if (!otPlatDiagModeGet ()) {
128+ if (!otPlatDiagModeGet () || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
129+ sTransmitMode != DIAG_TRANSMIT_MODE_CARRIER )) {
103130 return OT_ERROR_INVALID_STATE ;
104131 }
105132
133+ if (aEnable ) {
134+ sTransmitMode = DIAG_TRANSMIT_MODE_CARRIER ;
135+ } else {
136+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
137+ }
138+
106139 return platformRadioTransmitCarrier (aInstance , aEnable );
107140}
108141#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */
109142
110- void otPlatDiagAlarmCallback (otInstance * aInstance )
111- {
112- ARG_UNUSED (aInstance );
113- }
114-
115143/*
116144 * To enable gpio diag commands, in Devicetree create `openthread` node in `/options/` path
117145 * with `compatible = "openthread,config"` property and `diag-gpios` property,
@@ -291,25 +319,154 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
291319
292320static otError startModCarrier (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
293321{
294- ARG_UNUSED (aInstance );
295- ARG_UNUSED (aArgsLength );
296-
297322 bool enable = true;
298323 uint8_t data [OT_RADIO_FRAME_MAX_SIZE + 1 ];
299324
300325 if (aArgsLength <= 0 ) {
301326 return OT_ERROR_INVALID_ARGS ;
302327 }
303328
329+ if (!otPlatDiagModeGet () || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
330+ sTransmitMode != DIAG_TRANSMIT_MODE_MODCARRIER )) {
331+ return OT_ERROR_INVALID_STATE ;
332+ }
333+
304334 if (strcmp (aArgs [0 ], "stop" ) == 0 ) {
305335 enable = false;
336+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
306337 } else {
307338 if (hex2bin (aArgs [0 ], strlen (aArgs [0 ]), data , ARRAY_SIZE (data )) == 0 ) {
308339 return OT_ERROR_INVALID_ARGS ;
309340 }
341+ sTransmitMode = DIAG_TRANSMIT_MODE_MODCARRIER ;
310342 }
311343
312344 return platformRadioTransmitModulatedCarrier (aInstance , enable , data );
313345}
314346
315347#endif
348+
349+ void otPlatDiagAlarmCallback (otInstance * aInstance )
350+ {
351+ uint32_t now ;
352+ otRadioFrame * txPacket ;
353+ const uint16_t diag_packet_len = 30 ;
354+
355+ if (sTransmitMode == DIAG_TRANSMIT_MODE_PACKETS ) {
356+ if ((sTxCount > 0 ) || (sTxCount == -1 )) {
357+ txPacket = otPlatRadioGetTransmitBuffer (aInstance );
358+
359+ txPacket -> mInfo .mTxInfo .mTxDelayBaseTime = 0 ;
360+ txPacket -> mInfo .mTxInfo .mTxDelay = 0 ;
361+ txPacket -> mInfo .mTxInfo .mMaxCsmaBackoffs = 0 ;
362+ txPacket -> mInfo .mTxInfo .mMaxFrameRetries = 0 ;
363+ txPacket -> mInfo .mTxInfo .mRxChannelAfterTxDone = sChannel ;
364+ txPacket -> mInfo .mTxInfo .mTxPower = OT_RADIO_POWER_INVALID ;
365+ txPacket -> mInfo .mTxInfo .mIsHeaderUpdated = false;
366+ txPacket -> mInfo .mTxInfo .mIsARetx = false;
367+ txPacket -> mInfo .mTxInfo .mCsmaCaEnabled = false;
368+ txPacket -> mInfo .mTxInfo .mCslPresent = false;
369+ txPacket -> mInfo .mTxInfo .mIsSecurityProcessed = false;
370+
371+ txPacket -> mLength = diag_packet_len ;
372+
373+ for (uint8_t i = 0 ; i < diag_packet_len ; i ++ ) {
374+ txPacket -> mPsdu [i ] = i ;
375+ }
376+
377+ otPlatRadioTransmit (aInstance , txPacket );
378+
379+ if (sTxCount != -1 ) {
380+ sTxCount -- ;
381+ }
382+
383+ now = otPlatAlarmMilliGetNow ();
384+ otPlatAlarmMilliStartAt (aInstance , now , sTxPeriod );
385+ } else {
386+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
387+ otPlatAlarmMilliStop (aInstance );
388+ otPlatLog (OT_LOG_LEVEL_DEBG , OT_LOG_REGION_PLATFORM , "Transmit done" );
389+ }
390+ }
391+ }
392+
393+ static otError processTransmit (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
394+ {
395+ otError error = OT_ERROR_NONE ;
396+ long value ;
397+ uint32_t now ;
398+
399+ if (!otPlatDiagModeGet ()) {
400+ return OT_ERROR_INVALID_STATE ;
401+ }
402+
403+ if (aArgsLength == 0 ) {
404+ diag_output ("transmit will send %" PRId32 " diagnostic messages with %" PRIu32
405+ " ms interval\r\n" ,
406+ sTxRequestedCount , sTxPeriod );
407+
408+ } else if (strcmp (aArgs [0 ], "stop" ) == 0 ) {
409+ if (sTransmitMode == DIAG_TRANSMIT_MODE_IDLE ) {
410+ return OT_ERROR_INVALID_STATE ;
411+ }
412+
413+ otPlatAlarmMilliStop (aInstance );
414+ diag_output ("diagnostic message transmission is stopped\r\n" );
415+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
416+ otPlatRadioReceive (aInstance , sChannel );
417+
418+ } else if (strcmp (aArgs [0 ], "start" ) == 0 ) {
419+ if (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE ) {
420+ return OT_ERROR_INVALID_STATE ;
421+ }
422+
423+ otPlatAlarmMilliStop (aInstance );
424+ sTransmitMode = DIAG_TRANSMIT_MODE_PACKETS ;
425+ sTxCount = sTxRequestedCount ;
426+ now = otPlatAlarmMilliGetNow ();
427+ otPlatAlarmMilliStartAt (aInstance , now , sTxPeriod );
428+ diag_output ("sending %" PRId32 " diagnostic messages with %" PRIu32
429+ " ms interval\r\n" ,
430+ sTxRequestedCount , sTxPeriod );
431+ } else if (strcmp (aArgs [0 ], "interval" ) == 0 ) {
432+
433+ if (aArgsLength != 2 ) {
434+ return OT_ERROR_INVALID_ARGS ;
435+ }
436+
437+ error = parse_long (aArgs [1 ], & value );
438+ if (error != OT_ERROR_NONE ) {
439+ return error ;
440+ }
441+
442+ if (value <= 0 ) {
443+ return OT_ERROR_INVALID_ARGS ;
444+ }
445+ sTxPeriod = (uint32_t )(value );
446+ diag_output ("set diagnostic messages interval to %" PRIu32
447+ " ms\r\n" , sTxPeriod );
448+
449+ } else if (strcmp (aArgs [0 ], "count" ) == 0 ) {
450+
451+ if (aArgsLength != 2 ) {
452+ return OT_ERROR_INVALID_ARGS ;
453+ }
454+
455+ error = parse_long (aArgs [1 ], & value );
456+ if (error != OT_ERROR_NONE ) {
457+ return error ;
458+ }
459+
460+ if ((value <= 0 ) && (value != -1 )) {
461+ return OT_ERROR_INVALID_ARGS ;
462+ }
463+
464+ sTxRequestedCount = (uint32_t )(value );
465+ diag_output ("set diagnostic messages count to %" PRId32 "\r\n" ,
466+ sTxRequestedCount );
467+ } else {
468+ return OT_ERROR_INVALID_ARGS ;
469+ }
470+
471+ return error ;
472+ }
0 commit comments