otError NcpBase::HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader) { const uint8_t *frameBuffer = NULL; otRadioFrame * frame; uint16_t frameLen = 0; otError error = OT_ERROR_NONE; VerifyOrExit(otLinkRawIsEnabled(mInstance), error = OT_ERROR_INVALID_STATE); frame = otLinkRawGetTransmitBuffer(mInstance); SuccessOrExit(error = mDecoder.ReadDataWithLen(frameBuffer, frameLen)); SuccessOrExit(error = mDecoder.ReadUint8(frame->mChannel)); VerifyOrExit(frameLen <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_PARSE); // Cache the transaction ID for async response mCurTransmitTID = SPINEL_HEADER_GET_TID(aHeader); // Update frame buffer and length frame->mLength = static_cast<uint8_t>(frameLen); memcpy(frame->mPsdu, frameBuffer, frame->mLength); // TODO: This should be later added in the STREAM_RAW argument to allow user to directly specify it. frame->mInfo.mTxInfo.mMaxCsmaBackoffs = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT; frame->mInfo.mTxInfo.mMaxFrameRetries = OPENTHREAD_CONFIG_MAC_MAX_FRAME_RETRIES_DIRECT; // Pass frame to the radio layer. Note, this fails if we // haven't enabled raw stream or are already transmitting. error = otLinkRawTransmit(mInstance, frame, &NcpBase::LinkRawTransmitDone); exit: if (error == OT_ERROR_NONE) { // Don't do anything here yet. We will complete the transaction when we get a transmit done callback } else { error = WriteLastStatusFrame(aHeader, ThreadErrorToSpinelStatus(error)); } return error; }
otError NcpBase::HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader) { bool enabled = false; otError error = OT_ERROR_NONE; SuccessOrExit(error = mDecoder.ReadBool(enabled)); if (enabled == false) { error = otCommissionerStop(mInstance); } else { error = otCommissionerStart(mInstance); } exit: return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error)); }
void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError) { if (mCurTransmitTID) { uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | mCurTransmitTID; bool framePending = (aAckFrame != NULL && static_cast<Mac::Frame *>(aAckFrame)->GetFramePending()); // Clear cached transmit TID mCurTransmitTID = 0; SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_LAST_STATUS)); SuccessOrExit(mEncoder.WriteUintPacked(ThreadErrorToSpinelStatus(aError))); SuccessOrExit(mEncoder.WriteBool(framePending)); if (aAckFrame && aError == OT_ERROR_NONE) { SuccessOrExit(mEncoder.WriteUint16(aAckFrame->mLength)); SuccessOrExit(mEncoder.WriteData(aAckFrame->mPsdu, aAckFrame->mLength)); SuccessOrExit(mEncoder.WriteInt8(aAckFrame->mInfo.mRxInfo.mRssi)); // RSSI SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise Floor (Currently unused) SuccessOrExit(mEncoder.WriteUint16(0)); // Flags SuccessOrExit(mEncoder.OpenStruct()); // PHY-data SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mInfo.mRxInfo.mLqi)); // Link Quality Indicator SuccessOrExit(mEncoder.CloseStruct()); } SuccessOrExit(mEncoder.EndFrame()); } exit: OT_UNUSED_VARIABLE(aFrame); return; }