xref: /aosp_15_r20/system/nfc/src/nfc/ndef/ndef_utils.cc (revision 7eba2f3b06c51ae21384f6a4f14577b668a869b3)
1*7eba2f3bSAndroid Build Coastguard Worker /******************************************************************************
2*7eba2f3bSAndroid Build Coastguard Worker  *
3*7eba2f3bSAndroid Build Coastguard Worker  *  Copyright (C) 2010-2014 Broadcom Corporation
4*7eba2f3bSAndroid Build Coastguard Worker  *
5*7eba2f3bSAndroid Build Coastguard Worker  *  Licensed under the Apache License, Version 2.0 (the "License");
6*7eba2f3bSAndroid Build Coastguard Worker  *  you may not use this file except in compliance with the License.
7*7eba2f3bSAndroid Build Coastguard Worker  *  You may obtain a copy of the License at:
8*7eba2f3bSAndroid Build Coastguard Worker  *
9*7eba2f3bSAndroid Build Coastguard Worker  *  http://www.apache.org/licenses/LICENSE-2.0
10*7eba2f3bSAndroid Build Coastguard Worker  *
11*7eba2f3bSAndroid Build Coastguard Worker  *  Unless required by applicable law or agreed to in writing, software
12*7eba2f3bSAndroid Build Coastguard Worker  *  distributed under the License is distributed on an "AS IS" BASIS,
13*7eba2f3bSAndroid Build Coastguard Worker  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*7eba2f3bSAndroid Build Coastguard Worker  *  See the License for the specific language governing permissions and
15*7eba2f3bSAndroid Build Coastguard Worker  *  limitations under the License.
16*7eba2f3bSAndroid Build Coastguard Worker  *
17*7eba2f3bSAndroid Build Coastguard Worker  ******************************************************************************/
18*7eba2f3bSAndroid Build Coastguard Worker 
19*7eba2f3bSAndroid Build Coastguard Worker /******************************************************************************
20*7eba2f3bSAndroid Build Coastguard Worker  *
21*7eba2f3bSAndroid Build Coastguard Worker  *  This file contains source code for some utility functions to help parse
22*7eba2f3bSAndroid Build Coastguard Worker  *  and build NFC Data Exchange Format (NDEF) messages
23*7eba2f3bSAndroid Build Coastguard Worker  *
24*7eba2f3bSAndroid Build Coastguard Worker  ******************************************************************************/
25*7eba2f3bSAndroid Build Coastguard Worker #include "ndef_utils.h"
26*7eba2f3bSAndroid Build Coastguard Worker 
27*7eba2f3bSAndroid Build Coastguard Worker #include <log/log.h>
28*7eba2f3bSAndroid Build Coastguard Worker #include <string.h>
29*7eba2f3bSAndroid Build Coastguard Worker 
30*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
31*7eba2f3bSAndroid Build Coastguard Worker **
32*7eba2f3bSAndroid Build Coastguard Worker **              Static Local Functions
33*7eba2f3bSAndroid Build Coastguard Worker **
34*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
35*7eba2f3bSAndroid Build Coastguard Worker 
36*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
37*7eba2f3bSAndroid Build Coastguard Worker **
38*7eba2f3bSAndroid Build Coastguard Worker ** Function         shiftdown
39*7eba2f3bSAndroid Build Coastguard Worker **
40*7eba2f3bSAndroid Build Coastguard Worker ** Description      shift memory down (to make space to insert a record)
41*7eba2f3bSAndroid Build Coastguard Worker **
42*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
shiftdown(uint8_t * p_mem,uint32_t len,uint32_t shift_amount)43*7eba2f3bSAndroid Build Coastguard Worker static void shiftdown(uint8_t* p_mem, uint32_t len, uint32_t shift_amount) {
44*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* ps = p_mem + len - 1;
45*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pd = ps + shift_amount;
46*7eba2f3bSAndroid Build Coastguard Worker   uint32_t xx;
47*7eba2f3bSAndroid Build Coastguard Worker 
48*7eba2f3bSAndroid Build Coastguard Worker   for (xx = 0; xx < len; xx++) *pd-- = *ps--;
49*7eba2f3bSAndroid Build Coastguard Worker }
50*7eba2f3bSAndroid Build Coastguard Worker 
51*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
52*7eba2f3bSAndroid Build Coastguard Worker **
53*7eba2f3bSAndroid Build Coastguard Worker ** Function         shiftup
54*7eba2f3bSAndroid Build Coastguard Worker **
55*7eba2f3bSAndroid Build Coastguard Worker ** Description      shift memory up (to delete a record)
56*7eba2f3bSAndroid Build Coastguard Worker **
57*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
shiftup(uint8_t * p_dest,uint8_t * p_src,uint32_t len)58*7eba2f3bSAndroid Build Coastguard Worker static void shiftup(uint8_t* p_dest, uint8_t* p_src, uint32_t len) {
59*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* ps = p_src;
60*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pd = p_dest;
61*7eba2f3bSAndroid Build Coastguard Worker   uint32_t xx;
62*7eba2f3bSAndroid Build Coastguard Worker 
63*7eba2f3bSAndroid Build Coastguard Worker   for (xx = 0; xx < len; xx++) *pd++ = *ps++;
64*7eba2f3bSAndroid Build Coastguard Worker }
65*7eba2f3bSAndroid Build Coastguard Worker 
66*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
67*7eba2f3bSAndroid Build Coastguard Worker **
68*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgValidate
69*7eba2f3bSAndroid Build Coastguard Worker **
70*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function validates an NDEF message.
71*7eba2f3bSAndroid Build Coastguard Worker **
72*7eba2f3bSAndroid Build Coastguard Worker ** Returns          TRUE if all OK, or FALSE if the message is invalid.
73*7eba2f3bSAndroid Build Coastguard Worker **
74*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgValidate(uint8_t * p_msg,uint32_t msg_len,bool b_allow_chunks)75*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgValidate(uint8_t* p_msg, uint32_t msg_len,
76*7eba2f3bSAndroid Build Coastguard Worker                               bool b_allow_chunks) {
77*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
78*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_end = p_msg + msg_len;
79*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_new;
80*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr = 0, type_len, id_len;
81*7eba2f3bSAndroid Build Coastguard Worker   int count;
82*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
83*7eba2f3bSAndroid Build Coastguard Worker   bool bInChunk = false;
84*7eba2f3bSAndroid Build Coastguard Worker 
85*7eba2f3bSAndroid Build Coastguard Worker   if ((p_msg == nullptr) || (msg_len < 3)) return (NDEF_MSG_TOO_SHORT);
86*7eba2f3bSAndroid Build Coastguard Worker 
87*7eba2f3bSAndroid Build Coastguard Worker   /* The first record must have the MB bit set */
88*7eba2f3bSAndroid Build Coastguard Worker   if ((*p_msg & NDEF_MB_MASK) == 0) return (NDEF_MSG_NO_MSG_BEGIN);
89*7eba2f3bSAndroid Build Coastguard Worker 
90*7eba2f3bSAndroid Build Coastguard Worker   /* The first record cannot be a chunk */
91*7eba2f3bSAndroid Build Coastguard Worker   if ((*p_msg & NDEF_TNF_MASK) == NDEF_TNF_UNCHANGED)
92*7eba2f3bSAndroid Build Coastguard Worker     return (NDEF_MSG_UNEXPECTED_CHUNK);
93*7eba2f3bSAndroid Build Coastguard Worker 
94*7eba2f3bSAndroid Build Coastguard Worker   for (count = 0; p_rec < p_end; count++) {
95*7eba2f3bSAndroid Build Coastguard Worker     /* if less than short record header */
96*7eba2f3bSAndroid Build Coastguard Worker     if (p_rec + 3 > p_end) return (NDEF_MSG_TOO_SHORT);
97*7eba2f3bSAndroid Build Coastguard Worker 
98*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
99*7eba2f3bSAndroid Build Coastguard Worker 
100*7eba2f3bSAndroid Build Coastguard Worker     /* header should have a valid TNF */
101*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_MASK)
102*7eba2f3bSAndroid Build Coastguard Worker       return NDEF_MSG_INVALID_CHUNK;
103*7eba2f3bSAndroid Build Coastguard Worker 
104*7eba2f3bSAndroid Build Coastguard Worker     /* The second and all subsequent records must NOT have the MB bit set */
105*7eba2f3bSAndroid Build Coastguard Worker     if ((count > 0) && (rec_hdr & NDEF_MB_MASK))
106*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_EXTRA_MSG_BEGIN);
107*7eba2f3bSAndroid Build Coastguard Worker 
108*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
109*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
110*7eba2f3bSAndroid Build Coastguard Worker 
111*7eba2f3bSAndroid Build Coastguard Worker     /* If the record is chunked, first record must contain the type unless
112*7eba2f3bSAndroid Build Coastguard Worker      * it's Type Name Format is Unknown */
113*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_CF_MASK) && (rec_hdr & NDEF_MB_MASK) && type_len == 0 &&
114*7eba2f3bSAndroid Build Coastguard Worker         (rec_hdr & NDEF_TNF_MASK) != NDEF_TNF_UNKNOWN)
115*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_INVALID_CHUNK);
116*7eba2f3bSAndroid Build Coastguard Worker 
117*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
118*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
119*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
120*7eba2f3bSAndroid Build Coastguard Worker     else {
121*7eba2f3bSAndroid Build Coastguard Worker       /* if less than 4 bytes payload length */
122*7eba2f3bSAndroid Build Coastguard Worker       if (p_rec + 4 > p_end) return (NDEF_MSG_TOO_SHORT);
123*7eba2f3bSAndroid Build Coastguard Worker 
124*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
125*7eba2f3bSAndroid Build Coastguard Worker     }
126*7eba2f3bSAndroid Build Coastguard Worker 
127*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
128*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK) {
129*7eba2f3bSAndroid Build Coastguard Worker       /* if less than 1 byte ID field length */
130*7eba2f3bSAndroid Build Coastguard Worker       if (p_rec + 1 > p_end) return (NDEF_MSG_TOO_SHORT);
131*7eba2f3bSAndroid Build Coastguard Worker 
132*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
133*7eba2f3bSAndroid Build Coastguard Worker     } else {
134*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
135*7eba2f3bSAndroid Build Coastguard Worker       /* Empty record must have the id_len */
136*7eba2f3bSAndroid Build Coastguard Worker       if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_EMPTY)
137*7eba2f3bSAndroid Build Coastguard Worker         return (NDEF_MSG_INVALID_EMPTY_REC);
138*7eba2f3bSAndroid Build Coastguard Worker     }
139*7eba2f3bSAndroid Build Coastguard Worker 
140*7eba2f3bSAndroid Build Coastguard Worker     /* A chunk must have type "unchanged", and no type or ID fields */
141*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_CF_MASK) {
142*7eba2f3bSAndroid Build Coastguard Worker       if (!b_allow_chunks) return (NDEF_MSG_UNEXPECTED_CHUNK);
143*7eba2f3bSAndroid Build Coastguard Worker 
144*7eba2f3bSAndroid Build Coastguard Worker       /* Inside a chunk, the type must be unchanged and no type or ID field i
145*7eba2f3bSAndroid Build Coastguard Worker        * sallowed */
146*7eba2f3bSAndroid Build Coastguard Worker       if (bInChunk) {
147*7eba2f3bSAndroid Build Coastguard Worker         if ((type_len != 0) || (id_len != 0) ||
148*7eba2f3bSAndroid Build Coastguard Worker             ((rec_hdr & NDEF_TNF_MASK) != NDEF_TNF_UNCHANGED))
149*7eba2f3bSAndroid Build Coastguard Worker           return (NDEF_MSG_INVALID_CHUNK);
150*7eba2f3bSAndroid Build Coastguard Worker       } else {
151*7eba2f3bSAndroid Build Coastguard Worker         /* First record of a chunk must NOT have type "unchanged" */
152*7eba2f3bSAndroid Build Coastguard Worker         if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_UNCHANGED)
153*7eba2f3bSAndroid Build Coastguard Worker           return (NDEF_MSG_INVALID_CHUNK);
154*7eba2f3bSAndroid Build Coastguard Worker 
155*7eba2f3bSAndroid Build Coastguard Worker         bInChunk = true;
156*7eba2f3bSAndroid Build Coastguard Worker       }
157*7eba2f3bSAndroid Build Coastguard Worker     } else {
158*7eba2f3bSAndroid Build Coastguard Worker       /* This may be the last guy in a chunk. */
159*7eba2f3bSAndroid Build Coastguard Worker       if (bInChunk) {
160*7eba2f3bSAndroid Build Coastguard Worker         if ((type_len != 0) || (id_len != 0) ||
161*7eba2f3bSAndroid Build Coastguard Worker             ((rec_hdr & NDEF_TNF_MASK) != NDEF_TNF_UNCHANGED))
162*7eba2f3bSAndroid Build Coastguard Worker           return (NDEF_MSG_INVALID_CHUNK);
163*7eba2f3bSAndroid Build Coastguard Worker 
164*7eba2f3bSAndroid Build Coastguard Worker         bInChunk = false;
165*7eba2f3bSAndroid Build Coastguard Worker       } else {
166*7eba2f3bSAndroid Build Coastguard Worker         /* If not in a chunk, the record must NOT have type "unchanged" */
167*7eba2f3bSAndroid Build Coastguard Worker         if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_UNCHANGED)
168*7eba2f3bSAndroid Build Coastguard Worker           return (NDEF_MSG_INVALID_CHUNK);
169*7eba2f3bSAndroid Build Coastguard Worker       }
170*7eba2f3bSAndroid Build Coastguard Worker     }
171*7eba2f3bSAndroid Build Coastguard Worker 
172*7eba2f3bSAndroid Build Coastguard Worker     /* An empty record must NOT have a type, ID or payload */
173*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_EMPTY) {
174*7eba2f3bSAndroid Build Coastguard Worker       if ((type_len != 0) || (id_len != 0) || (payload_len != 0))
175*7eba2f3bSAndroid Build Coastguard Worker         return (NDEF_MSG_INVALID_EMPTY_REC);
176*7eba2f3bSAndroid Build Coastguard Worker     }
177*7eba2f3bSAndroid Build Coastguard Worker 
178*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_UNKNOWN) {
179*7eba2f3bSAndroid Build Coastguard Worker       if (type_len != 0) return (NDEF_MSG_LENGTH_MISMATCH);
180*7eba2f3bSAndroid Build Coastguard Worker     }
181*7eba2f3bSAndroid Build Coastguard Worker 
182*7eba2f3bSAndroid Build Coastguard Worker     /* External type should have non-zero type length */
183*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_EXT) {
184*7eba2f3bSAndroid Build Coastguard Worker       if (type_len == 0) return (NDEF_MSG_LENGTH_MISMATCH);
185*7eba2f3bSAndroid Build Coastguard Worker     }
186*7eba2f3bSAndroid Build Coastguard Worker 
187*7eba2f3bSAndroid Build Coastguard Worker     /* External type and Well Known types should have valid characters
188*7eba2f3bSAndroid Build Coastguard Worker        in the TYPE field */
189*7eba2f3bSAndroid Build Coastguard Worker     if ((rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_EXT ||
190*7eba2f3bSAndroid Build Coastguard Worker         (rec_hdr & NDEF_TNF_MASK) == NDEF_TNF_WKT) {
191*7eba2f3bSAndroid Build Coastguard Worker       uint8_t* p_rec_type = p_rec;
192*7eba2f3bSAndroid Build Coastguard Worker       if ((p_rec_type + type_len) > p_end) return (NDEF_MSG_TOO_SHORT);
193*7eba2f3bSAndroid Build Coastguard Worker 
194*7eba2f3bSAndroid Build Coastguard Worker       for (int type_index = 0; type_index < type_len; type_index++) {
195*7eba2f3bSAndroid Build Coastguard Worker         if (p_rec_type[type_index] < NDEF_RTD_VALID_START ||
196*7eba2f3bSAndroid Build Coastguard Worker             p_rec_type[type_index] > NDEF_RTD_VALID_END)
197*7eba2f3bSAndroid Build Coastguard Worker           return (NDEF_MSG_INVALID_TYPE);
198*7eba2f3bSAndroid Build Coastguard Worker       }
199*7eba2f3bSAndroid Build Coastguard Worker     }
200*7eba2f3bSAndroid Build Coastguard Worker 
201*7eba2f3bSAndroid Build Coastguard Worker     /* Check for OOB */
202*7eba2f3bSAndroid Build Coastguard Worker     if (payload_len + type_len + id_len < payload_len ||
203*7eba2f3bSAndroid Build Coastguard Worker         payload_len + type_len + id_len > msg_len) {
204*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_LENGTH_MISMATCH);
205*7eba2f3bSAndroid Build Coastguard Worker     }
206*7eba2f3bSAndroid Build Coastguard Worker     p_new = p_rec + (payload_len + type_len + id_len);
207*7eba2f3bSAndroid Build Coastguard Worker     if (p_rec > p_new || p_end < p_new) {
208*7eba2f3bSAndroid Build Coastguard Worker       android_errorWriteLog(0x534e4554, "126200054");
209*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_LENGTH_MISMATCH);
210*7eba2f3bSAndroid Build Coastguard Worker     }
211*7eba2f3bSAndroid Build Coastguard Worker 
212*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
213*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
214*7eba2f3bSAndroid Build Coastguard Worker 
215*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) break;
216*7eba2f3bSAndroid Build Coastguard Worker 
217*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = 0;
218*7eba2f3bSAndroid Build Coastguard Worker   }
219*7eba2f3bSAndroid Build Coastguard Worker 
220*7eba2f3bSAndroid Build Coastguard Worker   /* The last record should have the ME bit set */
221*7eba2f3bSAndroid Build Coastguard Worker   if ((rec_hdr & NDEF_ME_MASK) == 0) return (NDEF_MSG_NO_MSG_END);
222*7eba2f3bSAndroid Build Coastguard Worker 
223*7eba2f3bSAndroid Build Coastguard Worker   /* p_rec should equal p_end if all the length fields were correct */
224*7eba2f3bSAndroid Build Coastguard Worker   if (p_rec != p_end) return (NDEF_MSG_LENGTH_MISMATCH);
225*7eba2f3bSAndroid Build Coastguard Worker 
226*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
227*7eba2f3bSAndroid Build Coastguard Worker }
228*7eba2f3bSAndroid Build Coastguard Worker 
229*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
230*7eba2f3bSAndroid Build Coastguard Worker **
231*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetNumRecs
232*7eba2f3bSAndroid Build Coastguard Worker **
233*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets the number of records in the given NDEF
234*7eba2f3bSAndroid Build Coastguard Worker **                  message.
235*7eba2f3bSAndroid Build Coastguard Worker **
236*7eba2f3bSAndroid Build Coastguard Worker ** Returns          The record count, or 0 if the message is invalid.
237*7eba2f3bSAndroid Build Coastguard Worker **
238*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetNumRecs(uint8_t * p_msg)239*7eba2f3bSAndroid Build Coastguard Worker int32_t NDEF_MsgGetNumRecs(uint8_t* p_msg) {
240*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
241*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
242*7eba2f3bSAndroid Build Coastguard Worker   int count;
243*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
244*7eba2f3bSAndroid Build Coastguard Worker 
245*7eba2f3bSAndroid Build Coastguard Worker   for (count = 0;;) {
246*7eba2f3bSAndroid Build Coastguard Worker     count++;
247*7eba2f3bSAndroid Build Coastguard Worker 
248*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
249*7eba2f3bSAndroid Build Coastguard Worker 
250*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) break;
251*7eba2f3bSAndroid Build Coastguard Worker 
252*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
253*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
254*7eba2f3bSAndroid Build Coastguard Worker 
255*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
256*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
257*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
258*7eba2f3bSAndroid Build Coastguard Worker     else
259*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
260*7eba2f3bSAndroid Build Coastguard Worker 
261*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
262*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
263*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
264*7eba2f3bSAndroid Build Coastguard Worker     else
265*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
266*7eba2f3bSAndroid Build Coastguard Worker 
267*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
268*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
269*7eba2f3bSAndroid Build Coastguard Worker   }
270*7eba2f3bSAndroid Build Coastguard Worker 
271*7eba2f3bSAndroid Build Coastguard Worker   /* Return the number of records found */
272*7eba2f3bSAndroid Build Coastguard Worker   return (count);
273*7eba2f3bSAndroid Build Coastguard Worker }
274*7eba2f3bSAndroid Build Coastguard Worker 
275*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
276*7eba2f3bSAndroid Build Coastguard Worker **
277*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetRecLength
278*7eba2f3bSAndroid Build Coastguard Worker **
279*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function returns length of the current record in the
280*7eba2f3bSAndroid Build Coastguard Worker **                  given NDEF message.
281*7eba2f3bSAndroid Build Coastguard Worker **
282*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Length of record
283*7eba2f3bSAndroid Build Coastguard Worker **
284*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetRecLength(uint8_t * p_cur_rec)285*7eba2f3bSAndroid Build Coastguard Worker uint32_t NDEF_MsgGetRecLength(uint8_t* p_cur_rec) {
286*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
287*7eba2f3bSAndroid Build Coastguard Worker   uint32_t rec_len = 0;
288*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
289*7eba2f3bSAndroid Build Coastguard Worker 
290*7eba2f3bSAndroid Build Coastguard Worker   /* Get the current record's header */
291*7eba2f3bSAndroid Build Coastguard Worker   rec_hdr = *p_cur_rec++;
292*7eba2f3bSAndroid Build Coastguard Worker   rec_len++;
293*7eba2f3bSAndroid Build Coastguard Worker 
294*7eba2f3bSAndroid Build Coastguard Worker   /* Type field length */
295*7eba2f3bSAndroid Build Coastguard Worker   type_len = *p_cur_rec++;
296*7eba2f3bSAndroid Build Coastguard Worker   rec_len++;
297*7eba2f3bSAndroid Build Coastguard Worker 
298*7eba2f3bSAndroid Build Coastguard Worker   /* Payload length - can be 1 or 4 bytes */
299*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_SR_MASK) {
300*7eba2f3bSAndroid Build Coastguard Worker     payload_len = *p_cur_rec++;
301*7eba2f3bSAndroid Build Coastguard Worker     rec_len++;
302*7eba2f3bSAndroid Build Coastguard Worker   } else {
303*7eba2f3bSAndroid Build Coastguard Worker     BE_STREAM_TO_UINT32(payload_len, p_cur_rec);
304*7eba2f3bSAndroid Build Coastguard Worker     rec_len += 4;
305*7eba2f3bSAndroid Build Coastguard Worker   }
306*7eba2f3bSAndroid Build Coastguard Worker 
307*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
308*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_IL_MASK) {
309*7eba2f3bSAndroid Build Coastguard Worker     id_len = *p_cur_rec++;
310*7eba2f3bSAndroid Build Coastguard Worker     rec_len++;
311*7eba2f3bSAndroid Build Coastguard Worker   } else
312*7eba2f3bSAndroid Build Coastguard Worker     id_len = 0;
313*7eba2f3bSAndroid Build Coastguard Worker 
314*7eba2f3bSAndroid Build Coastguard Worker   /* Total length of record */
315*7eba2f3bSAndroid Build Coastguard Worker   rec_len += (payload_len + type_len + id_len);
316*7eba2f3bSAndroid Build Coastguard Worker 
317*7eba2f3bSAndroid Build Coastguard Worker   return (rec_len);
318*7eba2f3bSAndroid Build Coastguard Worker }
319*7eba2f3bSAndroid Build Coastguard Worker 
320*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
321*7eba2f3bSAndroid Build Coastguard Worker **
322*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetNextRec
323*7eba2f3bSAndroid Build Coastguard Worker **
324*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the next record in the given
325*7eba2f3bSAndroid Build Coastguard Worker **                  NDEF message. If the current record pointer is NULL, a
326*7eba2f3bSAndroid Build Coastguard Worker **                  pointer to the first record is returned.
327*7eba2f3bSAndroid Build Coastguard Worker **
328*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL if no more
329*7eba2f3bSAndroid Build Coastguard Worker **
330*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetNextRec(uint8_t * p_cur_rec)331*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetNextRec(uint8_t* p_cur_rec) {
332*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
333*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
334*7eba2f3bSAndroid Build Coastguard Worker 
335*7eba2f3bSAndroid Build Coastguard Worker   /* Get the current record's header */
336*7eba2f3bSAndroid Build Coastguard Worker   rec_hdr = *p_cur_rec++;
337*7eba2f3bSAndroid Build Coastguard Worker 
338*7eba2f3bSAndroid Build Coastguard Worker   /* If this is the last record, return NULL */
339*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_ME_MASK) return (nullptr);
340*7eba2f3bSAndroid Build Coastguard Worker 
341*7eba2f3bSAndroid Build Coastguard Worker   /* Type field length */
342*7eba2f3bSAndroid Build Coastguard Worker   type_len = *p_cur_rec++;
343*7eba2f3bSAndroid Build Coastguard Worker 
344*7eba2f3bSAndroid Build Coastguard Worker   /* Payload length - can be 1 or 4 bytes */
345*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_SR_MASK)
346*7eba2f3bSAndroid Build Coastguard Worker     payload_len = *p_cur_rec++;
347*7eba2f3bSAndroid Build Coastguard Worker   else
348*7eba2f3bSAndroid Build Coastguard Worker     BE_STREAM_TO_UINT32(payload_len, p_cur_rec);
349*7eba2f3bSAndroid Build Coastguard Worker 
350*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
351*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_IL_MASK)
352*7eba2f3bSAndroid Build Coastguard Worker     id_len = *p_cur_rec++;
353*7eba2f3bSAndroid Build Coastguard Worker   else
354*7eba2f3bSAndroid Build Coastguard Worker     id_len = 0;
355*7eba2f3bSAndroid Build Coastguard Worker 
356*7eba2f3bSAndroid Build Coastguard Worker   /* Point to next record */
357*7eba2f3bSAndroid Build Coastguard Worker   p_cur_rec += (payload_len + type_len + id_len);
358*7eba2f3bSAndroid Build Coastguard Worker 
359*7eba2f3bSAndroid Build Coastguard Worker   return (p_cur_rec);
360*7eba2f3bSAndroid Build Coastguard Worker }
361*7eba2f3bSAndroid Build Coastguard Worker 
362*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
363*7eba2f3bSAndroid Build Coastguard Worker **
364*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetRecByIndex
365*7eba2f3bSAndroid Build Coastguard Worker **
366*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the record with the given
367*7eba2f3bSAndroid Build Coastguard Worker **                  index (0-based index) in the given NDEF message.
368*7eba2f3bSAndroid Build Coastguard Worker **
369*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL
370*7eba2f3bSAndroid Build Coastguard Worker **
371*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetRecByIndex(uint8_t * p_msg,int32_t index)372*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetRecByIndex(uint8_t* p_msg, int32_t index) {
373*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
374*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
375*7eba2f3bSAndroid Build Coastguard Worker   int32_t count;
376*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
377*7eba2f3bSAndroid Build Coastguard Worker 
378*7eba2f3bSAndroid Build Coastguard Worker   for (count = 0;; count++) {
379*7eba2f3bSAndroid Build Coastguard Worker     if (count == index) return (p_rec);
380*7eba2f3bSAndroid Build Coastguard Worker 
381*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
382*7eba2f3bSAndroid Build Coastguard Worker 
383*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) return (nullptr);
384*7eba2f3bSAndroid Build Coastguard Worker 
385*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
386*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
387*7eba2f3bSAndroid Build Coastguard Worker 
388*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
389*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
390*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
391*7eba2f3bSAndroid Build Coastguard Worker     else
392*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
393*7eba2f3bSAndroid Build Coastguard Worker 
394*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
395*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
396*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
397*7eba2f3bSAndroid Build Coastguard Worker     else
398*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
399*7eba2f3bSAndroid Build Coastguard Worker 
400*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
401*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
402*7eba2f3bSAndroid Build Coastguard Worker   }
403*7eba2f3bSAndroid Build Coastguard Worker 
404*7eba2f3bSAndroid Build Coastguard Worker   /* If here, there is no record of that index */
405*7eba2f3bSAndroid Build Coastguard Worker   return (nullptr);
406*7eba2f3bSAndroid Build Coastguard Worker }
407*7eba2f3bSAndroid Build Coastguard Worker 
408*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
409*7eba2f3bSAndroid Build Coastguard Worker **
410*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetLastRecInMsg
411*7eba2f3bSAndroid Build Coastguard Worker **
412*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the last record in the
413*7eba2f3bSAndroid Build Coastguard Worker **                  given NDEF message.
414*7eba2f3bSAndroid Build Coastguard Worker **
415*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the last record, or NULL if some
416*7eba2f3bSAndroid Build Coastguard Worker **                  problem
417*7eba2f3bSAndroid Build Coastguard Worker **
418*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetLastRecInMsg(uint8_t * p_msg)419*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetLastRecInMsg(uint8_t* p_msg) {
420*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
421*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pRecStart;
422*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
423*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
424*7eba2f3bSAndroid Build Coastguard Worker 
425*7eba2f3bSAndroid Build Coastguard Worker   for (;;) {
426*7eba2f3bSAndroid Build Coastguard Worker     pRecStart = p_rec;
427*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
428*7eba2f3bSAndroid Build Coastguard Worker 
429*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) break;
430*7eba2f3bSAndroid Build Coastguard Worker 
431*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
432*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
433*7eba2f3bSAndroid Build Coastguard Worker 
434*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
435*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
436*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
437*7eba2f3bSAndroid Build Coastguard Worker     else
438*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
439*7eba2f3bSAndroid Build Coastguard Worker 
440*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
441*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
442*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
443*7eba2f3bSAndroid Build Coastguard Worker     else
444*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
445*7eba2f3bSAndroid Build Coastguard Worker 
446*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
447*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
448*7eba2f3bSAndroid Build Coastguard Worker   }
449*7eba2f3bSAndroid Build Coastguard Worker 
450*7eba2f3bSAndroid Build Coastguard Worker   return (pRecStart);
451*7eba2f3bSAndroid Build Coastguard Worker }
452*7eba2f3bSAndroid Build Coastguard Worker 
453*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
454*7eba2f3bSAndroid Build Coastguard Worker **
455*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetFirstRecByType
456*7eba2f3bSAndroid Build Coastguard Worker **
457*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the first record with the
458*7eba2f3bSAndroid Build Coastguard Worker **                  given record type in the given NDEF message.
459*7eba2f3bSAndroid Build Coastguard Worker **
460*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL
461*7eba2f3bSAndroid Build Coastguard Worker **
462*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetFirstRecByType(uint8_t * p_msg,uint8_t tnf,uint8_t * p_type,uint8_t tlen)463*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetFirstRecByType(uint8_t* p_msg, uint8_t tnf, uint8_t* p_type,
464*7eba2f3bSAndroid Build Coastguard Worker                                    uint8_t tlen) {
465*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
466*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pRecStart;
467*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
468*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
469*7eba2f3bSAndroid Build Coastguard Worker 
470*7eba2f3bSAndroid Build Coastguard Worker   for (;;) {
471*7eba2f3bSAndroid Build Coastguard Worker     pRecStart = p_rec;
472*7eba2f3bSAndroid Build Coastguard Worker 
473*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
474*7eba2f3bSAndroid Build Coastguard Worker 
475*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
476*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
477*7eba2f3bSAndroid Build Coastguard Worker 
478*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
479*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
480*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
481*7eba2f3bSAndroid Build Coastguard Worker     else
482*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
483*7eba2f3bSAndroid Build Coastguard Worker 
484*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
485*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
486*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
487*7eba2f3bSAndroid Build Coastguard Worker     else
488*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
489*7eba2f3bSAndroid Build Coastguard Worker 
490*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the type field. We need to */
491*7eba2f3bSAndroid Build Coastguard Worker     /* compare the type of the type, the length of the type and the data     */
492*7eba2f3bSAndroid Build Coastguard Worker     if (((rec_hdr & NDEF_TNF_MASK) == tnf) && (type_len == tlen) &&
493*7eba2f3bSAndroid Build Coastguard Worker         (!memcmp(p_rec, p_type, tlen)))
494*7eba2f3bSAndroid Build Coastguard Worker       return (pRecStart);
495*7eba2f3bSAndroid Build Coastguard Worker 
496*7eba2f3bSAndroid Build Coastguard Worker     /* If this was the last record, return NULL */
497*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) return (nullptr);
498*7eba2f3bSAndroid Build Coastguard Worker 
499*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
500*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
501*7eba2f3bSAndroid Build Coastguard Worker   }
502*7eba2f3bSAndroid Build Coastguard Worker 
503*7eba2f3bSAndroid Build Coastguard Worker   /* If here, there is no record of that type */
504*7eba2f3bSAndroid Build Coastguard Worker   return (nullptr);
505*7eba2f3bSAndroid Build Coastguard Worker }
506*7eba2f3bSAndroid Build Coastguard Worker 
507*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
508*7eba2f3bSAndroid Build Coastguard Worker **
509*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetNextRecByType
510*7eba2f3bSAndroid Build Coastguard Worker **
511*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the next record with the
512*7eba2f3bSAndroid Build Coastguard Worker **                  given record type in the given NDEF message.
513*7eba2f3bSAndroid Build Coastguard Worker **
514*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL
515*7eba2f3bSAndroid Build Coastguard Worker **
516*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetNextRecByType(uint8_t * p_cur_rec,uint8_t tnf,uint8_t * p_type,uint8_t tlen)517*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetNextRecByType(uint8_t* p_cur_rec, uint8_t tnf,
518*7eba2f3bSAndroid Build Coastguard Worker                                   uint8_t* p_type, uint8_t tlen) {
519*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec;
520*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pRecStart;
521*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
522*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
523*7eba2f3bSAndroid Build Coastguard Worker 
524*7eba2f3bSAndroid Build Coastguard Worker   /* If this is the last record in the message, return NULL */
525*7eba2f3bSAndroid Build Coastguard Worker   p_rec = NDEF_MsgGetNextRec(p_cur_rec);
526*7eba2f3bSAndroid Build Coastguard Worker   if (p_rec == nullptr) return (nullptr);
527*7eba2f3bSAndroid Build Coastguard Worker 
528*7eba2f3bSAndroid Build Coastguard Worker   for (;;) {
529*7eba2f3bSAndroid Build Coastguard Worker     pRecStart = p_rec;
530*7eba2f3bSAndroid Build Coastguard Worker 
531*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
532*7eba2f3bSAndroid Build Coastguard Worker 
533*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
534*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
535*7eba2f3bSAndroid Build Coastguard Worker 
536*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
537*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
538*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
539*7eba2f3bSAndroid Build Coastguard Worker     else
540*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
541*7eba2f3bSAndroid Build Coastguard Worker 
542*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
543*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
544*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
545*7eba2f3bSAndroid Build Coastguard Worker     else
546*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
547*7eba2f3bSAndroid Build Coastguard Worker 
548*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the type field. We need to */
549*7eba2f3bSAndroid Build Coastguard Worker     /* compare the type of the type, the length of the type and the data     */
550*7eba2f3bSAndroid Build Coastguard Worker     if (((rec_hdr & NDEF_TNF_MASK) == tnf) && (type_len == tlen) &&
551*7eba2f3bSAndroid Build Coastguard Worker         (!memcmp(p_rec, p_type, tlen)))
552*7eba2f3bSAndroid Build Coastguard Worker       return (pRecStart);
553*7eba2f3bSAndroid Build Coastguard Worker 
554*7eba2f3bSAndroid Build Coastguard Worker     /* If this was the last record, return NULL */
555*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) break;
556*7eba2f3bSAndroid Build Coastguard Worker 
557*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
558*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (payload_len + type_len + id_len);
559*7eba2f3bSAndroid Build Coastguard Worker   }
560*7eba2f3bSAndroid Build Coastguard Worker 
561*7eba2f3bSAndroid Build Coastguard Worker   /* If here, there is no record of that type */
562*7eba2f3bSAndroid Build Coastguard Worker   return (nullptr);
563*7eba2f3bSAndroid Build Coastguard Worker }
564*7eba2f3bSAndroid Build Coastguard Worker 
565*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
566*7eba2f3bSAndroid Build Coastguard Worker **
567*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetFirstRecById
568*7eba2f3bSAndroid Build Coastguard Worker **
569*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the first record with the
570*7eba2f3bSAndroid Build Coastguard Worker **                  given record id in the given NDEF message.
571*7eba2f3bSAndroid Build Coastguard Worker **
572*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL
573*7eba2f3bSAndroid Build Coastguard Worker **
574*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetFirstRecById(uint8_t * p_msg,uint8_t * p_id,uint8_t ilen)575*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetFirstRecById(uint8_t* p_msg, uint8_t* p_id, uint8_t ilen) {
576*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg;
577*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pRecStart;
578*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
579*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
580*7eba2f3bSAndroid Build Coastguard Worker 
581*7eba2f3bSAndroid Build Coastguard Worker   for (;;) {
582*7eba2f3bSAndroid Build Coastguard Worker     pRecStart = p_rec;
583*7eba2f3bSAndroid Build Coastguard Worker 
584*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
585*7eba2f3bSAndroid Build Coastguard Worker 
586*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
587*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
588*7eba2f3bSAndroid Build Coastguard Worker 
589*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
590*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
591*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
592*7eba2f3bSAndroid Build Coastguard Worker     else
593*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
594*7eba2f3bSAndroid Build Coastguard Worker 
595*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
596*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
597*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
598*7eba2f3bSAndroid Build Coastguard Worker     else
599*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
600*7eba2f3bSAndroid Build Coastguard Worker 
601*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the type field. Skip it */
602*7eba2f3bSAndroid Build Coastguard Worker     p_rec += type_len;
603*7eba2f3bSAndroid Build Coastguard Worker 
604*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the ID field. Compare length
605*7eba2f3bSAndroid Build Coastguard Worker      * and data */
606*7eba2f3bSAndroid Build Coastguard Worker     if ((id_len == ilen) && (!memcmp(p_rec, p_id, ilen))) return (pRecStart);
607*7eba2f3bSAndroid Build Coastguard Worker 
608*7eba2f3bSAndroid Build Coastguard Worker     /* If this was the last record, return NULL */
609*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) return (nullptr);
610*7eba2f3bSAndroid Build Coastguard Worker 
611*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
612*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (id_len + payload_len);
613*7eba2f3bSAndroid Build Coastguard Worker   }
614*7eba2f3bSAndroid Build Coastguard Worker 
615*7eba2f3bSAndroid Build Coastguard Worker   /* If here, there is no record of that ID */
616*7eba2f3bSAndroid Build Coastguard Worker   return (nullptr);
617*7eba2f3bSAndroid Build Coastguard Worker }
618*7eba2f3bSAndroid Build Coastguard Worker 
619*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
620*7eba2f3bSAndroid Build Coastguard Worker **
621*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgGetNextRecById
622*7eba2f3bSAndroid Build Coastguard Worker **
623*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the next record with the
624*7eba2f3bSAndroid Build Coastguard Worker **                  given record id in the given NDEF message.
625*7eba2f3bSAndroid Build Coastguard Worker **
626*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to the start of the record, or NULL
627*7eba2f3bSAndroid Build Coastguard Worker **
628*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgGetNextRecById(uint8_t * p_cur_rec,uint8_t * p_id,uint8_t ilen)629*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_MsgGetNextRecById(uint8_t* p_cur_rec, uint8_t* p_id,
630*7eba2f3bSAndroid Build Coastguard Worker                                 uint8_t ilen) {
631*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec;
632*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pRecStart;
633*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
634*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
635*7eba2f3bSAndroid Build Coastguard Worker 
636*7eba2f3bSAndroid Build Coastguard Worker   /* If this is the last record in the message, return NULL */
637*7eba2f3bSAndroid Build Coastguard Worker   p_rec = NDEF_MsgGetNextRec(p_cur_rec);
638*7eba2f3bSAndroid Build Coastguard Worker   if (p_rec == nullptr) return (nullptr);
639*7eba2f3bSAndroid Build Coastguard Worker 
640*7eba2f3bSAndroid Build Coastguard Worker   for (;;) {
641*7eba2f3bSAndroid Build Coastguard Worker     pRecStart = p_rec;
642*7eba2f3bSAndroid Build Coastguard Worker 
643*7eba2f3bSAndroid Build Coastguard Worker     rec_hdr = *p_rec++;
644*7eba2f3bSAndroid Build Coastguard Worker 
645*7eba2f3bSAndroid Build Coastguard Worker     /* Type field length */
646*7eba2f3bSAndroid Build Coastguard Worker     type_len = *p_rec++;
647*7eba2f3bSAndroid Build Coastguard Worker 
648*7eba2f3bSAndroid Build Coastguard Worker     /* Payload length - can be 1 or 4 bytes */
649*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_SR_MASK)
650*7eba2f3bSAndroid Build Coastguard Worker       payload_len = *p_rec++;
651*7eba2f3bSAndroid Build Coastguard Worker     else
652*7eba2f3bSAndroid Build Coastguard Worker       BE_STREAM_TO_UINT32(payload_len, p_rec);
653*7eba2f3bSAndroid Build Coastguard Worker 
654*7eba2f3bSAndroid Build Coastguard Worker     /* ID field Length */
655*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_IL_MASK)
656*7eba2f3bSAndroid Build Coastguard Worker       id_len = *p_rec++;
657*7eba2f3bSAndroid Build Coastguard Worker     else
658*7eba2f3bSAndroid Build Coastguard Worker       id_len = 0;
659*7eba2f3bSAndroid Build Coastguard Worker 
660*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the type field. Skip it */
661*7eba2f3bSAndroid Build Coastguard Worker     p_rec += type_len;
662*7eba2f3bSAndroid Build Coastguard Worker 
663*7eba2f3bSAndroid Build Coastguard Worker     /* At this point, p_rec points to the start of the ID field. Compare length
664*7eba2f3bSAndroid Build Coastguard Worker      * and data */
665*7eba2f3bSAndroid Build Coastguard Worker     if ((id_len == ilen) && (!memcmp(p_rec, p_id, ilen))) return (pRecStart);
666*7eba2f3bSAndroid Build Coastguard Worker 
667*7eba2f3bSAndroid Build Coastguard Worker     /* If this was the last record, return NULL */
668*7eba2f3bSAndroid Build Coastguard Worker     if (rec_hdr & NDEF_ME_MASK) break;
669*7eba2f3bSAndroid Build Coastguard Worker 
670*7eba2f3bSAndroid Build Coastguard Worker     /* Point to next record */
671*7eba2f3bSAndroid Build Coastguard Worker     p_rec += (id_len + payload_len);
672*7eba2f3bSAndroid Build Coastguard Worker   }
673*7eba2f3bSAndroid Build Coastguard Worker 
674*7eba2f3bSAndroid Build Coastguard Worker   /* If here, there is no record of that ID */
675*7eba2f3bSAndroid Build Coastguard Worker   return (nullptr);
676*7eba2f3bSAndroid Build Coastguard Worker }
677*7eba2f3bSAndroid Build Coastguard Worker 
678*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
679*7eba2f3bSAndroid Build Coastguard Worker **
680*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_RecGetType
681*7eba2f3bSAndroid Build Coastguard Worker **
682*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the record type for the
683*7eba2f3bSAndroid Build Coastguard Worker **                  given NDEF record.
684*7eba2f3bSAndroid Build Coastguard Worker **
685*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to Type (NULL if none). TNF and len are filled in.
686*7eba2f3bSAndroid Build Coastguard Worker **
687*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_RecGetType(uint8_t * p_rec,uint8_t * p_tnf,uint8_t * p_type_len)688*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_RecGetType(uint8_t* p_rec, uint8_t* p_tnf, uint8_t* p_type_len) {
689*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len;
690*7eba2f3bSAndroid Build Coastguard Worker 
691*7eba2f3bSAndroid Build Coastguard Worker   /* First byte is the record header */
692*7eba2f3bSAndroid Build Coastguard Worker   rec_hdr = *p_rec++;
693*7eba2f3bSAndroid Build Coastguard Worker 
694*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
695*7eba2f3bSAndroid Build Coastguard Worker   type_len = *p_rec++;
696*7eba2f3bSAndroid Build Coastguard Worker 
697*7eba2f3bSAndroid Build Coastguard Worker   /* Skip the payload length */
698*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_SR_MASK)
699*7eba2f3bSAndroid Build Coastguard Worker     p_rec += 1;
700*7eba2f3bSAndroid Build Coastguard Worker   else
701*7eba2f3bSAndroid Build Coastguard Worker     p_rec += 4;
702*7eba2f3bSAndroid Build Coastguard Worker 
703*7eba2f3bSAndroid Build Coastguard Worker   /* Skip ID field Length, if present */
704*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_IL_MASK) p_rec++;
705*7eba2f3bSAndroid Build Coastguard Worker 
706*7eba2f3bSAndroid Build Coastguard Worker   /* At this point, p_rec points to the start of the type field.  */
707*7eba2f3bSAndroid Build Coastguard Worker   *p_type_len = type_len;
708*7eba2f3bSAndroid Build Coastguard Worker   *p_tnf = rec_hdr & NDEF_TNF_MASK;
709*7eba2f3bSAndroid Build Coastguard Worker 
710*7eba2f3bSAndroid Build Coastguard Worker   if (type_len == 0)
711*7eba2f3bSAndroid Build Coastguard Worker     return (nullptr);
712*7eba2f3bSAndroid Build Coastguard Worker   else
713*7eba2f3bSAndroid Build Coastguard Worker     return (p_rec);
714*7eba2f3bSAndroid Build Coastguard Worker }
715*7eba2f3bSAndroid Build Coastguard Worker 
716*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
717*7eba2f3bSAndroid Build Coastguard Worker **
718*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_RecGetId
719*7eba2f3bSAndroid Build Coastguard Worker **
720*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the record id for the given
721*7eba2f3bSAndroid Build Coastguard Worker **                  NDEF record.
722*7eba2f3bSAndroid Build Coastguard Worker **
723*7eba2f3bSAndroid Build Coastguard Worker ** Returns          Pointer to Id (NULL if none). ID Len is filled in.
724*7eba2f3bSAndroid Build Coastguard Worker **
725*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_RecGetId(uint8_t * p_rec,uint8_t * p_id_len)726*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_RecGetId(uint8_t* p_rec, uint8_t* p_id_len) {
727*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len;
728*7eba2f3bSAndroid Build Coastguard Worker 
729*7eba2f3bSAndroid Build Coastguard Worker   /* First byte is the record header */
730*7eba2f3bSAndroid Build Coastguard Worker   rec_hdr = *p_rec++;
731*7eba2f3bSAndroid Build Coastguard Worker 
732*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
733*7eba2f3bSAndroid Build Coastguard Worker   type_len = *p_rec++;
734*7eba2f3bSAndroid Build Coastguard Worker 
735*7eba2f3bSAndroid Build Coastguard Worker   /* Skip the payload length */
736*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_SR_MASK)
737*7eba2f3bSAndroid Build Coastguard Worker     p_rec++;
738*7eba2f3bSAndroid Build Coastguard Worker   else
739*7eba2f3bSAndroid Build Coastguard Worker     p_rec += 4;
740*7eba2f3bSAndroid Build Coastguard Worker 
741*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
742*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_IL_MASK)
743*7eba2f3bSAndroid Build Coastguard Worker     *p_id_len = *p_rec++;
744*7eba2f3bSAndroid Build Coastguard Worker   else
745*7eba2f3bSAndroid Build Coastguard Worker     *p_id_len = 0;
746*7eba2f3bSAndroid Build Coastguard Worker 
747*7eba2f3bSAndroid Build Coastguard Worker   /* p_rec now points to the start of the type field. The ID field follows it */
748*7eba2f3bSAndroid Build Coastguard Worker   if (*p_id_len == 0)
749*7eba2f3bSAndroid Build Coastguard Worker     return (nullptr);
750*7eba2f3bSAndroid Build Coastguard Worker   else
751*7eba2f3bSAndroid Build Coastguard Worker     return (p_rec + type_len);
752*7eba2f3bSAndroid Build Coastguard Worker }
753*7eba2f3bSAndroid Build Coastguard Worker 
754*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
755*7eba2f3bSAndroid Build Coastguard Worker **
756*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_RecGetPayload
757*7eba2f3bSAndroid Build Coastguard Worker **
758*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function gets a pointer to the payload for the given
759*7eba2f3bSAndroid Build Coastguard Worker **                  NDEF record.
760*7eba2f3bSAndroid Build Coastguard Worker **
761*7eba2f3bSAndroid Build Coastguard Worker ** Returns          a pointer to the payload (or NULL none). Payload len filled
762*7eba2f3bSAndroid Build Coastguard Worker **                  in.
763*7eba2f3bSAndroid Build Coastguard Worker **
764*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_RecGetPayload(uint8_t * p_rec,uint32_t * p_payload_len)765*7eba2f3bSAndroid Build Coastguard Worker uint8_t* NDEF_RecGetPayload(uint8_t* p_rec, uint32_t* p_payload_len) {
766*7eba2f3bSAndroid Build Coastguard Worker   uint8_t rec_hdr, type_len, id_len;
767*7eba2f3bSAndroid Build Coastguard Worker   uint32_t payload_len;
768*7eba2f3bSAndroid Build Coastguard Worker 
769*7eba2f3bSAndroid Build Coastguard Worker   /* First byte is the record header */
770*7eba2f3bSAndroid Build Coastguard Worker   rec_hdr = *p_rec++;
771*7eba2f3bSAndroid Build Coastguard Worker 
772*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
773*7eba2f3bSAndroid Build Coastguard Worker   type_len = *p_rec++;
774*7eba2f3bSAndroid Build Coastguard Worker 
775*7eba2f3bSAndroid Build Coastguard Worker   /* Next is the payload length (1 or 4 bytes) */
776*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_SR_MASK)
777*7eba2f3bSAndroid Build Coastguard Worker     payload_len = *p_rec++;
778*7eba2f3bSAndroid Build Coastguard Worker   else
779*7eba2f3bSAndroid Build Coastguard Worker     BE_STREAM_TO_UINT32(payload_len, p_rec);
780*7eba2f3bSAndroid Build Coastguard Worker 
781*7eba2f3bSAndroid Build Coastguard Worker   *p_payload_len = payload_len;
782*7eba2f3bSAndroid Build Coastguard Worker 
783*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
784*7eba2f3bSAndroid Build Coastguard Worker   if (rec_hdr & NDEF_IL_MASK)
785*7eba2f3bSAndroid Build Coastguard Worker     id_len = *p_rec++;
786*7eba2f3bSAndroid Build Coastguard Worker   else
787*7eba2f3bSAndroid Build Coastguard Worker     id_len = 0;
788*7eba2f3bSAndroid Build Coastguard Worker 
789*7eba2f3bSAndroid Build Coastguard Worker   /* p_rec now points to the start of the type field. The ID field follows it,
790*7eba2f3bSAndroid Build Coastguard Worker    * then the payload */
791*7eba2f3bSAndroid Build Coastguard Worker   if (payload_len == 0)
792*7eba2f3bSAndroid Build Coastguard Worker     return (nullptr);
793*7eba2f3bSAndroid Build Coastguard Worker   else
794*7eba2f3bSAndroid Build Coastguard Worker     return (p_rec + type_len + id_len);
795*7eba2f3bSAndroid Build Coastguard Worker }
796*7eba2f3bSAndroid Build Coastguard Worker 
797*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
798*7eba2f3bSAndroid Build Coastguard Worker **
799*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgInit
800*7eba2f3bSAndroid Build Coastguard Worker **
801*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function initializes an NDEF message.
802*7eba2f3bSAndroid Build Coastguard Worker **
803*7eba2f3bSAndroid Build Coastguard Worker ** Returns          void
804*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is initialized to 0
805*7eba2f3bSAndroid Build Coastguard Worker **
806*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgInit(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size)807*7eba2f3bSAndroid Build Coastguard Worker void NDEF_MsgInit(uint8_t* p_msg, uint32_t max_size, uint32_t* p_cur_size) {
808*7eba2f3bSAndroid Build Coastguard Worker   *p_cur_size = 0;
809*7eba2f3bSAndroid Build Coastguard Worker   memset(p_msg, 0, max_size);
810*7eba2f3bSAndroid Build Coastguard Worker }
811*7eba2f3bSAndroid Build Coastguard Worker 
812*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
813*7eba2f3bSAndroid Build Coastguard Worker **
814*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgAddRec
815*7eba2f3bSAndroid Build Coastguard Worker **
816*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function adds an NDEF record to the end of an NDEF
817*7eba2f3bSAndroid Build Coastguard Worker **                  message.
818*7eba2f3bSAndroid Build Coastguard Worker **
819*7eba2f3bSAndroid Build Coastguard Worker ** Returns          OK, or error if the record did not fit
820*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
821*7eba2f3bSAndroid Build Coastguard Worker **
822*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgAddRec(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size,uint8_t tnf,uint8_t * p_type,uint8_t type_len,uint8_t * p_id,uint8_t id_len,uint8_t * p_payload,uint32_t payload_len)823*7eba2f3bSAndroid Build Coastguard Worker extern tNDEF_STATUS NDEF_MsgAddRec(uint8_t* p_msg, uint32_t max_size,
824*7eba2f3bSAndroid Build Coastguard Worker                                    uint32_t* p_cur_size, uint8_t tnf,
825*7eba2f3bSAndroid Build Coastguard Worker                                    uint8_t* p_type, uint8_t type_len,
826*7eba2f3bSAndroid Build Coastguard Worker                                    uint8_t* p_id, uint8_t id_len,
827*7eba2f3bSAndroid Build Coastguard Worker                                    uint8_t* p_payload, uint32_t payload_len) {
828*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = p_msg + *p_cur_size;
829*7eba2f3bSAndroid Build Coastguard Worker   uint32_t recSize;
830*7eba2f3bSAndroid Build Coastguard Worker   int plen = (payload_len < 256) ? 1 : 4;
831*7eba2f3bSAndroid Build Coastguard Worker   int ilen = (id_len == 0) ? 0 : 1;
832*7eba2f3bSAndroid Build Coastguard Worker 
833*7eba2f3bSAndroid Build Coastguard Worker   if (tnf > NDEF_TNF_RESERVED) {
834*7eba2f3bSAndroid Build Coastguard Worker     tnf = NDEF_TNF_UNKNOWN;
835*7eba2f3bSAndroid Build Coastguard Worker     type_len = 0;
836*7eba2f3bSAndroid Build Coastguard Worker   }
837*7eba2f3bSAndroid Build Coastguard Worker 
838*7eba2f3bSAndroid Build Coastguard Worker   /* First, make sure the record will fit. we need at least 2 bytes for header
839*7eba2f3bSAndroid Build Coastguard Worker    * and type length */
840*7eba2f3bSAndroid Build Coastguard Worker   recSize = payload_len + 2 + type_len + plen + ilen + id_len;
841*7eba2f3bSAndroid Build Coastguard Worker 
842*7eba2f3bSAndroid Build Coastguard Worker   if ((*p_cur_size + recSize) > max_size) return (NDEF_MSG_INSUFFICIENT_MEM);
843*7eba2f3bSAndroid Build Coastguard Worker 
844*7eba2f3bSAndroid Build Coastguard Worker   /* Construct the record header. For the first record, set both begin and end
845*7eba2f3bSAndroid Build Coastguard Worker    * bits */
846*7eba2f3bSAndroid Build Coastguard Worker   if (*p_cur_size == 0)
847*7eba2f3bSAndroid Build Coastguard Worker     *p_rec = tnf | NDEF_MB_MASK | NDEF_ME_MASK;
848*7eba2f3bSAndroid Build Coastguard Worker   else {
849*7eba2f3bSAndroid Build Coastguard Worker     /* Find the previous last and clear his 'Message End' bit */
850*7eba2f3bSAndroid Build Coastguard Worker     uint8_t* pLast = NDEF_MsgGetLastRecInMsg(p_msg);
851*7eba2f3bSAndroid Build Coastguard Worker 
852*7eba2f3bSAndroid Build Coastguard Worker     if (!pLast) return (NDEF_MSG_NO_MSG_END);
853*7eba2f3bSAndroid Build Coastguard Worker 
854*7eba2f3bSAndroid Build Coastguard Worker     *pLast &= ~NDEF_ME_MASK;
855*7eba2f3bSAndroid Build Coastguard Worker     *p_rec = tnf | NDEF_ME_MASK;
856*7eba2f3bSAndroid Build Coastguard Worker   }
857*7eba2f3bSAndroid Build Coastguard Worker 
858*7eba2f3bSAndroid Build Coastguard Worker   if (plen == 1) *p_rec |= NDEF_SR_MASK;
859*7eba2f3bSAndroid Build Coastguard Worker 
860*7eba2f3bSAndroid Build Coastguard Worker   if (ilen != 0) *p_rec |= NDEF_IL_MASK;
861*7eba2f3bSAndroid Build Coastguard Worker 
862*7eba2f3bSAndroid Build Coastguard Worker   p_rec++;
863*7eba2f3bSAndroid Build Coastguard Worker 
864*7eba2f3bSAndroid Build Coastguard Worker   /* The next byte is the type field length */
865*7eba2f3bSAndroid Build Coastguard Worker   *p_rec++ = type_len;
866*7eba2f3bSAndroid Build Coastguard Worker 
867*7eba2f3bSAndroid Build Coastguard Worker   /* Payload length - can be 1 or 4 bytes */
868*7eba2f3bSAndroid Build Coastguard Worker   if (plen == 1)
869*7eba2f3bSAndroid Build Coastguard Worker     *p_rec++ = (uint8_t)payload_len;
870*7eba2f3bSAndroid Build Coastguard Worker   else
871*7eba2f3bSAndroid Build Coastguard Worker     UINT32_TO_BE_STREAM(p_rec, payload_len);
872*7eba2f3bSAndroid Build Coastguard Worker 
873*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length (optional) */
874*7eba2f3bSAndroid Build Coastguard Worker   if (ilen > 0) *p_rec++ = id_len;
875*7eba2f3bSAndroid Build Coastguard Worker 
876*7eba2f3bSAndroid Build Coastguard Worker   /* Next comes the type */
877*7eba2f3bSAndroid Build Coastguard Worker   if (type_len) {
878*7eba2f3bSAndroid Build Coastguard Worker     if (p_type) memcpy(p_rec, p_type, type_len);
879*7eba2f3bSAndroid Build Coastguard Worker 
880*7eba2f3bSAndroid Build Coastguard Worker     p_rec += type_len;
881*7eba2f3bSAndroid Build Coastguard Worker   }
882*7eba2f3bSAndroid Build Coastguard Worker 
883*7eba2f3bSAndroid Build Coastguard Worker   /* Next comes the ID */
884*7eba2f3bSAndroid Build Coastguard Worker   if (id_len) {
885*7eba2f3bSAndroid Build Coastguard Worker     if (p_id) memcpy(p_rec, p_id, id_len);
886*7eba2f3bSAndroid Build Coastguard Worker 
887*7eba2f3bSAndroid Build Coastguard Worker     p_rec += id_len;
888*7eba2f3bSAndroid Build Coastguard Worker   }
889*7eba2f3bSAndroid Build Coastguard Worker 
890*7eba2f3bSAndroid Build Coastguard Worker   /* And lastly the payload. If NULL, the app just wants to reserve memory */
891*7eba2f3bSAndroid Build Coastguard Worker   if (p_payload) memcpy(p_rec, p_payload, payload_len);
892*7eba2f3bSAndroid Build Coastguard Worker 
893*7eba2f3bSAndroid Build Coastguard Worker   *p_cur_size += recSize;
894*7eba2f3bSAndroid Build Coastguard Worker 
895*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
896*7eba2f3bSAndroid Build Coastguard Worker }
897*7eba2f3bSAndroid Build Coastguard Worker 
898*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
899*7eba2f3bSAndroid Build Coastguard Worker **
900*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgAppendPayload
901*7eba2f3bSAndroid Build Coastguard Worker **
902*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function appends extra payload to a specific record in
903*7eba2f3bSAndroid Build Coastguard Worker **                  the given NDEF message
904*7eba2f3bSAndroid Build Coastguard Worker **
905*7eba2f3bSAndroid Build Coastguard Worker ** Returns          OK, or error if the extra payload did not fit
906*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
907*7eba2f3bSAndroid Build Coastguard Worker **
908*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgAppendPayload(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size,uint8_t * p_rec,uint8_t * p_add_pl,uint32_t add_pl_len)909*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgAppendPayload(uint8_t* p_msg, uint32_t max_size,
910*7eba2f3bSAndroid Build Coastguard Worker                                    uint32_t* p_cur_size, uint8_t* p_rec,
911*7eba2f3bSAndroid Build Coastguard Worker                                    uint8_t* p_add_pl, uint32_t add_pl_len) {
912*7eba2f3bSAndroid Build Coastguard Worker   uint32_t prev_paylen, new_paylen;
913*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *p_prev_pl, *pp;
914*7eba2f3bSAndroid Build Coastguard Worker   uint8_t incr_lenfld = 0;
915*7eba2f3bSAndroid Build Coastguard Worker   uint8_t type_len, id_len;
916*7eba2f3bSAndroid Build Coastguard Worker 
917*7eba2f3bSAndroid Build Coastguard Worker   /* Skip header */
918*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 1;
919*7eba2f3bSAndroid Build Coastguard Worker 
920*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
921*7eba2f3bSAndroid Build Coastguard Worker   type_len = *pp++;
922*7eba2f3bSAndroid Build Coastguard Worker 
923*7eba2f3bSAndroid Build Coastguard Worker   /* Next is the payload length (1 or 4 bytes) */
924*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_SR_MASK)
925*7eba2f3bSAndroid Build Coastguard Worker     prev_paylen = *pp++;
926*7eba2f3bSAndroid Build Coastguard Worker   else
927*7eba2f3bSAndroid Build Coastguard Worker     BE_STREAM_TO_UINT32(prev_paylen, pp);
928*7eba2f3bSAndroid Build Coastguard Worker 
929*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
930*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_IL_MASK)
931*7eba2f3bSAndroid Build Coastguard Worker     id_len = *pp++;
932*7eba2f3bSAndroid Build Coastguard Worker   else
933*7eba2f3bSAndroid Build Coastguard Worker     id_len = 0;
934*7eba2f3bSAndroid Build Coastguard Worker 
935*7eba2f3bSAndroid Build Coastguard Worker   p_prev_pl = pp + type_len + id_len;
936*7eba2f3bSAndroid Build Coastguard Worker 
937*7eba2f3bSAndroid Build Coastguard Worker   new_paylen = prev_paylen + add_pl_len;
938*7eba2f3bSAndroid Build Coastguard Worker 
939*7eba2f3bSAndroid Build Coastguard Worker   /* Previous payload may be < 256, and this addition may make it larger than
940*7eba2f3bSAndroid Build Coastguard Worker    * 256 */
941*7eba2f3bSAndroid Build Coastguard Worker   /* If that were to happen, the payload length field goes from 1 byte to 4
942*7eba2f3bSAndroid Build Coastguard Worker    * bytes */
943*7eba2f3bSAndroid Build Coastguard Worker   if ((prev_paylen < 256) && (new_paylen > 255)) incr_lenfld = 3;
944*7eba2f3bSAndroid Build Coastguard Worker 
945*7eba2f3bSAndroid Build Coastguard Worker   /* Check that it all fits */
946*7eba2f3bSAndroid Build Coastguard Worker   if ((*p_cur_size + add_pl_len + incr_lenfld) > max_size)
947*7eba2f3bSAndroid Build Coastguard Worker     return (NDEF_MSG_INSUFFICIENT_MEM);
948*7eba2f3bSAndroid Build Coastguard Worker 
949*7eba2f3bSAndroid Build Coastguard Worker   /* Point to payload length field */
950*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 2;
951*7eba2f3bSAndroid Build Coastguard Worker 
952*7eba2f3bSAndroid Build Coastguard Worker   /* If we need to increase the length field from 1 to 4 bytes, do it first */
953*7eba2f3bSAndroid Build Coastguard Worker   if (incr_lenfld) {
954*7eba2f3bSAndroid Build Coastguard Worker     shiftdown(pp + 1, (uint32_t)(*p_cur_size - (pp - p_msg) - 1), 3);
955*7eba2f3bSAndroid Build Coastguard Worker     p_prev_pl += 3;
956*7eba2f3bSAndroid Build Coastguard Worker   }
957*7eba2f3bSAndroid Build Coastguard Worker 
958*7eba2f3bSAndroid Build Coastguard Worker   /* Store in the new length */
959*7eba2f3bSAndroid Build Coastguard Worker   if (new_paylen > 255) {
960*7eba2f3bSAndroid Build Coastguard Worker     *p_rec &= ~NDEF_SR_MASK;
961*7eba2f3bSAndroid Build Coastguard Worker     UINT32_TO_BE_STREAM(pp, new_paylen);
962*7eba2f3bSAndroid Build Coastguard Worker   } else
963*7eba2f3bSAndroid Build Coastguard Worker     *pp = (uint8_t)new_paylen;
964*7eba2f3bSAndroid Build Coastguard Worker 
965*7eba2f3bSAndroid Build Coastguard Worker   /* Point to the end of the previous payload */
966*7eba2f3bSAndroid Build Coastguard Worker   pp = p_prev_pl + prev_paylen;
967*7eba2f3bSAndroid Build Coastguard Worker 
968*7eba2f3bSAndroid Build Coastguard Worker   /* If we are not the last record, make space for the extra payload */
969*7eba2f3bSAndroid Build Coastguard Worker   if ((*p_rec & NDEF_ME_MASK) == 0)
970*7eba2f3bSAndroid Build Coastguard Worker     shiftdown(pp, (uint32_t)(*p_cur_size - (pp - p_msg)), add_pl_len);
971*7eba2f3bSAndroid Build Coastguard Worker 
972*7eba2f3bSAndroid Build Coastguard Worker   /* Now copy in the additional payload data */
973*7eba2f3bSAndroid Build Coastguard Worker   memcpy(pp, p_add_pl, add_pl_len);
974*7eba2f3bSAndroid Build Coastguard Worker 
975*7eba2f3bSAndroid Build Coastguard Worker   *p_cur_size += add_pl_len + incr_lenfld;
976*7eba2f3bSAndroid Build Coastguard Worker 
977*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
978*7eba2f3bSAndroid Build Coastguard Worker }
979*7eba2f3bSAndroid Build Coastguard Worker 
980*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
981*7eba2f3bSAndroid Build Coastguard Worker **
982*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgReplacePayload
983*7eba2f3bSAndroid Build Coastguard Worker **
984*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function replaces the payload of a specific record in
985*7eba2f3bSAndroid Build Coastguard Worker **                  the given NDEF message
986*7eba2f3bSAndroid Build Coastguard Worker **
987*7eba2f3bSAndroid Build Coastguard Worker ** Returns          OK, or error if the new payload did not fit
988*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
989*7eba2f3bSAndroid Build Coastguard Worker **
990*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgReplacePayload(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size,uint8_t * p_rec,uint8_t * p_new_pl,uint32_t new_pl_len)991*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgReplacePayload(uint8_t* p_msg, uint32_t max_size,
992*7eba2f3bSAndroid Build Coastguard Worker                                     uint32_t* p_cur_size, uint8_t* p_rec,
993*7eba2f3bSAndroid Build Coastguard Worker                                     uint8_t* p_new_pl, uint32_t new_pl_len) {
994*7eba2f3bSAndroid Build Coastguard Worker   uint32_t prev_paylen;
995*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *p_prev_pl, *pp;
996*7eba2f3bSAndroid Build Coastguard Worker   uint32_t paylen_delta;
997*7eba2f3bSAndroid Build Coastguard Worker   uint8_t type_len, id_len;
998*7eba2f3bSAndroid Build Coastguard Worker 
999*7eba2f3bSAndroid Build Coastguard Worker   /* Skip header */
1000*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 1;
1001*7eba2f3bSAndroid Build Coastguard Worker 
1002*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
1003*7eba2f3bSAndroid Build Coastguard Worker   type_len = *pp++;
1004*7eba2f3bSAndroid Build Coastguard Worker 
1005*7eba2f3bSAndroid Build Coastguard Worker   /* Next is the payload length (1 or 4 bytes) */
1006*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_SR_MASK)
1007*7eba2f3bSAndroid Build Coastguard Worker     prev_paylen = *pp++;
1008*7eba2f3bSAndroid Build Coastguard Worker   else
1009*7eba2f3bSAndroid Build Coastguard Worker     BE_STREAM_TO_UINT32(prev_paylen, pp);
1010*7eba2f3bSAndroid Build Coastguard Worker 
1011*7eba2f3bSAndroid Build Coastguard Worker   /* ID field Length */
1012*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_IL_MASK)
1013*7eba2f3bSAndroid Build Coastguard Worker     id_len = *pp++;
1014*7eba2f3bSAndroid Build Coastguard Worker   else
1015*7eba2f3bSAndroid Build Coastguard Worker     id_len = 0;
1016*7eba2f3bSAndroid Build Coastguard Worker 
1017*7eba2f3bSAndroid Build Coastguard Worker   p_prev_pl = pp + type_len + id_len;
1018*7eba2f3bSAndroid Build Coastguard Worker 
1019*7eba2f3bSAndroid Build Coastguard Worker   /* Point to payload length field again */
1020*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 2;
1021*7eba2f3bSAndroid Build Coastguard Worker 
1022*7eba2f3bSAndroid Build Coastguard Worker   if (new_pl_len > prev_paylen) {
1023*7eba2f3bSAndroid Build Coastguard Worker     /* New payload is larger than the previous */
1024*7eba2f3bSAndroid Build Coastguard Worker     paylen_delta = new_pl_len - prev_paylen;
1025*7eba2f3bSAndroid Build Coastguard Worker 
1026*7eba2f3bSAndroid Build Coastguard Worker     /* If the previous payload length was < 256, and new is > 255 */
1027*7eba2f3bSAndroid Build Coastguard Worker     /* the payload length field goes from 1 byte to 4 bytes       */
1028*7eba2f3bSAndroid Build Coastguard Worker     if ((prev_paylen < 256) && (new_pl_len > 255)) {
1029*7eba2f3bSAndroid Build Coastguard Worker       if ((*p_cur_size + paylen_delta + 3) > max_size)
1030*7eba2f3bSAndroid Build Coastguard Worker         return (NDEF_MSG_INSUFFICIENT_MEM);
1031*7eba2f3bSAndroid Build Coastguard Worker 
1032*7eba2f3bSAndroid Build Coastguard Worker       shiftdown(pp + 1, (uint32_t)(*p_cur_size - (pp - p_msg) - 1), 3);
1033*7eba2f3bSAndroid Build Coastguard Worker       p_prev_pl += 3;
1034*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size += 3;
1035*7eba2f3bSAndroid Build Coastguard Worker       *p_rec &= ~NDEF_SR_MASK;
1036*7eba2f3bSAndroid Build Coastguard Worker     } else if ((*p_cur_size + paylen_delta) > max_size)
1037*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_INSUFFICIENT_MEM);
1038*7eba2f3bSAndroid Build Coastguard Worker 
1039*7eba2f3bSAndroid Build Coastguard Worker     /* Store in the new length */
1040*7eba2f3bSAndroid Build Coastguard Worker     if (new_pl_len > 255) {
1041*7eba2f3bSAndroid Build Coastguard Worker       UINT32_TO_BE_STREAM(pp, new_pl_len);
1042*7eba2f3bSAndroid Build Coastguard Worker     } else
1043*7eba2f3bSAndroid Build Coastguard Worker       *pp = (uint8_t)new_pl_len;
1044*7eba2f3bSAndroid Build Coastguard Worker 
1045*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous payload */
1046*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_pl + prev_paylen;
1047*7eba2f3bSAndroid Build Coastguard Worker 
1048*7eba2f3bSAndroid Build Coastguard Worker     /* If we are not the last record, make space for the extra payload */
1049*7eba2f3bSAndroid Build Coastguard Worker     if ((*p_rec & NDEF_ME_MASK) == 0)
1050*7eba2f3bSAndroid Build Coastguard Worker       shiftdown(pp, (uint32_t)(*p_cur_size - (pp - p_msg)), paylen_delta);
1051*7eba2f3bSAndroid Build Coastguard Worker 
1052*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size += paylen_delta;
1053*7eba2f3bSAndroid Build Coastguard Worker   } else if (new_pl_len < prev_paylen) {
1054*7eba2f3bSAndroid Build Coastguard Worker     /* New payload is smaller than the previous */
1055*7eba2f3bSAndroid Build Coastguard Worker     paylen_delta = prev_paylen - new_pl_len;
1056*7eba2f3bSAndroid Build Coastguard Worker 
1057*7eba2f3bSAndroid Build Coastguard Worker     /* If the previous payload was > 256, and new is less than 256 */
1058*7eba2f3bSAndroid Build Coastguard Worker     /* the payload length field goes from 4 bytes to 1 byte        */
1059*7eba2f3bSAndroid Build Coastguard Worker     if ((prev_paylen > 255) && (new_pl_len < 256)) {
1060*7eba2f3bSAndroid Build Coastguard Worker       shiftup(pp + 1, pp + 4, (uint32_t)(*p_cur_size - (pp - p_msg) - 3));
1061*7eba2f3bSAndroid Build Coastguard Worker       p_prev_pl -= 3;
1062*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size -= 3;
1063*7eba2f3bSAndroid Build Coastguard Worker       *p_rec |= NDEF_SR_MASK;
1064*7eba2f3bSAndroid Build Coastguard Worker     }
1065*7eba2f3bSAndroid Build Coastguard Worker 
1066*7eba2f3bSAndroid Build Coastguard Worker     /* Store in the new length */
1067*7eba2f3bSAndroid Build Coastguard Worker     if (new_pl_len > 255) {
1068*7eba2f3bSAndroid Build Coastguard Worker       UINT32_TO_BE_STREAM(pp, new_pl_len);
1069*7eba2f3bSAndroid Build Coastguard Worker     } else
1070*7eba2f3bSAndroid Build Coastguard Worker       *pp = (uint8_t)new_pl_len;
1071*7eba2f3bSAndroid Build Coastguard Worker 
1072*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous payload */
1073*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_pl + prev_paylen;
1074*7eba2f3bSAndroid Build Coastguard Worker 
1075*7eba2f3bSAndroid Build Coastguard Worker     /* If we are not the last record, remove the extra space from the previous
1076*7eba2f3bSAndroid Build Coastguard Worker      * payload */
1077*7eba2f3bSAndroid Build Coastguard Worker     if ((*p_rec & NDEF_ME_MASK) == 0)
1078*7eba2f3bSAndroid Build Coastguard Worker       shiftup(pp - paylen_delta, pp, (uint32_t)(*p_cur_size - (pp - p_msg)));
1079*7eba2f3bSAndroid Build Coastguard Worker 
1080*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size -= paylen_delta;
1081*7eba2f3bSAndroid Build Coastguard Worker   }
1082*7eba2f3bSAndroid Build Coastguard Worker 
1083*7eba2f3bSAndroid Build Coastguard Worker   /* Now copy in the new payload data */
1084*7eba2f3bSAndroid Build Coastguard Worker   if (p_new_pl) memcpy(p_prev_pl, p_new_pl, new_pl_len);
1085*7eba2f3bSAndroid Build Coastguard Worker 
1086*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
1087*7eba2f3bSAndroid Build Coastguard Worker }
1088*7eba2f3bSAndroid Build Coastguard Worker 
1089*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
1090*7eba2f3bSAndroid Build Coastguard Worker **
1091*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgReplaceType
1092*7eba2f3bSAndroid Build Coastguard Worker **
1093*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function replaces the type field of a specific record
1094*7eba2f3bSAndroid Build Coastguard Worker **                  in the given NDEF message
1095*7eba2f3bSAndroid Build Coastguard Worker **
1096*7eba2f3bSAndroid Build Coastguard Worker ** Returns          OK, or error if the new type field did not fit
1097*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
1098*7eba2f3bSAndroid Build Coastguard Worker **
1099*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgReplaceType(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size,uint8_t * p_rec,uint8_t * p_new_type,uint8_t new_type_len)1100*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgReplaceType(uint8_t* p_msg, uint32_t max_size,
1101*7eba2f3bSAndroid Build Coastguard Worker                                  uint32_t* p_cur_size, uint8_t* p_rec,
1102*7eba2f3bSAndroid Build Coastguard Worker                                  uint8_t* p_new_type, uint8_t new_type_len) {
1103*7eba2f3bSAndroid Build Coastguard Worker   uint8_t typelen_delta;
1104*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *p_prev_type, prev_type_len;
1105*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pp;
1106*7eba2f3bSAndroid Build Coastguard Worker 
1107*7eba2f3bSAndroid Build Coastguard Worker   /* Skip header */
1108*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 1;
1109*7eba2f3bSAndroid Build Coastguard Worker 
1110*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
1111*7eba2f3bSAndroid Build Coastguard Worker   prev_type_len = *pp++;
1112*7eba2f3bSAndroid Build Coastguard Worker 
1113*7eba2f3bSAndroid Build Coastguard Worker   /* Skip the payload length */
1114*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_SR_MASK)
1115*7eba2f3bSAndroid Build Coastguard Worker     pp += 1;
1116*7eba2f3bSAndroid Build Coastguard Worker   else
1117*7eba2f3bSAndroid Build Coastguard Worker     pp += 4;
1118*7eba2f3bSAndroid Build Coastguard Worker 
1119*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_IL_MASK) pp++;
1120*7eba2f3bSAndroid Build Coastguard Worker 
1121*7eba2f3bSAndroid Build Coastguard Worker   /* Save pointer to the start of the type field */
1122*7eba2f3bSAndroid Build Coastguard Worker   p_prev_type = pp;
1123*7eba2f3bSAndroid Build Coastguard Worker 
1124*7eba2f3bSAndroid Build Coastguard Worker   if (new_type_len > prev_type_len) {
1125*7eba2f3bSAndroid Build Coastguard Worker     /* New type is larger than the previous */
1126*7eba2f3bSAndroid Build Coastguard Worker     typelen_delta = new_type_len - prev_type_len;
1127*7eba2f3bSAndroid Build Coastguard Worker 
1128*7eba2f3bSAndroid Build Coastguard Worker     if ((*p_cur_size + typelen_delta) > max_size)
1129*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_INSUFFICIENT_MEM);
1130*7eba2f3bSAndroid Build Coastguard Worker 
1131*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous type, and make space for the extra data
1132*7eba2f3bSAndroid Build Coastguard Worker      */
1133*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_type + prev_type_len;
1134*7eba2f3bSAndroid Build Coastguard Worker     shiftdown(pp, (uint32_t)(*p_cur_size - (pp - p_msg)), typelen_delta);
1135*7eba2f3bSAndroid Build Coastguard Worker 
1136*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size += typelen_delta;
1137*7eba2f3bSAndroid Build Coastguard Worker   } else if (new_type_len < prev_type_len) {
1138*7eba2f3bSAndroid Build Coastguard Worker     /* New type field is smaller than the previous */
1139*7eba2f3bSAndroid Build Coastguard Worker     typelen_delta = prev_type_len - new_type_len;
1140*7eba2f3bSAndroid Build Coastguard Worker 
1141*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous type, and shift up to fill the the
1142*7eba2f3bSAndroid Build Coastguard Worker      * unused space */
1143*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_type + prev_type_len;
1144*7eba2f3bSAndroid Build Coastguard Worker     shiftup(pp - typelen_delta, pp, (uint32_t)(*p_cur_size - (pp - p_msg)));
1145*7eba2f3bSAndroid Build Coastguard Worker 
1146*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size -= typelen_delta;
1147*7eba2f3bSAndroid Build Coastguard Worker   }
1148*7eba2f3bSAndroid Build Coastguard Worker 
1149*7eba2f3bSAndroid Build Coastguard Worker   /* Save in new type length */
1150*7eba2f3bSAndroid Build Coastguard Worker   p_rec[1] = new_type_len;
1151*7eba2f3bSAndroid Build Coastguard Worker 
1152*7eba2f3bSAndroid Build Coastguard Worker   /* Now copy in the new type field data */
1153*7eba2f3bSAndroid Build Coastguard Worker   if (p_new_type) memcpy(p_prev_type, p_new_type, new_type_len);
1154*7eba2f3bSAndroid Build Coastguard Worker 
1155*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
1156*7eba2f3bSAndroid Build Coastguard Worker }
1157*7eba2f3bSAndroid Build Coastguard Worker 
1158*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
1159*7eba2f3bSAndroid Build Coastguard Worker **
1160*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgReplaceId
1161*7eba2f3bSAndroid Build Coastguard Worker **
1162*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function replaces the ID field of a specific record in
1163*7eba2f3bSAndroid Build Coastguard Worker **                  the given NDEF message
1164*7eba2f3bSAndroid Build Coastguard Worker **
1165*7eba2f3bSAndroid Build Coastguard Worker ** Returns          OK, or error if the new ID field did not fit
1166*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
1167*7eba2f3bSAndroid Build Coastguard Worker **
1168*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgReplaceId(uint8_t * p_msg,uint32_t max_size,uint32_t * p_cur_size,uint8_t * p_rec,uint8_t * p_new_id,uint8_t new_id_len)1169*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgReplaceId(uint8_t* p_msg, uint32_t max_size,
1170*7eba2f3bSAndroid Build Coastguard Worker                                uint32_t* p_cur_size, uint8_t* p_rec,
1171*7eba2f3bSAndroid Build Coastguard Worker                                uint8_t* p_new_id, uint8_t new_id_len) {
1172*7eba2f3bSAndroid Build Coastguard Worker   uint8_t idlen_delta;
1173*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *p_prev_id, *p_idlen_field;
1174*7eba2f3bSAndroid Build Coastguard Worker   uint8_t prev_id_len, type_len;
1175*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* pp;
1176*7eba2f3bSAndroid Build Coastguard Worker 
1177*7eba2f3bSAndroid Build Coastguard Worker   /* Skip header */
1178*7eba2f3bSAndroid Build Coastguard Worker   pp = p_rec + 1;
1179*7eba2f3bSAndroid Build Coastguard Worker 
1180*7eba2f3bSAndroid Build Coastguard Worker   /* Next byte is the type field length */
1181*7eba2f3bSAndroid Build Coastguard Worker   type_len = *pp++;
1182*7eba2f3bSAndroid Build Coastguard Worker 
1183*7eba2f3bSAndroid Build Coastguard Worker   /* Skip the payload length */
1184*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_SR_MASK)
1185*7eba2f3bSAndroid Build Coastguard Worker     pp += 1;
1186*7eba2f3bSAndroid Build Coastguard Worker   else
1187*7eba2f3bSAndroid Build Coastguard Worker     pp += 4;
1188*7eba2f3bSAndroid Build Coastguard Worker 
1189*7eba2f3bSAndroid Build Coastguard Worker   p_idlen_field = pp;
1190*7eba2f3bSAndroid Build Coastguard Worker 
1191*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_IL_MASK)
1192*7eba2f3bSAndroid Build Coastguard Worker     prev_id_len = *pp++;
1193*7eba2f3bSAndroid Build Coastguard Worker   else
1194*7eba2f3bSAndroid Build Coastguard Worker     prev_id_len = 0;
1195*7eba2f3bSAndroid Build Coastguard Worker 
1196*7eba2f3bSAndroid Build Coastguard Worker   /* Save pointer to the start of the ID field (right after the type field) */
1197*7eba2f3bSAndroid Build Coastguard Worker   p_prev_id = pp + type_len;
1198*7eba2f3bSAndroid Build Coastguard Worker 
1199*7eba2f3bSAndroid Build Coastguard Worker   if (new_id_len > prev_id_len) {
1200*7eba2f3bSAndroid Build Coastguard Worker     /* New ID field is larger than the previous */
1201*7eba2f3bSAndroid Build Coastguard Worker     idlen_delta = new_id_len - prev_id_len;
1202*7eba2f3bSAndroid Build Coastguard Worker 
1203*7eba2f3bSAndroid Build Coastguard Worker     /* If the previous ID length was 0, we need to add a 1-byte ID length */
1204*7eba2f3bSAndroid Build Coastguard Worker     if (prev_id_len == 0) {
1205*7eba2f3bSAndroid Build Coastguard Worker       if ((*p_cur_size + idlen_delta + 1) > max_size)
1206*7eba2f3bSAndroid Build Coastguard Worker         return (NDEF_MSG_INSUFFICIENT_MEM);
1207*7eba2f3bSAndroid Build Coastguard Worker 
1208*7eba2f3bSAndroid Build Coastguard Worker       shiftdown(p_idlen_field,
1209*7eba2f3bSAndroid Build Coastguard Worker                 (uint32_t)(*p_cur_size - (p_idlen_field - p_msg)), 1);
1210*7eba2f3bSAndroid Build Coastguard Worker       p_prev_id += 1;
1211*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size += 1;
1212*7eba2f3bSAndroid Build Coastguard Worker       *p_rec |= NDEF_IL_MASK;
1213*7eba2f3bSAndroid Build Coastguard Worker     } else if ((*p_cur_size + idlen_delta) > max_size)
1214*7eba2f3bSAndroid Build Coastguard Worker       return (NDEF_MSG_INSUFFICIENT_MEM);
1215*7eba2f3bSAndroid Build Coastguard Worker 
1216*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous ID field, and make space for the extra
1217*7eba2f3bSAndroid Build Coastguard Worker      * data */
1218*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_id + prev_id_len;
1219*7eba2f3bSAndroid Build Coastguard Worker     shiftdown(pp, (uint32_t)(*p_cur_size - (pp - p_msg)), idlen_delta);
1220*7eba2f3bSAndroid Build Coastguard Worker 
1221*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size += idlen_delta;
1222*7eba2f3bSAndroid Build Coastguard Worker   } else if (new_id_len < prev_id_len) {
1223*7eba2f3bSAndroid Build Coastguard Worker     /* New ID field is smaller than the previous */
1224*7eba2f3bSAndroid Build Coastguard Worker     idlen_delta = prev_id_len - new_id_len;
1225*7eba2f3bSAndroid Build Coastguard Worker 
1226*7eba2f3bSAndroid Build Coastguard Worker     /* Point to the end of the previous ID, and shift up to fill the the unused
1227*7eba2f3bSAndroid Build Coastguard Worker      * space */
1228*7eba2f3bSAndroid Build Coastguard Worker     pp = p_prev_id + prev_id_len;
1229*7eba2f3bSAndroid Build Coastguard Worker     shiftup(pp - idlen_delta, pp, (uint32_t)(*p_cur_size - (pp - p_msg)));
1230*7eba2f3bSAndroid Build Coastguard Worker 
1231*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size -= idlen_delta;
1232*7eba2f3bSAndroid Build Coastguard Worker 
1233*7eba2f3bSAndroid Build Coastguard Worker     /* If removing the ID, make sure that length field is also removed */
1234*7eba2f3bSAndroid Build Coastguard Worker     if (new_id_len == 0) {
1235*7eba2f3bSAndroid Build Coastguard Worker       shiftup(p_idlen_field, p_idlen_field + 1,
1236*7eba2f3bSAndroid Build Coastguard Worker               (uint32_t)(*p_cur_size - (p_idlen_field - p_msg - (uint32_t)1)));
1237*7eba2f3bSAndroid Build Coastguard Worker       *p_rec &= ~NDEF_IL_MASK;
1238*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size -= 1;
1239*7eba2f3bSAndroid Build Coastguard Worker     }
1240*7eba2f3bSAndroid Build Coastguard Worker   }
1241*7eba2f3bSAndroid Build Coastguard Worker 
1242*7eba2f3bSAndroid Build Coastguard Worker   /* Save in new ID length and data */
1243*7eba2f3bSAndroid Build Coastguard Worker   if (new_id_len) {
1244*7eba2f3bSAndroid Build Coastguard Worker     *p_idlen_field = new_id_len;
1245*7eba2f3bSAndroid Build Coastguard Worker 
1246*7eba2f3bSAndroid Build Coastguard Worker     if (p_new_id) memcpy(p_prev_id, p_new_id, new_id_len);
1247*7eba2f3bSAndroid Build Coastguard Worker   }
1248*7eba2f3bSAndroid Build Coastguard Worker 
1249*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
1250*7eba2f3bSAndroid Build Coastguard Worker }
1251*7eba2f3bSAndroid Build Coastguard Worker 
1252*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
1253*7eba2f3bSAndroid Build Coastguard Worker **
1254*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgRemoveRec
1255*7eba2f3bSAndroid Build Coastguard Worker **
1256*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function removes the record at the given
1257*7eba2f3bSAndroid Build Coastguard Worker **                  index in the given NDEF message.
1258*7eba2f3bSAndroid Build Coastguard Worker **
1259*7eba2f3bSAndroid Build Coastguard Worker ** Returns          TRUE if OK, FALSE if the index was invalid
1260*7eba2f3bSAndroid Build Coastguard Worker **                  *p_cur_size is updated
1261*7eba2f3bSAndroid Build Coastguard Worker **
1262*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgRemoveRec(uint8_t * p_msg,uint32_t * p_cur_size,int32_t index)1263*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgRemoveRec(uint8_t* p_msg, uint32_t* p_cur_size,
1264*7eba2f3bSAndroid Build Coastguard Worker                                int32_t index) {
1265*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec = NDEF_MsgGetRecByIndex(p_msg, index);
1266*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *pNext, *pPrev;
1267*7eba2f3bSAndroid Build Coastguard Worker 
1268*7eba2f3bSAndroid Build Coastguard Worker   if (!p_rec) return (NDEF_REC_NOT_FOUND);
1269*7eba2f3bSAndroid Build Coastguard Worker 
1270*7eba2f3bSAndroid Build Coastguard Worker   /* If this is the first record in the message... */
1271*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_MB_MASK) {
1272*7eba2f3bSAndroid Build Coastguard Worker     /* Find the second record (if any) and set his 'Message Begin' bit */
1273*7eba2f3bSAndroid Build Coastguard Worker     pNext = NDEF_MsgGetRecByIndex(p_msg, 1);
1274*7eba2f3bSAndroid Build Coastguard Worker     if (pNext != nullptr) {
1275*7eba2f3bSAndroid Build Coastguard Worker       *pNext |= NDEF_MB_MASK;
1276*7eba2f3bSAndroid Build Coastguard Worker 
1277*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size -= (uint32_t)(pNext - p_msg);
1278*7eba2f3bSAndroid Build Coastguard Worker 
1279*7eba2f3bSAndroid Build Coastguard Worker       shiftup(p_msg, pNext, *p_cur_size);
1280*7eba2f3bSAndroid Build Coastguard Worker     } else
1281*7eba2f3bSAndroid Build Coastguard Worker       *p_cur_size = 0; /* No more records, lenght must be zero */
1282*7eba2f3bSAndroid Build Coastguard Worker 
1283*7eba2f3bSAndroid Build Coastguard Worker     return (NDEF_OK);
1284*7eba2f3bSAndroid Build Coastguard Worker   }
1285*7eba2f3bSAndroid Build Coastguard Worker 
1286*7eba2f3bSAndroid Build Coastguard Worker   /* If this is the last record in the message... */
1287*7eba2f3bSAndroid Build Coastguard Worker   if (*p_rec & NDEF_ME_MASK) {
1288*7eba2f3bSAndroid Build Coastguard Worker     if (index > 0) {
1289*7eba2f3bSAndroid Build Coastguard Worker       /* Find the previous record and set his 'Message End' bit */
1290*7eba2f3bSAndroid Build Coastguard Worker       pPrev = NDEF_MsgGetRecByIndex(p_msg, index - 1);
1291*7eba2f3bSAndroid Build Coastguard Worker       if (pPrev == nullptr) return false;
1292*7eba2f3bSAndroid Build Coastguard Worker 
1293*7eba2f3bSAndroid Build Coastguard Worker       *pPrev |= NDEF_ME_MASK;
1294*7eba2f3bSAndroid Build Coastguard Worker     }
1295*7eba2f3bSAndroid Build Coastguard Worker     *p_cur_size = (uint32_t)(p_rec - p_msg);
1296*7eba2f3bSAndroid Build Coastguard Worker 
1297*7eba2f3bSAndroid Build Coastguard Worker     return (NDEF_OK);
1298*7eba2f3bSAndroid Build Coastguard Worker   }
1299*7eba2f3bSAndroid Build Coastguard Worker 
1300*7eba2f3bSAndroid Build Coastguard Worker   /* Not the first or the last... get the address of the next record */
1301*7eba2f3bSAndroid Build Coastguard Worker   pNext = NDEF_MsgGetNextRec(p_rec);
1302*7eba2f3bSAndroid Build Coastguard Worker   if (pNext == nullptr) return false;
1303*7eba2f3bSAndroid Build Coastguard Worker 
1304*7eba2f3bSAndroid Build Coastguard Worker   /* We are removing p_rec, so shift from pNext to the end */
1305*7eba2f3bSAndroid Build Coastguard Worker   shiftup(p_rec, pNext, (uint32_t)(*p_cur_size - (pNext - p_msg)));
1306*7eba2f3bSAndroid Build Coastguard Worker 
1307*7eba2f3bSAndroid Build Coastguard Worker   *p_cur_size -= (uint32_t)(pNext - p_rec);
1308*7eba2f3bSAndroid Build Coastguard Worker 
1309*7eba2f3bSAndroid Build Coastguard Worker   return (NDEF_OK);
1310*7eba2f3bSAndroid Build Coastguard Worker }
1311*7eba2f3bSAndroid Build Coastguard Worker 
1312*7eba2f3bSAndroid Build Coastguard Worker /*******************************************************************************
1313*7eba2f3bSAndroid Build Coastguard Worker **
1314*7eba2f3bSAndroid Build Coastguard Worker ** Function         NDEF_MsgCopyAndDechunk
1315*7eba2f3bSAndroid Build Coastguard Worker **
1316*7eba2f3bSAndroid Build Coastguard Worker ** Description      This function copies and de-chunks an NDEF message.
1317*7eba2f3bSAndroid Build Coastguard Worker **                  It is assumed that the destination is at least as large
1318*7eba2f3bSAndroid Build Coastguard Worker **                  as the source, since the source may not actually contain
1319*7eba2f3bSAndroid Build Coastguard Worker **                  any chunks.
1320*7eba2f3bSAndroid Build Coastguard Worker **
1321*7eba2f3bSAndroid Build Coastguard Worker ** Returns          The output byte count
1322*7eba2f3bSAndroid Build Coastguard Worker **
1323*7eba2f3bSAndroid Build Coastguard Worker *******************************************************************************/
NDEF_MsgCopyAndDechunk(uint8_t * p_src,uint32_t src_len,uint8_t * p_dest,uint32_t * p_out_len)1324*7eba2f3bSAndroid Build Coastguard Worker tNDEF_STATUS NDEF_MsgCopyAndDechunk(uint8_t* p_src, uint32_t src_len,
1325*7eba2f3bSAndroid Build Coastguard Worker                                     uint8_t* p_dest, uint32_t* p_out_len) {
1326*7eba2f3bSAndroid Build Coastguard Worker   uint32_t out_len, max_out_len;
1327*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_rec;
1328*7eba2f3bSAndroid Build Coastguard Worker   uint8_t* p_prev_rec = p_dest;
1329*7eba2f3bSAndroid Build Coastguard Worker   uint8_t *p_type, *p_id, *p_pay;
1330*7eba2f3bSAndroid Build Coastguard Worker   uint8_t type_len, id_len, tnf;
1331*7eba2f3bSAndroid Build Coastguard Worker   uint32_t pay_len;
1332*7eba2f3bSAndroid Build Coastguard Worker   tNDEF_STATUS status;
1333*7eba2f3bSAndroid Build Coastguard Worker 
1334*7eba2f3bSAndroid Build Coastguard Worker   /* First, validate the source */
1335*7eba2f3bSAndroid Build Coastguard Worker   status = NDEF_MsgValidate(p_src, src_len, true);
1336*7eba2f3bSAndroid Build Coastguard Worker   if (status != NDEF_OK) return (status);
1337*7eba2f3bSAndroid Build Coastguard Worker 
1338*7eba2f3bSAndroid Build Coastguard Worker   /* The output buffer must be at least as large as the input buffer */
1339*7eba2f3bSAndroid Build Coastguard Worker   max_out_len = src_len;
1340*7eba2f3bSAndroid Build Coastguard Worker 
1341*7eba2f3bSAndroid Build Coastguard Worker   /* Initialize output */
1342*7eba2f3bSAndroid Build Coastguard Worker   NDEF_MsgInit(p_dest, max_out_len, &out_len);
1343*7eba2f3bSAndroid Build Coastguard Worker 
1344*7eba2f3bSAndroid Build Coastguard Worker   p_rec = p_src;
1345*7eba2f3bSAndroid Build Coastguard Worker 
1346*7eba2f3bSAndroid Build Coastguard Worker   /* Now, copy record by record */
1347*7eba2f3bSAndroid Build Coastguard Worker   while ((p_rec != nullptr) && (status == NDEF_OK)) {
1348*7eba2f3bSAndroid Build Coastguard Worker     p_type = NDEF_RecGetType(p_rec, &tnf, &type_len);
1349*7eba2f3bSAndroid Build Coastguard Worker     p_id = NDEF_RecGetId(p_rec, &id_len);
1350*7eba2f3bSAndroid Build Coastguard Worker     p_pay = NDEF_RecGetPayload(p_rec, &pay_len);
1351*7eba2f3bSAndroid Build Coastguard Worker 
1352*7eba2f3bSAndroid Build Coastguard Worker     /* If this is the continuation of a chunk, append the payload to the
1353*7eba2f3bSAndroid Build Coastguard Worker      * previous */
1354*7eba2f3bSAndroid Build Coastguard Worker     if (tnf == NDEF_TNF_UNCHANGED) {
1355*7eba2f3bSAndroid Build Coastguard Worker       if (p_pay) {
1356*7eba2f3bSAndroid Build Coastguard Worker         status = NDEF_MsgAppendPayload(p_dest, max_out_len, &out_len,
1357*7eba2f3bSAndroid Build Coastguard Worker                                        p_prev_rec, p_pay, pay_len);
1358*7eba2f3bSAndroid Build Coastguard Worker       }
1359*7eba2f3bSAndroid Build Coastguard Worker     } else {
1360*7eba2f3bSAndroid Build Coastguard Worker       p_prev_rec = p_dest + out_len;
1361*7eba2f3bSAndroid Build Coastguard Worker 
1362*7eba2f3bSAndroid Build Coastguard Worker       status = NDEF_MsgAddRec(p_dest, max_out_len, &out_len, tnf, p_type,
1363*7eba2f3bSAndroid Build Coastguard Worker                               type_len, p_id, id_len, p_pay, pay_len);
1364*7eba2f3bSAndroid Build Coastguard Worker     }
1365*7eba2f3bSAndroid Build Coastguard Worker 
1366*7eba2f3bSAndroid Build Coastguard Worker     p_rec = NDEF_MsgGetNextRec(p_rec);
1367*7eba2f3bSAndroid Build Coastguard Worker   }
1368*7eba2f3bSAndroid Build Coastguard Worker 
1369*7eba2f3bSAndroid Build Coastguard Worker   *p_out_len = out_len;
1370*7eba2f3bSAndroid Build Coastguard Worker 
1371*7eba2f3bSAndroid Build Coastguard Worker   return (status);
1372*7eba2f3bSAndroid Build Coastguard Worker }
1373