1 /*
2  * Copyright (C) 2010 NXP Semiconductors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*!
18  * \file  phFriNfc_NdefRecord.c
19  * \brief NFC Ndef Record component file.
20  *
21  * Project: NFC-FRI
22  *
23  * $Date: Thu Jun 25 11:01:24 2009 $
24  * $Author: ing07336 $
25  * $Revision: 1.4 $
26  * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
27  *
28  */
29 
30 
31 /*! \ingroup grp_file_attributes
32  *  \name \name NDEF Record Tools Header
33  *
34  * File: \ref phFriNfc_NdefRecord.h
35  *
36  */
37 /*@{*/
38 #define PHFRINFCNDEFRECORD_FILEREVISION "$Revision: 1.4 $"
39 #define PHFRINFCNDEFRECORD_FILEALIASES  "$Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $"
40 /*@}*/
41 
42 #include <phFriNfc_NdefRecord.h>
43 #include <phNfcCompId.h>
44 #include <stdlib.h>
45 
46 /* Harsha: To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */
47 #include <string.h>
48 
49 
50 /*!
51  *
52  *  Get a specific NDEF record from the data, provided by the caller. The data is a buffer holding
53  *  one or more (nested) NDEF records within a NDEF packet (received via the NFC link, for example).
54  *
55  * \param[in]     Buffer                The data buffer holding the NDEF Message, as provided by the caller.
56  * \param[in]     BufferLength          The data length, as provided by the caller.
57  * \param[in,out] RawRecords            Array of pointers, receiving the references to the found Ndef Records
58  *                                      in the Message. The caller has to provide the array of pointers.
59  *                                      The array is filled with valid pointers up to the number of records
60  *                                      found or the array size if the number of found records exceeds the size.
61  *                                      If the value is NULL the function only yields the number of records
62  *                                      without filling in pointers.
63  * \param[in]     IsChunked             This boolean tells the user that the record of a certain position within
64  *                                      an array has the CHUNKED flag set (is a partial record). The number
65  *                                      of caller-provided array positions has to be the same as "NumberOfRawRecords".
66  *                                      In case that this parameter is NULL the function ignores it.
67  * \param[in,out] NumberOfRawRecords    Length of the Record pointer array. The caller has to provide
68  *                                      the number of pointers provided in the NDEF Type array. \n
69  *                                      The value is set by the extracting function to the actual number of
70  *                                      records found in the data. If the user specifies 0 (zero) the function
71  *                                      only yields the number of records without filling in pointers.\n
72  *                                      The value of NULL is invalid.
73  *
74  * \retval NFCSTATUS_SUCCESS            Operation successful.
75  * \retval NFCSTATUS_INVALID_PARAMETER  At least one parameter of the function is invalid.
76  *
77  * \note The correct number of found records is returned by the function also in case that:
78  *       - The "RawRecords" array is too short to hold all values: It is filled up to the allowed maximum.
79  *       - The "RawRecords" array is NULL: Only the number is returned.
80  *       - The "NumberOfRawRecords" parameter is 0 (zero): The array is not filled, just the number is returned.
81  *       .
82  *       This can be exploited for targeted memory allocation: Specify NULL for "RawRecords" and/or
83  *       0 (zero) for "NumberOfRawRecords" and the function yields the correct array size to allocate
84  *       for a second call.
85  *
86  */
phFriNfc_NdefRecord_GetRecords(uint8_t * Buffer,uint32_t BufferLength,uint8_t * RawRecords[],uint8_t IsChunked[],uint32_t * NumberOfRawRecords)87  NFCSTATUS phFriNfc_NdefRecord_GetRecords(  uint8_t     *Buffer,
88                                             uint32_t    BufferLength,
89                                             uint8_t     *RawRecords[],
90                                             uint8_t     IsChunked[],
91                                             uint32_t    *NumberOfRawRecords)
92 {
93     NFCSTATUS   Status = NFCSTATUS_SUCCESS;
94     uint8_t     PayloadLengthByte = 0,
95                 TypeLengthByte = 0,
96                 TypeLength = 0,
97                 IDLengthByte = 0,
98                 NoOfRecordsReturnFlag = 0,
99                 IDLength = 0;
100     uint32_t    Count = 0,
101                 PayloadLength = 0,
102                 BytesTraversed = 0;
103 
104     /*  Validate the input parameters */
105     if (Buffer == NULL || BufferLength == 0 || NumberOfRawRecords == NULL)
106     {
107         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
108                             NFCSTATUS_INVALID_PARAMETER);
109         return Status;
110     }
111 
112     if((*NumberOfRawRecords) > 0)
113     {
114         /*  The number of caller-provided array positions for the array IsChunked
115             has to be the same as NumberOfRawRecords. Hence,
116             if NumberOfRawRecords > 0, the array IsChunked cannot be null */
117         if(IsChunked == NULL)
118         {
119             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
120                                 NFCSTATUS_INVALID_PARAMETER);
121             return Status;
122         }
123     }
124 
125     /* Check Raw Records input is NULL and Number of Raw records is 0*/
126     if ( RawRecords == NULL || *NumberOfRawRecords == 0)
127     {
128         /*  This flag is set, to return only number of records
129             this is done when the Raw Records is NULL or
130             Number of Raw records is 0 */
131         NoOfRecordsReturnFlag = 1;
132     }
133 
134     /* Check for the MB bit*/
135     if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) !=
136             PH_FRINFC_NDEFRECORD_FLAGS_MB )
137     {
138         /* MB  Error */
139         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
140                             NFCSTATUS_INVALID_FORMAT);
141 
142         /*  Number of valid records found in the message is 0 */
143         *NumberOfRawRecords = 0;
144         return Status;
145     }
146 
147     /* Check for Tnf bits 0x07 is reserved for future use */
148     if ((*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
149         PH_FRINFC_NDEFRECORD_TNF_RESERVED)
150     {
151         /* TNF 07  Error */
152         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
153                             NFCSTATUS_INVALID_FORMAT);
154         /*  Number of valid records found in the message is 0 */
155         *NumberOfRawRecords = 0;
156         return Status;
157     }
158 
159     /* Check the First Record(MB = 0) for TNF = 0x06(Unchanged) */
160     if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB &&
161         (*Buffer & PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
162     {
163         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
164                             NFCSTATUS_INVALID_FORMAT);
165         /*  Number of valid records found in the message is 0 */
166         *NumberOfRawRecords = 0;
167         return Status;
168     }
169 
170     /* First Record i.e., MB = 1, TNF != 0x05 and TypeLength = 0 */
171     if ( (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB &&
172          (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN &&
173          (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_EMPTY &&
174          *(Buffer + 1) == 0)
175     {
176         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
177                             NFCSTATUS_INVALID_FORMAT);
178         /*  Number of valid records found in the message is 0  */
179         *NumberOfRawRecords = 0;
180         return Status;
181     }
182 
183     /* Check till Buffer Length exceeds */
184     while ( BytesTraversed < BufferLength )
185     {
186     	if (Buffer == NULL)
187     	{
188 			break;
189     	}
190 
191         /* For Each Record Check whether it contains the ME bit set and CF bit Set
192             if YES return ERROR*/
193         if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
194                     PH_FRINFC_NDEFRECORD_FLAGS_CF  &&
195             (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
196              PH_FRINFC_NDEFRECORD_FLAGS_ME)
197         {
198             /* CF and ME Error */
199             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
200                     NFCSTATUS_INVALID_FORMAT);
201             break;
202         }
203 
204         if (NoOfRecordsReturnFlag == 0)
205         {
206             /*  Harsha: Fix for 0000241: [gk], NDEF Tools: GetRecords() overshoots
207                 a given array boundary if the number of records != 0. */
208             /*  Actual Number of Records should not exceed Number of records
209                 required by caller*/
210             if(Count >= *NumberOfRawRecords)
211             {
212                 break;
213             }
214             /* To fix the mantis entry 0388 */
215             if((Buffer != NULL)&&(RawRecords!=NULL))/*QMOR FIX*/
216             {
217                 RawRecords[Count] = Buffer;
218             }
219             else
220             {
221                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
222                                     NFCSTATUS_INVALID_PARAMETER);
223                 break;
224             }
225         }
226 
227         /* To Calculate the IDLength and PayloadLength for
228             short or normal record */
229         Status = phFriNfc_NdefRecord_RecordIDCheck (    Buffer,
230                                                         &TypeLength,
231                                                         &TypeLengthByte,
232                                                         &PayloadLengthByte,
233                                                         &PayloadLength,
234                                                         &IDLengthByte,
235                                                         &IDLength);
236         if (Status != NFCSTATUS_SUCCESS)
237         {
238             break;
239         }
240 
241         /* Check for the Chunk Flag */
242         if (NoOfRecordsReturnFlag == 0)
243         {
244             /*  If NoOfRecordsReturnFlag = 0, that means we have enough space  */
245             /*  in the array IsChunked, to write  */
246             if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
247                 PH_FRINFC_NDEFRECORD_FLAGS_CF)
248             {
249                 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET;
250             }
251             else
252             {
253                 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO;
254             }
255         }
256 
257         /* Check the record is not the first record */
258         if (Count > 0)
259         {
260             /* Not a first record, if chunk record is present and IL bit is set
261                 also if the MB bit is set */
262             if(((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF &&
263                 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL &&
264                 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) ||
265                 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB)
266             {
267                 /* IL or MB Error */
268                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
269                                     NFCSTATUS_INVALID_FORMAT);
270                 break;
271             }
272 
273             /* Check for the Chunk Flag */
274             if (NoOfRecordsReturnFlag == 0)
275             {
276                 /*  If NoOfRecordsReturnFlag = 0, that means the array IsChunked
277                     contains valid values. So, cannot check the value
278                     of IsChunked if NoOfRecordsReturnFlag = 1.  */
279 
280                 /*  Check whether the previous record has the chunk flag and
281                     TNF of present record is not 0x06 */
282                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
283                     (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) !=
284                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
285                 {
286                     /* CF or TNF  Error */
287                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
288                                         NFCSTATUS_INVALID_FORMAT);
289                     break;
290                 }
291 
292                 /*  Check whether the previous record doesnot have the chunk flag and
293                     TNF of present record is 0x06 */
294                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO &&
295                     (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
296                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
297                 {
298                     /* CF or TNF  Error */
299                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
300                                         NFCSTATUS_INVALID_FORMAT);
301                     break;
302                 }
303 
304                 /* Check for the last chunk */
305                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
306                     IsChunked [Count] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO)
307                 {
308                     /* Check for the TypeLength, IDLength = 0 */
309                     if (TypeLength != 0 || IDLength != 0)
310                     {
311                         /* last chunk record Error */
312                         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
313                                             NFCSTATUS_INVALID_FORMAT);
314                         break;
315                     }
316                 }
317             }   /*  if (NoOfRecordsReturnFlag == 0)  */
318         }   /*  if (Count > 0)  */
319 
320         /*  Calculate the bytes already traversed. */
321         BytesTraversed = (BytesTraversed + PayloadLengthByte + IDLengthByte + TypeLength
322                          + IDLength + TypeLengthByte + PayloadLength
323                          + PH_FRINFC_NDEFRECORD_BUF_INC1);
324 
325         if(BytesTraversed == BufferLength)
326         {
327             /*  We have reached the last record, and everything is fine.  */
328             /*  Check for the ME Byte */
329             if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
330                 PH_FRINFC_NDEFRECORD_FLAGS_ME)
331             {
332                 Count++;
333                 break;
334             }
335             else
336             {
337                 /* Each message must have ME flag in the last record, Since
338                 ME is not set raise an error */
339                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
340                 NFCSTATUS_INVALID_FORMAT);
341                 break;
342             }
343         }
344        else
345         {
346             /* Buffer Overshoot: Inconsistency in the message length
347               and actual value of the bytes in the message detected.
348               Report error.*/
349             if(BytesTraversed > BufferLength)
350             {
351                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
352                                 NFCSTATUS_INVALID_FORMAT);
353                 break;
354             }
355         }
356         /*  For Each Record Check whether it contains the ME bit set
357             if YES return*/
358         if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
359             PH_FRINFC_NDEFRECORD_FLAGS_ME)
360         {
361             Count++;
362             break;
363         }
364 
365         /* +1 is for first byte */
366         Buffer = (Buffer + PayloadLengthByte + IDLengthByte + TypeLength
367                  + TypeLengthByte + IDLength + PayloadLength
368                  + PH_FRINFC_NDEFRECORD_BUF_INC1);
369 
370         /*  Increment the number of valid records found in the message  */
371         Count++;
372     }
373 
374     /*  Whatever is the error, update the NumberOfRawRecords with the number
375         of proper records found till the error was detected in the message. */
376     *NumberOfRawRecords = Count;
377     return Status;
378 }
379 
380 /* to check the bitfields in the Flags Byte and return the status flag */
phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask)381 static uint8_t phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask)
382 {
383     uint8_t check_flag = 0x00;
384     check_flag = Flags & Mask;
385     return check_flag;
386 }
387 
phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t * Record)388 uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t *Record)
389 {
390     uint32_t RecordLength=1;
391     uint8_t  FlagCheck=0;
392 
393     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
394     /* Type length is present only for following TNF
395                     PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN
396                     PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE
397                     PH_FRINFC_NDEFRECORD_TNF_ABSURI
398                     PH_FRINFC_NDEFRECORD_TNF_NFCEXT
399     */
400 
401     /* ++ is for the Type Length Byte */
402     RecordLength++;
403     if( FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY &&
404         FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN &&
405         FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNCHANGED )
406     {
407         RecordLength += Record->TypeLength;
408     }
409 
410     /* to check if payloadlength is 8bit or 32bit*/
411     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
412     if(FlagCheck!=0)
413     {
414         /* ++ is for the Payload Length Byte */
415         RecordLength++;/* for short record*/
416     }
417     else
418     {
419         /* + PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE is for the Payload Length Byte */
420         RecordLength += PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;/* for normal record*/
421     }
422 
423     /* for non empty record */
424     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
425     if(FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY)
426     {
427         RecordLength += Record->PayloadLength;
428     }
429 
430     /* ID and IDlength are present only if IL flag is set*/
431     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
432     if(FlagCheck!=0)
433     {
434         RecordLength +=Record->IdLength;
435         /* ++ is for the ID Length Byte */
436         RecordLength ++;
437     }
438     return RecordLength;
439 }
440 
441 /*!
442  *
443  *  Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding
444  *  at least the entire NDEF record (received via the NFC link, for example).
445  *
446  * \param[out] Record               The NDEF record structure. The storage for the structure has to be provided by the
447  *                                  caller matching the requirements for \b Extraction, as described in the compound
448  *                                  documentation.
449  * \param[in]  RawRecord            The Pointer to the buffer, selected out of the array returned by
450  *                                  the \ref phFriNfc_NdefRecord_GetRecords function.
451  *
452  * \retval NFCSTATUS_SUCCESS                Operation successful.
453  * \retval NFCSTATUS_INVALID_PARAMETER      At least one parameter of the function is invalid.
454  *
455  * \note There are some caveats:
456  *       - The "RawRecord" Data buffer must exist at least as long as the function execution time plus the time
457  *         needed by the caller to evaluate the extracted information. No copying of the contained data is done.
458  *       - Using the "RawRecord" and "RawRecordMaxSize" parameters the function internally checks whether the
459  *         data to extract are within the bounds of the buffer.
460  *
461  *
462  */
phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t * Record,uint8_t * RawRecord)463 NFCSTATUS phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t *Record,
464                                     uint8_t               *RawRecord)
465 {
466     NFCSTATUS       Status = NFCSTATUS_SUCCESS;
467     uint8_t         PayloadLengthByte = 0,
468                     TypeLengthByte = 0,
469                     TypeLength = 0,
470                     IDLengthByte = 0,
471                     IDLength = 0,
472                     Tnf     =   0;
473     uint32_t        PayloadLength = 0;
474 
475     if (Record == NULL || RawRecord == NULL)
476     {
477         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
478                             NFCSTATUS_INVALID_PARAMETER);
479     }
480 
481     else
482     {
483 
484         /* Calculate the Flag Value */
485         Record->Flags = phFriNfc_NdefRecord_RecordFlag ( RawRecord);
486 
487         /* Calculate the Type Namr format of the record */
488         Tnf = phFriNfc_NdefRecord_TypeNameFormat( RawRecord);
489         if(Tnf != 0xFF)
490         {
491             Record->Tnf = Tnf;
492             /* To Calculate the IDLength and PayloadLength for short or normal record */
493             Status = phFriNfc_NdefRecord_RecordIDCheck (    RawRecord,
494                                                             &TypeLength,
495                                                             &TypeLengthByte,
496                                                             &PayloadLengthByte,
497                                                             &PayloadLength,
498                                                             &IDLengthByte,
499                                                             &IDLength);
500             Record->TypeLength = TypeLength;
501             Record->PayloadLength = PayloadLength;
502             Record->IdLength = IDLength;
503             RawRecord = (RawRecord +  PayloadLengthByte + IDLengthByte + TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
504             Record->Type = RawRecord;
505 
506             RawRecord = (RawRecord + Record->TypeLength);
507 
508             if (Record->IdLength != 0)
509             {
510                 Record->Id = RawRecord;
511             }
512 
513             RawRecord = RawRecord + Record->IdLength;
514             Record->PayloadData = RawRecord;
515         }
516         else
517         {
518             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
519                                 NFCSTATUS_INVALID_PARAMETER);
520         }
521     }
522     return Status;
523 }
524 
525 
526 
527 /*!
528  *  The function writes one NDEF record to a specified memory location. Called within a loop, it is possible to
529  *  write more records into a contiguous buffer, in each cycle advancing by the number of bytes written for
530  *  each record.
531  *
532  * \param[in]     Record             The Array of NDEF record structures to append. The structures
533  *                                   have to be filled by the caller matching the requirements for
534  *                                   \b Composition, as described in the documentation of
535  *                                   the \ref phFriNfc_NdefRecord_t "NDEF Record" structure.
536  * \param[in]     Buffer             The pointer to the buffer.
537  * \param[in]     MaxBufferSize      The data buffer's maximum size, provided by the caller.
538  * \param[out]    BytesWritten       The actual number of bytes written to the buffer. This can be used by
539  *                                   the caller to serialise more than one record into the same buffer before
540  *                                   handing it over to another instance.
541  *
542  * \retval NFCSTATUS_SUCCESS                  Operation successful.
543  * \retval NFCSTATUS_INVALID_PARAMETER        At least one parameter of the function is invalid.
544  * \retval NFCSTATUS_BUFFER_TOO_SMALL         The data buffer, provided by the caller is to small to
545  *                                            hold the composed NDEF record. The existing content is not changed.
546  *
547  */
phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t * Record,uint8_t * Buffer,uint32_t MaxBufferSize,uint32_t * BytesWritten)548  NFCSTATUS phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t *Record,
549                                         uint8_t               *Buffer,
550                                         uint32_t               MaxBufferSize,
551                                         uint32_t              *BytesWritten)
552 {
553     uint8_t     FlagCheck,
554                 TypeCheck=0,
555                 *temp,
556                 i;
557     uint32_t    i_data=0;
558 
559     if(Record==NULL ||Buffer==NULL||BytesWritten==NULL||MaxBufferSize == 0)
560     {
561         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
562     }
563 
564     if (Record->Tnf == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
565     {
566         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_FORMAT));
567     }
568 
569      /* calculate the length of the record and check with the buffersize if it exceeds return */
570     i_data=phFriNfc_NdefRecord_GetLength(Record);
571     if(i_data > MaxBufferSize)
572     {
573         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_BUFFER_TOO_SMALL));
574     }
575     *BytesWritten = i_data;
576 
577     /*fill the first byte of the message(all the flags) */
578     /*increment the buffer*/
579     *Buffer = ( (Record->Flags & PH_FRINFC_NDEFRECORD_FLAG_MASK) | (Record->Tnf & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK));
580     Buffer++;
581 
582     /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_EMPTY */
583     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
584     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_EMPTY)
585     {
586         /* fill the typelength idlength and payloadlength with zero(empty message)*/
587         for(i=0;i<3;i++)
588         {
589             *Buffer=PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
590             Buffer++;
591         }
592         return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
593      }
594 
595     /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_RESERVED */
596     /* TNF should not be reserved one*/
597     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
598     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
599     {
600         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
601     }
602 
603     /* check for TNF Unknown or Unchanged */
604     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
605     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNKNOWN || \
606         FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
607     {
608         *Buffer = PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
609         Buffer++;
610     }
611     else
612     {
613         *Buffer = Record->TypeLength;
614         Buffer++;
615         TypeCheck=1;
616     }
617 
618     /* check for the short record bit if it is then payloadlength is only one byte */
619     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
620     if(FlagCheck!=0)
621     {
622         *Buffer = (uint8_t)(Record->PayloadLength & 0x000000ff);
623         Buffer++;
624     }
625     else
626     {
627         /* if it is normal record payloadlength is 4 byte(32 bit)*/
628         *Buffer = (uint8_t)((Record->PayloadLength & 0xff000000) >> PHNFCSTSHL24);
629         Buffer++;
630         *Buffer = (uint8_t)((Record->PayloadLength & 0x00ff0000) >> PHNFCSTSHL16);
631         Buffer++;
632         *Buffer = (uint8_t)((Record->PayloadLength & 0x0000ff00) >> PHNFCSTSHL8);
633         Buffer++;
634         *Buffer = (uint8_t)((Record->PayloadLength & 0x000000ff));
635         Buffer++;
636     }
637 
638     /*check for IL bit set(Flag), if so then IDlength is present*/
639     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
640     if(FlagCheck!=0)
641     {
642         *Buffer=Record->IdLength;
643         Buffer++;
644     }
645 
646     /*check for TNF and fill the Type*/
647     temp=Record->Type;
648     if(TypeCheck!=0)
649     {
650         for(i=0;i<(Record->TypeLength);i++)
651         {
652             *Buffer = *temp;
653             Buffer++;
654             temp++;
655         }
656     }
657 
658     /*check for IL bit set(Flag), if so then IDlength is present and fill the ID*/
659     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
660     temp=Record->Id;
661     if(FlagCheck!=0)
662     {
663         for(i=0;i<(Record->IdLength);i++)
664         {
665             *Buffer = *temp;
666             Buffer++;
667             temp++;
668         }
669     }
670 
671     temp=Record->PayloadData;
672     /*check for SR bit and then correspondingly use the payload length*/
673     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
674     for(i_data=0;i_data < (Record->PayloadLength) ;i_data++)
675     {
676         *Buffer = *temp;
677         Buffer++;
678         temp++;
679     }
680 
681     return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
682 }
683 
684 /* Calculate the Flags of the record */
phFriNfc_NdefRecord_RecordFlag(uint8_t * Record)685 static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t    *Record)
686 {
687     uint8_t flag = 0;
688 
689     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB )
690     {
691         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_MB;
692     }
693     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_ME) == PH_FRINFC_NDEFRECORD_FLAGS_ME )
694     {
695         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_ME;
696     }
697     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF )
698     {
699         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_CF;
700     }
701     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR )
702     {
703         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_SR;
704     }
705     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL )
706     {
707         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_IL;
708     }
709     return flag;
710 }
711 
712 /* Calculate the Type Name Format for the record */
phFriNfc_NdefRecord_TypeNameFormat(uint8_t * Record)713 static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t    *Record)
714 {
715     uint8_t     tnf = 0;
716 
717     switch (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)
718     {
719     case PH_FRINFC_NDEFRECORD_TNF_EMPTY:
720         tnf = PH_FRINFC_NDEFRECORD_TNF_EMPTY;
721         break;
722 
723     case PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN:
724         tnf = PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN;
725         break;
726 
727     case PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE:
728         tnf = PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE;
729         break;
730 
731     case PH_FRINFC_NDEFRECORD_TNF_ABSURI:
732         tnf = PH_FRINFC_NDEFRECORD_TNF_ABSURI;
733         break;
734 
735     case PH_FRINFC_NDEFRECORD_TNF_NFCEXT:
736         tnf = PH_FRINFC_NDEFRECORD_TNF_NFCEXT;
737         break;
738 
739     case PH_FRINFC_NDEFRECORD_TNF_UNKNOWN:
740         tnf = PH_FRINFC_NDEFRECORD_TNF_UNKNOWN;
741         break;
742 
743     case PH_FRINFC_NDEFRECORD_TNF_UNCHANGED:
744         tnf = PH_FRINFC_NDEFRECORD_TNF_UNCHANGED;
745         break;
746 
747     case PH_FRINFC_NDEFRECORD_TNF_RESERVED:
748         tnf = PH_FRINFC_NDEFRECORD_TNF_RESERVED;
749         break;
750     default :
751         tnf = 0xFF;
752         break;
753     }
754 
755     return tnf;
756 }
757 
758 
phFriNfc_NdefRecord_RecordIDCheck(uint8_t * Record,uint8_t * TypeLength,uint8_t * TypeLengthByte,uint8_t * PayloadLengthByte,uint32_t * PayloadLength,uint8_t * IDLengthByte,uint8_t * IDLength)759 static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t       *Record,
760                                               uint8_t       *TypeLength,
761                                               uint8_t       *TypeLengthByte,
762                                               uint8_t       *PayloadLengthByte,
763                                               uint32_t      *PayloadLength,
764                                               uint8_t       *IDLengthByte,
765                                               uint8_t       *IDLength)
766 {
767     NFCSTATUS   Status = NFCSTATUS_SUCCESS;
768 
769     /* Check for Tnf bits 0x07 is reserved for future use */
770     if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
771         PH_FRINFC_NDEFRECORD_TNF_RESERVED)
772     {
773         /* TNF 07  Error */
774         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
775                             NFCSTATUS_INVALID_FORMAT);
776         return Status;
777     }
778 
779     /* Check for Type Name Format  depending on the TNF,  Type Length value is set*/
780     if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)==
781         PH_FRINFC_NDEFRECORD_TNF_EMPTY)
782     {
783         *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
784 
785         if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
786         {
787             /* Type Length  Error */
788             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
789                                 NFCSTATUS_INVALID_FORMAT);
790             return Status;
791         }
792 
793         *TypeLengthByte = 1;
794 
795         /* Check for Short Record */
796         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR)
797         {
798             /* For Short Record, Payload Length Byte is 1 */
799             *PayloadLengthByte = 1;
800             /*  1 for Header byte */
801             *PayloadLength = *(Record + *TypeLengthByte + 1);
802             if (*PayloadLength != 0)
803             {
804                 /* PayloadLength  Error */
805                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
806                                     NFCSTATUS_INVALID_FORMAT);
807                 return Status;
808             }
809         }
810         else
811         {
812             /* For Normal Record, Payload Length Byte is 4 */
813             *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
814             *PayloadLength =    ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
815                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
816                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8)  +
817                                              *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
818             if (*PayloadLength != 0)
819             {
820                 /* PayloadLength  Error */
821                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
822                                     NFCSTATUS_INVALID_FORMAT);
823                 return Status;
824             }
825         }
826 
827         /* Check for ID Length existence */
828         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL)
829         {
830             /* Length Byte exists and it is 1 byte */
831             *IDLengthByte = 1;
832             /*  1 for Header byte */
833             *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
834             if (*IDLength != 0)
835             {
836                 /* IDLength  Error */
837                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
838                                     NFCSTATUS_INVALID_FORMAT);
839                 return Status;
840             }
841         }
842         else
843         {
844             *IDLengthByte = 0;
845             *IDLength = 0;
846         }
847     }
848     else
849     {
850         if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== PH_FRINFC_NDEFRECORD_TNF_UNKNOWN
851                 || (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
852                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
853         {
854             if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
855             {
856                 /* Type Length  Error */
857                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
858                             NFCSTATUS_INVALID_FORMAT);
859                 return Status;
860             }
861             *TypeLength = 0;
862             *TypeLengthByte = 1;
863         }
864         else
865         {
866             /*  1 for Header byte */
867             *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
868             *TypeLengthByte = 1;
869         }
870 
871         /* Check for Short Record */
872         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) ==
873                 PH_FRINFC_NDEFRECORD_FLAGS_SR)
874         {
875             /* For Short Record, Payload Length Byte is 1 */
876             *PayloadLengthByte = 1;
877             /*  1 for Header byte */
878             *PayloadLength = *(Record + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
879         }
880         else
881         {
882             /* For Normal Record, Payload Length Byte is 4 */
883             *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
884             *PayloadLength =    ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
885                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
886                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8)  +
887                                              *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
888         }
889 
890         /* Check for ID Length existence */
891         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) ==
892                 PH_FRINFC_NDEFRECORD_FLAGS_IL)
893         {
894             *IDLengthByte = 1;
895             /*  1 for Header byte */
896             *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
897         }
898         else
899         {
900             *IDLengthByte = 0;
901             *IDLength = 0;
902         }
903     }
904     return Status;
905 }
906 
907