1*cfb92d14SAndroid Build Coastguard Worker /* 2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2016, The OpenThread Authors. 3*cfb92d14SAndroid Build Coastguard Worker * All rights reserved. 4*cfb92d14SAndroid Build Coastguard Worker * 5*cfb92d14SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 6*cfb92d14SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met: 7*cfb92d14SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright 8*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 9*cfb92d14SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright 10*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the 11*cfb92d14SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution. 12*cfb92d14SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the 13*cfb92d14SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products 14*cfb92d14SAndroid Build Coastguard Worker * derived from this software without specific prior written permission. 15*cfb92d14SAndroid Build Coastguard Worker * 16*cfb92d14SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17*cfb92d14SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18*cfb92d14SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19*cfb92d14SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20*cfb92d14SAndroid Build Coastguard Worker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22*cfb92d14SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23*cfb92d14SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25*cfb92d14SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*cfb92d14SAndroid Build Coastguard Worker */ 27*cfb92d14SAndroid Build Coastguard Worker 28*cfb92d14SAndroid Build Coastguard Worker /** 29*cfb92d14SAndroid Build Coastguard Worker * @file 30*cfb92d14SAndroid Build Coastguard Worker * This file contains definitions for the NCP frame buffer class. 31*cfb92d14SAndroid Build Coastguard Worker */ 32*cfb92d14SAndroid Build Coastguard Worker 33*cfb92d14SAndroid Build Coastguard Worker #ifndef NCP_FRAME_BUFFER_HPP_ 34*cfb92d14SAndroid Build Coastguard Worker #define NCP_FRAME_BUFFER_HPP_ 35*cfb92d14SAndroid Build Coastguard Worker 36*cfb92d14SAndroid Build Coastguard Worker #include "openthread-spinel-config.h" 37*cfb92d14SAndroid Build Coastguard Worker 38*cfb92d14SAndroid Build Coastguard Worker #include <openthread/message.h> 39*cfb92d14SAndroid Build Coastguard Worker 40*cfb92d14SAndroid Build Coastguard Worker namespace ot { 41*cfb92d14SAndroid Build Coastguard Worker namespace Spinel { 42*cfb92d14SAndroid Build Coastguard Worker 43*cfb92d14SAndroid Build Coastguard Worker /** 44*cfb92d14SAndroid Build Coastguard Worker * Implements a buffer/queue for storing Ncp frames. 45*cfb92d14SAndroid Build Coastguard Worker * 46*cfb92d14SAndroid Build Coastguard Worker * A frame can consist of a sequence of data bytes and/or the content of an `otMessage` or a combination of the two. 47*cfb92d14SAndroid Build Coastguard Worker * `Buffer` implements priority FIFO logic for storing and reading frames. Two priority levels of high and low 48*cfb92d14SAndroid Build Coastguard Worker * are supported. Within same priority level first-in-first-out order is preserved. High priority frames are read 49*cfb92d14SAndroid Build Coastguard Worker * ahead of any low priority ones. 50*cfb92d14SAndroid Build Coastguard Worker * 51*cfb92d14SAndroid Build Coastguard Worker */ 52*cfb92d14SAndroid Build Coastguard Worker class Buffer 53*cfb92d14SAndroid Build Coastguard Worker { 54*cfb92d14SAndroid Build Coastguard Worker friend class Encoder; 55*cfb92d14SAndroid Build Coastguard Worker 56*cfb92d14SAndroid Build Coastguard Worker public: 57*cfb92d14SAndroid Build Coastguard Worker /** 58*cfb92d14SAndroid Build Coastguard Worker * Defines the priority of a frame. High priority frames are read before low priority frames. Within same priority 59*cfb92d14SAndroid Build Coastguard Worker * level FIFO order is preserved. 60*cfb92d14SAndroid Build Coastguard Worker * 61*cfb92d14SAndroid Build Coastguard Worker */ 62*cfb92d14SAndroid Build Coastguard Worker enum Priority 63*cfb92d14SAndroid Build Coastguard Worker { 64*cfb92d14SAndroid Build Coastguard Worker kPriorityLow = 0, ///< Indicates low/normal priority for a frame. 65*cfb92d14SAndroid Build Coastguard Worker kPriorityHigh = 1, ///< Indicates high priority for a frame. 66*cfb92d14SAndroid Build Coastguard Worker }; 67*cfb92d14SAndroid Build Coastguard Worker 68*cfb92d14SAndroid Build Coastguard Worker /** 69*cfb92d14SAndroid Build Coastguard Worker * Defines the (abstract) frame tag type. The tag is a unique value (within currently queued frames) associated 70*cfb92d14SAndroid Build Coastguard Worker * with a frame in the `Buffer`. Frame tags can be compared with one another using operator `==`. 71*cfb92d14SAndroid Build Coastguard Worker * 72*cfb92d14SAndroid Build Coastguard Worker */ 73*cfb92d14SAndroid Build Coastguard Worker typedef const void *FrameTag; 74*cfb92d14SAndroid Build Coastguard Worker 75*cfb92d14SAndroid Build Coastguard Worker /** 76*cfb92d14SAndroid Build Coastguard Worker * Defines the tag value indicating an invalid tag (e.g., when there is no frame). 77*cfb92d14SAndroid Build Coastguard Worker * 78*cfb92d14SAndroid Build Coastguard Worker */ 79*cfb92d14SAndroid Build Coastguard Worker static const FrameTag kInvalidTag; 80*cfb92d14SAndroid Build Coastguard Worker 81*cfb92d14SAndroid Build Coastguard Worker /** 82*cfb92d14SAndroid Build Coastguard Worker * Defines the structure to hold a write position for an input frame (frame being written). 83*cfb92d14SAndroid Build Coastguard Worker * 84*cfb92d14SAndroid Build Coastguard Worker * It should be considered as an opaque data structure to users of `Buffer`. 85*cfb92d14SAndroid Build Coastguard Worker * 86*cfb92d14SAndroid Build Coastguard Worker */ 87*cfb92d14SAndroid Build Coastguard Worker struct WritePosition 88*cfb92d14SAndroid Build Coastguard Worker { 89*cfb92d14SAndroid Build Coastguard Worker public: 90*cfb92d14SAndroid Build Coastguard Worker /** 91*cfb92d14SAndroid Build Coastguard Worker * The constructor for a `WritePosition` object. 92*cfb92d14SAndroid Build Coastguard Worker * 93*cfb92d14SAndroid Build Coastguard Worker */ WritePositionot::Spinel::Buffer::WritePosition94*cfb92d14SAndroid Build Coastguard Worker WritePosition(void) 95*cfb92d14SAndroid Build Coastguard Worker : mPosition(nullptr) 96*cfb92d14SAndroid Build Coastguard Worker , mSegmentHead(nullptr) 97*cfb92d14SAndroid Build Coastguard Worker { 98*cfb92d14SAndroid Build Coastguard Worker } 99*cfb92d14SAndroid Build Coastguard Worker 100*cfb92d14SAndroid Build Coastguard Worker private: 101*cfb92d14SAndroid Build Coastguard Worker uint8_t *mPosition; // Pointer into buffer corresponding to saved write position. 102*cfb92d14SAndroid Build Coastguard Worker uint8_t *mSegmentHead; // Pointer to segment head. 103*cfb92d14SAndroid Build Coastguard Worker 104*cfb92d14SAndroid Build Coastguard Worker friend class Buffer; 105*cfb92d14SAndroid Build Coastguard Worker }; 106*cfb92d14SAndroid Build Coastguard Worker 107*cfb92d14SAndroid Build Coastguard Worker /** 108*cfb92d14SAndroid Build Coastguard Worker * Defines a function pointer callback which is invoked to inform a change in `Buffer` either when a new 109*cfb92d14SAndroid Build Coastguard Worker * frame is added/written to `Buffer` or when a frame is removed from `Buffer`. 110*cfb92d14SAndroid Build Coastguard Worker * 111*cfb92d14SAndroid Build Coastguard Worker * @param[in] aContext A pointer to arbitrary context information. 112*cfb92d14SAndroid Build Coastguard Worker * @param[in] aTag The tag associated with the frame which is added or removed. 113*cfb92d14SAndroid Build Coastguard Worker * @param[in] aPriority The priority of frame. 114*cfb92d14SAndroid Build Coastguard Worker * @param[in] aBuffer A pointer to the `Buffer`. 115*cfb92d14SAndroid Build Coastguard Worker * 116*cfb92d14SAndroid Build Coastguard Worker */ 117*cfb92d14SAndroid Build Coastguard Worker typedef void (*BufferCallback)(void *aContext, FrameTag aTag, Priority aPriority, Buffer *aBuffer); 118*cfb92d14SAndroid Build Coastguard Worker 119*cfb92d14SAndroid Build Coastguard Worker /** 120*cfb92d14SAndroid Build Coastguard Worker * Initializes an NCP frame buffer. 121*cfb92d14SAndroid Build Coastguard Worker * 122*cfb92d14SAndroid Build Coastguard Worker * @param[in] aBuffer A pointer to a buffer which will be used by NCP frame buffer. 123*cfb92d14SAndroid Build Coastguard Worker * @param[in] aBufferLength The buffer size (in bytes). 124*cfb92d14SAndroid Build Coastguard Worker * 125*cfb92d14SAndroid Build Coastguard Worker */ 126*cfb92d14SAndroid Build Coastguard Worker Buffer(uint8_t *aBuffer, uint16_t aBufferLength); 127*cfb92d14SAndroid Build Coastguard Worker 128*cfb92d14SAndroid Build Coastguard Worker /** 129*cfb92d14SAndroid Build Coastguard Worker * Clears the NCP frame buffer. All the frames are cleared/removed. 130*cfb92d14SAndroid Build Coastguard Worker * 131*cfb92d14SAndroid Build Coastguard Worker */ 132*cfb92d14SAndroid Build Coastguard Worker void Clear(void); 133*cfb92d14SAndroid Build Coastguard Worker 134*cfb92d14SAndroid Build Coastguard Worker /** 135*cfb92d14SAndroid Build Coastguard Worker * Sets the FrameAdded callback and its context. 136*cfb92d14SAndroid Build Coastguard Worker * 137*cfb92d14SAndroid Build Coastguard Worker * Subsequent calls to this method will overwrite the previous callback and its context. 138*cfb92d14SAndroid Build Coastguard Worker * 139*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrameAddedCallback Callback invoked when a new frame is successfully added to buffer. 140*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrameAddedContext A pointer to arbitrary context used with frame added callback. 141*cfb92d14SAndroid Build Coastguard Worker * 142*cfb92d14SAndroid Build Coastguard Worker */ 143*cfb92d14SAndroid Build Coastguard Worker void SetFrameAddedCallback(BufferCallback aFrameAddedCallback, void *aFrameAddedContext); 144*cfb92d14SAndroid Build Coastguard Worker 145*cfb92d14SAndroid Build Coastguard Worker /** 146*cfb92d14SAndroid Build Coastguard Worker * Sets the FrameRemoved callback and its context. 147*cfb92d14SAndroid Build Coastguard Worker * 148*cfb92d14SAndroid Build Coastguard Worker * Subsequent calls to this method will overwrite the previous callback and its context. 149*cfb92d14SAndroid Build Coastguard Worker * 150*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrameRemovedCallback Callback invoked when a frame is removed from buffer. 151*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrameRemovedContext A pointer to arbitrary context used with frame removed callback. 152*cfb92d14SAndroid Build Coastguard Worker * 153*cfb92d14SAndroid Build Coastguard Worker */ 154*cfb92d14SAndroid Build Coastguard Worker void SetFrameRemovedCallback(BufferCallback aFrameRemovedCallback, void *aFrameRemovedContext); 155*cfb92d14SAndroid Build Coastguard Worker 156*cfb92d14SAndroid Build Coastguard Worker /** 157*cfb92d14SAndroid Build Coastguard Worker * Begins a new input frame (InFrame) to be added/written to the frame buffer. 158*cfb92d14SAndroid Build Coastguard Worker 159*cfb92d14SAndroid Build Coastguard Worker * If there is a previous frame being written (for which `InFrameEnd()` has not yet been called), calling 160*cfb92d14SAndroid Build Coastguard Worker * `InFrameBegin()` will discard and clear the previous unfinished frame. 161*cfb92d14SAndroid Build Coastguard Worker * 162*cfb92d14SAndroid Build Coastguard Worker * @param[in] aPriority Priority level of the new input frame. 163*cfb92d14SAndroid Build Coastguard Worker * 164*cfb92d14SAndroid Build Coastguard Worker */ 165*cfb92d14SAndroid Build Coastguard Worker void InFrameBegin(Priority aPriority); 166*cfb92d14SAndroid Build Coastguard Worker 167*cfb92d14SAndroid Build Coastguard Worker /** 168*cfb92d14SAndroid Build Coastguard Worker * Adds a single byte to current input frame. 169*cfb92d14SAndroid Build Coastguard Worker * 170*cfb92d14SAndroid Build Coastguard Worker * Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this 171*cfb92d14SAndroid Build Coastguard Worker * method does nothing and returns error status `OT_ERROR_INVALID_STATE`. 172*cfb92d14SAndroid Build Coastguard Worker * 173*cfb92d14SAndroid Build Coastguard Worker * If no buffer space is available, this method will discard and clear the current input frame and return the 174*cfb92d14SAndroid Build Coastguard Worker * error status `OT_ERROR_NO_BUFS`. 175*cfb92d14SAndroid Build Coastguard Worker * 176*cfb92d14SAndroid Build Coastguard Worker * @param[in] aByte The byte value to add to input frame. 177*cfb92d14SAndroid Build Coastguard Worker * 178*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully added given byte to the frame. 179*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte. 180*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame. 181*cfb92d14SAndroid Build Coastguard Worker * 182*cfb92d14SAndroid Build Coastguard Worker */ 183*cfb92d14SAndroid Build Coastguard Worker otError InFrameFeedByte(uint8_t aByte); 184*cfb92d14SAndroid Build Coastguard Worker 185*cfb92d14SAndroid Build Coastguard Worker /** 186*cfb92d14SAndroid Build Coastguard Worker * Adds data to the current input frame. 187*cfb92d14SAndroid Build Coastguard Worker * 188*cfb92d14SAndroid Build Coastguard Worker * Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this 189*cfb92d14SAndroid Build Coastguard Worker * method does nothing and returns error status `OT_ERROR_INVALID_STATE`. 190*cfb92d14SAndroid Build Coastguard Worker * 191*cfb92d14SAndroid Build Coastguard Worker * If no buffer space is available, this method will discard and clear the current input frame and return the 192*cfb92d14SAndroid Build Coastguard Worker * error status `OT_ERROR_NO_BUFS`. 193*cfb92d14SAndroid Build Coastguard Worker * 194*cfb92d14SAndroid Build Coastguard Worker * @param[in] aDataBuffer A pointer to data buffer. 195*cfb92d14SAndroid Build Coastguard Worker * @param[in] aDataBufferLength The length of the data buffer. 196*cfb92d14SAndroid Build Coastguard Worker * 197*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully added new data to the frame. 198*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add data. 199*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame. 200*cfb92d14SAndroid Build Coastguard Worker * 201*cfb92d14SAndroid Build Coastguard Worker */ 202*cfb92d14SAndroid Build Coastguard Worker otError InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength); 203*cfb92d14SAndroid Build Coastguard Worker 204*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE 205*cfb92d14SAndroid Build Coastguard Worker /** 206*cfb92d14SAndroid Build Coastguard Worker * Adds a message to the current input frame. 207*cfb92d14SAndroid Build Coastguard Worker * 208*cfb92d14SAndroid Build Coastguard Worker * Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this 209*cfb92d14SAndroid Build Coastguard Worker * method does nothing and returns error status `OT_ERROR_INVALID_STATE`. 210*cfb92d14SAndroid Build Coastguard Worker * 211*cfb92d14SAndroid Build Coastguard Worker * If no buffer space is available, this method will discard and clear the frame and return error status 212*cfb92d14SAndroid Build Coastguard Worker * `OT_ERROR_NO_BUFS`. 213*cfb92d14SAndroid Build Coastguard Worker * 214*cfb92d14SAndroid Build Coastguard Worker * The ownership of the passed-in message @p aMessage changes to `Buffer` ONLY when the entire frame is 215*cfb92d14SAndroid Build Coastguard Worker * successfully finished (i.e., with a successful call to `InFrameEnd()` for the current input frame), and in this 216*cfb92d14SAndroid Build Coastguard Worker * case the `otMessage` instance will be freed once the frame is removed (using `OutFrameRemove()`) from NCP buffer. 217*cfb92d14SAndroid Build Coastguard Worker * However, if the input frame gets discarded before it is finished (e.g., running out of buffer space), the 218*cfb92d14SAndroid Build Coastguard Worker * `otMessage` instance remains unchanged. 219*cfb92d14SAndroid Build Coastguard Worker * 220*cfb92d14SAndroid Build Coastguard Worker * @param[in] aMessage A message to be added to current frame. 221*cfb92d14SAndroid Build Coastguard Worker * 222*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully added the message to the frame. 223*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the message. 224*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame. 225*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_ARGS If @p aMessage is nullptr. 226*cfb92d14SAndroid Build Coastguard Worker * 227*cfb92d14SAndroid Build Coastguard Worker */ 228*cfb92d14SAndroid Build Coastguard Worker otError InFrameFeedMessage(otMessage *aMessage); 229*cfb92d14SAndroid Build Coastguard Worker #endif 230*cfb92d14SAndroid Build Coastguard Worker 231*cfb92d14SAndroid Build Coastguard Worker /** 232*cfb92d14SAndroid Build Coastguard Worker * Gets the current write position in the input frame. 233*cfb92d14SAndroid Build Coastguard Worker * 234*cfb92d14SAndroid Build Coastguard Worker * The write position is returned in @p aPosition. The saved position can later be used to overwrite the frame 235*cfb92d14SAndroid Build Coastguard Worker * content (using `InFrameOverwrite()`) or discard a portion of written frame and move the write pointer back to 236*cfb92d14SAndroid Build Coastguard Worker * the saved position (using `InFrameReset()`). 237*cfb92d14SAndroid Build Coastguard Worker * 238*cfb92d14SAndroid Build Coastguard Worker * @param[out] aPosition A reference to a `WritePosition` to save the current write position. 239*cfb92d14SAndroid Build Coastguard Worker * 240*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully saved current write position in @p aPosition. 241*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame. 242*cfb92d14SAndroid Build Coastguard Worker * 243*cfb92d14SAndroid Build Coastguard Worker */ 244*cfb92d14SAndroid Build Coastguard Worker otError InFrameGetPosition(WritePosition &aPosition); 245*cfb92d14SAndroid Build Coastguard Worker 246*cfb92d14SAndroid Build Coastguard Worker /** 247*cfb92d14SAndroid Build Coastguard Worker * Overwrites the previously written content in the current input frame at a given write position. 248*cfb92d14SAndroid Build Coastguard Worker * 249*cfb92d14SAndroid Build Coastguard Worker * The write position @p aPostion must belong to the same input frame saved earlier with `InFrameGetPosition()`. 250*cfb92d14SAndroid Build Coastguard Worker * Does not allow writing beyond the current end of the input frame (i.e., it can only write over 251*cfb92d14SAndroid Build Coastguard Worker * previously added content). If writing @p aDataBufferLength bytes from write position @p aPosition goes beyond 252*cfb92d14SAndroid Build Coastguard Worker * the end, this method does not change the input frame and returns error status `OT_ERROR_INVALID_ARGS`. 253*cfb92d14SAndroid Build Coastguard Worker * Cannot be used if the input frame has an added `otMessage` (i.e., a previous call to 254*cfb92d14SAndroid Build Coastguard Worker * `InFrameFeedMessage()`). 255*cfb92d14SAndroid Build Coastguard Worker * 256*cfb92d14SAndroid Build Coastguard Worker * @param[in] aPosition A reference to the write position. 257*cfb92d14SAndroid Build Coastguard Worker * @param[in] aDataBuffer A pointer to data buffer. 258*cfb92d14SAndroid Build Coastguard Worker * @param[in] aDataBufferLength The length of the data buffer. 259*cfb92d14SAndroid Build Coastguard Worker * 260*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully overwrote the data at the given write position. 261*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE No input frame (`InFrameBegin()` has not been called). 262*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_ARGS The given write position is not valid (i.e., if it does not belong to same 263*cfb92d14SAndroid Build Coastguard Worker * input frame), or the input frame has an added `otMessage`, or the write 264*cfb92d14SAndroid Build Coastguard Worker * operation will go beyond the current end of the input frame. 265*cfb92d14SAndroid Build Coastguard Worker * 266*cfb92d14SAndroid Build Coastguard Worker */ 267*cfb92d14SAndroid Build Coastguard Worker otError InFrameOverwrite(const WritePosition &aPosition, const uint8_t *aDataBuffer, uint16_t aDataBufferLength); 268*cfb92d14SAndroid Build Coastguard Worker 269*cfb92d14SAndroid Build Coastguard Worker /** 270*cfb92d14SAndroid Build Coastguard Worker * Resets the write position of input frame back to a previously saved position. Any previously 271*cfb92d14SAndroid Build Coastguard Worker * added content after the write position is discarded. 272*cfb92d14SAndroid Build Coastguard Worker * 273*cfb92d14SAndroid Build Coastguard Worker * The write position @p aPosition must belong to the same input frame saved earlier with `InFrameGetPosition()`. 274*cfb92d14SAndroid Build Coastguard Worker * Cannot be used if the input frame has an added `otMessage` (i.e., a previous call to 275*cfb92d14SAndroid Build Coastguard Worker * `InFrameFeedMessage()`). 276*cfb92d14SAndroid Build Coastguard Worker * 277*cfb92d14SAndroid Build Coastguard Worker * @param[in] aPosition A reference to write position 278*cfb92d14SAndroid Build Coastguard Worker * 279*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully reset the write position of current input frame.. 280*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE No input frame (`InFrameBegin()` has not been called). 281*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_ARGS The given write position is not valid (does not belong to same input frame), or 282*cfb92d14SAndroid Build Coastguard Worker * the input frame has an added `otMessage`. 283*cfb92d14SAndroid Build Coastguard Worker * 284*cfb92d14SAndroid Build Coastguard Worker */ 285*cfb92d14SAndroid Build Coastguard Worker otError InFrameReset(const WritePosition &aPosition); 286*cfb92d14SAndroid Build Coastguard Worker 287*cfb92d14SAndroid Build Coastguard Worker /** 288*cfb92d14SAndroid Build Coastguard Worker * Gets the distance (number of bytes) from a given saved position to current end of frame. 289*cfb92d14SAndroid Build Coastguard Worker * 290*cfb92d14SAndroid Build Coastguard Worker * The write position @p aPosition must belong to the same input frame saved earlier with `InFrameGetPosition()`. 291*cfb92d14SAndroid Build Coastguard Worker * Cannot be used if the input frame has an added `otMessage` (i.e., a previous call to 292*cfb92d14SAndroid Build Coastguard Worker * `InFrameFeedMessage()`). In case of invalid argument, this method returns zero. 293*cfb92d14SAndroid Build Coastguard Worker * 294*cfb92d14SAndroid Build Coastguard Worker * @param[in] aPosition A reference to write position 295*cfb92d14SAndroid Build Coastguard Worker * 296*cfb92d14SAndroid Build Coastguard Worker * @returns The distance (number of bytes) from a write position to current end of frame, or zero for invalid 297*cfb92d14SAndroid Build Coastguard Worker * arguments. 298*cfb92d14SAndroid Build Coastguard Worker * 299*cfb92d14SAndroid Build Coastguard Worker */ 300*cfb92d14SAndroid Build Coastguard Worker uint16_t InFrameGetDistance(const WritePosition &aPosition) const; 301*cfb92d14SAndroid Build Coastguard Worker 302*cfb92d14SAndroid Build Coastguard Worker /** 303*cfb92d14SAndroid Build Coastguard Worker * Finalizes/ends the current input frame being written to the buffer. 304*cfb92d14SAndroid Build Coastguard Worker * 305*cfb92d14SAndroid Build Coastguard Worker * Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this 306*cfb92d14SAndroid Build Coastguard Worker * method does nothing and returns error status `OT_ERROR_INVALID_STATE`. 307*cfb92d14SAndroid Build Coastguard Worker * 308*cfb92d14SAndroid Build Coastguard Worker * If no buffer space is available, this method will discard and clear the frame and return error status 309*cfb92d14SAndroid Build Coastguard Worker * `OT_ERROR_NO_BUFS`. 310*cfb92d14SAndroid Build Coastguard Worker * 311*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully ended the input frame. 312*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message. 313*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame. 314*cfb92d14SAndroid Build Coastguard Worker * 315*cfb92d14SAndroid Build Coastguard Worker */ 316*cfb92d14SAndroid Build Coastguard Worker otError InFrameEnd(void); 317*cfb92d14SAndroid Build Coastguard Worker 318*cfb92d14SAndroid Build Coastguard Worker /** 319*cfb92d14SAndroid Build Coastguard Worker * Returns the tag assigned to last successfully written/added frame to NcpBuffer (i.e., last input 320*cfb92d14SAndroid Build Coastguard Worker * frame for which `InFrameEnd()` was called and returned success status). The tag is a unique value (within 321*cfb92d14SAndroid Build Coastguard Worker * currently queued frames) associated with a frame in the `Buffer`. The tag can be used to identify the 322*cfb92d14SAndroid Build Coastguard Worker * same frame when it is read and removed from the NcpBuffer. Tags can be compared using operator `==`. 323*cfb92d14SAndroid Build Coastguard Worker * 324*cfb92d14SAndroid Build Coastguard Worker * @returns The tag of the last successfully written frame, or `kInvalidTag` if no frame is written so far. 325*cfb92d14SAndroid Build Coastguard Worker */ 326*cfb92d14SAndroid Build Coastguard Worker FrameTag InFrameGetLastTag(void) const; 327*cfb92d14SAndroid Build Coastguard Worker 328*cfb92d14SAndroid Build Coastguard Worker /** 329*cfb92d14SAndroid Build Coastguard Worker * Checks if the buffer is empty. A non-empty buffer contains at least one full frame for reading. 330*cfb92d14SAndroid Build Coastguard Worker * 331*cfb92d14SAndroid Build Coastguard Worker * @retval TRUE Buffer is not empty and contains at least one full frame for reading. 332*cfb92d14SAndroid Build Coastguard Worker * @retval FALSE Buffer is empty and contains no frame for reading. 333*cfb92d14SAndroid Build Coastguard Worker * 334*cfb92d14SAndroid Build Coastguard Worker */ 335*cfb92d14SAndroid Build Coastguard Worker bool IsEmpty(void) const; 336*cfb92d14SAndroid Build Coastguard Worker 337*cfb92d14SAndroid Build Coastguard Worker /** 338*cfb92d14SAndroid Build Coastguard Worker * Begins/prepares an output frame to be read from the frame buffer if there is no current active output 339*cfb92d14SAndroid Build Coastguard Worker * frame, or resets the read offset if there is a current active output frame. 340*cfb92d14SAndroid Build Coastguard Worker * 341*cfb92d14SAndroid Build Coastguard Worker * The NCP buffer maintains a read offset for the current frame being read. Before reading any bytes from the frame 342*cfb92d14SAndroid Build Coastguard Worker * this method should be called to prepare the frame and set the read offset. 343*cfb92d14SAndroid Build Coastguard Worker * 344*cfb92d14SAndroid Build Coastguard Worker * If part or even all of current frame has been read, a sub-sequent call to this method will reset the read 345*cfb92d14SAndroid Build Coastguard Worker * offset back to beginning of current output frame (note that the current output frame will remain unchanged even 346*cfb92d14SAndroid Build Coastguard Worker * in case where a higher priority frame was written to buffer while reading current output frame). A prepared 347*cfb92d14SAndroid Build Coastguard Worker * output frame will stay active as current output frame until it is explicitly removed using `OutFrameRemove()`. 348*cfb92d14SAndroid Build Coastguard Worker * 349*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully started/prepared a new output frame for reading. 350*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NOT_FOUND No frame available in buffer for reading. 351*cfb92d14SAndroid Build Coastguard Worker * 352*cfb92d14SAndroid Build Coastguard Worker */ 353*cfb92d14SAndroid Build Coastguard Worker otError OutFrameBegin(void); 354*cfb92d14SAndroid Build Coastguard Worker 355*cfb92d14SAndroid Build Coastguard Worker /** 356*cfb92d14SAndroid Build Coastguard Worker * Checks if the current output frame (being read) has ended. 357*cfb92d14SAndroid Build Coastguard Worker * 358*cfb92d14SAndroid Build Coastguard Worker * The NCP buffer maintains a read offset for the current output frame being read. This method returns `true` if 359*cfb92d14SAndroid Build Coastguard Worker * the read offset has reached the end of the frame and there are no more bytes available to read, or if there is 360*cfb92d14SAndroid Build Coastguard Worker * no currently active output frame. 361*cfb92d14SAndroid Build Coastguard Worker * 362*cfb92d14SAndroid Build Coastguard Worker * @retval TRUE Frame has ended (no more bytes available to read from current output frame), or 363*cfb92d14SAndroid Build Coastguard Worker * there is currently no prepared/active output frame. 364*cfb92d14SAndroid Build Coastguard Worker * @retval FALSE Frame still has more data to read. 365*cfb92d14SAndroid Build Coastguard Worker * 366*cfb92d14SAndroid Build Coastguard Worker */ 367*cfb92d14SAndroid Build Coastguard Worker bool OutFrameHasEnded(void); 368*cfb92d14SAndroid Build Coastguard Worker 369*cfb92d14SAndroid Build Coastguard Worker /** 370*cfb92d14SAndroid Build Coastguard Worker * Reads and returns the next byte from the current output frame. 371*cfb92d14SAndroid Build Coastguard Worker * 372*cfb92d14SAndroid Build Coastguard Worker * The NCP buffer maintains a read offset for the current output frame being read. This method reads and returns 373*cfb92d14SAndroid Build Coastguard Worker * the next byte from the current frame and moves the read offset forward. If read offset is already at the end 374*cfb92d14SAndroid Build Coastguard Worker * current output frame, this method returns zero. 375*cfb92d14SAndroid Build Coastguard Worker * 376*cfb92d14SAndroid Build Coastguard Worker * @returns The next byte from the current output frame or zero if current output frame has ended or there is 377*cfb92d14SAndroid Build Coastguard Worker * prepared/active output from. 378*cfb92d14SAndroid Build Coastguard Worker * 379*cfb92d14SAndroid Build Coastguard Worker */ 380*cfb92d14SAndroid Build Coastguard Worker uint8_t OutFrameReadByte(void); 381*cfb92d14SAndroid Build Coastguard Worker 382*cfb92d14SAndroid Build Coastguard Worker /** 383*cfb92d14SAndroid Build Coastguard Worker * Reads and copies bytes from the current output frame into a given buffer. 384*cfb92d14SAndroid Build Coastguard Worker * 385*cfb92d14SAndroid Build Coastguard Worker * The NCP buffer maintains a read offset for the current output frame being read. This method attempts to read 386*cfb92d14SAndroid Build Coastguard Worker * the given number of bytes (@p aReadLength) from the current frame and copies the bytes into the given 387*cfb92d14SAndroid Build Coastguard Worker * data buffer (@p aDataBuffer). It also moves the read offset forward accordingly. If there are fewer bytes 388*cfb92d14SAndroid Build Coastguard Worker * remaining in current frame than the requested @p aReadLength, the available bytes are read/copied. This methods 389*cfb92d14SAndroid Build Coastguard Worker * returns the number of bytes read from frame and copied into @p aDataBuffer. 390*cfb92d14SAndroid Build Coastguard Worker * 391*cfb92d14SAndroid Build Coastguard Worker * @param[in] aReadLength Number of bytes to read. 392*cfb92d14SAndroid Build Coastguard Worker * @param[out] aDataBuffer A pointer to a data buffer. 393*cfb92d14SAndroid Build Coastguard Worker * 394*cfb92d14SAndroid Build Coastguard Worker * @returns The number of bytes read and copied into data buffer. 395*cfb92d14SAndroid Build Coastguard Worker * 396*cfb92d14SAndroid Build Coastguard Worker */ 397*cfb92d14SAndroid Build Coastguard Worker uint16_t OutFrameRead(uint16_t aReadLength, uint8_t *aDataBuffer); 398*cfb92d14SAndroid Build Coastguard Worker 399*cfb92d14SAndroid Build Coastguard Worker /** 400*cfb92d14SAndroid Build Coastguard Worker * Removes the current or front output frame from the buffer. 401*cfb92d14SAndroid Build Coastguard Worker * 402*cfb92d14SAndroid Build Coastguard Worker * If there is an active output from being read (an output frame was prepared earlier with a successful call to 403*cfb92d14SAndroid Build Coastguard Worker * `OutFrameBegin()`), this method removes the current active output frame. If there is no current active frame, 404*cfb92d14SAndroid Build Coastguard Worker * the front frame in the queue (the next frame which would have been read) will be removed. 405*cfb92d14SAndroid Build Coastguard Worker * 406*cfb92d14SAndroid Build Coastguard Worker * When a frame is removed all its associated messages will be freed. 407*cfb92d14SAndroid Build Coastguard Worker * 408*cfb92d14SAndroid Build Coastguard Worker * If the remove operation is successful, this method will invoke the `FrameRemovedCallback` (if not nullptr) before 409*cfb92d14SAndroid Build Coastguard Worker * returning the success state. 410*cfb92d14SAndroid Build Coastguard Worker * 411*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully removed the front frame. 412*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NOT_FOUND No frame available in NCP frame buffer to remove. 413*cfb92d14SAndroid Build Coastguard Worker * 414*cfb92d14SAndroid Build Coastguard Worker */ 415*cfb92d14SAndroid Build Coastguard Worker otError OutFrameRemove(void); 416*cfb92d14SAndroid Build Coastguard Worker 417*cfb92d14SAndroid Build Coastguard Worker /** 418*cfb92d14SAndroid Build Coastguard Worker * Returns the number of bytes (length) of current or front frame in the NCP frame buffer. 419*cfb92d14SAndroid Build Coastguard Worker * 420*cfb92d14SAndroid Build Coastguard Worker * If there is an active output from being read (an output frame was prepared earlier with successful call to 421*cfb92d14SAndroid Build Coastguard Worker * `OutFrameBegin()`), this method returns the length of the current output frame. If there is no current active 422*cfb92d14SAndroid Build Coastguard Worker * frame, the length of the front frame in the queue (the next frame which would have been read) will be returned. 423*cfb92d14SAndroid Build Coastguard Worker * 424*cfb92d14SAndroid Build Coastguard Worker * If there is no frame in buffer, this method returns zero. 425*cfb92d14SAndroid Build Coastguard Worker * 426*cfb92d14SAndroid Build Coastguard Worker * @returns The number of bytes (length) of current/front frame, or zero if no frame in buffer. 427*cfb92d14SAndroid Build Coastguard Worker * 428*cfb92d14SAndroid Build Coastguard Worker */ 429*cfb92d14SAndroid Build Coastguard Worker uint16_t OutFrameGetLength(void); 430*cfb92d14SAndroid Build Coastguard Worker 431*cfb92d14SAndroid Build Coastguard Worker /** 432*cfb92d14SAndroid Build Coastguard Worker * Returns the tag value associated to current or front frame in the NCP frame buffer. 433*cfb92d14SAndroid Build Coastguard Worker * 434*cfb92d14SAndroid Build Coastguard Worker * If there is an active output from being read (an output frame was prepared earlier with successful call to 435*cfb92d14SAndroid Build Coastguard Worker * `OutFrameBegin()`), this method returns the tag associated with current output frame. If there is no current 436*cfb92d14SAndroid Build Coastguard Worker * active frame, the tag associated with the front frame in the queue (the next frame which would have been read) 437*cfb92d14SAndroid Build Coastguard Worker * will be returned. 438*cfb92d14SAndroid Build Coastguard Worker * 439*cfb92d14SAndroid Build Coastguard Worker * If there is no frame in buffer, this method returns `kInvalidTag`. 440*cfb92d14SAndroid Build Coastguard Worker * 441*cfb92d14SAndroid Build Coastguard Worker * @returns The tag assigned to the current/from output frame, or `kInvalidTag` if no frame in buffer. 442*cfb92d14SAndroid Build Coastguard Worker * 443*cfb92d14SAndroid Build Coastguard Worker */ 444*cfb92d14SAndroid Build Coastguard Worker FrameTag OutFrameGetTag(void); 445*cfb92d14SAndroid Build Coastguard Worker 446*cfb92d14SAndroid Build Coastguard Worker private: 447*cfb92d14SAndroid Build Coastguard Worker /* 448*cfb92d14SAndroid Build Coastguard Worker * `Buffer` Implementation 449*cfb92d14SAndroid Build Coastguard Worker * ------------------------------- 450*cfb92d14SAndroid Build Coastguard Worker * 451*cfb92d14SAndroid Build Coastguard Worker * `Buffer` internally stores a frame as a sequence of data segments. Each segment stores a portion of 452*cfb92d14SAndroid Build Coastguard Worker * frame. The data segments are stored in the main buffer `mBuffer`. `mBuffer` is utilized as a circular buffer. 453*cfb92d14SAndroid Build Coastguard Worker 454*cfb92d14SAndroid Build Coastguard Worker * The content of messages (which are added using `InFrameFeedMessage()`) are not directly copied in the `mBuffer` 455*cfb92d14SAndroid Build Coastguard Worker * but instead they are enqueued in a message queue `mMessageQueue`. 456*cfb92d14SAndroid Build Coastguard Worker * 457*cfb92d14SAndroid Build Coastguard Worker * Every data segments starts with a header before the data portion. The header is 2 bytes long with the following 458*cfb92d14SAndroid Build Coastguard Worker * format: 459*cfb92d14SAndroid Build Coastguard Worker * 460*cfb92d14SAndroid Build Coastguard Worker * Bit 0-13: Give the length of the data segment (max segment len is 2^14 = 16,384 bytes). 461*cfb92d14SAndroid Build Coastguard Worker * Bit 14: Flag bit set to indicate that this segment has an associated `Message` (appended to its end). 462*cfb92d14SAndroid Build Coastguard Worker * Bit 15: Flag bit set to indicate that this segment defines the start of a new frame. 463*cfb92d14SAndroid Build Coastguard Worker * 464*cfb92d14SAndroid Build Coastguard Worker * Bit 15 Bit 14 Bits: 0 - 13 465*cfb92d14SAndroid Build Coastguard Worker * +--------------+--------------+--------------------------------------------------------+ 466*cfb92d14SAndroid Build Coastguard Worker * | New Frame | Has Message | Length of segment (excluding the header) | 467*cfb92d14SAndroid Build Coastguard Worker * +--------------+--------------+--------------------------------------------------------+ 468*cfb92d14SAndroid Build Coastguard Worker * 469*cfb92d14SAndroid Build Coastguard Worker * The header is encoded in big-endian (msb first) style. 470*cfb92d14SAndroid Build Coastguard Worker 471*cfb92d14SAndroid Build Coastguard Worker * Consider the following calls to create a frame: 472*cfb92d14SAndroid Build Coastguard Worker * 473*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameBegin(); 474*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameFeedData("Hello", 5); 475*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameFeedData("There", 5); 476*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameFeedMessage(*someMessage); 477*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameFeedData("Bye", 3); 478*cfb92d14SAndroid Build Coastguard Worker * ncpBuffer.InFrameEnd(); 479*cfb92d14SAndroid Build Coastguard Worker * 480*cfb92d14SAndroid Build Coastguard Worker * This frame is stored as two segments: 481*cfb92d14SAndroid Build Coastguard Worker * 482*cfb92d14SAndroid Build Coastguard Worker * - Segment #1 contains "HelloThere" with a header value `0xC00A` which shows that this segment contains 10 483*cfb92d14SAndroid Build Coastguard Worker * data bytes, and it starts a new frame, and also includes an appended message from the message queue. 484*cfb92d14SAndroid Build Coastguard Worker * 485*cfb92d14SAndroid Build Coastguard Worker * - Segment #2 contains "Bye" with a header value of `0x0003` showing length of 3 and no appended message. 486*cfb92d14SAndroid Build Coastguard Worker * 487*cfb92d14SAndroid Build Coastguard Worker * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 488*cfb92d14SAndroid Build Coastguard Worker * | C0 | 0A | 'H' | 'e' | 'l' | 'l' | 'o' | 'T' | 'h' | 'e' | 'r' | 'e' | 00 | 03 | 'B' | 'y' | 'e' | 489*cfb92d14SAndroid Build Coastguard Worker * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 490*cfb92d14SAndroid Build Coastguard Worker * \ / \ / 491*cfb92d14SAndroid Build Coastguard Worker * Segment #1 Header Segment #2 Header 492*cfb92d14SAndroid Build Coastguard Worker * 493*cfb92d14SAndroid Build Coastguard Worker * 494*cfb92d14SAndroid Build Coastguard Worker * `Buffer` uses the `mBuffer` as a circular/ring buffer. To support two frame priorities the buffer is 495*cfb92d14SAndroid Build Coastguard Worker * divided into two high-priority and low-priority regions. The high priority frames are stored in buffer in 496*cfb92d14SAndroid Build Coastguard Worker * backward direction while the low-priority frames use the buffer in forward direction. This model ensures the 497*cfb92d14SAndroid Build Coastguard Worker * available buffer space is utilized efficiently between all frame types. 498*cfb92d14SAndroid Build Coastguard Worker * 499*cfb92d14SAndroid Build Coastguard Worker * mReadFrameStart[kPriorityLow] 500*cfb92d14SAndroid Build Coastguard Worker * | 501*cfb92d14SAndroid Build Coastguard Worker * | mWriteFrameStart[kPriorityLow] 502*cfb92d14SAndroid Build Coastguard Worker * | | 503*cfb92d14SAndroid Build Coastguard Worker * V Low Priority Frames V 504*cfb92d14SAndroid Build Coastguard Worker * --------------+------------------------------+------------------------------+------------------ 505*cfb92d14SAndroid Build Coastguard Worker * ... | <-------- | --------> | ... 506*cfb92d14SAndroid Build Coastguard Worker * --------------+------------------------------+------------------------------+------------------ 507*cfb92d14SAndroid Build Coastguard Worker * ^ High Priority Frames ^ 508*cfb92d14SAndroid Build Coastguard Worker * | | 509*cfb92d14SAndroid Build Coastguard Worker * | mReadFrameStart[kPriorityHigh] 510*cfb92d14SAndroid Build Coastguard Worker * | 511*cfb92d14SAndroid Build Coastguard Worker * mWriteFrameStart[kPriorityHigh] 512*cfb92d14SAndroid Build Coastguard Worker * 513*cfb92d14SAndroid Build Coastguard Worker * 514*cfb92d14SAndroid Build Coastguard Worker * 515*cfb92d14SAndroid Build Coastguard Worker * When frames are removed, if possible, the `mReadFrameStart` and `mWriteFrameStart` pointers of the two priority 516*cfb92d14SAndroid Build Coastguard Worker * levels are moved closer to avoid gaps. 517*cfb92d14SAndroid Build Coastguard Worker * 518*cfb92d14SAndroid Build Coastguard Worker * For an output frame (frame being read), Buffer maintains a `ReadState` along with a set of pointers 519*cfb92d14SAndroid Build Coastguard Worker * into the buffer: 520*cfb92d14SAndroid Build Coastguard Worker * 521*cfb92d14SAndroid Build Coastguard Worker * mReadFrameStart[priority]: Start of the current/front frame. 522*cfb92d14SAndroid Build Coastguard Worker * | 523*cfb92d14SAndroid Build Coastguard Worker * | mReadSegmentHead: Start of the current segment. 524*cfb92d14SAndroid Build Coastguard Worker * | | 525*cfb92d14SAndroid Build Coastguard Worker * | | mReadPointer: Pointer to the next byte to read. 526*cfb92d14SAndroid Build Coastguard Worker * | | | 527*cfb92d14SAndroid Build Coastguard Worker * | | | mReadSegmentTail: End of the current segment. 528*cfb92d14SAndroid Build Coastguard Worker * | | | | 529*cfb92d14SAndroid Build Coastguard Worker * V V V V 530*cfb92d14SAndroid Build Coastguard Worker * ---------+------------+--------------------------+------+----------------+----------------------------------- 531*cfb92d14SAndroid Build Coastguard Worker * ... | Segment 1 | Segment 2 | ... | Last Segment | ... (possible) next frame 532*cfb92d14SAndroid Build Coastguard Worker * ---------+------------+--------------------------+------+----------------+----------------------------------- 533*cfb92d14SAndroid Build Coastguard Worker * \ | | / 534*cfb92d14SAndroid Build Coastguard Worker * | \------------v-----------/ | 535*cfb92d14SAndroid Build Coastguard Worker * | Current Segment | 536*cfb92d14SAndroid Build Coastguard Worker * | | 537*cfb92d14SAndroid Build Coastguard Worker * \---------------------------V-----------------------------/ 538*cfb92d14SAndroid Build Coastguard Worker * Current OutFrame (being read) 539*cfb92d14SAndroid Build Coastguard Worker * 540*cfb92d14SAndroid Build Coastguard Worker * Note that the diagram above shows the pointers for a low-priority frame (with pointers increasing in forward 541*cfb92d14SAndroid Build Coastguard Worker * direction). 542*cfb92d14SAndroid Build Coastguard Worker * 543*cfb92d14SAndroid Build Coastguard Worker * The `ReadState` indicates the state of current output frame and its read offset (e.g., if read offset is in 544*cfb92d14SAndroid Build Coastguard Worker * middle of a segment or if it is is middle of an appended message, or if we are done with entire frame). 545*cfb92d14SAndroid Build Coastguard Worker * 546*cfb92d14SAndroid Build Coastguard Worker * For an input frame (frame being written), the following pointers are maintained: 547*cfb92d14SAndroid Build Coastguard Worker * 548*cfb92d14SAndroid Build Coastguard Worker * mWriteFrameWrite[priority]: Start of the current/next frame being written. 549*cfb92d14SAndroid Build Coastguard Worker * | 550*cfb92d14SAndroid Build Coastguard Worker * | mWriteSegmentHead: Start of the current segment of the active input frame. 551*cfb92d14SAndroid Build Coastguard Worker * | | 552*cfb92d14SAndroid Build Coastguard Worker * | | mWriteSegmentTail: Pointer to the next byte to write. 553*cfb92d14SAndroid Build Coastguard Worker * | | | 554*cfb92d14SAndroid Build Coastguard Worker * | | | 555*cfb92d14SAndroid Build Coastguard Worker * | | | 556*cfb92d14SAndroid Build Coastguard Worker * V V V 557*cfb92d14SAndroid Build Coastguard Worker * ------------------+------------------+------------------------------------------------------------------- 558*cfb92d14SAndroid Build Coastguard Worker * Previous Frames | Segment 1 | Segment 2 : . . . 559*cfb92d14SAndroid Build Coastguard Worker * ------------------+------------------+------------------------------------------------------------------- 560*cfb92d14SAndroid Build Coastguard Worker * \ / 561*cfb92d14SAndroid Build Coastguard Worker * | | 562*cfb92d14SAndroid Build Coastguard Worker * \------------------V-----------------/ 563*cfb92d14SAndroid Build Coastguard Worker * Current InFrame (being written) 564*cfb92d14SAndroid Build Coastguard Worker * 565*cfb92d14SAndroid Build Coastguard Worker * 566*cfb92d14SAndroid Build Coastguard Worker */ 567*cfb92d14SAndroid Build Coastguard Worker 568*cfb92d14SAndroid Build Coastguard Worker enum 569*cfb92d14SAndroid Build Coastguard Worker { 570*cfb92d14SAndroid Build Coastguard Worker kReadByteAfterFrameHasEnded = 0, // Value returned by ReadByte() when frame has ended. 571*cfb92d14SAndroid Build Coastguard Worker kMessageReadBufferSize = 16, // Size of message buffer array `mMessageBuffer`. 572*cfb92d14SAndroid Build Coastguard Worker kUnknownFrameLength = 0xffff, // Value used when frame length is unknown. 573*cfb92d14SAndroid Build Coastguard Worker kSegmentHeaderSize = 2, // Length of the segment header. 574*cfb92d14SAndroid Build Coastguard Worker kSegmentHeaderLengthMask = 0x3fff, // Bit mask to get the length from the segment header 575*cfb92d14SAndroid Build Coastguard Worker kMaxSegments = 10, // Max number of segments allowed in a frame 576*cfb92d14SAndroid Build Coastguard Worker 577*cfb92d14SAndroid Build Coastguard Worker kSegmentHeaderNoFlag = 0, // No flags are set. 578*cfb92d14SAndroid Build Coastguard Worker kSegmentHeaderNewFrameFlag = (1 << 15), // Indicates that this segment starts a new frame. 579*cfb92d14SAndroid Build Coastguard Worker kSegmentHeaderMessageIndicatorFlag = (1 << 14), // Indicates this segment ends with a Message. 580*cfb92d14SAndroid Build Coastguard Worker 581*cfb92d14SAndroid Build Coastguard Worker kNumPrios = (kPriorityHigh + 1), // Number of priorities. 582*cfb92d14SAndroid Build Coastguard Worker }; 583*cfb92d14SAndroid Build Coastguard Worker 584*cfb92d14SAndroid Build Coastguard Worker enum ReadState 585*cfb92d14SAndroid Build Coastguard Worker { 586*cfb92d14SAndroid Build Coastguard Worker kReadStateNotActive, // No current prepared output frame. 587*cfb92d14SAndroid Build Coastguard Worker kReadStateInSegment, // In middle of a data segment while reading current frame. 588*cfb92d14SAndroid Build Coastguard Worker kReadStateInMessage, // In middle of a message while reading current frame. 589*cfb92d14SAndroid Build Coastguard Worker kReadStateDone, // Current output frame is read fully. 590*cfb92d14SAndroid Build Coastguard Worker }; 591*cfb92d14SAndroid Build Coastguard Worker 592*cfb92d14SAndroid Build Coastguard Worker enum Direction 593*cfb92d14SAndroid Build Coastguard Worker { 594*cfb92d14SAndroid Build Coastguard Worker kForward = kPriorityLow, 595*cfb92d14SAndroid Build Coastguard Worker kBackward = kPriorityHigh, 596*cfb92d14SAndroid Build Coastguard Worker kUnknown, 597*cfb92d14SAndroid Build Coastguard Worker }; 598*cfb92d14SAndroid Build Coastguard Worker 599*cfb92d14SAndroid Build Coastguard Worker uint8_t *GetUpdatedBufPtr(uint8_t *aBufPtr, uint16_t aOffset, Direction aDirection) const; 600*cfb92d14SAndroid Build Coastguard Worker uint16_t GetDistance(const uint8_t *aStartPtr, const uint8_t *aEndPtr, Direction aDirection) const; 601*cfb92d14SAndroid Build Coastguard Worker 602*cfb92d14SAndroid Build Coastguard Worker uint16_t ReadUint16At(uint8_t *aBufPtr, Direction aDirection); 603*cfb92d14SAndroid Build Coastguard Worker void WriteUint16At(uint8_t *aBufPtr, uint16_t aValue, Direction aDirection); 604*cfb92d14SAndroid Build Coastguard Worker 605*cfb92d14SAndroid Build Coastguard Worker bool HasFrame(Priority aPriority) const; 606*cfb92d14SAndroid Build Coastguard Worker void UpdateReadWriteStartPointers(void); 607*cfb92d14SAndroid Build Coastguard Worker 608*cfb92d14SAndroid Build Coastguard Worker otError InFrameAppend(uint8_t aByte); 609*cfb92d14SAndroid Build Coastguard Worker otError InFrameBeginSegment(void); 610*cfb92d14SAndroid Build Coastguard Worker void InFrameEndSegment(uint16_t aSegmentHeaderFlags); 611*cfb92d14SAndroid Build Coastguard Worker void InFrameDiscard(void); 612*cfb92d14SAndroid Build Coastguard Worker bool InFrameIsWriting(Priority aPriority) const; 613*cfb92d14SAndroid Build Coastguard Worker 614*cfb92d14SAndroid Build Coastguard Worker void OutFrameSelectReadDirection(void); 615*cfb92d14SAndroid Build Coastguard Worker otError OutFramePrepareSegment(void); 616*cfb92d14SAndroid Build Coastguard Worker void OutFrameMoveToNextSegment(void); 617*cfb92d14SAndroid Build Coastguard Worker 618*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE 619*cfb92d14SAndroid Build Coastguard Worker otError OutFramePrepareMessage(void); 620*cfb92d14SAndroid Build Coastguard Worker otError OutFrameFillMessageBuffer(void); 621*cfb92d14SAndroid Build Coastguard Worker #endif 622*cfb92d14SAndroid Build Coastguard Worker 623*cfb92d14SAndroid Build Coastguard Worker uint8_t *const mBuffer; // Pointer to the buffer used to store the data. 624*cfb92d14SAndroid Build Coastguard Worker uint8_t *const mBufferEnd; // Points to after the end of buffer. 625*cfb92d14SAndroid Build Coastguard Worker const uint16_t mBufferLength; // Length of the buffer. 626*cfb92d14SAndroid Build Coastguard Worker 627*cfb92d14SAndroid Build Coastguard Worker BufferCallback mFrameAddedCallback; // Callback to signal when a new frame is added 628*cfb92d14SAndroid Build Coastguard Worker void *mFrameAddedContext; // Context passed to `mFrameAddedCallback`. 629*cfb92d14SAndroid Build Coastguard Worker BufferCallback mFrameRemovedCallback; // Callback to signal when a frame is removed. 630*cfb92d14SAndroid Build Coastguard Worker void *mFrameRemovedContext; // Context passed to `mFrameRemovedCallback`. 631*cfb92d14SAndroid Build Coastguard Worker 632*cfb92d14SAndroid Build Coastguard Worker Direction mWriteDirection; // Direction (priority) for current frame being read. 633*cfb92d14SAndroid Build Coastguard Worker uint8_t *mWriteFrameStart[kNumPrios]; // Pointer to start of current frame being written. 634*cfb92d14SAndroid Build Coastguard Worker uint8_t *mWriteSegmentHead; // Pointer to start of current segment in the frame being written. 635*cfb92d14SAndroid Build Coastguard Worker uint8_t *mWriteSegmentTail; // Pointer to end of current segment in the frame being written. 636*cfb92d14SAndroid Build Coastguard Worker FrameTag mWriteFrameTag; // Tag associated with last successfully written frame. 637*cfb92d14SAndroid Build Coastguard Worker 638*cfb92d14SAndroid Build Coastguard Worker Direction mReadDirection; // Direction (priority) for current frame being read. 639*cfb92d14SAndroid Build Coastguard Worker ReadState mReadState; // Read state. 640*cfb92d14SAndroid Build Coastguard Worker uint16_t mReadFrameLength; // Length of current frame being read. 641*cfb92d14SAndroid Build Coastguard Worker 642*cfb92d14SAndroid Build Coastguard Worker uint8_t *mReadFrameStart[kNumPrios]; // Pointer to start of current frame being read. 643*cfb92d14SAndroid Build Coastguard Worker uint8_t *mReadSegmentHead; // Pointer to start of current segment in the frame being read. 644*cfb92d14SAndroid Build Coastguard Worker uint8_t *mReadSegmentTail; // Pointer to end of current segment in the frame being read. 645*cfb92d14SAndroid Build Coastguard Worker uint8_t *mReadPointer; // Pointer to next byte to read (either in segment or in msg buffer). 646*cfb92d14SAndroid Build Coastguard Worker 647*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE 648*cfb92d14SAndroid Build Coastguard Worker otMessageQueue mWriteFrameMessageQueue; // Message queue for the current frame being written. 649*cfb92d14SAndroid Build Coastguard Worker otMessageQueue mMessageQueue[kNumPrios]; // Main message queues. 650*cfb92d14SAndroid Build Coastguard Worker otMessage *mReadMessage; // Current Message in the frame being read. 651*cfb92d14SAndroid Build Coastguard Worker uint16_t mReadMessageOffset; // Offset within current message being read. 652*cfb92d14SAndroid Build Coastguard Worker uint8_t mMessageBuffer[kMessageReadBufferSize]; // Buffer to hold part of current message being read. 653*cfb92d14SAndroid Build Coastguard Worker uint8_t *mReadMessageTail; // Pointer to end of current part in mMessageBuffer. 654*cfb92d14SAndroid Build Coastguard Worker #endif 655*cfb92d14SAndroid Build Coastguard Worker }; 656*cfb92d14SAndroid Build Coastguard Worker 657*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel 658*cfb92d14SAndroid Build Coastguard Worker } // namespace ot 659*cfb92d14SAndroid Build Coastguard Worker 660*cfb92d14SAndroid Build Coastguard Worker #endif // NCP_FRAME_BUFFER_HPP_ 661