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