X_NUCLEO_NFC02A1 library for M24LR
Dependencies: ST_INTERFACES
Dependents: HelloWorld_NFC02A1_mbedOS HelloWorld_NFC02A1laatste HelloWorld_NFC02A1
Fork of X_NUCLEO_NFC02A1 by
NDefNfcTagM24LR.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file NdefNfcTagM24LR.cpp 00004 * @author AMG Central Lab 00005 * @version V2.0.0 00006 * @date 19 May 2017 00007 * @brief Wrapper class of the NDefLib library to write/read NDEF messages. 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 00039 #include <cmath> 00040 #include "NDefNfcTagM24LR.h" 00041 00042 00043 /* wait 1sec, driver is configured to let 200ms for command to complete */ 00044 /* which is enough for all commands except GetSession if RF session is already opened */ 00045 /* Smartphone generally releases the session within the second, anyway the user can modify this value */ 00046 #define OPENSESSION_NTRIALS 5 00047 00048 #define CC_FILE_LENGTH_BYTE 15 00049 00050 00051 #define NFCT5_MAGICNUMBER_E1_CCFILE 0xE1 00052 #define NFCT5_MAGICNUMBER_E2_CCFILE 0xE2 00053 #define NFCT5_EXTENDED_CCFILE 0xFF 00054 #define NFCT5_VERSION_V1_0 0x40 00055 #define NFCT5_READ_ACCESS 0x0C 00056 #define NFCT5_WRITE_ACCESS 0x03 00057 00058 #define NFCT5_NDEF_MSG_TLV 0x03 00059 #define NFCT5_PROPRIETARY_TLV 0xFD 00060 #define NFCT5_TERMINATOR_TLV 0xFE 00061 #define NFCT5_3_BYTES_L_TLV 0xFF 00062 00063 00064 #define NDEF_MAX_SIZE NFC_DEVICE_MAX_NDEFMEMORY 00065 00066 #define NDEF_SIZE_OFFSET 0 00067 #define FIRST_RECORD_OFFSET 2 00068 00069 #ifndef MIN 00070 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 00071 #endif 00072 00073 #define NFCTAG_4M_SIZE 0x200 00074 #define NFCTAG_16M_SIZE 0x800 00075 #define NFCTAG_64M_SIZE 0x2000 00076 00077 #define MAX_NDEF_MEM 0x200 00078 #define M24LR_MAX_SIZE NFCTAG_4M_SIZE 00079 #define M24LR_NDEF_MAX_SIZE MIN(M24LR_MAX_SIZE,MAX_NDEF_MEM) 00080 #define NFC_DEVICE_MAX_NDEFMEMORY M24LR_NDEF_MAX_SIZE 00081 00082 /** 00083 * @brief This function read the data stored in NDEF file at defined offset. 00084 * @param Offset : Offset in the NDEF file. 00085 * @param DataSize : Number of byte to read. 00086 * @param pData : pointer on buffer to store read data. 00087 * @retval NDEF_ERROR_MEMORY_INTERNAL : Size not compatible with memory. 00088 * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported. 00089 * @retval NDEF_ERROR : No NDEF in the tag. 00090 * @retval NDEF_OK : The operation is completed. 00091 */ 00092 uint16_t NDefNfcTagM24LR::ReadData( uint16_t Offset , uint16_t DataSize , uint8_t* pData ) 00093 { 00094 uint16_t status = NDEF_ERROR; 00095 uint8_t atlv_detect[4]; 00096 uint8_t index = 0; 00097 00098 /* If too many data to write return error */ 00099 if ( DataSize > NDEF_MAX_SIZE ) { 00100 return NDEF_ERROR_MEMORY_INTERNAL; 00101 } 00102 00103 /* Detect NDEF message in memory */ 00104 status = NfcType5_NDEFDetection( ); 00105 if ( status != NDEF_OK ) { 00106 return status; 00107 } 00108 00109 /* Read TL of Type 5 */ 00110 status = NDefReadByte(CCFileStruct.NDEF_offset, 4, atlv_detect); 00111 if ( status != NDEF_OK ){ 00112 return status; 00113 } 00114 00115 if ( atlv_detect[1] == NFCT5_3_BYTES_L_TLV ) { 00116 index = 2; 00117 } 00118 00119 if (Offset==0 && DataSize>=2) { 00120 if ( atlv_detect[1] == NFCT5_3_BYTES_L_TLV ) { 00121 pData[0] = atlv_detect[2]; 00122 pData[1] = atlv_detect[3]; 00123 } else { 00124 pData[0] = 0x00; 00125 pData[1] = atlv_detect[1]; 00126 } 00127 DataSize -= 2; 00128 pData += 2; 00129 } 00130 00131 /* Check CC file is in the correct mode to proceed */ 00132 if ( CCFileStruct.State == TT5_INITIALIZED ) { 00133 return NDEF_ERROR; 00134 } 00135 00136 if (DataSize > 0) { 00137 /* Read NDEF */ 00138 if ( NDefReadByte(CCFileStruct.NDEF_offset + index + Offset, DataSize, pData) != NFC_SUCCESS ) { 00139 return NDEF_ERROR; 00140 } 00141 } 00142 00143 return NDEF_OK; 00144 } 00145 00146 /** 00147 * @brief This function writes data in NDEF file at defined offset. 00148 * @param Offset : Offset in the NDEF file. 00149 * @param DataSize : Number of byte to write. 00150 * @param pData : pointer on buffer to copy. 00151 * @retval NDEF_ERROR_MEMORY_INTERNAL : Size not compatible with memory. 00152 * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported. 00153 * @retval NDEF_ERROR : No NDEF in the tag. 00154 * @retval NDEF_OK : The operation is completed. 00155 */ 00156 uint16_t NDefNfcTagM24LR::WriteData( uint16_t Offset , uint32_t DataSize , uint8_t *pData ) 00157 { 00158 uint8_t atlv[4]; 00159 uint8_t index = 0; 00160 uint16_t NDEF_Size = 0; 00161 bool status; 00162 00163 /* Do not include length bytes */ 00164 DataSize -= FIRST_RECORD_OFFSET; 00165 00166 /* If too many data to write return error */ 00167 if ( DataSize > NDEF_MAX_SIZE ) { 00168 return NDEF_ERROR_MEMORY_INTERNAL; 00169 } 00170 00171 /* Detect NDEF message in memory */ 00172 if ( NfcType5_NDEFDetection( ) != NDEF_OK ) { 00173 return NDEF_ERROR; 00174 } 00175 00176 /* Extract NDEF Size from buffer */ 00177 NDEF_Size = (uint16_t)(pData[0] << 8); 00178 NDEF_Size = NDEF_Size | (uint16_t)(pData[1] ); 00179 00180 /* If entire NDEF is written, update Length of Type 5 */ 00181 if ( DataSize == NDEF_Size ) { 00182 /* Check if L is on 3 or 1 byte */ 00183 if ( NDEF_Size >= NFCT5_3_BYTES_L_TLV ) { 00184 /* First init L with 0, will be updated at the end */ 00185 atlv[1] = 0x00; 00186 atlv[2] = 0x00; 00187 atlv[3] = 0x00; 00188 status = NDefWriteByte( (atlv + 1), 3, (CCFileStruct.NDEF_offset + 1)); 00189 index += 4; 00190 } else { 00191 /* First inti L with 0, will be updated at the end */ 00192 atlv[1] = 0x00; 00193 status = NDefWriteByte( (atlv + 1), 1, (CCFileStruct.NDEF_offset + 1)); 00194 index += 2; 00195 } 00196 } 00197 00198 /* Start write NDEF message to EEPROM */ 00199 status = NDefWriteByte( (pData + FIRST_RECORD_OFFSET), DataSize, CCFileStruct.NDEF_offset + index + Offset); 00200 if ( status != NFC_SUCCESS ) { 00201 return NDEF_ERROR; 00202 } 00203 00204 /* If entire NDEF is written, update Length of Type 5 */ 00205 if ( DataSize == NDEF_Size ) { 00206 /* Check if L is on 3 or 1 byte */ 00207 if ( NDEF_Size >= NFCT5_3_BYTES_L_TLV ) { 00208 /* Update Length value */ 00209 atlv[1] = NFCT5_3_BYTES_L_TLV; 00210 atlv[2] = pData[0]; 00211 atlv[3] = pData[1]; 00212 status = NDefWriteByte( (atlv + 1), 3, (CCFileStruct.NDEF_offset + 1)); 00213 } else { 00214 /* Update Length value */ 00215 atlv[1] = pData[1]; 00216 status = NDefWriteByte( (atlv + 1), 1, (CCFileStruct.NDEF_offset + 1)); 00217 } 00218 00219 /* Write Terminator TLV */ 00220 atlv[0] = NFCT5_TERMINATOR_TLV; 00221 status = NDefWriteByte( atlv, 1, CCFileStruct.NDEF_offset + index + NDEF_Size); 00222 } 00223 00224 return NDEF_OK; 00225 } 00226 00227 /** 00228 * @brief This functions writes CCFile in EEPROM. 00229 * @param pCCBuffer : pointer on the buffer containnig CC file. 00230 * @retval NFCTAG status. 00231 */ 00232 uint16_t NDefNfcTagM24LR::NfcType5_WriteCCFile( const uint8_t * const pCCBuffer ) 00233 { 00234 bool ret_value; 00235 00236 /* Write first block of CCFile */ 00237 ret_value = NDefWriteByte( pCCBuffer, 0x4, 0x00); 00238 00239 /* If extended memory writes the next 4 bytes */ 00240 if ( (pCCBuffer[2] == 0x00) && (ret_value == NFC_SUCCESS) ) { 00241 ret_value = NDefWriteByte( pCCBuffer + 4, 4, 0x04); 00242 } 00243 00244 if ( ret_value != NFC_SUCCESS ) { 00245 return NDEF_ERROR; 00246 } 00247 00248 return NDEF_OK; 00249 } 00250 00251 /** 00252 * @brief This functions reads CCFile from EEPROM. 00253 * @param pCCBuffer : pointer on the buffer containnig CC file. 00254 * @retval NFCTAG status. 00255 */ 00256 uint16_t NDefNfcTagM24LR::NfcType5_ReadCCFile( uint8_t * const pCCBuffer ) 00257 { 00258 bool ret_value; 00259 00260 /* Read 4 bytes of CC File */ 00261 ret_value = NDefReadByte(0x00, 4, pCCBuffer); 00262 00263 /* If extended memory reads the next 4 bytes */ 00264 if ( (pCCBuffer[2] == 0x00) && (ret_value == NFC_SUCCESS) ) { 00265 ret_value = NDefReadByte(0x04, 4, pCCBuffer + 4 ); 00266 } 00267 00268 if ( ret_value != NFC_SUCCESS ) { 00269 return NDEF_ERROR; 00270 } 00271 00272 return NDEF_OK; 00273 } 00274 00275 /** 00276 * @brief This functions initializes Nfc Type. 00277 * @param None. 00278 * @retval NFCTAG status. 00279 */ 00280 uint16_t NDefNfcTagM24LR::NfcType5_TT5Init( void ) 00281 { 00282 bool ret_value ; 00283 uint16_t status; 00284 uint8_t accbuffer[8]; 00285 uint8_t cdata; 00286 00287 /* Prepare buffer to update CCFile */ 00288 accbuffer[0] = CCFileStruct.MagicNumber; 00289 accbuffer[1] = CCFileStruct.Version; 00290 accbuffer[2] = CCFileStruct.MemorySize; 00291 accbuffer[3] = CCFileStruct.TT5Tag; 00292 CCFileStruct.NDEF_offset = 0x04; 00293 00294 /* If extended memory prepare the length bytes */ 00295 if ( CCFileStruct.MemorySize == NFCT5_EXTENDED_CCFILE ) { 00296 accbuffer[6] = (uint8_t)(CCFileStruct.ExtMemorySize >> 8); 00297 accbuffer[7] = (uint8_t)(CCFileStruct.ExtMemorySize & 0xFF); 00298 CCFileStruct.NDEF_offset = 0x08; 00299 } 00300 00301 /* Update CCFile */ 00302 status = NfcType5_WriteCCFile( accbuffer ); 00303 if ( status != NDEF_OK ) { 00304 return status; 00305 } 00306 00307 /* Update NDEF TLV for INITIALIZED state */ 00308 /* Update T */ 00309 cdata = NFCT5_NDEF_MSG_TLV; 00310 ret_value = NDefWriteByte( &cdata, 1, CCFileStruct.NDEF_offset); 00311 if ( ret_value != NFC_SUCCESS ) { 00312 return NDEF_ERROR; 00313 } 00314 00315 /* Update L */ 00316 cdata = 0x00; 00317 ret_value = NDefWriteByte( &cdata, 1, (CCFileStruct.NDEF_offset + 1)); 00318 if ( ret_value != NFC_SUCCESS ) { 00319 return NDEF_ERROR; 00320 } 00321 00322 return NDEF_OK; 00323 } 00324 00325 /** 00326 * @brief This functions detects Nfc Tyoe. 00327 * @param None. 00328 * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported. 00329 * @retval NDEF_OK : The operation is completed. 00330 */ 00331 uint16_t NDefNfcTagM24LR::NfcType5_NDEFDetection( void ) 00332 { 00333 uint8_t acc_buffer[8]; 00334 uint8_t atlv_detect[4]; 00335 uint16_t status; 00336 uint32_t memory_size; 00337 00338 CCFileStruct.State = TT5_NO_NDEF; 00339 00340 /* Read CCFile */ 00341 status = NfcType5_ReadCCFile( acc_buffer ); 00342 if ( status != NDEF_OK ) { 00343 return status; 00344 } 00345 00346 /* Check Byte 0 is equal to magic number */ 00347 if ( ( acc_buffer[0] != NFCT5_MAGICNUMBER_E1_CCFILE ) && ( acc_buffer[0] != NFCT5_MAGICNUMBER_E2_CCFILE ) ) { 00348 return NDEF_ERROR_NOT_FORMATED; 00349 } else if ( ( (acc_buffer[1]&0xFC) != 0x40 ) ) { /* Check Version number */ 00350 return NDEF_ERROR_NOT_FORMATED; 00351 } 00352 00353 /* Check if CCFile is on 4 Bytes or 8 Bytes */ 00354 if ( acc_buffer[2] == 0x00 ) { 00355 /* Update CCFIle structure */ 00356 CCFileStruct.MemorySize = 0x0; 00357 CCFileStruct.ExtMemorySize = (uint16_t)acc_buffer[6]; 00358 CCFileStruct.ExtMemorySize = ( CCFileStruct.ExtMemorySize << 8 ) | acc_buffer[7]; 00359 memory_size = CCFileStruct.ExtMemorySize; 00360 CCFileStruct.NDEF_offset = 8; 00361 } else { 00362 /* Update CCFIle structure */ 00363 CCFileStruct.MemorySize = acc_buffer[2]; 00364 CCFileStruct.ExtMemorySize = 0x0; 00365 memory_size = CCFileStruct.MemorySize; 00366 CCFileStruct.NDEF_offset = 4; 00367 } 00368 00369 /* Update CCFIle structure */ 00370 CCFileStruct.MagicNumber = acc_buffer[0]; 00371 CCFileStruct.Version = acc_buffer[1]; 00372 CCFileStruct.TT5Tag = acc_buffer[3]; 00373 00374 /* Search for position of NDEF TLV in memory and tag status */ 00375 while( ( NDefReadByte(CCFileStruct.NDEF_offset, 4, atlv_detect) == NFC_SUCCESS ) && ( CCFileStruct.NDEF_offset < memory_size ) ) { 00376 /* Detect first NDEF Message in memory */ 00377 if ( atlv_detect[0] == NFCT5_NDEF_MSG_TLV ) { 00378 if ( atlv_detect[1] == 0x00 ) { 00379 CCFileStruct.State = TT5_INITIALIZED; 00380 } else { 00381 if ( CCFileStruct.Version & 0x3 ) { 00382 CCFileStruct.State = TT5_READ; 00383 } else { 00384 CCFileStruct.State = TT5_READ_WRITE; 00385 } 00386 } 00387 return NDEF_OK; 00388 } else if ( atlv_detect[0] == NFCT5_PROPRIETARY_TLV ) { /* If Proprietary NDEF jump to end of proprietary message */ 00389 if ( atlv_detect[1] == NFCT5_3_BYTES_L_TLV ) { 00390 CCFileStruct.NDEF_offset = CCFileStruct.NDEF_offset + ( (uint32_t)atlv_detect[2] << 8 ) + atlv_detect[3]; 00391 continue; 00392 } else { 00393 CCFileStruct.NDEF_offset = CCFileStruct.NDEF_offset + atlv_detect[1]; 00394 continue; 00395 } 00396 } else if ( atlv_detect[0] == NFCT5_TERMINATOR_TLV ) { /* if Terminator no NDEF detected */ 00397 return NDEF_ERROR_NOT_FORMATED; 00398 } 00399 00400 CCFileStruct.NDEF_offset++; 00401 } 00402 00403 return NDEF_ERROR_NOT_FORMATED; 00404 } 00405 00406 /** 00407 * @brief This functions opens a session. 00408 * @param force : force the opening. 00409 * @retval true. 00410 */ 00411 bool NDefNfcTagM24LR::open_session(bool force) { 00412 uint16_t status = NfcType5_NDEFDetection(); 00413 00414 if ( status != NDEF_OK ) { 00415 CCFileStruct.MagicNumber = NFCT5_MAGICNUMBER_E1_CCFILE; 00416 CCFileStruct.Version = NFCT5_VERSION_V1_0; 00417 CCFileStruct.MemorySize = ( M24LR_MAX_SIZE / 8 ) & 0xFF; 00418 CCFileStruct.TT5Tag = 0x05; 00419 /* Init of the Type Tag 5 component (M24LR) */ 00420 while ( NfcType5_TT5Init( ) != NDEF_OK ); 00421 } 00422 00423 mIsSessionOpen = 1; 00424 00425 return true; 00426 } 00427 00428 00429 /** 00430 * @brief This functions closes a session. 00431 * @param None. 00432 * @retval true. 00433 */ 00434 bool NDefNfcTagM24LR::close_session() 00435 { 00436 return true; 00437 } 00438 00439 /** 00440 * @brief This functions writes bytes. 00441 * @param byffer : the buffer containing data. 00442 * @param length: the length of the buffer in bytes. 00443 * @param offset: the offset of the buffer in bytes. 00444 * @retval true if written, false otherwise. 00445 */ 00446 bool NDefNfcTagM24LR::writeByte(const uint8_t *buffer, uint16_t length, uint16_t offset, 00447 byteOperationCallback_t callback,CallbackStatus_t *callbackStatus) 00448 { 00449 if (WriteData(offset, length, (uint8_t*)buffer)== NDEF_OK) { 00450 callback(callbackStatus,true,buffer,length); 00451 return true; 00452 } 00453 00454 callback(callbackStatus,false,buffer,length); 00455 return false; 00456 } 00457 00458 /** 00459 * @brief This functions reads bytes. 00460 * @param byteOffset : the offset of the buffer in bytes. 00461 * @param length: the length of the buffer in bytes. 00462 * @param buffer : the buffer containing data. 00463 * @param callback : a function to call after reading data. 00464 * @param callbackStatus : the status of the callback. 00465 * @retval true if read, false otherwise. 00466 */ 00467 bool NDefNfcTagM24LR::readByte(const uint16_t byteOffset, const uint16_t length, 00468 uint8_t *buffer, byteOperationCallback_t callback, CallbackStatus_t *callbackStatus) 00469 { 00470 00471 //first it reads the 2 byte for the length then when it will have the callback it reads the real message 00472 if (ReadData(byteOffset, length, (uint8_t*)buffer)== NDEF_OK){ 00473 callback(callbackStatus,true,buffer,length); 00474 return true; 00475 } 00476 00477 callback(callbackStatus,false,buffer,length); 00478 return false; 00479 } 00480 00481 /** 00482 * @brief This functions writes bytes. 00483 * @param byffer : the buffer containing data. 00484 * @param length: the length of the buffer in bytes. 00485 * @param offset: the offset of the buffer in bytes. 00486 * @retval NFCTAG status. 00487 */ 00488 uint16_t NDefNfcTagM24LR::NDefWriteByte(const uint8_t *buffer, uint16_t length, uint16_t offset) 00489 { 00490 uint16_t status; 00491 do { 00492 uint8_t writeLength =(uint8_t) std::min<uint16_t>(0xFF,length); 00493 status = mDevice.update_binary(offset, writeLength, (uint8_t*)buffer); 00494 offset+=writeLength; 00495 buffer+=writeLength; 00496 length-=writeLength; 00497 } while (status==NDEF_OK && length!=0); 00498 00499 return status; 00500 } 00501 00502 /** 00503 * @brief This functions reads bytes. 00504 * @param byteOffset : the offset of the buffer in bytes. 00505 * @param length: the length of the buffer in bytes. 00506 * @param buffer : the buffer containing data. 00507 * @retval NFCTAG status. 00508 */ 00509 uint16_t NDefNfcTagM24LR::NDefReadByte(uint16_t byteOffset, uint16_t length, uint8_t *buffer) 00510 { 00511 uint16_t status; 00512 do { 00513 uint8_t readBuffer = (uint8_t)std::min<uint16_t>(0xFF,length); 00514 status= mDevice.read_binary(byteOffset, readBuffer, (uint8_t*)buffer); 00515 byteOffset+=readBuffer; 00516 buffer+=readBuffer; 00517 length-=readBuffer; 00518 } while (status==NDEF_OK && length!=0); 00519 00520 return status; 00521 } 00522 00523 00524 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jul 13 2022 03:37:30 by
