xref: /aosp_15_r20/external/openthread/src/lib/spinel/spinel_buffer.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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