1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2017, 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 implements a spinel encoder.
31*cfb92d14SAndroid Build Coastguard Worker */
32*cfb92d14SAndroid Build Coastguard Worker
33*cfb92d14SAndroid Build Coastguard Worker #include "spinel_encoder.hpp"
34*cfb92d14SAndroid Build Coastguard Worker
35*cfb92d14SAndroid Build Coastguard Worker #include <string.h>
36*cfb92d14SAndroid Build Coastguard Worker
37*cfb92d14SAndroid Build Coastguard Worker #include "lib/utils/utils.hpp"
38*cfb92d14SAndroid Build Coastguard Worker
39*cfb92d14SAndroid Build Coastguard Worker namespace ot {
40*cfb92d14SAndroid Build Coastguard Worker namespace Spinel {
41*cfb92d14SAndroid Build Coastguard Worker
BeginFrame(Spinel::Buffer::Priority aPriority)42*cfb92d14SAndroid Build Coastguard Worker otError Encoder::BeginFrame(Spinel::Buffer::Priority aPriority)
43*cfb92d14SAndroid Build Coastguard Worker {
44*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs = 0;
45*cfb92d14SAndroid Build Coastguard Worker mNcpBuffer.InFrameBegin(aPriority);
46*cfb92d14SAndroid Build Coastguard Worker return OT_ERROR_NONE;
47*cfb92d14SAndroid Build Coastguard Worker }
48*cfb92d14SAndroid Build Coastguard Worker
BeginFrame(uint8_t aHeader,unsigned int aCommand)49*cfb92d14SAndroid Build Coastguard Worker otError Encoder::BeginFrame(uint8_t aHeader, unsigned int aCommand)
50*cfb92d14SAndroid Build Coastguard Worker {
51*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
52*cfb92d14SAndroid Build Coastguard Worker
53*cfb92d14SAndroid Build Coastguard Worker // Non-zero TID indicates this is a response to a spinel command.
54*cfb92d14SAndroid Build Coastguard Worker
55*cfb92d14SAndroid Build Coastguard Worker if (SPINEL_HEADER_GET_TID(aHeader) != 0)
56*cfb92d14SAndroid Build Coastguard Worker {
57*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = BeginFrame(Spinel::Buffer::kPriorityHigh));
58*cfb92d14SAndroid Build Coastguard Worker }
59*cfb92d14SAndroid Build Coastguard Worker else
60*cfb92d14SAndroid Build Coastguard Worker {
61*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = BeginFrame(Spinel::Buffer::kPriorityLow));
62*cfb92d14SAndroid Build Coastguard Worker }
63*cfb92d14SAndroid Build Coastguard Worker
64*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUint8(aHeader));
65*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUintPacked(aCommand));
66*cfb92d14SAndroid Build Coastguard Worker
67*cfb92d14SAndroid Build Coastguard Worker exit:
68*cfb92d14SAndroid Build Coastguard Worker return error;
69*cfb92d14SAndroid Build Coastguard Worker }
70*cfb92d14SAndroid Build Coastguard Worker
BeginFrame(uint8_t aHeader,unsigned int aCommand,spinel_prop_key_t aKey)71*cfb92d14SAndroid Build Coastguard Worker otError Encoder::BeginFrame(uint8_t aHeader, unsigned int aCommand, spinel_prop_key_t aKey)
72*cfb92d14SAndroid Build Coastguard Worker {
73*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
74*cfb92d14SAndroid Build Coastguard Worker
75*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = BeginFrame(aHeader, aCommand));
76*cfb92d14SAndroid Build Coastguard Worker
77*cfb92d14SAndroid Build Coastguard Worker // The write position is saved before writing the property key,
78*cfb92d14SAndroid Build Coastguard Worker // so that if fetching the property fails and we need to
79*cfb92d14SAndroid Build Coastguard Worker // reply with a `LAST_STATUS` error we can get back to
80*cfb92d14SAndroid Build Coastguard Worker // this saved write position and update the property key.
81*cfb92d14SAndroid Build Coastguard Worker // (Also see `OverwriteWithLastStatusError()`).
82*cfb92d14SAndroid Build Coastguard Worker
83*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = SavePosition());
84*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUintPacked(aKey));
85*cfb92d14SAndroid Build Coastguard Worker
86*cfb92d14SAndroid Build Coastguard Worker exit:
87*cfb92d14SAndroid Build Coastguard Worker return error;
88*cfb92d14SAndroid Build Coastguard Worker }
89*cfb92d14SAndroid Build Coastguard Worker
OverwriteWithLastStatusError(spinel_status_t aStatus)90*cfb92d14SAndroid Build Coastguard Worker otError Encoder::OverwriteWithLastStatusError(spinel_status_t aStatus)
91*cfb92d14SAndroid Build Coastguard Worker {
92*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
93*cfb92d14SAndroid Build Coastguard Worker
94*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ResetToSaved());
95*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUintPacked(SPINEL_PROP_LAST_STATUS));
96*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUintPacked(aStatus));
97*cfb92d14SAndroid Build Coastguard Worker
98*cfb92d14SAndroid Build Coastguard Worker exit:
99*cfb92d14SAndroid Build Coastguard Worker return error;
100*cfb92d14SAndroid Build Coastguard Worker }
101*cfb92d14SAndroid Build Coastguard Worker
EndFrame(void)102*cfb92d14SAndroid Build Coastguard Worker otError Encoder::EndFrame(void)
103*cfb92d14SAndroid Build Coastguard Worker {
104*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
105*cfb92d14SAndroid Build Coastguard Worker
106*cfb92d14SAndroid Build Coastguard Worker while (mNumOpenStructs > 0)
107*cfb92d14SAndroid Build Coastguard Worker {
108*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = CloseStruct());
109*cfb92d14SAndroid Build Coastguard Worker }
110*cfb92d14SAndroid Build Coastguard Worker
111*cfb92d14SAndroid Build Coastguard Worker error = mNcpBuffer.InFrameEnd();
112*cfb92d14SAndroid Build Coastguard Worker
113*cfb92d14SAndroid Build Coastguard Worker exit:
114*cfb92d14SAndroid Build Coastguard Worker return error;
115*cfb92d14SAndroid Build Coastguard Worker }
116*cfb92d14SAndroid Build Coastguard Worker
WriteUint16(uint16_t aUint16)117*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteUint16(uint16_t aUint16)
118*cfb92d14SAndroid Build Coastguard Worker {
119*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
120*cfb92d14SAndroid Build Coastguard Worker
121*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 0) & 0xff));
122*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 8) & 0xff));
123*cfb92d14SAndroid Build Coastguard Worker
124*cfb92d14SAndroid Build Coastguard Worker exit:
125*cfb92d14SAndroid Build Coastguard Worker return error;
126*cfb92d14SAndroid Build Coastguard Worker }
127*cfb92d14SAndroid Build Coastguard Worker
WriteUint32(uint32_t aUint32)128*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteUint32(uint32_t aUint32)
129*cfb92d14SAndroid Build Coastguard Worker {
130*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
131*cfb92d14SAndroid Build Coastguard Worker
132*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 0) & 0xff));
133*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 8) & 0xff));
134*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 16) & 0xff));
135*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 24) & 0xff));
136*cfb92d14SAndroid Build Coastguard Worker
137*cfb92d14SAndroid Build Coastguard Worker exit:
138*cfb92d14SAndroid Build Coastguard Worker return error;
139*cfb92d14SAndroid Build Coastguard Worker }
140*cfb92d14SAndroid Build Coastguard Worker
WriteUint64(uint64_t aUint64)141*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteUint64(uint64_t aUint64)
142*cfb92d14SAndroid Build Coastguard Worker {
143*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
144*cfb92d14SAndroid Build Coastguard Worker
145*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 0) & 0xff));
146*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 8) & 0xff));
147*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 16) & 0xff));
148*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 24) & 0xff));
149*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 32) & 0xff));
150*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 40) & 0xff));
151*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 48) & 0xff));
152*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 56) & 0xff));
153*cfb92d14SAndroid Build Coastguard Worker
154*cfb92d14SAndroid Build Coastguard Worker exit:
155*cfb92d14SAndroid Build Coastguard Worker return error;
156*cfb92d14SAndroid Build Coastguard Worker }
157*cfb92d14SAndroid Build Coastguard Worker
WriteUintPacked(unsigned int aUint)158*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteUintPacked(unsigned int aUint)
159*cfb92d14SAndroid Build Coastguard Worker {
160*cfb92d14SAndroid Build Coastguard Worker uint8_t buffer[6];
161*cfb92d14SAndroid Build Coastguard Worker spinel_ssize_t len;
162*cfb92d14SAndroid Build Coastguard Worker
163*cfb92d14SAndroid Build Coastguard Worker len = spinel_packed_uint_encode(buffer, sizeof(buffer), aUint);
164*cfb92d14SAndroid Build Coastguard Worker
165*cfb92d14SAndroid Build Coastguard Worker return WriteData(buffer, static_cast<uint16_t>(len));
166*cfb92d14SAndroid Build Coastguard Worker }
167*cfb92d14SAndroid Build Coastguard Worker
WriteDataWithLen(const uint8_t * aData,uint16_t aDataLen)168*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteDataWithLen(const uint8_t *aData, uint16_t aDataLen)
169*cfb92d14SAndroid Build Coastguard Worker {
170*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
171*cfb92d14SAndroid Build Coastguard Worker
172*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteUint16(aDataLen));
173*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteData(aData, aDataLen));
174*cfb92d14SAndroid Build Coastguard Worker
175*cfb92d14SAndroid Build Coastguard Worker exit:
176*cfb92d14SAndroid Build Coastguard Worker return error;
177*cfb92d14SAndroid Build Coastguard Worker }
178*cfb92d14SAndroid Build Coastguard Worker
WriteUtf8(const char * aUtf8)179*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteUtf8(const char *aUtf8)
180*cfb92d14SAndroid Build Coastguard Worker {
181*cfb92d14SAndroid Build Coastguard Worker otError error;
182*cfb92d14SAndroid Build Coastguard Worker size_t len = strlen(aUtf8);
183*cfb92d14SAndroid Build Coastguard Worker
184*cfb92d14SAndroid Build Coastguard Worker if (len >= 0xffff)
185*cfb92d14SAndroid Build Coastguard Worker {
186*cfb92d14SAndroid Build Coastguard Worker len = 0xffff;
187*cfb92d14SAndroid Build Coastguard Worker }
188*cfb92d14SAndroid Build Coastguard Worker
189*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = WriteData(reinterpret_cast<const uint8_t *>(aUtf8), static_cast<uint16_t>(len)));
190*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte(0));
191*cfb92d14SAndroid Build Coastguard Worker
192*cfb92d14SAndroid Build Coastguard Worker exit:
193*cfb92d14SAndroid Build Coastguard Worker return error;
194*cfb92d14SAndroid Build Coastguard Worker }
195*cfb92d14SAndroid Build Coastguard Worker
OpenStruct(void)196*cfb92d14SAndroid Build Coastguard Worker otError Encoder::OpenStruct(void)
197*cfb92d14SAndroid Build Coastguard Worker {
198*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
199*cfb92d14SAndroid Build Coastguard Worker
200*cfb92d14SAndroid Build Coastguard Worker EXPECT(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
201*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameGetPosition(mStructPosition[mNumOpenStructs]));
202*cfb92d14SAndroid Build Coastguard Worker
203*cfb92d14SAndroid Build Coastguard Worker // Reserve bytes for the length to be filled when the struct gets closed.
204*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte(0));
205*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameFeedByte(0));
206*cfb92d14SAndroid Build Coastguard Worker
207*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs++;
208*cfb92d14SAndroid Build Coastguard Worker
209*cfb92d14SAndroid Build Coastguard Worker exit:
210*cfb92d14SAndroid Build Coastguard Worker return error;
211*cfb92d14SAndroid Build Coastguard Worker }
212*cfb92d14SAndroid Build Coastguard Worker
CloseStruct(void)213*cfb92d14SAndroid Build Coastguard Worker otError Encoder::CloseStruct(void)
214*cfb92d14SAndroid Build Coastguard Worker {
215*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
216*cfb92d14SAndroid Build Coastguard Worker uint16_t len;
217*cfb92d14SAndroid Build Coastguard Worker uint8_t buffer[sizeof(uint16_t)];
218*cfb92d14SAndroid Build Coastguard Worker
219*cfb92d14SAndroid Build Coastguard Worker EXPECT(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
220*cfb92d14SAndroid Build Coastguard Worker
221*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs--;
222*cfb92d14SAndroid Build Coastguard Worker
223*cfb92d14SAndroid Build Coastguard Worker len = mNcpBuffer.InFrameGetDistance(mStructPosition[mNumOpenStructs]);
224*cfb92d14SAndroid Build Coastguard Worker EXPECT(len >= sizeof(uint16_t), error = OT_ERROR_INVALID_STATE);
225*cfb92d14SAndroid Build Coastguard Worker
226*cfb92d14SAndroid Build Coastguard Worker len -= sizeof(uint16_t);
227*cfb92d14SAndroid Build Coastguard Worker
228*cfb92d14SAndroid Build Coastguard Worker buffer[0] = (len >> 0 & 0xff);
229*cfb92d14SAndroid Build Coastguard Worker buffer[1] = (len >> 8 & 0xff);
230*cfb92d14SAndroid Build Coastguard Worker
231*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameOverwrite(mStructPosition[mNumOpenStructs], buffer, sizeof(buffer)));
232*cfb92d14SAndroid Build Coastguard Worker
233*cfb92d14SAndroid Build Coastguard Worker exit:
234*cfb92d14SAndroid Build Coastguard Worker return error;
235*cfb92d14SAndroid Build Coastguard Worker }
236*cfb92d14SAndroid Build Coastguard Worker
SavePosition(void)237*cfb92d14SAndroid Build Coastguard Worker otError Encoder::SavePosition(void)
238*cfb92d14SAndroid Build Coastguard Worker {
239*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
240*cfb92d14SAndroid Build Coastguard Worker
241*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameGetPosition(mSavedPosition));
242*cfb92d14SAndroid Build Coastguard Worker mSavedNumOpenStructs = mNumOpenStructs;
243*cfb92d14SAndroid Build Coastguard Worker
244*cfb92d14SAndroid Build Coastguard Worker exit:
245*cfb92d14SAndroid Build Coastguard Worker return error;
246*cfb92d14SAndroid Build Coastguard Worker }
247*cfb92d14SAndroid Build Coastguard Worker
ResetToSaved(void)248*cfb92d14SAndroid Build Coastguard Worker otError Encoder::ResetToSaved(void)
249*cfb92d14SAndroid Build Coastguard Worker {
250*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
251*cfb92d14SAndroid Build Coastguard Worker
252*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = mNcpBuffer.InFrameReset(mSavedPosition));
253*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs = mSavedNumOpenStructs;
254*cfb92d14SAndroid Build Coastguard Worker
255*cfb92d14SAndroid Build Coastguard Worker exit:
256*cfb92d14SAndroid Build Coastguard Worker return error;
257*cfb92d14SAndroid Build Coastguard Worker }
258*cfb92d14SAndroid Build Coastguard Worker
WritePacked(const char * aPackFormat,...)259*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WritePacked(const char *aPackFormat, ...)
260*cfb92d14SAndroid Build Coastguard Worker {
261*cfb92d14SAndroid Build Coastguard Worker uint8_t buf[kPackFormatBufferSize];
262*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
263*cfb92d14SAndroid Build Coastguard Worker spinel_ssize_t packedLen;
264*cfb92d14SAndroid Build Coastguard Worker va_list args;
265*cfb92d14SAndroid Build Coastguard Worker
266*cfb92d14SAndroid Build Coastguard Worker va_start(args, aPackFormat);
267*cfb92d14SAndroid Build Coastguard Worker
268*cfb92d14SAndroid Build Coastguard Worker packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, args);
269*cfb92d14SAndroid Build Coastguard Worker EXPECT((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);
270*cfb92d14SAndroid Build Coastguard Worker
271*cfb92d14SAndroid Build Coastguard Worker error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));
272*cfb92d14SAndroid Build Coastguard Worker
273*cfb92d14SAndroid Build Coastguard Worker exit:
274*cfb92d14SAndroid Build Coastguard Worker va_end(args);
275*cfb92d14SAndroid Build Coastguard Worker
276*cfb92d14SAndroid Build Coastguard Worker return error;
277*cfb92d14SAndroid Build Coastguard Worker }
278*cfb92d14SAndroid Build Coastguard Worker
WriteVPacked(const char * aPackFormat,va_list aArgs)279*cfb92d14SAndroid Build Coastguard Worker otError Encoder::WriteVPacked(const char *aPackFormat, va_list aArgs)
280*cfb92d14SAndroid Build Coastguard Worker {
281*cfb92d14SAndroid Build Coastguard Worker uint8_t buf[kPackFormatBufferSize];
282*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
283*cfb92d14SAndroid Build Coastguard Worker spinel_ssize_t packedLen;
284*cfb92d14SAndroid Build Coastguard Worker
285*cfb92d14SAndroid Build Coastguard Worker packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, aArgs);
286*cfb92d14SAndroid Build Coastguard Worker EXPECT((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);
287*cfb92d14SAndroid Build Coastguard Worker
288*cfb92d14SAndroid Build Coastguard Worker error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));
289*cfb92d14SAndroid Build Coastguard Worker
290*cfb92d14SAndroid Build Coastguard Worker exit:
291*cfb92d14SAndroid Build Coastguard Worker return error;
292*cfb92d14SAndroid Build Coastguard Worker }
293*cfb92d14SAndroid Build Coastguard Worker
ClearNcpBuffer(void)294*cfb92d14SAndroid Build Coastguard Worker void Encoder::ClearNcpBuffer(void) { mNcpBuffer.Clear(); }
295*cfb92d14SAndroid Build Coastguard Worker
296*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel
297*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
298