Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-nfc04a1 Wiagro-Lanza34-XDot
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>© 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****/
Generated on Fri Jul 15 2022 08:51:12 by
1.7.2