Fork for the GitHub
lib_NDEF.cpp
- Committer:
- DiegoOstuni
- Date:
- 2019-11-14
- Revision:
- 0:de13951f30f6
File content as of revision 0:de13951f30f6:
/** ****************************************************************************** * @file lib_NDEF.c * @author MMY Application Team * @version $Revision: 3210 $ * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ * @brief This file help to manage NDEF file, to parse and identify them. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> * * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty * * 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, * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "lib_NDEF.h" #include "lib_NDEF_Bluetooth.h" #include "lib_NDEF_Handover.h" #include "lib_NDEF_Wifi.h" #include "mbed.h" /** @addtogroup NFC_libraries * @{ * @brief <b>This is the library used to manage the content of the TAG (data) * But also the specific feature of the tag, for instance * password, gpo... </b> */ /** @addtogroup libNFC_FORUM * @{ * @brief This part of the library manage data which follow NFC forum organisation. */ /** @defgroup libNDEF_Private_Functions * @{ */ static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel ); static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct ); static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct ); static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct ); static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct ); static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct ); static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct ); static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload ); /** @brief This buffer is used to store the data sent/received by the TAG. */ uint8_t NDEF_Buffer [NDEF_MAX_SIZE]; /** @brief Size of the buffer used to build the NDEF messages. */ uint32_t NDEF_Buffer_size = NDEF_MAX_SIZE; /** @brief This buffer is used when it's required to prepare a record before adding it to the NDEF_Buffer. */ uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE]; /** @brief Size of the buffer used when a record has to be prepared. */ uint32_t NDEF_Record_Buffer_size = NDEF_RECORD_MAX_SIZE; /* In case of smart Poster composed with different record, 3 records supported so far */ sRecordInfo_t SPRecordStruct1, SPRecordStruct2, SPRecordStruct3, SPRecordStruct4; sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD] = { &SPRecordStruct1, &SPRecordStruct2, &SPRecordStruct3, &SPRecordStruct4 }; /** * @brief This function checks that the tag contain a NDEF message. * @retval NDEF_OK : There is a NDEF file stored in tag. * @retval NDEF_ERROR : No NDEF in the tag. */ static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel ) { uint16_t FileSize; /* Check NDEF existence */ NfcTag_GetLength(&FileSize, mi2cChannel); if( FileSize != 0 ) return NDEF_OK; else return NDEF_ERROR; } /** * @brief This function identify the type of record. * @param pRecordStruct : pointer on the record structure to fill. * @param pPayload : pointer on the payload. * @retval Status : Status of the operation. */ static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload ) { uint16_t status = NDEF_ERROR; uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; /* Is ID length field present */ if( (*pPayload) & IL_Mask ) { IDLengthField = ID_LENGTH_FIELD; } else { IDLengthField = 0; } /* it's a SR */ if( (*pPayload) & SR_Mask ) { TypeNbByte = pPayload[1]; PayloadLengthField = 1; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pPayload[3]; else IDNbByte = 0; } else { TypeNbByte = pPayload[1]; PayloadLengthField = 4; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pPayload[6]; else IDNbByte = 0; } SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; /* it's a SR */ if( pPayload[0] & SR_Mask ) { pRecordStruct->RecordFlags = pPayload[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = pPayload[2]; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pPayload[3+IDNbByte], TypeNbByte ); memcpy( pRecordStruct->ID, &pPayload[3+IDNbByte+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } else { pRecordStruct->RecordFlags = pPayload[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = ( ((uint32_t)pPayload[2]) << 24 ) | ( ((uint32_t)pPayload[3]) << 16 ) | ( ((uint32_t)pPayload[4]) << 8 ) | pPayload[5] ; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pPayload[6+IDNbByte], TypeNbByte ); memcpy( pRecordStruct->ID, &pPayload[6+IDNbByte+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } pRecordStruct->PayloadBufferAdd = pPayload + SizeOfRecordHeader ; status = NDEF_ParseRecordHeader( pRecordStruct ); return status; } /** * @brief This function parse the record header and dispatch regarding TNF value. * @param pRecordStruct : pointer on the record structure to fill. * @retval NDEF_OK : record identified and structure filled. * @retval NDEF_ERROR : Not supported. */ static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct ) { uint16_t status = NDEF_OK; switch( (pRecordStruct->RecordFlags & TNF_Mask) ) { case TNF_WellKnown: NDEF_ParseWellKnownType( pRecordStruct ); break; case TNF_MediaType: NDEF_ParseMediaType( pRecordStruct ); break; case TNF_NFCForumExternal: NDEF_ParseForumExternalType( pRecordStruct); break; default: /* currently not supported or unknown*/ pRecordStruct->NDEF_Type = UNKNOWN_TYPE; status = NDEF_ERROR; } return status; } /** * @brief This function parse the Well Known type record. * @param pRecordStruct : pointer on the record structure to fill. */ static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct ) { uint8_t* pPayload; pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); if( !memcmp( &(pRecordStruct->Type), SMART_POSTER_TYPE_STRING, pRecordStruct->TypeLength ) ) { /* special case where we have to parse others records */ pRecordStruct->NDEF_Type = SMARTPOSTER_TYPE; NDEF_ParseSP( pRecordStruct ); } else if( !memcmp( &(pRecordStruct->Type), URI_TYPE_STRING, pRecordStruct->TypeLength ) ) { /* it's an URI Type check if it's an URL or SMS or ... */ /* check identifier */ if( *pPayload == URI_ID_0x00 ) { NDEF_ParseURI( pRecordStruct ); } else if( (*pPayload > URI_ID_0x00) && (*pPayload < URI_RFU) ) { /* email special case */ if( *pPayload == (uint8_t) URI_ID_0x06 ) { pRecordStruct->NDEF_Type = URI_EMAIL_TYPE; } else { pRecordStruct->NDEF_Type = WELL_KNOWN_ABRIDGED_URI_TYPE; } } else { pRecordStruct->NDEF_Type = UNKNOWN_TYPE; } } else if( !memcmp( &(pRecordStruct->Type), TEXT_TYPE_STRING, pRecordStruct->TypeLength ) ) { pRecordStruct->NDEF_Type = TEXT_TYPE; } else if ((!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_SELECT_TYPE_STR, pRecordStruct->TypeLength )) || (!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_REQUEST_TYPE_STR, pRecordStruct->TypeLength ) )) { pRecordStruct->NDEF_Type = HANDOVER_TYPE; } else pRecordStruct->NDEF_Type = UNKNOWN_TYPE; } /** * @brief This function parse the Media type record. * @param pRecordStruct : pointer on the record structure to fill. */ static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct ) { if( !memcmp( &(pRecordStruct->Type), VCARD_TYPE_STRING, pRecordStruct->TypeLength ) ) pRecordStruct->NDEF_Type = VCARD_TYPE; else if( !memcmp( &(pRecordStruct->Type), XVCARD_TYPE_STRING, pRecordStruct->TypeLength ) ) pRecordStruct->NDEF_Type = VCARD_TYPE; else if( !memcmp( &(pRecordStruct->Type), XVCARD2_TYPE_STRING, pRecordStruct->TypeLength ) ) pRecordStruct->NDEF_Type = VCARD_TYPE; else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BREDR_MIME_TYPE, pRecordStruct->TypeLength)) pRecordStruct->NDEF_Type = BT_TYPE; else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BLE_MIME_TYPE, pRecordStruct->TypeLength)) pRecordStruct->NDEF_Type = BLE_TYPE; else if (!memcmp(&pRecordStruct->Type, WIFITOKEN_TYPE_STRING, pRecordStruct->TypeLength)) pRecordStruct->NDEF_Type = URI_WIFITOKEN_TYPE; else pRecordStruct->NDEF_Type = UNKNOWN_TYPE; } /** * @brief This function parse the Forum External type record. * @param pRecordStruct : pointer on the record structure to fill. */ static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct ) { if( !memcmp( &(pRecordStruct->Type), M24SR_DISCOVERY_APP_STRING, pRecordStruct->TypeLength ) ) pRecordStruct->NDEF_Type = M24SR_DISCOVERY_APP_TYPE; else pRecordStruct->NDEF_Type = UNKNOWN_TYPE; } /** * @brief This function parse the URI type record. * @param pRecordStruct : pointer on the record structure to fill. */ static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct ) { uint8_t* pPayload; pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); pPayload++; /* to skip URI identifier first URI payload byte */ if( !memcmp( pPayload, SMS_TYPE_STRING, strlen(SMS_TYPE_STRING) ) ) { pRecordStruct->NDEF_Type = URI_SMS_TYPE; } else if( !memcmp( pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING) ) ) { pRecordStruct->NDEF_Type = URI_GEO_TYPE; } else pRecordStruct->NDEF_Type = UNKNOWN_TYPE; } /** * @brief This function parse the Smart Poster. * @param pRecordStruct : pointer on the record structure to fill. */ static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct ) { uint8_t* pPayload; uint32_t PayloadSize = 0; uint32_t SPPayloadSize = 0; uint32_t OffsetInSPPayload = 0; uint32_t RecordPosition = 0; sRecordInfo_t *pSPRecordStruct; /* initialize variable with size of the payload and poiter on data */ PayloadSize = pRecordStruct->PayloadLength; pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); pSPRecordStruct = SPRecordStructAdd[0]; /* Initailize the number of record find in the SP payload */ pRecordStruct->NbOfRecordInSPPayload = 0; do { pSPRecordStruct = SPRecordStructAdd[RecordPosition]; /* identify the record in the SP payload */ if( NDEF_IdentifySPRecord( pSPRecordStruct, pPayload ) == NDEF_OK ) { /* store add of structure that will contain the other record information */ pRecordStruct->NbOfRecordInSPPayload++; pRecordStruct->SPRecordStructAdd[RecordPosition] = pSPRecordStruct; /* After SPRecord + First Record check if we are at the end of NDEF file */ SPPayloadSize = pSPRecordStruct->PayloadLength; OffsetInSPPayload += pSPRecordStruct->PayloadOffset + SPPayloadSize; pPayload += OffsetInSPPayload; } else /* Recommended Action Record for example */ { SPPayloadSize = 0; } RecordPosition++; } while( (OffsetInSPPayload < PayloadSize) && RecordPosition<SP_MAX_RECORD); /* there is another record */ } /** * @} */ /** @defgroup libNDEF_Public_Functions * @{ */ /** * @brief This function identify the NDEF message stored in tag. * @param pRecordStruct : Structure to fill with record information. * @param pNDEF : pointer on the NDEF message data. * @retval NDEF_OK : record struct filled. * @retval NDEF_ERROR : record struct not updated. */ uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF, I2C* mi2cChannel ) { uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; /* check NDEF present */ if( NDEF_IsNDEFPresent(mi2cChannel) != NDEF_OK ) { return NDEF_ERROR; } /* Read the NDEF file */ NfcTag_ReadNDEF( pNDEF, mi2cChannel ); /* Is ID length field present */ if( (*pNDEF) & IL_Mask ) { IDLengthField = ID_LENGTH_FIELD; } else { IDLengthField = 0; } /* it's a SR */ if( (*pNDEF) & SR_Mask ) { /* Analyse short record layout */ TypeNbByte = pNDEF[1]; PayloadLengthField = 1; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pNDEF[3]; else IDNbByte = 0; } else { /* Analyse normal record layout */ TypeNbByte = pNDEF[1]; PayloadLengthField = 4; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pNDEF[6]; else IDNbByte = 0; } SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; /* Read record header */ /* it's a SR */ if( pNDEF[0] & SR_Mask ) { pRecordStruct->RecordFlags = pNDEF[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = pNDEF[2]; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pNDEF[3+IDNbByte], TypeNbByte ); memcpy( pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } else { pRecordStruct->RecordFlags = pNDEF[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) | ( ((uint32_t)pNDEF[3]) << 16 ) | ( ((uint32_t)pNDEF[4]) << 8 ) | pNDEF[5] ; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte ); memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } pRecordStruct->PayloadBufferAdd = pNDEF; NDEF_ParseRecordHeader( pRecordStruct ); return NDEF_OK; } /** * @brief This function read the NDEF content of the TAG. * @param pNDEF : pointer on the buffer to store NDEF data. * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. * @retval NDEF_ERROR : not able to read NDEF from tag. * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. */ uint16_t NDEF_ReadNDEF( uint8_t* pNDEF, I2C* mi2cChannel ) { return NfcTag_ReadNDEF( pNDEF, mi2cChannel ); } /** * @brief This function read the NDEF size of the TAG. * @param Size : pointer to a 16-bit Size (in bytes) to be returned. * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. * @retval NDEF_ERROR : not able to read NDEF from tag. * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. */ uint16_t NDEF_getNDEFSize(uint16_t* Size, I2C* mi2cChannel) { return NfcTag_GetLength(Size, mi2cChannel); } /** * @brief This function write the NDEF in the TAG. * @param pNDEF : pointer on the buffer containing the NDEF data. * @retval NDEF_OK : NDEF file data written in the tag. * @retval NDEF_ERROR : not able to store NDEF in tag. * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. */ uint16_t NDEF_WriteNDEF( uint16_t NDEF_Size, uint8_t *pNDEF, I2C* mi2cChannel ) { return NfcTag_WriteNDEF( NDEF_Size, pNDEF, mi2cChannel ); } /** * @brief This function append the record to an the NDEF in the TAG. * @param pRecord : pointer on the record with data to be written. * @retval NDEF_OK : NDEF file data written in the tag. * @retval NDEF_ERROR : not able to store NDEF in tag. * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. */ uint16_t NDEF_AppendRecord(sRecordInfo_t *Record, I2C* mi2cChannel ) { uint16_t status; uint16_t NDEF_Size = 0; uint8_t* pData = NDEF_Buffer; status = NDEF_getNDEFSize(&NDEF_Size, mi2cChannel); if(status != NDEF_OK) return status ; if(NDEF_Size != 0) { // There are already records in the NDEF Record->RecordFlags &= ~MB_Mask; status = NfcTag_ReadNDEF(pData, mi2cChannel); if(status != NDEF_OK) return status ; uint8_t* pNdefRecord; sRecordInfo_t LastRecord; do { pNdefRecord = pData; NDEF_IdentifyBuffer(&LastRecord,pData); pData += LastRecord.PayloadOffset + LastRecord.PayloadLength; // TO DO: add a security condition to avoid infinite loop if NDEF file is corrupted } while(!(LastRecord.RecordFlags & ME_Mask)); LastRecord.RecordFlags &= ~ME_Mask; *pNdefRecord = LastRecord.RecordFlags; } else { // This will be the first message in memory Record->RecordFlags |= MB_Mask; } Record->RecordFlags |= ME_Mask; uint32_t RecordLength = NDEF_WriteRecord(Record,pData, mi2cChannel); return NfcTag_WriteNDEF( NDEF_Size + RecordLength, NDEF_Buffer, mi2cChannel ); } /** * @brief This function identify the NDEF message stored in tag. * @param pRecordStruct : Structure to fill with record information. * @param pNDEF : pointer on the NDEF message data. * @retval NDEF_OK : record struct filled. * @retval NDEF_ERROR : record struct not updated. */ uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF ) { uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; /* Is ID length field present */ if( (*pNDEF) & IL_Mask ) { IDLengthField = ID_LENGTH_FIELD; } else { IDLengthField = 0; } /* it's a SR */ if( (*pNDEF) & SR_Mask ) { /* Analyse short record layout */ TypeNbByte = pNDEF[1]; PayloadLengthField = 1; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pNDEF[3]; else IDNbByte = 0; } else { /* Analyse normal record layout */ TypeNbByte = pNDEF[1]; PayloadLengthField = 4; if( IDLengthField == ID_LENGTH_FIELD ) IDNbByte = pNDEF[6]; else IDNbByte = 0; } SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; /* it's a SR */ if( pNDEF[0] & SR_Mask ) { pRecordStruct->RecordFlags = pNDEF[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = pNDEF[2]; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pNDEF[3+IDLengthField], TypeNbByte ); memcpy( pRecordStruct->ID, &pNDEF[3+IDLengthField+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } else { pRecordStruct->RecordFlags = pNDEF[0]; pRecordStruct->TypeLength = TypeNbByte; pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) | ( ((uint32_t)pNDEF[3]) << 16 ) | ( ((uint32_t)pNDEF[4]) << 8 ) | pNDEF[5] ; pRecordStruct->IDLength = IDNbByte; memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte ); memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte ); pRecordStruct->PayloadOffset = SizeOfRecordHeader; } pRecordStruct->PayloadBufferAdd = &pNDEF[pRecordStruct->PayloadOffset]; NDEF_ParseRecordHeader( pRecordStruct ); return NDEF_OK; } /** * @brief This function writes a record into a NDEF buffer. (update SR flag if required) * @param pRecord : Structure with record information to be written. * @param pNDEF : pointer on the NDEF buffer. * @retval Length : Length of the written data (in bytes) */ uint32_t NDEF_WriteRecord( sRecordInfo_t *pRecord, uint8_t* pNDEF, I2C* mi2cChannel ) { /************************************/ /* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ /*----------------------------------*/ /* MB ME CF SR IL TNF */ /*----------------------------------*/ /* TYPE LENGTH */ /*----------------------------------*/ /* PAYLOAD LENGTH 3 */ /*----------------------------------*/ /* PAYLOAD LENGTH 2 */ /*----------------------------------*/ /* PAYLOAD LENGTH 1 */ /*----------------------------------*/ /* PAYLOAD LENGTH 0 */ /*----------------------------------*/ /* ID LENGTH */ /*----------------------------------*/ /* TYPE */ /*----------------------------------*/ /* ID */ /*----------------------------------*/ /* PAYLOAD */ /************************************/ uint8_t * start = pNDEF; // start by considering payload length if(pRecord->PayloadLength <= 0xFF) pRecord->RecordFlags |= SR_Mask; else pRecord->RecordFlags &= ~SR_Mask; // Then start writing! *pNDEF++ = pRecord->RecordFlags; *pNDEF++ = pRecord->TypeLength; if (!(pRecord->RecordFlags & SR_Mask)) { *pNDEF++ = (pRecord->PayloadLength >> 24) & 0xFF; *pNDEF++ = (pRecord->PayloadLength >> 16) & 0xFF ; *pNDEF++ = (pRecord->PayloadLength >> 8) & 0xFF; } *pNDEF++ = (pRecord->PayloadLength) & 0xFF; if(pRecord->RecordFlags & IL_Mask) *pNDEF++ = (pRecord->IDLength); memcpy(pNDEF,pRecord->Type,pRecord->TypeLength); pNDEF += pRecord->TypeLength; if(pRecord->RecordFlags & IL_Mask) { memcpy(pNDEF,pRecord->ID,pRecord->IDLength); pNDEF += pRecord->IDLength; } memcpy(pNDEF,pRecord->PayloadBufferAdd,pRecord->PayloadLength); pNDEF += pRecord->PayloadLength; return (pNDEF - start); } /** * @brief This function return the length a record data (update SR flag if required) * @param pRecord : Structure with record information * @retval Length : Length of the data (in bytes) */ uint32_t NDEF_GetRecordLength( sRecordInfo_t *pRecord ) { // start by considering payload length if(pRecord->PayloadLength <= 0xFF) pRecord->RecordFlags |= SR_Mask; else pRecord->RecordFlags &= ~SR_Mask; // Then compute the length uint32_t length = 1 + // Flags 1 + // Type length ((pRecord->RecordFlags & SR_Mask)? 1 : 4) + // Payload length ((pRecord->RecordFlags & IL_Mask)? 1 : 0) + // ID length pRecord->TypeLength + // Type ((pRecord->RecordFlags & IL_Mask)? pRecord->IDLength : 0) + // ID pRecord->PayloadLength; // Payload; return length; } /** * @brief This function clears the NDEF file * @retval NDEF Status */ uint16_t NDEF_ClearNDEF(I2C* mi2cChannel) { return NDEF_WriteNDEF(0 , NULL, mi2cChannel); } /** * @} */ /** * @} */ /** * @} */ /******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/