summaryrefslogtreecommitdiffstats
path: root/src/phFriNfc_NdefRecord.c
diff options
context:
space:
mode:
authorNick Pelly <npelly@google.com>2010-10-16 17:51:57 -0700
committerNick Pelly <npelly@google.com>2010-10-16 17:51:57 -0700
commita5086a29ed4333070c7488765c22b6d3a8eef296 (patch)
tree5c92f196c0ff720018d2705cd268cacacae4c47b /src/phFriNfc_NdefRecord.c
parent4ff7c86a2c706b150078274455406f1b04966e1a (diff)
downloadexternal_libnfc-nxp-a5086a29ed4333070c7488765c22b6d3a8eef296.zip
external_libnfc-nxp-a5086a29ed4333070c7488765c22b6d3a8eef296.tar.gz
external_libnfc-nxp-a5086a29ed4333070c7488765c22b6d3a8eef296.tar.bz2
Merge libnfc_ndef from gingerbread.
libnfc_ndef is the NDEF message parsing library. Change-Id: I8bf13873342097eaf7c1237737f3230411be111e Signed-off-by: Nick Pelly <npelly@google.com>
Diffstat (limited to 'src/phFriNfc_NdefRecord.c')
-rw-r--r--src/phFriNfc_NdefRecord.c906
1 files changed, 906 insertions, 0 deletions
diff --git a/src/phFriNfc_NdefRecord.c b/src/phFriNfc_NdefRecord.c
new file mode 100644
index 0000000..7da565f
--- /dev/null
+++ b/src/phFriNfc_NdefRecord.c
@@ -0,0 +1,906 @@
+/*
+ * 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;
+}
+