1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /** 29 * @file 30 * This file contains definitions for a HDLC based NCP interface to the OpenThread stack. 31 */ 32 33 #ifndef NCP_HDLC_HPP_ 34 #define NCP_HDLC_HPP_ 35 36 #include "openthread-core-config.h" 37 38 #include "lib/hdlc/hdlc.hpp" 39 #include "ncp/ncp_base.hpp" 40 41 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 42 #include "lib/spinel/spinel_encrypter.hpp" 43 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 44 45 namespace ot { 46 namespace Ncp { 47 48 class NcpHdlc : public NcpBase 49 { 50 typedef NcpBase super_t; 51 52 public: 53 /** 54 * Constructor 55 * 56 * @param[in] aInstance The OpenThread instance structure. 57 * 58 */ 59 explicit NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback); 60 61 /** 62 * This method is called when uart tx is finished. It prepares and sends the next data chunk (if any) to uart. 63 * 64 */ 65 void HandleHdlcSendDone(void); 66 67 /** 68 * This method is called when uart received a data buffer. 69 * 70 */ 71 void HandleHdlcReceiveDone(const uint8_t *aBuf, uint16_t aBufLength); 72 73 private: 74 enum 75 { 76 kHdlcTxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE, // HDLC tx buffer size. 77 kRxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE + // Rx buffer size (should be large enough to fit 78 OPENTHREAD_CONFIG_NCP_SPINEL_ENCRYPTER_EXTRA_DATA_SIZE, // one whole (decoded) received frame). 79 }; 80 81 enum HdlcTxState 82 { 83 kStartingFrame, // Starting a new frame. 84 kEncodingFrame, // In middle of encoding a frame. 85 kFinalizingFrame, // Finalizing a frame. 86 }; 87 88 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 89 /** 90 * Wraps Spinel::Buffer allowing to read data through spinel encrypter. 91 * Creates additional buffers to allow transforming of the whole spinel frames. 92 */ 93 class BufferEncrypterReader 94 { 95 public: 96 /** 97 * C-tor. 98 * Takes a reference to Spinel::Buffer in order to read spinel frames. 99 */ 100 explicit BufferEncrypterReader(Spinel::Buffer &aTxFrameBuffer); 101 bool IsEmpty(void) const; 102 otError OutFrameBegin(void); 103 bool OutFrameHasEnded(void); 104 uint8_t OutFrameReadByte(void); 105 otError OutFrameRemove(void); 106 107 private: 108 void Reset(void); 109 110 Spinel::Buffer &mTxFrameBuffer; 111 uint8_t mDataBuffer[kRxBufferSize]; 112 size_t mDataBufferReadIndex; 113 size_t mOutputDataLength; 114 }; 115 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 116 117 void EncodeAndSend(void); 118 void HandleFrame(otError aError); 119 void HandleError(otError aError, uint8_t *aBuf, uint16_t aBufLength); 120 void TxFrameBufferHasData(void); 121 void HandleFrameAddedToNcpBuffer(void); 122 123 static void EncodeAndSend(Tasklet &aTasklet); 124 static void HandleFrame(void *aContext, otError aError); 125 static void HandleFrameAddedToNcpBuffer(void *aContext, 126 Spinel::Buffer::FrameTag aTag, 127 Spinel::Buffer::Priority aPriority, 128 Spinel::Buffer *aBuffer); 129 otNcpHdlcSendCallback mSendCallback; 130 131 Hdlc::FrameBuffer<kHdlcTxBufferSize> mHdlcBuffer; 132 Hdlc::Encoder mFrameEncoder; 133 Hdlc::Decoder mFrameDecoder; 134 HdlcTxState mState; 135 uint8_t mByte; 136 Hdlc::FrameBuffer<kRxBufferSize> mRxBuffer; 137 bool mHdlcSendImmediate; 138 Tasklet mHdlcSendTask; 139 140 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 141 BufferEncrypterReader mTxFrameBufferEncrypterReader; 142 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 143 }; 144 145 } // namespace Ncp 146 } // namespace ot 147 148 #endif // NCP_HDLC_HPP_ 149