diff --git a/src/core/diags/README.md b/src/core/diags/README.md index 95cedf531..595a06e9e 100644 --- a/src/core/diags/README.md +++ b/src/core/diags/README.md @@ -80,7 +80,7 @@ Done ### diag frame -Usage: `diag frame [-b MaxCsmaBackoffs] [-c] [-C RxChannelAfterTxDone] [-d TxDelay] [-p TxPower] [-r MaxFrameRetries] [-s] ` +Usage: `diag frame [-b MaxCsmaBackoffs] [-c] [-C RxChannelAfterTxDone] [-d TxDelay] [-p TxPower] [-r MaxFrameRetries] [-s] [-u] ` 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`. @@ -91,6 +91,7 @@ Set the frame (hex encoded) to be used by `diag send` and `diag repeat`. The fra - Specify `-p` to specify the tx power in dBm for this frame. - Specify `-r` to specify the `mInfo.mTxInfo.mMaxFrameRetries` field for this frame. - Specify `-s` to indicate that tx security is already processed thus it should be skipped in the radio layer. +- Specify `-u` to specify the `mInfo.mTxInfo.mIsHeaderUpdated` field for this frame. ```bash > diag frame 11223344 diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp index 784585bc2..914061b6c 100644 --- a/src/core/diags/factory_diags.cpp +++ b/src/core/diags/factory_diags.cpp @@ -212,6 +212,7 @@ Diags::Diags(Instance &aInstance) void Diags::ResetTxPacket(void) { + mIsHeaderUpdated = false; mTxPacket->mInfo.mTxInfo.mTxDelayBaseTime = 0; mTxPacket->mInfo.mTxInfo.mTxDelay = 0; mTxPacket->mInfo.mTxInfo.mMaxCsmaBackoffs = 0; @@ -231,6 +232,7 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) uint16_t size = OT_RADIO_FRAME_MAX_SIZE; bool securityProcessed = false; bool csmaCaEnabled = false; + bool isHeaderUpdated = false; int8_t txPower = OT_RADIO_POWER_INVALID; uint8_t maxFrameRetries = 0; uint8_t maxCsmaBackoffs = 0; @@ -289,6 +291,11 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) else if (StringMatch(aArgs[0], "-s")) { securityProcessed = true; + isHeaderUpdated = true; + } + else if (StringMatch(aArgs[0], "-u")) + { + isHeaderUpdated = true; } else { @@ -315,6 +322,7 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) mTxPacket->mInfo.mTxInfo.mMaxCsmaBackoffs = maxCsmaBackoffs; mTxPacket->mInfo.mTxInfo.mRxChannelAfterTxDone = rxChannelAfterTxDone; mTxPacket->mLength = size; + mIsHeaderUpdated = isHeaderUpdated; mIsTxPacketSet = true; exit: @@ -556,7 +564,13 @@ void Diags::TransmitPacket(void) { mTxPacket->mChannel = mChannel; - if (!mIsTxPacketSet) + if (mIsTxPacketSet) + { + // The `mInfo.mTxInfo.mIsHeaderUpdated` field may be updated by the radio driver after the frame is sent, + // set the `mInfo.mTxInfo.mIsHeaderUpdated` field before transmitting the frame. + mTxPacket->mInfo.mTxInfo.mIsHeaderUpdated = mIsHeaderUpdated; + } + else { ResetTxPacket(); mTxPacket->mLength = mTxLen; diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp index 074006202..354ac78c6 100644 --- a/src/core/diags/factory_diags.hpp +++ b/src/core/diags/factory_diags.hpp @@ -217,9 +217,10 @@ private: uint8_t mChannel; int8_t mTxPower; uint8_t mTxLen; - bool mIsTxPacketSet; - bool mRepeatActive; - bool mDiagSendOn; + bool mIsHeaderUpdated : 1; + bool mIsTxPacketSet : 1; + bool mRepeatActive : 1; + bool mDiagSendOn : 1; #endif otDiagOutputCallback mOutputCallback; diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index 52fec803d..f467c1f28 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -1583,10 +1583,8 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand, error = SpinelStatusToOtError(status); } - static_cast(mTransmitFrame)->SetIsHeaderUpdated(headerUpdated); - - if ((sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && headerUpdated && - static_cast(mTransmitFrame)->GetSecurityEnabled()) + if ((sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && (!mTransmitFrame->mInfo.mTxInfo.mIsHeaderUpdated) && + headerUpdated && static_cast(mTransmitFrame)->GetSecurityEnabled()) { uint8_t keyId; uint32_t frameCounter; @@ -1603,6 +1601,8 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand, #endif } + static_cast(mTransmitFrame)->SetIsHeaderUpdated(headerUpdated); + exit: // A parse error indicates an RCP misbehavior, so recover the RCP immediately. mState = kStateTransmitDone;