libNDEF library for the STMicroelectronics X-NUCLEO-NFC04A1

Dependents:   mbed-os-nfc04a1 Wiagro-Lanza34-XDot

Revision:
0:de13951f30f6
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Vcard.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib_NDEF_Vcard.cpp	Thu Nov 14 10:34:11 2019 +0000
@@ -0,0 +1,620 @@
+/**
+  ******************************************************************************
+  * @file    lib_NDEF_Vcard.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 that represent Vcard.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; 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_Vcard.h"
+
+
+/** @addtogroup lib_NDEF_Vcard
+  * @ingroup libNDEF
+  * @{
+  * @brief  This part of the library manage the data which follow NFC forum organisation.
+  */
+
+/*  This buffer contains the data sent/received by TAG */
+extern uint8_t NDEF_Buffer [];
+
+static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString );
+static void NDEF_ExtractVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct );
+
+/**
+  * @brief  This function extracts a Vcard particular property from a vCard.
+  * @param  pPayload      Pointer on the vCard payload data of the vCard record.
+  * @param  PayloadSize   Number of bytes in the vCard payload.
+  * @param  pKeyWord      Pointer on the vCard property keyword to look for.
+  * @param  SizeOfKeyWord Number of bytes of the vCard property keyword we are looking for.
+  * @param  pString       Pointer on a string used to return the vCard property read.
+  */
+static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString )
+{
+  uint8_t* pLastByteAdd, *pLook4Word, *pEndString;
+
+  /* First character force to NULL in case not matching found */
+  *pString = 0;
+  
+  /* Interresting information are stored before picture if any */
+  /* Moreover picture is not used in this demonstration SW */
+  pLastByteAdd = pPayload;
+  while( memcmp( pLastByteAdd, JPEG, JPEG_STRING_SIZE ) && (pLastByteAdd < (pPayload + PayloadSize)) )
+  {
+    pLastByteAdd++;
+  }
+
+  pLook4Word = pPayload;
+  while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) )
+  {
+    pLook4Word++;
+  }
+
+  /* Word found */
+  if( pLook4Word != pLastByteAdd )
+  {
+    pLook4Word += SizeOfKeyWord;
+    pEndString = pLook4Word;
+    while( memcmp( pEndString, LIMIT, LIMIT_STRING_SIZE ) && (pEndString < pLastByteAdd) )
+    {
+      pEndString++;
+    }
+    if( pEndString != pLastByteAdd )
+    {
+      memcpy( pString, pLook4Word, pEndString-pLook4Word );
+      /* add end of string character */
+      pString += pEndString - pLook4Word;
+      *pString = '\0';
+    }
+  }	
+}
+
+/**
+  * @brief  This function reads a Vcard record and stores data in a `sVcardInfo` structure.
+  * @param  pRecordStruct Pointer on the vCard record structure.
+  * @param  pVcardStruct  Pointer on the `sCardInfo` structure to fill.
+  */
+static void NDEF_ExtractVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct )
+{
+  uint32_t PayloadSize;
+  uint8_t* pPayload;
+
+
+  PayloadSize = pRecordStruct->PayloadLength;
+
+  /* Read record header */
+  pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd);
+
+  NDEF_FillVcardStruct( pPayload, PayloadSize, VERSION, VERSION_STRING_SIZE, (uint8_t*)(pVcardStruct->Version) );
+  if( !memcmp( pVcardStruct->Version, VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE ) )
+  {
+    NDEF_FillVcardStruct( pPayload, PayloadSize, FIRSTNAME, FIRSTNAME_STRING_SIZE, (uint8_t*)(pVcardStruct->FirstName) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, TITLE, TITLE_STRING_SIZE, (uint8_t*)(pVcardStruct->Title) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, ORG, ORG_STRING_SIZE, (uint8_t*)(pVcardStruct->Org) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeAddress) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, GEN_ADDRESS, strlen(GEN_ADDRESS), (uint8_t*)(pVcardStruct->Address) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkAddress) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_TEL, HOME_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeTel) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_TEL, WORK_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkTel) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, CELL_TEL, CELL_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->CellTel) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_EMAIL, HOME_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeEmail) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, GEN_EMAIL, strlen(GEN_EMAIL), (uint8_t*)(pVcardStruct->Email) );
+    NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_EMAIL, WORK_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkEmail) );
+  }
+  else if( !memcmp( pVcardStruct->Version, VCARD_VERSION_3_0, VCARD_VERSION_3_0_SIZE ) )
+  {
+    /* need to be implemented */
+  }
+  else
+  {
+    /* maybe new version but not supported in this sw */
+  }
+
+}
+
+/**
+  * @brief  This function reads a Vcard record and stores data in a `sVcardInfo` structure.
+  * @param  pRecordStruct Pointer on the vCard record structure.
+  * @param  pVcardStruct  Pointer on the `sCardInfo` structure to fill.
+  * @retval NDEF_OK     The Vcard information has been retrieved.
+  * @retval NDEF_ERROR  Not able to retrieve the Vcard information.
+  */
+uint16_t NDEF_ReadVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct )
+{
+  uint16_t status = NDEF_ERROR;
+
+  if( pRecordStruct->NDEF_Type == VCARD_TYPE )
+  {
+    NDEF_ExtractVcard( pRecordStruct, pVcardStruct );
+    status = NDEF_OK;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  This function writes a NDEF message to the NFC tag with the Vcard data given in a `sVcardInfo` structure.
+  * @param  pVcardStruct Pointer on a `sVcardInfo` structure containing the Vcard information.
+  * @retval NDEF_OK                     NDEF file data written in the tag.
+  * @retval NDEF_ERROR                  Not able to store the 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_WriteVcard( sVcardInfo *pVcardStruct, I2C* mi2cChannel )
+{
+  uint16_t status = NDEF_ERROR, Offset = 0;
+
+  NDEF_PrepareVcardMessage( pVcardStruct, NDEF_Buffer, &Offset );
+
+  status = NfcTag_WriteNDEF( Offset , NDEF_Buffer, mi2cChannel );
+
+  return status;
+}
+
+/**
+  * @brief  This function computes the size of a Vcard record from the data given in the `sVcardInfo` structure.
+  * @param  pVcardStruct Pointer on a `sVcardInfo` structure containing the Vcard information.
+  * @return vCard record data size in bytes (excluding record metadata).
+  */
+uint32_t NDEF_GetVcardLength( sVcardInfo *pVcardStruct)
+{
+
+  uint32_t PayloadSize = 0;
+
+  /* "BEGIN:VCARD\r\n" */
+  PayloadSize += BEGIN_STRING_SIZE;
+  PayloadSize += VCARD_STRING_SIZE;
+  PayloadSize += LIMIT_STRING_SIZE;
+
+  /* "VERSION:2.1\r\n" */
+  PayloadSize += VERSION_STRING_SIZE;
+  PayloadSize += VCARD_VERSION_2_1_SIZE;
+  PayloadSize += LIMIT_STRING_SIZE;
+
+  /* "N:\r\n" */
+  if(*pVcardStruct->Name != '\0')
+  {
+  PayloadSize += VCARD_NAME_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->Name );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  /* "FN:\r\n" */
+  if(*pVcardStruct->FirstName != '\0')
+  {
+    PayloadSize += FIRSTNAME_STRING_SIZE;
+    PayloadSize += strlen( pVcardStruct->FirstName );
+    PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Title != '\0')
+  {
+  /* "TITLE:\r\n" */
+  PayloadSize += TITLE_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->Title );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Org != '\0')
+  {
+  /* "ORG:\r\n" */
+  PayloadSize += ORG_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->Org );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Url != '\0')
+  {
+  /* "URL:\r\n" */
+  PayloadSize += URL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->Url );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeAddress != '\0')
+  {
+  /* "ADR;HOME:\r\n" */
+  PayloadSize += HOME_ADDRESS_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->HomeAddress );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkAddress != '\0')
+  {
+  /* "ADR;WORK:\r\n" */
+  PayloadSize += WORK_ADDRESS_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->WorkAddress );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeTel != '\0')
+  {
+  /* "TEL;HOME:\r\n" */
+  PayloadSize += HOME_TEL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->HomeTel );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkTel != '\0')
+  {
+  /* "TEL;WORK:\r\n" */
+  PayloadSize += WORK_TEL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->WorkTel );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->CellTel != '\0')
+  {
+  /* "TEL;CELL:\r\n" */
+  PayloadSize += CELL_TEL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->CellTel );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeEmail != '\0')
+  {
+  /* "EMAIL;HOME:\r\n" */
+  PayloadSize += HOME_EMAIL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->HomeEmail );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkEmail != '\0')
+  {
+  /* "EMAIL;WORK:\r\n" */
+  PayloadSize += WORK_EMAIL_STRING_SIZE;
+  PayloadSize += strlen( pVcardStruct->WorkEmail );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  /* "END:VCARD\r\n" */
+  PayloadSize += END_STRING_SIZE;
+  PayloadSize += VCARD_STRING_SIZE;
+ /* PayloadSize += LIMIT_STRING_SIZE;*/
+
+  return PayloadSize;
+  
+}
+
+/**
+  * @brief  This function write the NDEF file with the Vcard data given in the structure.
+  * @param  pVcardStruct : pointer on structure that contain the Vcard information.
+  * @param  pNDEFMessage : pointer on the NDEF message.
+  * @param  size : to store the size of the NDEF message generated.
+  */
+void NDEF_PrepareVcardMessage( sVcardInfo *pVcardStruct, uint8_t *pNDEFMessage, uint16_t *size )
+{
+
+  uint32_t PayloadSize = 0;
+
+  /* Vcard Record Header */
+/************************************/
+/*  7 |  6 |  5 |  4 |  3 | 2  1  0 */
+/*----------------------------------*/
+/* MB   ME   CF   SR   IL    TNF    */  /* <---- CF=0, IL=0 and SR=0 TNF=2 NFC Forum Media type*/
+/*----------------------------------*/
+/*          TYPE LENGTH             */
+/*----------------------------------*/
+/*        PAYLOAD LENGTH 3          */
+/*----------------------------------*/
+/*        PAYLOAD LENGTH 2          */
+/*----------------------------------*/
+/*        PAYLOAD LENGTH 1          */
+/*----------------------------------*/
+/*        PAYLOAD LENGTH 0          */
+/*----------------------------------*/
+/*           ID LENGTH              */  /* <---- Not Used  */
+/*----------------------------------*/
+/*              TYPE                */
+/*----------------------------------*/
+/*               ID                 */  /* <---- Not Used  */
+/************************************/
+
+  /* As we don't have embedded a jpeg encoder/decoder in this firmware */
+  /* We have made the choice to manage only string content of the vCard */
+  /* For demonstration purpose in order to fill the 8kB of the M24SR */
+  /* We have embedded a NDEF vCard in the STM32 to be able to fill M24SR */
+
+  /* fill record header */
+  uint32_t length = NDEF_GetVcardLength(pVcardStruct);
+  if(length >= 0xFF)
+  {
+  pNDEFMessage[0] = 0xC2;   /* Record Flag */
+  pNDEFMessage[1] = XVCARD_TYPE_STRING_LENGTH;
+  pNDEFMessage[5] = length & 0xff; 
+  pNDEFMessage[4] = (length>>8) & 0xff;
+  pNDEFMessage[3] = (length>>16) & 0xff;
+  pNDEFMessage[2] = length>>24;	
+  memcpy( &pNDEFMessage[6], XVCARD_TYPE_STRING, XVCARD_TYPE_STRING_LENGTH );
+
+  /* Payload is positionned in the NDEF after record header */
+  PayloadSize = 6 + XVCARD_TYPE_STRING_LENGTH;
+  } else {
+  pNDEFMessage[0] = 0xD2;   /* Record Flag */
+  pNDEFMessage[1] = XVCARD_TYPE_STRING_LENGTH;
+  pNDEFMessage[2] =  length;
+  memcpy( &pNDEFMessage[3], XVCARD_TYPE_STRING, XVCARD_TYPE_STRING_LENGTH );
+
+  /* Payload is positionned in the NDEF after record header */
+  PayloadSize = 3 + XVCARD_TYPE_STRING_LENGTH;
+  }
+
+  /* "BEGIN:VCARD\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], BEGIN, BEGIN_STRING_SIZE );
+  PayloadSize += BEGIN_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], VCARD,VCARD_STRING_SIZE );
+  PayloadSize += VCARD_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+
+  /* "VERSION:2.1\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], VERSION, VERSION_STRING_SIZE );
+  PayloadSize += VERSION_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE );
+  PayloadSize += VCARD_VERSION_2_1_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+
+  /* "N:\r\n" */
+  if(*pVcardStruct->Name != '\0')
+  {
+  memcpy( &pNDEFMessage[PayloadSize], VCARD_NAME, VCARD_NAME_STRING_SIZE );
+  PayloadSize += VCARD_NAME_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Name, strlen(pVcardStruct->Name) );
+  PayloadSize += strlen( pVcardStruct->Name );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  /* "FN:\r\n" */
+  if(*pVcardStruct->FirstName != '\0')
+  {
+  memcpy( &pNDEFMessage[PayloadSize], FIRSTNAME, FIRSTNAME_STRING_SIZE );
+  PayloadSize += FIRSTNAME_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->FirstName, strlen(pVcardStruct->FirstName) );
+  PayloadSize += strlen( pVcardStruct->FirstName );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeTel != '\0')
+  {
+
+  /* "TEL;HOME:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], HOME_TEL, HOME_TEL_STRING_SIZE );
+  PayloadSize += HOME_TEL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeTel, strlen(pVcardStruct->HomeTel) );
+  PayloadSize += strlen( pVcardStruct->HomeTel );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkTel != '\0')
+  {
+
+  /* "TEL;WORK:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], WORK_TEL, WORK_TEL_STRING_SIZE );
+  PayloadSize += WORK_TEL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkTel, strlen(pVcardStruct->WorkTel) );
+  PayloadSize += strlen( pVcardStruct->WorkTel );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->CellTel != '\0')
+  {
+
+  /* "TEL;CELL:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], CELL_TEL, CELL_TEL_STRING_SIZE );
+  PayloadSize += CELL_TEL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->CellTel, strlen(pVcardStruct->CellTel) );
+  PayloadSize += strlen( pVcardStruct->CellTel );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeEmail != '\0')
+  {
+
+  /* "EMAIL;HOME:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], HOME_EMAIL, HOME_EMAIL_STRING_SIZE );
+  PayloadSize += HOME_EMAIL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeEmail, strlen(pVcardStruct->HomeEmail) );
+  PayloadSize += strlen( pVcardStruct->HomeEmail );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkEmail != '\0')
+  {
+
+  /* "EMAIL;WORK:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], WORK_EMAIL, WORK_EMAIL_STRING_SIZE );
+  PayloadSize += WORK_EMAIL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkEmail, strlen(pVcardStruct->WorkEmail) );
+  PayloadSize += strlen( pVcardStruct->WorkEmail );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->HomeAddress != '\0')
+  {
+
+  /* "ADR;HOME:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE );
+  PayloadSize += HOME_ADDRESS_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeAddress, strlen(pVcardStruct->HomeAddress) );
+  PayloadSize += strlen( pVcardStruct->HomeAddress );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->WorkAddress != '\0')
+  {
+
+  /* "ADR;WORK:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE );
+  PayloadSize += WORK_ADDRESS_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkAddress, strlen(pVcardStruct->WorkAddress) );
+  PayloadSize += strlen( pVcardStruct->WorkAddress );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Org != '\0')
+  {
+
+  /* "ORG:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], ORG, ORG_STRING_SIZE );
+  PayloadSize += ORG_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Org, strlen(pVcardStruct->Org) );
+  PayloadSize += strlen( pVcardStruct->Org );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Title != '\0')
+  {
+  /* "TITLE:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], TITLE, TITLE_STRING_SIZE );
+  PayloadSize += TITLE_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Title, strlen(pVcardStruct->Title) );
+  PayloadSize += strlen( pVcardStruct->Title );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+  if(*pVcardStruct->Url != '\0')
+  {
+  /* "URL:\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], URL, URL_STRING_SIZE );
+  PayloadSize += URL_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Url, strlen(pVcardStruct->Url) );
+  PayloadSize += strlen( pVcardStruct->Url );
+  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+  PayloadSize += LIMIT_STRING_SIZE;
+  }
+
+  /* "END:VCARD\r\n" */
+  memcpy( &pNDEFMessage[PayloadSize], END, END_STRING_SIZE );
+  PayloadSize += END_STRING_SIZE;
+  memcpy( &pNDEFMessage[PayloadSize], VCARD, VCARD_STRING_SIZE );
+  PayloadSize += VCARD_STRING_SIZE;
+//  memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE );
+//  PayloadSize += LIMIT_STRING_SIZE;
+
+  *size = (uint16_t)(PayloadSize); /* Must not count the 2 byte that represent the NDEF size */
+/*
+  PayloadSize -= 6 + VCARD_TYPE_STRING_LENGTH;
+
+  pNDEFMessage[2] = (PayloadSize & 0xFF000000) >> 24;
+  pNDEFMessage[3] = (PayloadSize & 0x00FF0000) >> 16;
+  pNDEFMessage[4] = (PayloadSize & 0x0000FF00) >> 8;
+  pNDEFMessage[5] = PayloadSize & 0x000000FF;
+  */
+}
+
+
+/**
+  * @brief  This function extracts binary data from a base64 representation.
+  * @param  input64 : pointer on the input data in base64.
+  * @param  binary : returned binary data.
+  * @return Updated pointer on the input64 buffer (normal increment is 4 base64 char for 3 bytes of binary data, but special char are ignored)
+*/
+static uint8_t* from_base64(uint8_t *input64, uint32_t* binary)
+{
+  /* Read 4 base64 character & translate them into 3 bytes binary */ 
+  *binary = 0;
+  uint8_t base64_6bits;
+  int i = 0;
+  while(i<4)
+  {
+
+    if((*input64 >= 'A') && (*input64 <= 'Z'))
+    {
+      base64_6bits = *(input64++) - 'A';
+    } else if ((*input64 >= 'a') && (*input64 <= 'z'))
+    {
+      base64_6bits = *(input64++) - 'a' + 26;
+    } else if ((*input64 >= '0') && (*input64 <= '9')) {
+      base64_6bits = *(input64++) - '0' + 52;
+    } else if (*input64 == '+')
+    {
+      base64_6bits = 62;
+      input64++;
+    } else if (*input64 == '/')
+    {
+      base64_6bits = 63;  
+      input64++;
+    } else if (*input64 == '=') {
+      base64_6bits = 0;
+      input64++;
+    } else {
+      input64++;
+      continue;
+    }
+    
+    *binary |= base64_6bits << (6*(3-i));
+    i++;
+  }
+  *binary = ((*binary & 0xFF0000)>>16) | ((*binary & 0xFF)<<16) | (*binary & 0xFF00);
+  return input64;
+}
+
+
+/**
+  * @brief  This function return the picture stored in a VCARD.
+  * @param  pPayload : pointer on the payload data of the NDEF message.
+  * @param  PayloadSize : number of data in the payload.
+  * @param  pPict : Pointer on the dpicture buffer (must be big enough to contain the picture - warning: no check is done in the function).
+ */
+int NDEF_getVcardPicture( uint8_t* pPayload, uint32_t PayloadSize,  uint8_t* pPict )
+{
+  uint8_t* pSrcPict;
+
+  
+  /* Let's find the picture */
+  pSrcPict = pPayload;
+  while( memcmp( pSrcPict, JPEG, JPEG_STRING_SIZE ) && (pSrcPict < (pPayload + PayloadSize)) )
+  {
+    pSrcPict++;
+  }
+  while( (*pSrcPict != ':') && (pSrcPict < (pPayload + PayloadSize)) )
+  {
+    pSrcPict++;
+  }
+  /* Picture start at next char */
+  pSrcPict++;
+
+  
+  /* Word found */
+  while( memcmp( pSrcPict, LIMIT, LIMIT_STRING_SIZE ) && (pSrcPict < (pPayload + PayloadSize) ) )
+    {
+      uint32_t binary24;
+      pSrcPict = from_base64(pSrcPict, &binary24);
+      /* copy the 3 bytes read from the base64 data */
+      memcpy( pPict, &binary24, 3);
+      pPict += 3;
+      /* Ignore any line breaks */
+      while (*pSrcPict == 0x0A)
+      {
+        pSrcPict++;
+      }
+    }
+    
+    if(pSrcPict >= (pPayload + PayloadSize))
+    {
+      /* problem when parsing the picture */
+      return 1;
+    } else {
+      /* picture found */
+      return 0;
+    }
+}
+
+/**
+  * @}
+  */
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/