ST Expansion SW Team / libNDEF

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lib_NDEF.cpp Source File

lib_NDEF.cpp

00001 /**
00002   ******************************************************************************
00003   * @file    lib_NDEF.c
00004   * @author  MMY Application Team
00005   * @version $Revision: 3210 $
00006   * @date    $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $
00007   * @brief   This file help to manage NDEF file, to parse and identify them.
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
00012   *
00013   * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
00014   * You may not use this file except in compliance with the License.
00015   * You may obtain a copy of the License at:
00016   *
00017   *        http://www.st.com/myliberty  
00018   *
00019   * Unless required by applicable law or agreed to in writing, software 
00020   * distributed under the License is distributed on an "AS IS" BASIS, 
00021   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
00022   * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
00023   * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
00024   * See the License for the specific language governing permissions and
00025   * limitations under the License.
00026   *
00027   ******************************************************************************
00028   */
00029 
00030 /* Includes ------------------------------------------------------------------*/
00031 #include "lib_NDEF.h"
00032 #include "lib_NDEF_Bluetooth.h"
00033 #include "lib_NDEF_Handover.h"
00034 #include "lib_NDEF_Wifi.h"
00035 #include "mbed.h"
00036 
00037 /** @addtogroup NFC_libraries
00038  *  @{
00039  *  @brief  <b>This is the library used to manage the content of the TAG (data)
00040  *          But also the specific feature of the tag, for instance
00041  *          password, gpo... </b>
00042  */
00043 
00044 
00045 /** @addtogroup libNFC_FORUM
00046   * @{
00047   * @brief  This part of the library manage data which follow NFC forum organisation.
00048   */
00049 
00050 /** @defgroup libNDEF_Private_Functions
00051   * @{
00052   */
00053 
00054 
00055 static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel );
00056 static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct );
00057 static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct );
00058 static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct );
00059 static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct );
00060 static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct );
00061 static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct );
00062 static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload );
00063 
00064 /** @brief This buffer is used to store the data sent/received by the TAG. */
00065 uint8_t NDEF_Buffer [NDEF_MAX_SIZE];
00066 /** @brief Size of the buffer used to build the NDEF messages. */
00067 uint32_t NDEF_Buffer_size = NDEF_MAX_SIZE;
00068 /** @brief This buffer is used when it's required to prepare a record before adding it to the NDEF_Buffer. */
00069 uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE];
00070 /** @brief Size of the buffer used when a record has to be prepared. */
00071 uint32_t NDEF_Record_Buffer_size = NDEF_RECORD_MAX_SIZE;
00072 
00073 /* In case of smart Poster composed with different record, 3 records supported so far */
00074 sRecordInfo_t SPRecordStruct1, SPRecordStruct2, SPRecordStruct3, SPRecordStruct4;
00075 sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD] = { &SPRecordStruct1, &SPRecordStruct2, &SPRecordStruct3, &SPRecordStruct4 };
00076 
00077 /**
00078   * @brief  This function checks that the tag contain a NDEF message.
00079   * @retval NDEF_OK : There is a NDEF file stored in tag.
00080   * @retval NDEF_ERROR : No NDEF in the tag.
00081   */
00082 static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel )
00083 {
00084   uint16_t FileSize;
00085 
00086   /* Check NDEF existence */
00087   NfcTag_GetLength(&FileSize, mi2cChannel);
00088   
00089   if( FileSize != 0 )
00090     return NDEF_OK;
00091   else
00092     return NDEF_ERROR;
00093 }
00094 
00095 /**
00096   * @brief  This function identify the type of record.
00097   * @param  pRecordStruct : pointer on the record structure to fill.
00098   * @param  pPayload : pointer on the payload.
00099   * @retval Status : Status of the operation.
00100   */
00101 static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload )
00102 {
00103   uint16_t status = NDEF_ERROR;
00104   uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
00105 
00106   /* Is ID length field present */
00107   if( (*pPayload) & IL_Mask )
00108   {
00109     IDLengthField = ID_LENGTH_FIELD;
00110   }
00111   else
00112   {
00113     IDLengthField = 0;
00114   }
00115 
00116   /* it's a SR */
00117   if( (*pPayload) & SR_Mask )
00118   {
00119     TypeNbByte = pPayload[1];
00120     PayloadLengthField = 1;
00121     if( IDLengthField == ID_LENGTH_FIELD )
00122       IDNbByte = pPayload[3];
00123     else
00124       IDNbByte = 0;
00125   }
00126   else
00127   {
00128     TypeNbByte = pPayload[1];
00129     PayloadLengthField = 4;
00130     if( IDLengthField == ID_LENGTH_FIELD )
00131       IDNbByte = pPayload[6];
00132     else
00133       IDNbByte = 0;
00134   }
00135 
00136   SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
00137 
00138   /* it's a SR */
00139   if( pPayload[0] & SR_Mask )
00140   {
00141     pRecordStruct->RecordFlags = pPayload[0];
00142     pRecordStruct->TypeLength = TypeNbByte;
00143     pRecordStruct->PayloadLength = pPayload[2];
00144     pRecordStruct->IDLength = IDNbByte;
00145     memcpy( pRecordStruct->Type, &pPayload[3+IDNbByte], TypeNbByte );
00146     memcpy( pRecordStruct->ID, &pPayload[3+IDNbByte+TypeNbByte], IDNbByte );
00147     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00148   }
00149   else
00150   {
00151     pRecordStruct->RecordFlags = pPayload[0];
00152     pRecordStruct->TypeLength = TypeNbByte;
00153     pRecordStruct->PayloadLength = ( ((uint32_t)pPayload[2]) << 24 ) |
00154                                    ( ((uint32_t)pPayload[3]) << 16 ) |
00155                                    ( ((uint32_t)pPayload[4]) << 8 )
00156                                     | pPayload[5] ;
00157     pRecordStruct->IDLength = IDNbByte;
00158     memcpy( pRecordStruct->Type, &pPayload[6+IDNbByte], TypeNbByte );
00159     memcpy( pRecordStruct->ID, &pPayload[6+IDNbByte+TypeNbByte], IDNbByte );
00160     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00161   }
00162 
00163   pRecordStruct->PayloadBufferAdd =  pPayload + SizeOfRecordHeader ;
00164 
00165   status = NDEF_ParseRecordHeader( pRecordStruct );
00166 
00167   return status;
00168 }
00169 
00170 /**
00171   * @brief  This function parse the record header and dispatch regarding TNF value.
00172   * @param  pRecordStruct : pointer on the record structure to fill.
00173   * @retval NDEF_OK : record identified and structure filled.
00174   * @retval NDEF_ERROR : Not supported.
00175   */
00176 static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct )
00177 {
00178   uint16_t status = NDEF_OK;
00179 
00180   switch( (pRecordStruct->RecordFlags & TNF_Mask) )
00181   {
00182     case TNF_WellKnown:
00183       NDEF_ParseWellKnownType( pRecordStruct );
00184       break;
00185 
00186     case TNF_MediaType:
00187       NDEF_ParseMediaType( pRecordStruct );
00188       break;
00189 
00190     case TNF_NFCForumExternal:
00191       NDEF_ParseForumExternalType( pRecordStruct);
00192       break;
00193 
00194   default:
00195       /* currently not supported or unknown*/
00196       pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00197       status = NDEF_ERROR;
00198   }
00199   return status;
00200 }
00201 
00202 /**
00203   * @brief  This function parse the Well Known type record.
00204   * @param  pRecordStruct : pointer on the record structure to fill.
00205   */
00206 static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct )
00207 {
00208   uint8_t* pPayload;
00209 
00210   pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
00211 
00212   if( !memcmp( &(pRecordStruct->Type), SMART_POSTER_TYPE_STRING, pRecordStruct->TypeLength ) )
00213   { 
00214     /* special case where   we have to parse others records */
00215     pRecordStruct->NDEF_Type = SMARTPOSTER_TYPE;
00216     NDEF_ParseSP( pRecordStruct );
00217   }
00218 
00219   else if( !memcmp( &(pRecordStruct->Type), URI_TYPE_STRING, pRecordStruct->TypeLength ) )
00220   { 
00221     /* it's an URI Type check if it's an URL or SMS or ... */
00222     /* check identifier */
00223     if( *pPayload == URI_ID_0x00 ) 
00224     {
00225       NDEF_ParseURI( pRecordStruct );
00226     }
00227     else if( (*pPayload > URI_ID_0x00) && (*pPayload < URI_RFU) ) 
00228     {
00229       /* email special case  */
00230       if( *pPayload == (uint8_t) URI_ID_0x06 )
00231       {
00232         pRecordStruct->NDEF_Type = URI_EMAIL_TYPE;
00233       }
00234       else
00235       {
00236         pRecordStruct->NDEF_Type = WELL_KNOWN_ABRIDGED_URI_TYPE;
00237       }
00238     }
00239     else
00240     {
00241       pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00242     }
00243   }
00244 
00245   else if( !memcmp( &(pRecordStruct->Type), TEXT_TYPE_STRING, pRecordStruct->TypeLength ) )
00246   {
00247     pRecordStruct->NDEF_Type = TEXT_TYPE;
00248   } else if ((!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_SELECT_TYPE_STR, pRecordStruct->TypeLength )) ||
00249             (!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_REQUEST_TYPE_STR, pRecordStruct->TypeLength ) ))
00250   {
00251      pRecordStruct->NDEF_Type = HANDOVER_TYPE;
00252   }
00253   else
00254     pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00255 }
00256 
00257 /**
00258   * @brief  This function parse the Media type record.
00259   * @param  pRecordStruct : pointer on the record structure to fill.
00260   */
00261 static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct )
00262 {
00263   if( !memcmp( &(pRecordStruct->Type), VCARD_TYPE_STRING, pRecordStruct->TypeLength ) )
00264     pRecordStruct->NDEF_Type = VCARD_TYPE;
00265   else if( !memcmp( &(pRecordStruct->Type), XVCARD_TYPE_STRING, pRecordStruct->TypeLength ) )
00266     pRecordStruct->NDEF_Type = VCARD_TYPE;
00267   else if( !memcmp( &(pRecordStruct->Type), XVCARD2_TYPE_STRING, pRecordStruct->TypeLength ) )
00268     pRecordStruct->NDEF_Type = VCARD_TYPE;
00269   else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BREDR_MIME_TYPE,  pRecordStruct->TypeLength))
00270     pRecordStruct->NDEF_Type = BT_TYPE;
00271   else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BLE_MIME_TYPE,  pRecordStruct->TypeLength))
00272     pRecordStruct->NDEF_Type = BLE_TYPE;
00273   else if (!memcmp(&pRecordStruct->Type, WIFITOKEN_TYPE_STRING,  pRecordStruct->TypeLength))
00274     pRecordStruct->NDEF_Type = URI_WIFITOKEN_TYPE;
00275   else
00276     pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00277 }
00278 
00279 /**
00280   * @brief  This function parse the Forum External type record.
00281   * @param  pRecordStruct : pointer on the record structure to fill.
00282   */
00283 static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct )
00284 {
00285   if( !memcmp( &(pRecordStruct->Type), M24SR_DISCOVERY_APP_STRING, pRecordStruct->TypeLength ) )
00286     pRecordStruct->NDEF_Type = M24SR_DISCOVERY_APP_TYPE;
00287   else
00288     pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00289 }
00290 
00291 /**
00292   * @brief  This function parse the URI type record.
00293   * @param  pRecordStruct : pointer on the record structure to fill.
00294   */
00295 static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct )
00296 {
00297   uint8_t* pPayload;
00298 
00299   pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
00300   pPayload++; /* to skip URI identifier first URI payload byte */
00301 
00302   if( !memcmp( pPayload, SMS_TYPE_STRING, strlen(SMS_TYPE_STRING) ) )
00303   {
00304     pRecordStruct->NDEF_Type = URI_SMS_TYPE;
00305   }
00306   else if( !memcmp( pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING) ) )
00307   {
00308     pRecordStruct->NDEF_Type = URI_GEO_TYPE;
00309   }
00310   else
00311     pRecordStruct->NDEF_Type = UNKNOWN_TYPE;
00312 }
00313 
00314 /**
00315   * @brief  This function parse the Smart Poster.
00316   * @param  pRecordStruct : pointer on the record structure to fill.
00317   */
00318 static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct )
00319 {
00320   uint8_t* pPayload;
00321   uint32_t PayloadSize = 0;
00322   uint32_t SPPayloadSize = 0;
00323   uint32_t OffsetInSPPayload = 0;
00324   uint32_t RecordPosition = 0;
00325   sRecordInfo_t *pSPRecordStruct;
00326 
00327   /* initialize variable with size of the payload and poiter on data */
00328   PayloadSize = pRecordStruct->PayloadLength;
00329 
00330   pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd );
00331 
00332   pSPRecordStruct = SPRecordStructAdd[0];
00333 
00334   /* Initailize the number of record find in the SP payload */
00335   pRecordStruct->NbOfRecordInSPPayload = 0;
00336 
00337   do
00338   {
00339     pSPRecordStruct = SPRecordStructAdd[RecordPosition];
00340     /* identify the record in the SP payload */
00341     if( NDEF_IdentifySPRecord( pSPRecordStruct, pPayload ) == NDEF_OK )
00342     {
00343       /* store add of structure that will contain the other record information */
00344       pRecordStruct->NbOfRecordInSPPayload++;
00345       pRecordStruct->SPRecordStructAdd[RecordPosition] = pSPRecordStruct;
00346 
00347       /* After SPRecord + First Record check if we are at the end of NDEF file */
00348       SPPayloadSize = pSPRecordStruct->PayloadLength;
00349 
00350       OffsetInSPPayload += pSPRecordStruct->PayloadOffset + SPPayloadSize;
00351       pPayload += OffsetInSPPayload;
00352     }
00353     else /* Recommended Action Record for example */
00354     {
00355       SPPayloadSize = 0;
00356     }
00357     RecordPosition++;
00358   }
00359   while( (OffsetInSPPayload < PayloadSize) && RecordPosition<SP_MAX_RECORD); /* there is another record */
00360 }
00361 
00362 /**
00363   * @}
00364   */
00365 
00366 /** @defgroup libNDEF_Public_Functions
00367   * @{
00368   */
00369 
00370 
00371 /**
00372   * @brief  This function identify the NDEF message stored in tag.
00373   * @param  pRecordStruct : Structure to fill with record information.
00374   * @param  pNDEF : pointer on the NDEF message data.
00375   * @retval NDEF_OK : record struct filled.
00376   * @retval NDEF_ERROR : record struct not updated.
00377   */
00378 uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF, I2C* mi2cChannel )
00379 {
00380   uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
00381 
00382   /* check NDEF present */
00383   if( NDEF_IsNDEFPresent(mi2cChannel) != NDEF_OK )
00384   {
00385     return NDEF_ERROR;
00386   }
00387 
00388   /* Read the NDEF file */
00389   NfcTag_ReadNDEF( pNDEF, mi2cChannel );
00390 
00391   /* Is ID length field present */
00392   if( (*pNDEF) & IL_Mask )
00393   {
00394     IDLengthField = ID_LENGTH_FIELD;
00395   }
00396   else
00397   {
00398     IDLengthField = 0;
00399   }
00400 
00401   /* it's a SR */
00402   if( (*pNDEF) & SR_Mask )
00403   {
00404     /* Analyse short record layout */
00405     TypeNbByte = pNDEF[1];
00406     PayloadLengthField = 1;
00407     if( IDLengthField == ID_LENGTH_FIELD )
00408       IDNbByte = pNDEF[3];
00409     else
00410       IDNbByte = 0;
00411   }
00412   else
00413   {
00414     /* Analyse normal record layout */
00415     TypeNbByte = pNDEF[1];
00416     PayloadLengthField = 4;
00417     if( IDLengthField == ID_LENGTH_FIELD )
00418       IDNbByte = pNDEF[6];
00419     else
00420       IDNbByte = 0;
00421   }
00422 
00423   SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
00424 
00425   /* Read record header */
00426   /* it's a SR */
00427   if( pNDEF[0] & SR_Mask )
00428   {
00429     pRecordStruct->RecordFlags = pNDEF[0];
00430     pRecordStruct->TypeLength = TypeNbByte;
00431     pRecordStruct->PayloadLength = pNDEF[2];
00432     pRecordStruct->IDLength = IDNbByte;
00433     memcpy( pRecordStruct->Type, &pNDEF[3+IDNbByte], TypeNbByte );
00434     memcpy( pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte], IDNbByte );
00435     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00436   }
00437   else
00438   {
00439     pRecordStruct->RecordFlags = pNDEF[0];
00440     pRecordStruct->TypeLength = TypeNbByte;
00441     pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) |
00442                                    ( ((uint32_t)pNDEF[3]) << 16 ) |
00443                                    ( ((uint32_t)pNDEF[4]) << 8 )
00444                                     | pNDEF[5] ;
00445     pRecordStruct->IDLength = IDNbByte;
00446     memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte );
00447     memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte );
00448     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00449   }
00450 
00451   pRecordStruct->PayloadBufferAdd = pNDEF;
00452 
00453   NDEF_ParseRecordHeader( pRecordStruct );
00454 
00455   return NDEF_OK;
00456 }
00457 
00458 /**
00459   * @brief  This function read the NDEF content of the TAG.
00460   * @param  pNDEF : pointer on the buffer to store NDEF data.
00461   * @retval NDEF_OK : NDEF file data retrieve and store in the buffer.
00462   * @retval NDEF_ERROR : not able to read NDEF from tag.
00463   * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag.
00464   * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
00465   * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
00466   * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read.
00467   */
00468 uint16_t NDEF_ReadNDEF( uint8_t* pNDEF, I2C* mi2cChannel )
00469 {
00470    return NfcTag_ReadNDEF( pNDEF, mi2cChannel );
00471 }
00472 
00473 
00474 
00475 /**
00476   * @brief  This function read the NDEF size of the TAG.
00477   * @param  Size : pointer to a 16-bit Size (in bytes) to be returned.
00478   * @retval NDEF_OK : NDEF file data retrieve and store in the buffer.
00479   * @retval NDEF_ERROR : not able to read NDEF from tag.
00480   * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag.
00481   * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
00482   * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
00483   * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read.
00484   */
00485 uint16_t NDEF_getNDEFSize(uint16_t* Size, I2C* mi2cChannel)
00486 {
00487   return NfcTag_GetLength(Size, mi2cChannel);
00488 }
00489 /**
00490   * @brief  This function write the NDEF in the TAG.
00491   * @param  pNDEF : pointer on the buffer containing the NDEF data.
00492   * @retval NDEF_OK : NDEF file data written in the tag.
00493   * @retval NDEF_ERROR : not able to store NDEF in tag.
00494   * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
00495   * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
00496   * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
00497   * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
00498   */
00499 uint16_t NDEF_WriteNDEF( uint16_t NDEF_Size, uint8_t *pNDEF, I2C* mi2cChannel )
00500 {
00501   return NfcTag_WriteNDEF( NDEF_Size, pNDEF, mi2cChannel );
00502 
00503 }
00504 
00505 /**
00506   * @brief  This function append the record to an the NDEF in the TAG.
00507   * @param  pRecord : pointer on the record with data to be written.
00508   * @retval NDEF_OK : NDEF file data written in the tag.
00509   * @retval NDEF_ERROR : not able to store NDEF in tag.
00510   * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag.
00511   * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present.
00512   * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory.
00513   * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write.
00514   */
00515 uint16_t NDEF_AppendRecord(sRecordInfo_t  *Record, I2C* mi2cChannel )
00516 {
00517   uint16_t status;
00518   uint16_t NDEF_Size = 0;
00519   uint8_t* pData = NDEF_Buffer;
00520 
00521   status = NDEF_getNDEFSize(&NDEF_Size, mi2cChannel);
00522   if(status != NDEF_OK)  return status ;
00523 
00524   if(NDEF_Size != 0)
00525   {
00526     // There are already records in the NDEF
00527     Record->RecordFlags &= ~MB_Mask;
00528 
00529     status = NfcTag_ReadNDEF(pData, mi2cChannel);
00530     if(status != NDEF_OK)  return status ;
00531   
00532     uint8_t* pNdefRecord;
00533     sRecordInfo_t   LastRecord;
00534     do {
00535       pNdefRecord = pData;
00536       NDEF_IdentifyBuffer(&LastRecord,pData);
00537       pData  += LastRecord.PayloadOffset + LastRecord.PayloadLength;
00538    // TO DO: add a security condition to avoid infinite loop if NDEF file is corrupted
00539     } while(!(LastRecord.RecordFlags & ME_Mask));
00540     LastRecord.RecordFlags &= ~ME_Mask;
00541     *pNdefRecord = LastRecord.RecordFlags;
00542   } else {
00543     // This will be the first message in memory
00544     Record->RecordFlags |= MB_Mask;
00545   }
00546   Record->RecordFlags |= ME_Mask;
00547   uint32_t RecordLength = NDEF_WriteRecord(Record,pData, mi2cChannel);
00548   
00549 
00550   return NfcTag_WriteNDEF( NDEF_Size + RecordLength, NDEF_Buffer, mi2cChannel );
00551 
00552 }
00553 
00554 
00555 
00556 /**
00557   * @brief  This function identify the NDEF message stored in tag.
00558   * @param  pRecordStruct : Structure to fill with record information.
00559   * @param  pNDEF : pointer on the NDEF message data.
00560   * @retval NDEF_OK : record struct filled.
00561   * @retval NDEF_ERROR : record struct not updated.
00562   */
00563 uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF )
00564 {
00565   uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte;
00566 
00567   /* Is ID length field present */
00568   if( (*pNDEF) & IL_Mask )
00569   {
00570     IDLengthField = ID_LENGTH_FIELD;
00571   }
00572   else
00573   {
00574     IDLengthField = 0;
00575   }
00576 
00577   /* it's a SR */
00578   if( (*pNDEF) & SR_Mask )
00579   {
00580     /* Analyse short record layout */
00581     TypeNbByte = pNDEF[1];
00582     PayloadLengthField = 1;
00583     if( IDLengthField == ID_LENGTH_FIELD )
00584       IDNbByte = pNDEF[3];
00585     else
00586       IDNbByte = 0;
00587   }
00588   else
00589   {
00590     /* Analyse normal record layout */
00591     TypeNbByte = pNDEF[1];
00592     PayloadLengthField = 4;
00593     if( IDLengthField == ID_LENGTH_FIELD )
00594       IDNbByte = pNDEF[6];
00595     else
00596       IDNbByte = 0;
00597   }
00598 
00599   SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte;
00600 
00601   /* it's a SR */
00602   if( pNDEF[0] & SR_Mask )
00603   {
00604     pRecordStruct->RecordFlags = pNDEF[0];
00605     pRecordStruct->TypeLength = TypeNbByte;
00606     pRecordStruct->PayloadLength = pNDEF[2];
00607     pRecordStruct->IDLength = IDNbByte;
00608     memcpy( pRecordStruct->Type, &pNDEF[3+IDLengthField], TypeNbByte );
00609     memcpy( pRecordStruct->ID, &pNDEF[3+IDLengthField+TypeNbByte], IDNbByte );
00610     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00611   }
00612   else
00613   {
00614     pRecordStruct->RecordFlags = pNDEF[0];
00615     pRecordStruct->TypeLength = TypeNbByte;
00616     pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) |
00617                                    ( ((uint32_t)pNDEF[3]) << 16 ) |
00618                                    ( ((uint32_t)pNDEF[4]) << 8 )
00619                                     | pNDEF[5] ;
00620     pRecordStruct->IDLength = IDNbByte;
00621     memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte );
00622     memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte );
00623     pRecordStruct->PayloadOffset = SizeOfRecordHeader;
00624   }
00625 
00626   pRecordStruct->PayloadBufferAdd = &pNDEF[pRecordStruct->PayloadOffset];
00627 
00628   NDEF_ParseRecordHeader( pRecordStruct );
00629 
00630   return NDEF_OK;
00631 }
00632 
00633 /**
00634   * @brief  This function writes a record into a NDEF buffer. (update SR flag if required)
00635   * @param  pRecord : Structure with record information to be written.
00636   * @param  pNDEF : pointer on the NDEF buffer.
00637   * @retval Length : Length of the written data (in bytes)
00638   */
00639 uint32_t NDEF_WriteRecord( sRecordInfo_t *pRecord, uint8_t* pNDEF, I2C* mi2cChannel )
00640 {
00641   /************************************/
00642 /*  7 |  6 |  5 |  4 |  3 | 2  1  0 */
00643 /*----------------------------------*/
00644 /* MB   ME   CF   SR   IL    TNF    */  
00645 /*----------------------------------*/
00646 /*          TYPE LENGTH             */
00647 /*----------------------------------*/
00648 /*        PAYLOAD LENGTH 3          */  
00649 /*----------------------------------*/
00650 /*        PAYLOAD LENGTH 2          */  
00651 /*----------------------------------*/
00652 /*        PAYLOAD LENGTH 1          */  
00653 /*----------------------------------*/
00654 /*        PAYLOAD LENGTH 0          */
00655 /*----------------------------------*/
00656 /*           ID LENGTH              */  
00657 /*----------------------------------*/
00658 /*             TYPE                 */  
00659 /*----------------------------------*/
00660 /*              ID                  */  
00661 /*----------------------------------*/
00662 /*           PAYLOAD                */  
00663 /************************************/
00664   uint8_t * start = pNDEF;
00665 
00666   // start by considering payload length
00667   if(pRecord->PayloadLength <= 0xFF)
00668     pRecord->RecordFlags |= SR_Mask;
00669   else
00670     pRecord->RecordFlags &= ~SR_Mask;
00671   
00672   // Then start writing!
00673   *pNDEF++ = pRecord->RecordFlags;
00674 
00675   *pNDEF++ = pRecord->TypeLength;
00676 
00677   if (!(pRecord->RecordFlags & SR_Mask))
00678   {
00679     *pNDEF++ = (pRecord->PayloadLength >> 24) & 0xFF;
00680     *pNDEF++ = (pRecord->PayloadLength >> 16) & 0xFF ;
00681     *pNDEF++ = (pRecord->PayloadLength >> 8) & 0xFF;
00682   }
00683   *pNDEF++ = (pRecord->PayloadLength) & 0xFF;
00684 
00685   if(pRecord->RecordFlags & IL_Mask)
00686     *pNDEF++ = (pRecord->IDLength);
00687   
00688   memcpy(pNDEF,pRecord->Type,pRecord->TypeLength);
00689   pNDEF += pRecord->TypeLength;
00690 
00691   if(pRecord->RecordFlags & IL_Mask)
00692   {
00693     memcpy(pNDEF,pRecord->ID,pRecord->IDLength);
00694     pNDEF += pRecord->IDLength;
00695   }
00696 
00697   memcpy(pNDEF,pRecord->PayloadBufferAdd,pRecord->PayloadLength);
00698   pNDEF += pRecord->PayloadLength;
00699 
00700   return (pNDEF - start);
00701 }
00702 
00703 /**
00704   * @brief  This function return the length a record data (update SR flag if required)
00705   * @param  pRecord : Structure with record information
00706   * @retval Length : Length of the data (in bytes)
00707   */
00708 uint32_t NDEF_GetRecordLength( sRecordInfo_t *pRecord )
00709 {
00710   // start by considering payload length
00711   if(pRecord->PayloadLength <= 0xFF)
00712     pRecord->RecordFlags |= SR_Mask;
00713   else
00714     pRecord->RecordFlags &= ~SR_Mask;
00715   
00716   // Then compute the length
00717   uint32_t length = 1 +                                                         // Flags
00718                     1 +                                                         // Type length
00719                     ((pRecord->RecordFlags & SR_Mask)? 1 : 4) +                 // Payload length
00720                     ((pRecord->RecordFlags & IL_Mask)? 1 : 0) +                 // ID length
00721                     pRecord->TypeLength +                                       // Type
00722                     ((pRecord->RecordFlags & IL_Mask)? pRecord->IDLength : 0) + // ID 
00723                     pRecord->PayloadLength;                                     // Payload;
00724   
00725   return length;
00726 }
00727 
00728 /**
00729   * @brief  This function clears the NDEF file
00730   * @retval NDEF Status
00731   */
00732 uint16_t NDEF_ClearNDEF(I2C* mi2cChannel)
00733 {
00734   return NDEF_WriteNDEF(0 , NULL, mi2cChannel);
00735 }
00736 
00737 /**
00738   * @}
00739   */
00740 
00741 /**
00742   * @}
00743   */
00744 
00745 /**
00746   * @}
00747   */
00748 
00749 /******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/