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