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 "lib/spinel/multi_frame_buffer.hpp" 40 #include "ncp/ncp_base.hpp" 41 42 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 43 #include "lib/spinel/spinel_encrypter.hpp" 44 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 45 46 namespace ot { 47 namespace Ncp { 48 49 class NcpHdlc : public NcpBase 50 { 51 typedef NcpBase super_t; 52 53 public: 54 /** 55 * Constructor 56 * 57 * @param[in] aInstance The OpenThread instance structure. 58 * 59 */ 60 explicit NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback); 61 62 /** 63 * Is called when uart tx is finished. It prepares and sends the next data chunk (if any) to uart. 64 * 65 */ 66 void HandleHdlcSendDone(void); 67 68 /** 69 * Is called when uart received a data buffer. 70 * 71 */ 72 void HandleHdlcReceiveDone(const uint8_t *aBuf, uint16_t aBufLength); 73 74 private: 75 enum 76 { 77 kHdlcTxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE, // HDLC tx buffer size. 78 kRxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE + // Rx buffer size (should be large enough to fit 79 OPENTHREAD_CONFIG_NCP_SPINEL_ENCRYPTER_EXTRA_DATA_SIZE, // one whole (decoded) received frame). 80 }; 81 82 enum HdlcTxState 83 { 84 kStartingFrame, // Starting a new frame. 85 kEncodingFrame, // In middle of encoding a frame. 86 kFinalizingFrame, // Finalizing a frame. 87 }; 88 89 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 90 /** 91 * Wraps Spinel::Buffer allowing to read data through spinel encrypter. 92 * Creates additional buffers to allow transforming of the whole spinel frames. 93 */ 94 class BufferEncrypterReader 95 { 96 public: 97 /** 98 * C-tor. 99 * Takes a reference to Spinel::Buffer in order to read spinel frames. 100 */ 101 explicit BufferEncrypterReader(Spinel::Buffer &aTxFrameBuffer); 102 bool IsEmpty(void) const; 103 otError OutFrameBegin(void); 104 bool OutFrameHasEnded(void); 105 uint8_t OutFrameReadByte(void); 106 otError OutFrameRemove(void); 107 108 private: 109 void Reset(void); 110 111 Spinel::Buffer &mTxFrameBuffer; 112 uint8_t mDataBuffer[kRxBufferSize]; 113 size_t mDataBufferReadIndex; 114 size_t mOutputDataLength; 115 }; 116 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 117 118 void EncodeAndSend(void); 119 void HandleFrame(otError aError); 120 void HandleError(otError aError, uint8_t *aBuf, uint16_t aBufLength); 121 void TxFrameBufferHasData(void); 122 void HandleFrameAddedToNcpBuffer(void); 123 124 static void EncodeAndSend(Tasklet &aTasklet); 125 static void HandleFrame(void *aContext, otError aError); 126 static void HandleFrameAddedToNcpBuffer(void *aContext, 127 Spinel::Buffer::FrameTag aTag, 128 Spinel::Buffer::Priority aPriority, 129 Spinel::Buffer *aBuffer); 130 otNcpHdlcSendCallback mSendCallback; 131 132 Spinel::FrameBuffer<kHdlcTxBufferSize> mHdlcBuffer; 133 Hdlc::Encoder mFrameEncoder; 134 Hdlc::Decoder mFrameDecoder; 135 HdlcTxState mState; 136 uint8_t mByte; 137 Spinel::FrameBuffer<kRxBufferSize> mRxBuffer; 138 bool mHdlcSendImmediate; 139 Tasklet mHdlcSendTask; 140 141 #if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 142 BufferEncrypterReader mTxFrameBufferEncrypterReader; 143 #endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 144 }; 145 146 } // namespace Ncp 147 } // namespace ot 148 149 #endif // NCP_HDLC_HPP_ 150