void Uart::Send(void) { VerifyOrExit(mSendLength == 0); if (mTxLength > kTxBufferSize - mTxHead) { mSendLength = kTxBufferSize - mTxHead; } else { mSendLength = mTxLength; } if (mSendLength > 0) { #if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART /* duplicate the output to the debug uart */ otPlatDebugUart_write_bytes(reinterpret_cast<uint8_t *>(mTxBuffer + mTxHead), mSendLength); #endif otPlatUartSend(reinterpret_cast<uint8_t *>(mTxBuffer + mTxHead), mSendLength); } exit: return; }
// This method encodes a frame from the tx frame buffer (mTxFrameBuffer) into the uart buffer and sends it over uart. // If the uart buffer gets full, it sends the current encoded portion. This method remembers current state, so on // sub-sequent calls, it restarts encoding the bytes from where it left of in the frame . void NcpUart::EncodeAndSendToUart(void) { uint16_t len; while (!mTxFrameBuffer.IsEmpty()) { switch (mState) { case kStartingFrame: SuccessOrExit(mFrameEncoder.Init(mUartBuffer)); mTxFrameBuffer.OutFrameBegin(); mState = kEncodingFrame; while (!mTxFrameBuffer.OutFrameHasEnded()) { mByte = mTxFrameBuffer.OutFrameReadByte(); case kEncodingFrame: SuccessOrExit(mFrameEncoder.Encode(mByte, mUartBuffer)); } mTxFrameBuffer.OutFrameRemove(); // Notify the super/base class that there is space available in tx frame buffer for a new frame. super_t::HandleSpaceAvailableInTxBuffer(); mState = kFinalizingFrame; // fall through case kFinalizingFrame: SuccessOrExit(mFrameEncoder.Finalize(mUartBuffer)); mState = kStartingFrame; } } exit: len = mUartBuffer.GetLength(); if (len > 0) { otPlatUartSend(mUartBuffer.GetBuffer(), len); } }
ThreadError NcpUart::OutboundFrameSend(void) { ThreadError errorCode; uint16_t outLength(OutboundFrameGetRemaining()); errorCode = mFrameEncoder.Finalize(mSendFrameIter, outLength); if (errorCode == kThreadError_None) { mSendFrameIter += outLength; errorCode = otPlatUartSend(mSendFrame, mSendFrameIter - mSendFrame); } if (errorCode == kThreadError_None) { mSending = true; } return errorCode; }
// This method encodes a frame from the tx frame buffer (mTxFrameBuffer) into the uart buffer and sends it over uart. // If the uart buffer gets full, it sends the current encoded portion. This method remembers current state, so on // sub-sequent calls, it restarts encoding the bytes from where it left of in the frame . void NcpUart::EncodeAndSendToUart(void) { uint16_t len; bool prevHostPowerState; #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER NcpFrameBufferEncrypterReader &txFrameBuffer = mTxFrameBufferEncrypterReader; #else NcpFrameBuffer &txFrameBuffer = mTxFrameBuffer; #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER while (!txFrameBuffer.IsEmpty() || (mState == kFinalizingFrame)) { switch (mState) { case kStartingFrame: if (super_t::ShouldWakeHost()) { otPlatWakeHost(); } VerifyOrExit(super_t::ShouldDeferHostSend() == false); SuccessOrExit(mFrameEncoder.Init(mUartBuffer)); txFrameBuffer.OutFrameBegin(); mState = kEncodingFrame; while (!txFrameBuffer.OutFrameHasEnded()) { mByte = txFrameBuffer.OutFrameReadByte(); case kEncodingFrame: SuccessOrExit(mFrameEncoder.Encode(mByte, mUartBuffer)); } // track the change of mHostPowerStateInProgress by the // call to OutFrameRemove. prevHostPowerState = mHostPowerStateInProgress; txFrameBuffer.OutFrameRemove(); if (prevHostPowerState && !mHostPowerStateInProgress) { // If mHostPowerStateInProgress transitioned from true -> false // in the call to OutFrameRemove, then the frame should be sent // out the UART without attempting to push any new frames into // the mUartBuffer. This is necessary to avoid prematurely calling // otPlatWakeHost. mUartSendImmediate = true; } mState = kFinalizingFrame; // fall through case kFinalizingFrame: SuccessOrExit(mFrameEncoder.Finalize(mUartBuffer)); mState = kStartingFrame; if (mUartSendImmediate) { // clear state and break; mUartSendImmediate = false; break; } } } exit: len = mUartBuffer.GetLength(); if (len > 0) { if (otPlatUartSend(mUartBuffer.GetBuffer(), len) != OT_ERROR_NONE) { assert(false); } } }