otError LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback) { otError error = OT_ERROR_INVALID_STATE; if (mEnabled) { mEnergyScanDoneCallback = aCallback; #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN // Start listening on the scan channel otPlatRadioReceive(&mInstance, aScanChannel); // Reset the RSSI value and start scanning mEnergyScanRssi = kInvalidRssiValue; mTimerReason = kTimerReasonEnergyScanComplete; mTimer.Start(aScanDuration); mEnergyScanTask.Post(); #else // Do the HW offloaded energy scan error = otPlatRadioEnergyScan(&mInstance, aScanChannel, aScanDuration); #endif } return error; }
void LinkRaw::InvokeTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError) { otLogDebgPlat(&mInstance, "LinkRaw Transmit Done (err=0x%x)", aError); #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT mTimer.Stop(); #endif #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE) { if (mCsmaAttempts < Mac::kMaxCSMABackoffs) { mCsmaAttempts++; StartCsmaBackoff(); goto exit; } } else { mCsmaAttempts = 0; } if (aError == OT_ERROR_NO_ACK) { if (mTransmitAttempts < aFrame->mMaxTxAttempts) { mTransmitAttempts++; StartCsmaBackoff(); goto exit; } } #endif // Transition back to receive state on previous channel otPlatRadioReceive(&mInstance, mReceiveChannel); if (mTransmitDoneCallback) { if (aError == OT_ERROR_NONE) { otLogInfoPlat(&mInstance, "LinkRaw Invoke Transmit Done"); } else { otLogWarnPlat(&mInstance, "LinkRaw Invoke Transmit Failed (err=0x%x)", aError); } mTransmitDoneCallback(&mInstance, aFrame, aAckFrame, aError); mTransmitDoneCallback = NULL; } #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT exit: return; #endif }
void LinkRaw::HandleTimer(void) { TimerReason timerReason = mTimerReason; mTimerReason = kTimerReasonNone; switch (timerReason) { #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT case kTimerReasonAckTimeout: { // Transition back to receive state on previous channel otPlatRadioReceive(&mInstance, mReceiveChannel); // Invoke completion callback for transmit InvokeTransmitDone(otPlatRadioGetTransmitBuffer(&mInstance), NULL, OT_ERROR_NO_ACK); break; } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT case kTimerReasonRetransmitTimeout: { otRadioFrame *aFrame = otPlatRadioGetTransmitBuffer(&mInstance); // Start the transmit now otError error = DoTransmit(aFrame); if (error != OT_ERROR_NONE) { InvokeTransmitDone(aFrame, NULL, error); } break; } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN case kTimerReasonEnergyScanComplete: { // Invoke completion callback for the energy scan InvokeEnergyScanDone(mEnergyScanRssi); break; } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN default: assert(false); } }
otError LinkRaw::Receive(uint8_t aChannel, otLinkRawReceiveDone aCallback) { otError error = OT_ERROR_INVALID_STATE; if (mEnabled) { mReceiveChannel = aChannel; mReceiveDoneCallback = aCallback; error = otPlatRadioReceive(&mInstance, aChannel); } return error; }
void Mac::NextOperation(void) { switch (mState) { case kStateActiveScan: mReceiveFrame.SetChannel(mScanChannel); otPlatRadioReceive(&mReceiveFrame); break; default: if (mRxOnWhenIdle || mReceiveTimer.IsRunning()) { mReceiveFrame.SetChannel(mChannel); otPlatRadioReceive(&mReceiveFrame); } else { otPlatRadioSleep(); } break; } }