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 */
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 */
381static 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
388uint32_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 */
463NFCSTATUS 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 */
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 */
685static 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 */
713static 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
759static 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