/*
* Copyright (C) 2010 NXP Semiconductors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*!
* \file phFriNfc_NdefRecord.c
* \brief NFC Ndef Record component file.
*
* Project: NFC-FRI
*
* $Date: Thu Jun 25 11:01:24 2009 $
* $Author: ing07336 $
* $Revision: 1.4 $
* $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 $
*
*/
/*! \ingroup grp_file_attributes
* \name \name NDEF Record Tools Header
*
* File: \ref phFriNfc_NdefRecord.h
*
*/
/*@{*/
#define PHFRINFCNDEFRECORD_FILEREVISION "$Revision: 1.4 $"
#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 $"
/*@}*/
#include <phFriNfc_NdefRecord.h>
#include <phNfcCompId.h>
#include <stdlib.h>
/* Harsha: To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */
#include <string.h>
/*!
*
* Get a specific NDEF record from the data, provided by the caller. The data is a buffer holding
* one or more (nested) NDEF records within a NDEF packet (received via the NFC link, for example).
*
* \param[in] Buffer The data buffer holding the NDEF Message, as provided by the caller.
* \param[in] BufferLength The data length, as provided by the caller.
* \param[in,out] RawRecords Array of pointers, receiving the references to the found Ndef Records
* in the Message. The caller has to provide the array of pointers.
* The array is filled with valid pointers up to the number of records
* found or the array size if the number of found records exceeds the size.
* If the value is NULL the function only yields the number of records
* without filling in pointers.
* \param[in] IsChunked This boolean tells the user that the record of a certain position within
* an array has the CHUNKED flag set (is a partial record). The number
* of caller-provided array positions has to be the same as "NumberOfRawRecords".
* In case that this parameter is NULL the function ignores it.
* \param[in,out] NumberOfRawRecords Length of the Record pointer array. The caller has to provide
* the number of pointers provided in the NDEF Type array. \n
* The value is set by the extracting function to the actual number of
* records found in the data. If the user specifies 0 (zero) the function
* only yields the number of records without filling in pointers.\n
* The value of NULL is invalid.
*
* \retval NFCSTATUS_SUCCESS Operation successful.
* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
*
* \note The correct number of found records is returned by the function also in case that:
* - The "RawRecords" array is too short to hold all values: It is filled up to the allowed maximum.
* - The "RawRecords" array is NULL: Only the number is returned.
* - The "NumberOfRawRecords" parameter is 0 (zero): The array is not filled, just the number is returned.
* .
* This can be exploited for targeted memory allocation: Specify NULL for "RawRecords" and/or
* 0 (zero) for "NumberOfRawRecords" and the function yields the correct array size to allocate
* for a second call.
*
*/
NFCSTATUS phFriNfc_NdefRecord_GetRecords( uint8_t *Buffer,
uint32_t BufferLength,
uint8_t *RawRecords[],
uint8_t IsChunked[],
uint32_t *NumberOfRawRecords)
{
NFCSTATUS Status = NFCSTATUS_SUCCESS;
uint8_t PayloadLengthByte = 0,
TypeLengthByte = 0,
TypeLength = 0,
IDLengthByte = 0,
NoOfRecordsReturnFlag = 0,
IDLength = 0;
uint32_t Count = 0,
PayloadLength = 0,
BytesTraversed = 0;
/* Validate the input parameters */
if (Buffer == NULL || BufferLength == 0 || NumberOfRawRecords == NULL)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_PARAMETER);
return Status;
}
if((*NumberOfRawRecords) > 0)
{
/* The number of caller-provided array positions for the array IsChunked
has to be the same as NumberOfRawRecords. Hence,
if NumberOfRawRecords > 0, the array IsChunked cannot be null */
if(IsChunked == NULL)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_PARAMETER);
return Status;
}
}
/* Check Raw Records input is NULL and Number of Raw records is 0*/
if ( RawRecords == NULL || *NumberOfRawRecords == 0)
{
/* This flag is set, to return only number of records
this is done when the Raw Records is NULL or
Number of Raw records is 0 */
NoOfRecordsReturnFlag = 1;
}
/* Check for the MB bit*/
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) !=
PH_FRINFC_NDEFRECORD_FLAGS_MB )
{
/* MB Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
/* Number of valid records found in the message is 0 */
*NumberOfRawRecords = 0;
return Status;
}
/* Check for Tnf bits 0x07 is reserved for future use */
if ((*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
PH_FRINFC_NDEFRECORD_TNF_RESERVED)
{
/* TNF 07 Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
/* Number of valid records found in the message is 0 */
*NumberOfRawRecords = 0;
return Status;
}
/* Check the First Record(MB = 0) for TNF = 0x06(Unchanged) */
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
/* Number of valid records found in the message is 0 */
*NumberOfRawRecords = 0;
return Status;
}
/* First Record i.e., MB = 1, TNF != 0x05 and TypeLength = 0 */
if ( (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_EMPTY &&
*(Buffer + 1) == 0)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
/* Number of valid records found in the message is 0 */
*NumberOfRawRecords = 0;
return Status;
}
/* Check till Buffer Length exceeds */
while ( BytesTraversed < BufferLength )
{
if (Buffer == NULL)
{
break;
}
/* For Each Record Check whether it contains the ME bit set and CF bit Set
if YES return ERROR*/
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
PH_FRINFC_NDEFRECORD_FLAGS_CF &&
(*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
PH_FRINFC_NDEFRECORD_FLAGS_ME)
{
/* CF and ME Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
if (NoOfRecordsReturnFlag == 0)
{
/* Harsha: Fix for 0000241: [gk], NDEF Tools: GetRecords() overshoots
a given array boundary if the number of records != 0. */
/* Actual Number of Records should not exceed Number of records
required by caller*/
if(Count >= *NumberOfRawRecords)
{
break;
}
/* To fix the mantis entry 0388 */
if((Buffer != NULL)&&(RawRecords!=NULL))/*QMOR FIX*/
{
RawRecords[Count] = Buffer;
}
else
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_PARAMETER);
break;
}
}
/* To Calculate the IDLength and PayloadLength for
short or normal record */
Status = phFriNfc_NdefRecord_RecordIDCheck ( Buffer,
&TypeLength,
&TypeLengthByte,
&PayloadLengthByte,
&PayloadLength,
&IDLengthByte,
&IDLength);
if (Status != NFCSTATUS_SUCCESS)
{
break;
}
/* Check for the Chunk Flag */
if (NoOfRecordsReturnFlag == 0)
{
/* If NoOfRecordsReturnFlag = 0, that means we have enough space */
/* in the array IsChunked, to write */
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
PH_FRINFC_NDEFRECORD_FLAGS_CF)
{
IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET;
}
else
{
IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO;
}
}
/* Check the record is not the first record */
if (Count > 0)
{
/* Not a first record, if chunk record is present and IL bit is set
also if the MB bit is set */
if(((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF &&
(*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) ||
(*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB)
{
/* IL or MB Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
/* Check for the Chunk Flag */
if (NoOfRecordsReturnFlag == 0)
{
/* If NoOfRecordsReturnFlag = 0, that means the array IsChunked
contains valid values. So, cannot check the value
of IsChunked if NoOfRecordsReturnFlag = 1. */
/* Check whether the previous record has the chunk flag and
TNF of present record is not 0x06 */
if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) !=
PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
{
/* CF or TNF Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
/* Check whether the previous record doesnot have the chunk flag and
TNF of present record is 0x06 */
if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO &&
(*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
{
/* CF or TNF Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
/* Check for the last chunk */
if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
IsChunked [Count] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO)
{
/* Check for the TypeLength, IDLength = 0 */
if (TypeLength != 0 || IDLength != 0)
{
/* last chunk record Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
}
} /* if (NoOfRecordsReturnFlag == 0) */
} /* if (Count > 0) */
/* Calculate the bytes already traversed. */
BytesTraversed = (BytesTraversed + PayloadLengthByte + IDLengthByte + TypeLength
+ IDLength + TypeLengthByte + PayloadLength
+ PH_FRINFC_NDEFRECORD_BUF_INC1);
if(BytesTraversed == BufferLength)
{
/* We have reached the last record, and everything is fine. */
/* Check for the ME Byte */
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
PH_FRINFC_NDEFRECORD_FLAGS_ME)
{
Count++;
break;
}
else
{
/* Each message must have ME flag in the last record, Since
ME is not set raise an error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
}
else
{
/* Buffer Overshoot: Inconsistency in the message length
and actual value of the bytes in the message detected.
Report error.*/
if(BytesTraversed > BufferLength)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
break;
}
}
/* For Each Record Check whether it contains the ME bit set
if YES return*/
if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
PH_FRINFC_NDEFRECORD_FLAGS_ME)
{
Count++;
break;
}
/* +1 is for first byte */
Buffer = (Buffer + PayloadLengthByte + IDLengthByte + TypeLength
+ TypeLengthByte + IDLength + PayloadLength
+ PH_FRINFC_NDEFRECORD_BUF_INC1);
/* Increment the number of valid records found in the message */
Count++;
}
/* Whatever is the error, update the NumberOfRawRecords with the number
of proper records found till the error was detected in the message. */
*NumberOfRawRecords = Count;
return Status;
}
/* to check the bitfields in the Flags Byte and return the status flag */
static uint8_t phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask)
{
uint8_t check_flag = 0x00;
check_flag = Flags & Mask;
return check_flag;
}
uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t *Record)
{
uint32_t RecordLength=1;
uint8_t FlagCheck=0;
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
/* Type length is present only for following TNF
PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN
PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE
PH_FRINFC_NDEFRECORD_TNF_ABSURI
PH_FRINFC_NDEFRECORD_TNF_NFCEXT
*/
/* ++ is for the Type Length Byte */
RecordLength++;
if( FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY &&
FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN &&
FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNCHANGED )
{
RecordLength += Record->TypeLength;
}
/* to check if payloadlength is 8bit or 32bit*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
if(FlagCheck!=0)
{
/* ++ is for the Payload Length Byte */
RecordLength++;/* for short record*/
}
else
{
/* + PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE is for the Payload Length Byte */
RecordLength += PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;/* for normal record*/
}
/* for non empty record */
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
if(FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY)
{
RecordLength += Record->PayloadLength;
}
/* ID and IDlength are present only if IL flag is set*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
if(FlagCheck!=0)
{
RecordLength +=Record->IdLength;
/* ++ is for the ID Length Byte */
RecordLength ++;
}
return RecordLength;
}
/*!
*
* Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding
* at least the entire NDEF record (received via the NFC link, for example).
*
* \param[out] Record The NDEF record structure. The storage for the structure has to be provided by the
* caller matching the requirements for \b Extraction, as described in the compound
* documentation.
* \param[in] RawRecord The Pointer to the buffer, selected out of the array returned by
* the \ref phFriNfc_NdefRecord_GetRecords function.
*
* \retval NFCSTATUS_SUCCESS Operation successful.
* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
*
* \note There are some caveats:
* - The "RawRecord" Data buffer must exist at least as long as the function execution time plus the time
* needed by the caller to evaluate the extracted information. No copying of the contained data is done.
* - Using the "RawRecord" and "RawRecordMaxSize" parameters the function internally checks whether the
* data to extract are within the bounds of the buffer.
*
*
*/
NFCSTATUS phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t *Record,
uint8_t *RawRecord)
{
NFCSTATUS Status = NFCSTATUS_SUCCESS;
uint8_t PayloadLengthByte = 0,
TypeLengthByte = 0,
TypeLength = 0,
IDLengthByte = 0,
IDLength = 0,
Tnf = 0;
uint32_t PayloadLength = 0;
if (Record == NULL || RawRecord == NULL)
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_PARAMETER);
}
else
{
/* Calculate the Flag Value */
Record->Flags = phFriNfc_NdefRecord_RecordFlag ( RawRecord);
/* Calculate the Type Namr format of the record */
Tnf = phFriNfc_NdefRecord_TypeNameFormat( RawRecord);
if(Tnf != 0xFF)
{
Record->Tnf = Tnf;
/* To Calculate the IDLength and PayloadLength for short or normal record */
Status = phFriNfc_NdefRecord_RecordIDCheck ( RawRecord,
&TypeLength,
&TypeLengthByte,
&PayloadLengthByte,
&PayloadLength,
&IDLengthByte,
&IDLength);
Record->TypeLength = TypeLength;
Record->PayloadLength = PayloadLength;
Record->IdLength = IDLength;
RawRecord = (RawRecord + PayloadLengthByte + IDLengthByte + TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
Record->Type = RawRecord;
RawRecord = (RawRecord + Record->TypeLength);
if (Record->IdLength != 0)
{
Record->Id = RawRecord;
}
RawRecord = RawRecord + Record->IdLength;
Record->PayloadData = RawRecord;
}
else
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_PARAMETER);
}
}
return Status;
}
/*!
* The function writes one NDEF record to a specified memory location. Called within a loop, it is possible to
* write more records into a contiguous buffer, in each cycle advancing by the number of bytes written for
* each record.
*
* \param[in] Record The Array of NDEF record structures to append. The structures
* have to be filled by the caller matching the requirements for
* \b Composition, as described in the documentation of
* the \ref phFriNfc_NdefRecord_t "NDEF Record" structure.
* \param[in] Buffer The pointer to the buffer.
* \param[in] MaxBufferSize The data buffer's maximum size, provided by the caller.
* \param[out] BytesWritten The actual number of bytes written to the buffer. This can be used by
* the caller to serialise more than one record into the same buffer before
* handing it over to another instance.
*
* \retval NFCSTATUS_SUCCESS Operation successful.
* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
* \retval NFCSTATUS_BUFFER_TOO_SMALL The data buffer, provided by the caller is to small to
* hold the composed NDEF record. The existing content is not changed.
*
*/
NFCSTATUS phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t *Record,
uint8_t *Buffer,
uint32_t MaxBufferSize,
uint32_t *BytesWritten)
{
uint8_t FlagCheck,
TypeCheck=0,
*temp,
i;
uint32_t i_data=0;
if(Record==NULL ||Buffer==NULL||BytesWritten==NULL||MaxBufferSize == 0)
{
return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
}
if (Record->Tnf == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
{
return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_FORMAT));
}
/* calculate the length of the record and check with the buffersize if it exceeds return */
i_data=phFriNfc_NdefRecord_GetLength(Record);
if(i_data > MaxBufferSize)
{
return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_BUFFER_TOO_SMALL));
}
*BytesWritten = i_data;
/*fill the first byte of the message(all the flags) */
/*increment the buffer*/
*Buffer = ( (Record->Flags & PH_FRINFC_NDEFRECORD_FLAG_MASK) | (Record->Tnf & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK));
Buffer++;
/* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_EMPTY */
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_EMPTY)
{
/* fill the typelength idlength and payloadlength with zero(empty message)*/
for(i=0;i<3;i++)
{
*Buffer=PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
Buffer++;
}
return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
}
/* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_RESERVED */
/* TNF should not be reserved one*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
{
return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
}
/* check for TNF Unknown or Unchanged */
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNKNOWN || \
FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
{
*Buffer = PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
Buffer++;
}
else
{
*Buffer = Record->TypeLength;
Buffer++;
TypeCheck=1;
}
/* check for the short record bit if it is then payloadlength is only one byte */
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
if(FlagCheck!=0)
{
*Buffer = (uint8_t)(Record->PayloadLength & 0x000000ff);
Buffer++;
}
else
{
/* if it is normal record payloadlength is 4 byte(32 bit)*/
*Buffer = (uint8_t)((Record->PayloadLength & 0xff000000) >> PHNFCSTSHL24);
Buffer++;
*Buffer = (uint8_t)((Record->PayloadLength & 0x00ff0000) >> PHNFCSTSHL16);
Buffer++;
*Buffer = (uint8_t)((Record->PayloadLength & 0x0000ff00) >> PHNFCSTSHL8);
Buffer++;
*Buffer = (uint8_t)((Record->PayloadLength & 0x000000ff));
Buffer++;
}
/*check for IL bit set(Flag), if so then IDlength is present*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
if(FlagCheck!=0)
{
*Buffer=Record->IdLength;
Buffer++;
}
/*check for TNF and fill the Type*/
temp=Record->Type;
if(TypeCheck!=0)
{
for(i=0;i<(Record->TypeLength);i++)
{
*Buffer = *temp;
Buffer++;
temp++;
}
}
/*check for IL bit set(Flag), if so then IDlength is present and fill the ID*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
temp=Record->Id;
if(FlagCheck!=0)
{
for(i=0;i<(Record->IdLength);i++)
{
*Buffer = *temp;
Buffer++;
temp++;
}
}
temp=Record->PayloadData;
/*check for SR bit and then correspondingly use the payload length*/
FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
for(i_data=0;i_data < (Record->PayloadLength) ;i_data++)
{
*Buffer = *temp;
Buffer++;
temp++;
}
return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
}
/* Calculate the Flags of the record */
static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t *Record)
{
uint8_t flag = 0;
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB )
{
flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_MB;
}
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_ME) == PH_FRINFC_NDEFRECORD_FLAGS_ME )
{
flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_ME;
}
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF )
{
flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_CF;
}
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR )
{
flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_SR;
}
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL )
{
flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_IL;
}
return flag;
}
/* Calculate the Type Name Format for the record */
static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t *Record)
{
uint8_t tnf = 0;
switch (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)
{
case PH_FRINFC_NDEFRECORD_TNF_EMPTY:
tnf = PH_FRINFC_NDEFRECORD_TNF_EMPTY;
break;
case PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN:
tnf = PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN;
break;
case PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE:
tnf = PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE;
break;
case PH_FRINFC_NDEFRECORD_TNF_ABSURI:
tnf = PH_FRINFC_NDEFRECORD_TNF_ABSURI;
break;
case PH_FRINFC_NDEFRECORD_TNF_NFCEXT:
tnf = PH_FRINFC_NDEFRECORD_TNF_NFCEXT;
break;
case PH_FRINFC_NDEFRECORD_TNF_UNKNOWN:
tnf = PH_FRINFC_NDEFRECORD_TNF_UNKNOWN;
break;
case PH_FRINFC_NDEFRECORD_TNF_UNCHANGED:
tnf = PH_FRINFC_NDEFRECORD_TNF_UNCHANGED;
break;
case PH_FRINFC_NDEFRECORD_TNF_RESERVED:
tnf = PH_FRINFC_NDEFRECORD_TNF_RESERVED;
break;
default :
tnf = 0xFF;
break;
}
return tnf;
}
static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t *Record,
uint8_t *TypeLength,
uint8_t *TypeLengthByte,
uint8_t *PayloadLengthByte,
uint32_t *PayloadLength,
uint8_t *IDLengthByte,
uint8_t *IDLength)
{
NFCSTATUS Status = NFCSTATUS_SUCCESS;
/* Check for Tnf bits 0x07 is reserved for future use */
if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
PH_FRINFC_NDEFRECORD_TNF_RESERVED)
{
/* TNF 07 Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
/* Check for Type Name Format depending on the TNF, Type Length value is set*/
if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)==
PH_FRINFC_NDEFRECORD_TNF_EMPTY)
{
*TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
{
/* Type Length Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
*TypeLengthByte = 1;
/* Check for Short Record */
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR)
{
/* For Short Record, Payload Length Byte is 1 */
*PayloadLengthByte = 1;
/* 1 for Header byte */
*PayloadLength = *(Record + *TypeLengthByte + 1);
if (*PayloadLength != 0)
{
/* PayloadLength Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
}
else
{
/* For Normal Record, Payload Length Byte is 4 */
*PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
*PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
(((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
(((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) +
*(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
if (*PayloadLength != 0)
{
/* PayloadLength Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
}
/* Check for ID Length existence */
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL)
{
/* Length Byte exists and it is 1 byte */
*IDLengthByte = 1;
/* 1 for Header byte */
*IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
if (*IDLength != 0)
{
/* IDLength Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
}
else
{
*IDLengthByte = 0;
*IDLength = 0;
}
}
else
{
if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== PH_FRINFC_NDEFRECORD_TNF_UNKNOWN
|| (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
{
if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
{
/* Type Length Error */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
NFCSTATUS_INVALID_FORMAT);
return Status;
}
*TypeLength = 0;
*TypeLengthByte = 1;
}
else
{
/* 1 for Header byte */
*TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
*TypeLengthByte = 1;
}
/* Check for Short Record */
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) ==
PH_FRINFC_NDEFRECORD_FLAGS_SR)
{
/* For Short Record, Payload Length Byte is 1 */
*PayloadLengthByte = 1;
/* 1 for Header byte */
*PayloadLength = *(Record + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
}
else
{
/* For Normal Record, Payload Length Byte is 4 */
*PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
*PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
(((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
(((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) +
*(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
}
/* Check for ID Length existence */
if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) ==
PH_FRINFC_NDEFRECORD_FLAGS_IL)
{
*IDLengthByte = 1;
/* 1 for Header byte */
*IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
}
else
{
*IDLengthByte = 0;
*IDLength = 0;
}
}
return Status;
}