Home | History | Annotate | Download | only in src
      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 */
    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 
    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  */
    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  */
    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 */
    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 */
    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 
    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