ST / M24SR

Dependencies:   ST_INTERFACES

Dependents:   X_NUCLEO_NFC01A1

Fork of M24SR by ST Expansion SW Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers M24SR.cpp Source File

M24SR.cpp

00001 /**
00002  ******************************************************************************
00003  * @file    m24sr_class.cpp
00004  * @author  ST Central Labs
00005  * @version V2.0.0
00006  * @date    28 Apr 2017
00007  * @brief   This file provides a set of functions to interface with the M24SR
00008  *          device.
00009  ******************************************************************************
00010  * @attention
00011  *
00012  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
00013  *
00014  * Redistribution and use in source and binary forms, with or without modification,
00015  * are permitted provided that the following conditions are met:
00016  *   1. Redistributions of source code must retain the above copyright notice,
00017  *      this list of conditions and the following disclaimer.
00018  *   2. Redistributions in binary form must reproduce the above copyright notice,
00019  *      this list of conditions and the following disclaimer in the documentation
00020  *      and/or other materials provided with the distribution.
00021  *   3. Neither the name of STMicroelectronics nor the names of its contributors
00022  *      may be used to endorse or promote products derived from this software
00023  *      without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00029  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  ******************************************************************************
00037  */
00038 
00039 
00040 
00041 /* Includes ------------------------------------------------------------------*/
00042 #include "m24sr_def.h"
00043 #include "M24SR.h"
00044 #include "NDefNfcTagM24SR.h"
00045 
00046 #ifdef GPIO_PIN_RESET
00047     #undef GPIO_PIN_RESET
00048 #endif
00049 #define GPIO_PIN_RESET (0)
00050 
00051 #ifdef GPIO_PIN_SET
00052     #undef GPIO_PIN_SET
00053 #endif
00054 #define GPIO_PIN_SET (1)
00055 
00056 #define M24SR_MAX_BYTE_OPERATION_LENGHT (246)
00057 
00058 /**
00059  * default password, also used to enable super user mode through the I2C channel
00060  */
00061 const uint8_t M24SR::DEFAULT_PASSWORD[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00062     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00063 
00064 /** @addtogroup M24SR_Driver
00065  * @{
00066  *  @brief  <b>This folder contains the driver layer of M24SR family (M24SR64, M24SR16, M24SR04, M24SR02)</b> 
00067  */
00068 
00069 /** @defgroup drv_M24SR
00070  * @{
00071  *  @brief  This file contains the driver which implements all the M24SR commands.
00072  */
00073 
00074 #ifndef errchk
00075 
00076 /** value returned by the NFC chip when a command is successfully completed */
00077 #define NFC_COMMAND_SUCCESS 0x9000
00078 
00079 /** call the fCall function and check that the return status is M24SR_SUCCESS,
00080  *  otherwise return the error status*/
00081 #define errchk(fCall) {\
00082     const int status = (int) (fCall); \
00083     if((status!=M24SR_SUCCESS)) { \
00084         return (M24SR::StatusTypeDef)status; \
00085     }\
00086 }
00087 #endif
00088 
00089 /**
00090  * @brief  This function updates the CRC 
00091  * @param  None
00092  * @retval None
00093  */
00094  static uint16_t M24SR_UpdateCrc(uint8_t ch, uint16_t *lpwCrc) {
00095     ch = (ch ^ (uint8_t) ((*lpwCrc) & 0x00FF));
00096     ch = (ch ^ (ch << 4));
00097     *lpwCrc = (*lpwCrc >> 8) ^ ((uint16_t) ch << 8) ^ ((uint16_t) ch << 3) ^ ((uint16_t) ch >> 4);
00098 
00099     return (*lpwCrc);
00100 }
00101 
00102 /**
00103  * @brief  This function returns the CRC 16 
00104  * @param  Data : pointer on the data used to compute the CRC16
00105  * @param  Length : number of bytes of the data
00106  * @retval CRC16 
00107  */
00108  static uint16_t M24SR_ComputeCrc(uint8_t *Data, uint8_t Length) {
00109     uint8_t chBlock;
00110     uint16_t wCrc = 0x6363; // ITU-V.41
00111 
00112     do {
00113         chBlock = *Data++;
00114         M24SR_UpdateCrc(chBlock, &wCrc);
00115     } while (--Length);
00116 
00117     return wCrc;
00118 }
00119 
00120 /**  
00121  * @brief   This function computes the CRC16 residue as defined by CRC ISO/IEC 13239
00122  * @param   DataIn      :   input data 
00123  * @param   Length      :   Number of bits of DataIn
00124  * @retval  Status (SW1&SW2)    :   CRC16 residue is correct    
00125  * @retval  M24SR_ERROR_CRC     :  CRC16 residue is false
00126  */
00127  static M24SR::StatusTypeDef M24SR_IsCorrectCRC16Residue(uint8_t *DataIn, uint8_t Length) {
00128     uint16_t ResCRC = 0x0000;
00129     M24SR::StatusTypeDef status;
00130     /* check the CRC16 Residue */
00131     if (Length != 0) {
00132         ResCRC = M24SR_ComputeCrc(DataIn, Length);
00133     }
00134 
00135     if (ResCRC == 0x0000) {
00136         /* Good CRC, but error status from M24SR */
00137         status = (M24SR::StatusTypeDef) (((DataIn[Length - UB_STATUS_OFFSET] << 8)
00138                 & 0xFF00) | (DataIn[Length - LB_STATUS_OFFSET] & 0x00FF));
00139     } else {
00140         ResCRC = 0x0000;
00141         ResCRC = M24SR_ComputeCrc(DataIn, 5);
00142         if (ResCRC != 0x0000) {
00143             /* Bad CRC */
00144             return M24SR::M24SR_IO_ERROR_CRC;
00145         } else {
00146             /* Good CRC, but error status from M24SR */
00147             status= (M24SR::StatusTypeDef) (((DataIn[1] << 8) & 0xFF00)
00148                     | (DataIn[2] & 0x00FF));
00149         }
00150     }
00151     if (status==NFC_COMMAND_SUCCESS) {
00152         status =M24SR::M24SR_SUCCESS;
00153     }
00154 
00155     return status;
00156 }
00157 
00158 /**
00159  * @brief       This functions creates an I block command according to the structures CommandStructure and Command.
00160  * @param       Command : structure which contains the field of the different parameters
00161  * @param       CommandStructure : structure of the command 
00162  * @param       NbByte : number of bytes of the command
00163  * @param       pCommand : pointer to the command created
00164  */
00165 static void M24SR_BuildIBlockCommand(uint16_t CommandStructure, C_APDU *Command, uint8_t uDIDbyte, uint16_t *NbByte, uint8_t *pCommand) {
00166     uint16_t uCRC16;
00167     static uint8_t BlockNumber = 0x01;
00168 
00169     (*NbByte) = 0;
00170 
00171     /* add the PCD byte */
00172     if ((CommandStructure & M24SR_PCB_NEEDED) != 0) {
00173         /* toggle the block number */
00174         BlockNumber = TOGGLE(BlockNumber);
00175         /* Add the I block byte */
00176         pCommand[(*NbByte)++] = 0x02 | BlockNumber;
00177     }
00178 
00179     /* add the DID byte */
00180     if ((BlockNumber & M24SR_DID_NEEDED) != 0) {
00181         /* Add the I block byte */
00182         pCommand[(*NbByte)++] = uDIDbyte;
00183     }
00184 
00185     /* add the Class byte */
00186     if ((CommandStructure & M24SR_CLA_NEEDED) != 0) {
00187         pCommand[(*NbByte)++] = Command->Header.CLA;
00188     }
00189     /* add the instruction byte byte */
00190     if ((CommandStructure & M24SR_INS_NEEDED) != 0) {
00191         pCommand[(*NbByte)++] = Command->Header.INS;
00192     }
00193     /* add the Selection Mode byte */
00194     if ((CommandStructure & M24SR_P1_NEEDED) != 0) {
00195         pCommand[(*NbByte)++] = Command->Header.P1;
00196     }
00197     /* add the Selection Mode byte */
00198     if ((CommandStructure & M24SR_P2_NEEDED) != 0) {
00199         pCommand[(*NbByte)++] = Command->Header.P2;
00200     }
00201     /* add Data field lengthbyte */
00202     if ((CommandStructure & M24SR_LC_NEEDED) != 0) {
00203         pCommand[(*NbByte)++] = Command->Body.LC;
00204     }
00205     /* add Data field  */
00206     if ((CommandStructure & M24SR_DATA_NEEDED) != 0) {
00207         memcpy(&(pCommand[(*NbByte)]), Command->Body.pData, Command->Body.LC);
00208         (*NbByte) += Command->Body.LC;
00209     }
00210     /* add Le field  */
00211     if ((CommandStructure & M24SR_LE_NEEDED) != 0) {
00212         pCommand[(*NbByte)++] = Command->Body.LE;
00213     }
00214     /* add CRC field  */
00215     if ((CommandStructure & M24SR_CRC_NEEDED) != 0) {
00216         uCRC16 = M24SR_ComputeCrc(pCommand, (uint8_t) (*NbByte));
00217         /* append the CRC16 */
00218         pCommand[(*NbByte)++] = GETLSB(uCRC16);
00219         pCommand[(*NbByte)++] = GETMSB(uCRC16);
00220     }
00221 
00222 }
00223 
00224 
00225 
00226 
00227 /**  
00228  * @brief   This function returns M24SR_STATUS_SUCCESS if the pBuffer is an s-block
00229  * @param   pBuffer     :   pointer to the data
00230  * @retval  M24SR_SUCCESS  :  the data is a S-Block
00231  * @retval  NFC_ERROR   :  the data is not a S-Block
00232  */
00233  static M24SR::StatusTypeDef IsSBlock(uint8_t *pBuffer) {
00234 
00235     if ((pBuffer[M24SR_OFFSET_PCB] & M24SR_MASK_BLOCK) == M24SR_MASK_SBLOCK) {
00236         return M24SR::M24SR_SUCCESS;
00237     } else {
00238         return M24SR::M24SR_ERROR;
00239     }
00240 
00241 }
00242 
00243 M24SR::M24SR(const uint8_t address, I2C &I2C,gpoEventCallback eventCallback, const PinName& GPOPinName,
00244         const PinName& RFDISPinName) :
00245         who_am_i(0),
00246         type(0),
00247         address(address),
00248         dev_I2C(I2C),
00249         GPOPin(GPOPinName),
00250         RFDisablePin(RFDISPinName),
00251         mCommunicationType(SYNC),
00252         mLastCommandSend(NONE),
00253         mGpoEventInterrupt(GPOPinName),
00254         mCallback(&defaultCallback),
00255         mComponentCallback(NULL),
00256         mNDefTagUtil(new NDefNfcTagM24SR(*this)),
00257         mManageGPOCallback(*this),
00258         mReadIDCallback(*this){
00259         //mNDefTagUtil(NULL){
00260     memset(uM24SRbuffer, 0, 0xFF * sizeof(int8_t));
00261     uDIDbyte = 0;
00262     if (RFDisablePin.is_connected()!=0) {
00263         RFDisablePin = 0;
00264     }
00265     if(GPOPin.is_connected()!=0){
00266         if(eventCallback!=NULL)
00267             mGpoEventInterrupt.fall(eventCallback);
00268         mGpoEventInterrupt.mode(PullUp);
00269         mGpoEventInterrupt.disable_irq();
00270     }
00271 }
00272 
00273 M24SR::~M24SR(){
00274     delete mNDefTagUtil;
00275 }
00276 
00277 /**
00278  * @brief  This function sends the FWT extension command (S-Block format)
00279  * @param   FWTbyte : FWT value
00280  * @return M24SR_SUCCESS if no errors
00281  */
00282 M24SR::StatusTypeDef M24SR::M24SR_SendFWTExtension(uint8_t FWTbyte) {
00283     uint8_t pBuffer[M24SR_STATUSRESPONSE_NBBYTE];
00284     M24SR::StatusTypeDef status;
00285     uint8_t NthByte = 0;
00286     uint16_t uCRC16;
00287 
00288     /* create the response */
00289     pBuffer[NthByte++] = 0xF2;
00290     pBuffer[NthByte++] = FWTbyte;
00291     /* compute the CRC */
00292     uCRC16 = M24SR_ComputeCrc(pBuffer, 0x02);
00293     /* append the CRC16 */
00294     pBuffer[NthByte++] = GETLSB(uCRC16);
00295     pBuffer[NthByte++] = GETMSB(uCRC16);
00296 
00297     /* send the request */
00298     status = M24SR_IO_SendI2Ccommand(NthByte, pBuffer);
00299     if (status != M24SR_SUCCESS) {
00300         return status;
00301     }
00302 
00303     mLastCommandSend=UPDATE;
00304 
00305     if (mCommunicationType==M24SR::SYNC) {
00306         status = M24SR_IO_PollI2C();
00307         if (status == M24SR_SUCCESS) {
00308             return M24SR_ReceiveUpdateBinary();
00309         } else {
00310             mLastCommandSend = NONE;
00311             getCallback()->on_updated_binary(this,status,mLastCommandData.offset, mLastCommandData.data,mLastCommandData.length);
00312             return status;
00313         }//if-else
00314     }//if
00315 
00316     return M24SR_SUCCESS;
00317 }
00318 
00319 /**
00320  * @brief  This function initialize the M24SR device
00321  * @retval None
00322  */
00323 M24SR::StatusTypeDef M24SR::M24SR_Init(M24SR_InitTypeDef *notUsed) {
00324     (void) notUsed;
00325     //force to open a i2c session
00326     StatusTypeDef status = M24SR_ForceSession();
00327     if(status!= M24SR_SUCCESS) {
00328         return status;
00329     }
00330     //leave the gpo always up
00331     if(GPOPin.is_connected()!=0) {
00332         status = M24SR_ManageI2CGPO(DEFAULT_GPO_STATUS);
00333         if(status!= M24SR_SUCCESS)
00334             return status;
00335     }
00336     if(RFDisablePin.is_connected()!=0) {
00337         status = M24SR_ManageRFGPO(DEFAULT_GPO_STATUS);
00338         if(status!= M24SR_SUCCESS)
00339             return status;
00340     }
00341     //close the session
00342     status = M24SR_Deselect();
00343     if (status!= M24SR_SUCCESS) {
00344         return status;
00345     }
00346     if(GPOPin.is_connected()!=0) {
00347         mGpoEventInterrupt.enable_irq();
00348     }
00349     return M24SR_SUCCESS;
00350 }
00351 
00352 
00353 /**
00354  * @brief  This function sends the KillSession command to the M24SR device
00355  * @param  None
00356  * @return M24SR_SUCCESS if no errors
00357  */
00358 M24SR::StatusTypeDef M24SR::M24SR_ForceSession(void) {
00359     uint8_t commandBuffer[] = M24SR_KILLSESSION_COMMAND;
00360     M24SR::StatusTypeDef status;
00361     status = M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer);
00362     if(status!=M24SR_SUCCESS) {
00363         mCallback->on_session_open(this,status);
00364         return status;
00365     }
00366 
00367     /* Insure no access will be done just after open session */
00368     /* The only way here is to poll I2C to know when M24SR is ready */
00369     /* GPO can not be use with KillSession command */
00370     status = M24SR_IO_PollI2C();
00371 
00372     getCallback()->on_session_open(this,status);
00373     return status;
00374 
00375 }
00376 
00377 /**
00378  * @brief  This function sends the Deselect command (S-Block format)
00379  * @return M24SR_SUCCESS if no errors
00380  */
00381 M24SR::StatusTypeDef M24SR::M24SR_Deselect(void) {
00382     uint8_t pBuffer[] = M24SR_DESELECTREQUEST_COMMAND;
00383     M24SR::StatusTypeDef status;
00384     /* send the request */
00385     status = M24SR_IO_SendI2Ccommand(sizeof(pBuffer), pBuffer);
00386     if(status!=M24SR_SUCCESS) {
00387         getCallback()->on_deselect(this,status);
00388     }
00389 
00390     mLastCommandSend=DESELECT;
00391 
00392     if (mCommunicationType==M24SR::SYNC) {
00393         status = M24SR_IO_PollI2C();
00394         if(status == M24SR_SUCCESS) {
00395             return M24SR_ReceiveDeselect();
00396         } else {
00397             mLastCommandSend = NONE;
00398             getCallback()->on_selected_application(this,status);
00399             return status;
00400         }//if-else
00401 
00402     }
00403 
00404     return M24SR_SUCCESS;
00405 }
00406 
00407 M24SR::StatusTypeDef M24SR::M24SR_ReceiveDeselect(void) {
00408     uint8_t pBuffer[4];
00409     M24SR::StatusTypeDef status;
00410     status = M24SR_IO_ReceiveI2Cresponse(sizeof(pBuffer), pBuffer);
00411     getCallback()->on_deselect(this,status);
00412     return status;
00413 }
00414 
00415 /**
00416  * @brief  This function sends the GetSession command to the M24SR device
00417  * @retval M24SR_SUCCESS the function is successful.
00418  * @retval Status (SW1&SW2) if operation does not complete.
00419  */
00420 M24SR::StatusTypeDef M24SR::M24SR_GetSession(void) {
00421     uint8_t commandBuffer[] = M24SR_OPENSESSION_COMMAND;
00422 
00423     M24SR::StatusTypeDef status;
00424     status = M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer);
00425     if (status!=M24SR_SUCCESS) {
00426         getCallback()->on_session_open(this,status);
00427         return status;
00428     }
00429 
00430     /* Insure no access will be done just after open session */
00431     /* The only way here is to poll I2C to know when M24SR is ready */
00432     /* GPO can not be use with KillSession command */
00433     status = M24SR_IO_PollI2C();
00434 
00435     getCallback()->on_session_open(this,status);
00436     return status;
00437 }
00438 
00439 /**
00440  * @brief  This function sends the SelectApplication command
00441  * @return M24SR_SUCCESS if no errors
00442  */
00443 M24SR::StatusTypeDef M24SR::M24SR_SendSelectApplication(void) {
00444 
00445     C_APDU command;
00446     M24SR::StatusTypeDef status;
00447     uint8_t *pBuffer = uM24SRbuffer;
00448     uint8_t pDataOut[] = M24SR_SELECTAPPLICATION_COMMAND;
00449     uint8_t uLe = 0x00;
00450     uint16_t uP1P2 =0x0400, NbByte;
00451 
00452     /* build the command */
00453     command.Header.CLA = C_APDU_CLA_DEFAULT;
00454     command.Header.INS = C_APDU_SELECT_FILE;
00455     /* copy the offset */
00456     command.Header.P1 = GETMSB(uP1P2);
00457     command.Header.P2 = GETLSB(uP1P2);
00458     /* copy the number of byte of the data field */
00459     command.Body.LC = sizeof(pDataOut);
00460     /* copy the data */
00461     command.Body.pData = pDataOut;
00462     /* copy the number of byte to read */
00463     command.Body.LE = uLe;
00464     /* build the I2C command */
00465     M24SR_BuildIBlockCommand( M24SR_CMDSTRUCT_SELECTAPPLICATION, &command, uDIDbyte, &NbByte, pBuffer);
00466 
00467     /* send the request */
00468     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00469     if (status != M24SR_SUCCESS) {
00470         getCallback()->on_selected_application(this,status);
00471         return status;
00472     }
00473 
00474     mLastCommandSend=SELECT_APPLICATION;
00475 
00476     if (mCommunicationType==M24SR::SYNC) {
00477         status = M24SR_IO_PollI2C();
00478         if (status == M24SR_SUCCESS) {
00479             return M24SR_ReceiveSelectApplication();
00480         } else {
00481             mLastCommandSend = NONE;
00482             getCallback()->on_selected_application(this,status);
00483             return status;
00484         }//if-else
00485     }//if
00486 
00487     return M24SR_SUCCESS;
00488 }
00489 
00490 M24SR::StatusTypeDef M24SR::M24SR_ReceiveSelectApplication(void) {
00491     uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
00492     M24SR::StatusTypeDef status;
00493 
00494     mLastCommandSend = NONE;
00495 
00496     status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
00497     if (status!=M24SR_SUCCESS) {
00498         getCallback()->on_selected_application(this,status);
00499         return status;
00500     }//else
00501     status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
00502     getCallback()->on_selected_application(this,status);
00503 
00504     return status;
00505 }
00506 
00507 M24SR::StatusTypeDef M24SR::M24SR_ReadID(uint8_t *nfc_id) {
00508     if (!nfc_id) {
00509         return M24SR_ERROR;
00510     }
00511 
00512     //enable the callback for change the gpo
00513     mComponentCallback = &mReadIDCallback;
00514     mReadIDCallback.read_id_on(nfc_id);
00515 
00516     //start the readID procedure
00517     return M24SR_SendSelectApplication();
00518 }
00519 
00520 /**
00521  * @brief  This function sends the SelectCCFile command
00522  * @retval M24SR_SUCCESS the function is successful.
00523  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00524  * @retval Status (SW1&SW2)   if operation does not complete for another reason.
00525  */
00526 M24SR::StatusTypeDef M24SR::M24SR_SendSelectCCfile(void) {
00527     C_APDU command;
00528     M24SR::StatusTypeDef status;
00529     uint8_t *pBuffer = uM24SRbuffer;
00530     uint8_t pDataOut[] = CC_FILE_ID_BYTES;
00531     uint16_t uP1P2 =0x000C,
00532     NbByte;
00533 
00534     /* build the command */
00535     command.Header.CLA = C_APDU_CLA_DEFAULT;
00536     command.Header.INS = C_APDU_SELECT_FILE;
00537     /* copy the offset */
00538     command.Header.P1 = GETMSB(uP1P2);
00539     command.Header.P2 = GETLSB(uP1P2);
00540     /* copy the number of byte of the data field */
00541     command.Body.LC = sizeof(pDataOut);
00542     command.Body.pData = pDataOut;
00543     /* build the I2C command */
00544     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SELECTCCFILE, &command, uDIDbyte, &NbByte, pBuffer);
00545 
00546     /* send the request */
00547     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00548     if(status!=M24SR_SUCCESS) {
00549         getCallback()->on_selected_CC_file(this,status);
00550         return status;
00551     }//else
00552 
00553     mLastCommandSend=SELECT_CC_FILE;
00554 
00555     if (mCommunicationType==M24SR::SYNC){
00556         status = M24SR_IO_PollI2C();
00557         if (status==M24SR_SUCCESS) {
00558             return M24SR_ReceiveSelectCCfile();
00559         } else {
00560             mLastCommandSend = NONE;
00561             getCallback()->on_selected_CC_file(this,status);
00562             return status;
00563         }//if-else
00564     }//if
00565 
00566     return M24SR_SUCCESS;
00567 }
00568 
00569 M24SR::StatusTypeDef M24SR::M24SR_ReceiveSelectCCfile(void){
00570 
00571     uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
00572     M24SR::StatusTypeDef status;
00573 
00574     mLastCommandSend = NONE;
00575 
00576     status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
00577     if (status!=M24SR_SUCCESS) {
00578         getCallback()->on_selected_CC_file(this,status);
00579         return status;
00580     }//else
00581     status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
00582     getCallback()->on_selected_CC_file(this,status);
00583 
00584     return status;
00585 }
00586 
00587 /**
00588  * @brief  This function sends the SelectSystemFile command
00589  * @retval Status (SW1&SW2) Status of the operation to complete.
00590  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00591  */
00592 M24SR::StatusTypeDef M24SR::M24SR_SendSelectSystemfile(void) {
00593     C_APDU command;
00594 
00595     uint8_t *pBuffer = uM24SRbuffer;
00596     uint8_t pDataOut[] = SYSTEM_FILE_ID_BYTES;
00597     M24SR::StatusTypeDef status;
00598     uint16_t uP1P2 =0x000C, NbByte;
00599 
00600     /* build the command */
00601     command.Header.CLA = C_APDU_CLA_DEFAULT;
00602     command.Header.INS = C_APDU_SELECT_FILE;
00603     /* copy the offset */
00604     command.Header.P1 = GETMSB(uP1P2);
00605     command.Header.P2 = GETLSB(uP1P2);
00606     /* copy the number of byte of the data field */
00607     command.Body.LC = sizeof(pDataOut);
00608     command.Body.pData = pDataOut;
00609     /* build the I²C command */
00610     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SELECTCCFILE, &command, uDIDbyte, &NbByte, pBuffer);
00611 
00612     /* send the request */
00613     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00614     if (status!=M24SR_SUCCESS) {
00615         getCallback()->on_selected_system_file(this,status);
00616         return status;
00617     }//else
00618 
00619     mLastCommandSend=SELECT_SYSTEM_FILE;
00620 
00621     if (mCommunicationType==M24SR::SYNC) {
00622         status = M24SR_IO_PollI2C();
00623         if (status == M24SR_SUCCESS) {
00624             return M24SR_ReceiveSelectSystemfile();
00625         } else {
00626             mLastCommandSend = NONE;
00627             getCallback()->on_selected_system_file(this,status);
00628             return status;
00629         }//if-else
00630     }//if
00631 
00632     return M24SR_SUCCESS;
00633 }
00634 
00635 M24SR::StatusTypeDef M24SR::M24SR_ReceiveSelectSystemfile() {
00636     uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
00637     M24SR::StatusTypeDef status;
00638 
00639     mLastCommandSend = NONE;
00640 
00641     status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
00642     if (status!=M24SR_SUCCESS) {
00643         getCallback()->on_selected_system_file(this,status);
00644         return status;
00645     }//else
00646     status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
00647     getCallback()->on_selected_system_file(this,status);
00648 
00649     return status;
00650 }
00651 
00652 /**
00653  * @brief  This function sends the SelectNDEFfile command
00654  * @retval Status (SW1&SW2) Status of the operation to complete.
00655  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00656  */
00657 M24SR::StatusTypeDef M24SR::M24SR_SendSelectNDEFfile(uint16_t NDEFfileId) {
00658     C_APDU command;
00659     M24SR::StatusTypeDef status;
00660     uint8_t *pBuffer = uM24SRbuffer;
00661     uint8_t pDataOut[] = { GETMSB(NDEFfileId), GETLSB(NDEFfileId) };
00662     uint16_t uP1P2 = 0x000C, NbByte;
00663 
00664     /* build the command */
00665     command.Header.CLA = C_APDU_CLA_DEFAULT;
00666     command.Header.INS = C_APDU_SELECT_FILE;
00667     /* copy the offset */
00668     command.Header.P1 = GETMSB(uP1P2);
00669     command.Header.P2 = GETLSB(uP1P2);
00670     /* copy the number of byte of the data field */
00671     command.Body.LC = sizeof(pDataOut);
00672     command.Body.pData = pDataOut;
00673     /* copy the offset */
00674     /* build the I2C command */
00675     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SELECTNDEFFILE, &command, uDIDbyte, &NbByte, pBuffer);
00676 
00677     /* send the request */
00678     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00679     if (status!=M24SR_SUCCESS) {
00680         return status;
00681     }
00682     mLastCommandSend=SELECT_NDEF_FILE;
00683 
00684     if (mCommunicationType==M24SR::SYNC) {
00685         status = M24SR_IO_PollI2C();
00686         if (status==M24SR_SUCCESS) {
00687             return M24SR_ReceiveSelectNDEFfile();
00688         } else {
00689             mLastCommandSend = NONE;
00690             getCallback()->on_selected_NDEF_file(this,status);
00691             return status;
00692         }
00693     }
00694 
00695     return M24SR_SUCCESS;
00696 
00697 }
00698 
00699 M24SR::StatusTypeDef M24SR::M24SR_ReceiveSelectNDEFfile(){
00700 
00701     uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
00702     M24SR::StatusTypeDef status;
00703 
00704     mLastCommandSend = NONE;
00705 
00706     status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
00707     if (status!=M24SR_SUCCESS) {
00708         getCallback()->on_selected_NDEF_file(this,status);
00709         return status;
00710     }//else
00711     status= M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
00712     getCallback()->on_selected_NDEF_file(this,status);
00713 
00714     return status;
00715 }
00716 
00717 /**
00718  * @brief  This function sends a read binary command
00719  * @param   Offset   first byte to read
00720  * @param   NbByteToRead   number of bytes to read
00721  * @param   pBufferRead   pointer to the buffer read from the M24SR device
00722  * @retval Status (SW1&SW2) Status of the operation to complete.
00723  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00724  */
00725 M24SR::StatusTypeDef M24SR::M24SR_SendReadBinary(uint16_t Offset, uint8_t NbByteToRead, uint8_t *pBufferRead) {
00726     //clamp the buffer to the max size
00727     if (NbByteToRead>M24SR_MAX_BYTE_OPERATION_LENGHT) {
00728         NbByteToRead=M24SR_MAX_BYTE_OPERATION_LENGHT;
00729     }
00730 
00731     C_APDU command;
00732     uint8_t *pBuffer = uM24SRbuffer;
00733     uint16_t NbByte;
00734     M24SR::StatusTypeDef status;
00735 
00736     /* build the command */
00737     command.Header.CLA = C_APDU_CLA_DEFAULT;
00738     command.Header.INS = C_APDU_READ_BINARY;
00739     /* copy the offset */
00740     command.Header.P1 = GETMSB(Offset);
00741     command.Header.P2 = GETLSB(Offset);
00742     /* copy the number of byte to read */
00743     command.Body.LE = NbByteToRead;
00744 
00745     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_READBINARY, &command, uDIDbyte, &NbByte, pBuffer);
00746 
00747     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00748     if (status!=M24SR_SUCCESS) {
00749         getCallback()->on_read_byte(this,status,Offset,pBufferRead,NbByteToRead);
00750         return status;
00751     }
00752 
00753     mLastCommandSend=READ;
00754     mLastCommandData.data=pBufferRead;
00755     mLastCommandData.length=NbByteToRead;
00756     mLastCommandData.offset=Offset;
00757 
00758     if (mCommunicationType==M24SR::SYNC) {
00759         status = M24SR_IO_PollI2C();
00760         if (status==M24SR_SUCCESS) {
00761             return M24SR_ReceiveReadBinary();
00762         } else {
00763             mLastCommandSend = NONE;
00764             getCallback()->on_read_byte(this,status,Offset,pBufferRead,NbByteToRead);
00765             return status;
00766         }//if-else
00767     }//if
00768 
00769     return M24SR_SUCCESS;
00770 }
00771 
00772 M24SR::StatusTypeDef M24SR::M24SR_ReceiveReadBinary() {
00773     M24SR::StatusTypeDef status;
00774     const uint16_t length = mLastCommandData.length;
00775     const uint16_t offset = mLastCommandData.offset;
00776     uint8_t *data = mLastCommandData.data;
00777 
00778     mLastCommandSend = NONE;
00779 
00780     status = M24SR_IO_ReceiveI2Cresponse (length + M24SR_STATUSRESPONSE_NBBYTE , uM24SRbuffer );
00781     if (status!=M24SR_SUCCESS) {
00782         getCallback()->on_read_byte(this,status,offset,data,length);
00783         return status;
00784     }
00785     status = M24SR_IsCorrectCRC16Residue(uM24SRbuffer, length + M24SR_STATUSRESPONSE_NBBYTE);
00786     if (status != M24SR_SUCCESS) {
00787         getCallback()->on_read_byte(this,status,offset,data,length);
00788     } else{
00789         /* retrieve the data without SW1 & SW2 as provided as return value of the function */
00790         memcpy(mLastCommandData.data, &uM24SRbuffer[1], length);
00791         getCallback()->on_read_byte(this,status,offset,data,length);
00792     }
00793 
00794     return status;
00795 }
00796 
00797 /**
00798  * @brief  This function sends a ST read binary command (no error if access is not inside NDEF file)
00799  * @param   Offset   first byte to read
00800  * @param   NbByteToRead number of bytes to read
00801  * @param   pBufferRead  pointer to the buffer read from the M24SR device
00802  * @retval Status (SW1&SW2) Status of the operation to complete.
00803  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00804  */
00805 M24SR::StatusTypeDef M24SR::M24SR_SendSTReadBinary(uint16_t Offset, uint8_t NbByteToRead, uint8_t *pBufferRead) {
00806     //clamp the buffer to the max size
00807     if (NbByteToRead>M24SR_MAX_BYTE_OPERATION_LENGHT) {
00808         NbByteToRead=M24SR_MAX_BYTE_OPERATION_LENGHT;
00809     }
00810 
00811     C_APDU command;
00812     uint8_t *pBuffer = uM24SRbuffer;
00813     uint16_t NbByte;
00814     M24SR::StatusTypeDef status;
00815 
00816     /* build the command */
00817     command.Header.CLA = C_APDU_CLA_ST;
00818     command.Header.INS = C_APDU_READ_BINARY;
00819     /* copy the offset */
00820     command.Header.P1 = GETMSB(Offset);
00821     command.Header.P2 = GETLSB(Offset);
00822     /* copy the number of byte to read */
00823     command.Body.LE = NbByteToRead;
00824 
00825     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_READBINARY, &command, uDIDbyte, &NbByte, pBuffer);
00826 
00827     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00828     if (status!=M24SR_SUCCESS) {
00829         getCallback()->on_read_byte(this,status,Offset,pBufferRead,NbByteToRead);
00830         return status;
00831     }
00832 
00833     mLastCommandSend=READ;
00834     mLastCommandData.data=pBufferRead;
00835     mLastCommandData.length=NbByteToRead;
00836 
00837     if (mCommunicationType==M24SR::SYNC) {
00838         status = M24SR_IO_PollI2C();
00839         if (status==M24SR_SUCCESS) {
00840             return M24SR_ReceiveReadBinary();
00841         } else {
00842             mLastCommandSend = NONE;
00843             getCallback()->on_read_byte(this,status,Offset,pBufferRead,NbByteToRead);
00844             return status;
00845         }//if-else
00846     }//if
00847 
00848     return M24SR_SUCCESS;
00849 }
00850 
00851 /**
00852  * @brief  This function sends a Update binary command
00853  * @param   Offset   first byte to read
00854  * @param   NbByteToWrite   number of bytes to write
00855  * @param   pBufferRead   pointer to the buffer read from the M24SR device
00856  * @retval Status (SW1&SW2) Status of the operation to complete.
00857  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00858  */
00859 M24SR::StatusTypeDef M24SR::M24SR_SendUpdateBinary(uint16_t Offset, uint8_t NbByteToWrite, uint8_t *pDataToWrite) {
00860     //clamp the buffer to the max size
00861     if (NbByteToWrite>M24SR_MAX_BYTE_OPERATION_LENGHT) {
00862         NbByteToWrite=M24SR_MAX_BYTE_OPERATION_LENGHT;
00863     }
00864 
00865     C_APDU command;
00866     M24SR::StatusTypeDef status;
00867     uint8_t *pBuffer = uM24SRbuffer;
00868     uint16_t NbByte;
00869 
00870     /* build the command */
00871     command.Header.CLA = C_APDU_CLA_DEFAULT;
00872     command.Header.INS = C_APDU_UPDATE_BINARY;
00873     /* copy the offset */
00874     command.Header.P1 = GETMSB(Offset);
00875     command.Header.P2 = GETLSB(Offset);
00876     /* copy the number of byte of the data field */
00877     command.Body.LC = NbByteToWrite;
00878     command.Body.pData = pDataToWrite;
00879     /* copy the File Id */
00880     //memcpy(command.Body.pData ,pDataToWrite, NbByteToWrite );
00881     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_UPDATEBINARY, &command, uDIDbyte, &NbByte, pBuffer);
00882 
00883     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00884     if (status!=M24SR_SUCCESS){
00885         getCallback()->on_updated_binary(this,status,Offset,pDataToWrite,NbByteToWrite);
00886         return status;
00887     }
00888 
00889     mLastCommandSend=UPDATE;
00890     mLastCommandData.data=pDataToWrite;
00891     mLastCommandData.length=NbByteToWrite;
00892     mLastCommandData.offset=Offset;
00893 
00894     if (mCommunicationType==M24SR::SYNC) {
00895         status = M24SR_IO_PollI2C();
00896         if (status==M24SR_SUCCESS) {
00897             return M24SR_ReceiveUpdateBinary();
00898         } else {
00899             mLastCommandSend = NONE;
00900             getCallback()->on_updated_binary(this,status,Offset,pDataToWrite,NbByteToWrite);
00901             return status;
00902         }//if-else
00903     }
00904 
00905     return M24SR_SUCCESS;
00906 }
00907 
00908 M24SR::StatusTypeDef M24SR::M24SR_ReceiveUpdateBinary() {
00909     uint8_t respBuffer[M24SR_STATUSRESPONSE_NBBYTE];
00910     M24SR::StatusTypeDef status;
00911     const uint16_t length = mLastCommandData.length;
00912     uint8_t *data = mLastCommandData.data;
00913     const uint16_t offset = mLastCommandData.offset;
00914 
00915     mLastCommandSend=NONE;
00916 
00917     status= M24SR_IO_ReceiveI2Cresponse (sizeof(respBuffer) , respBuffer);
00918     if(status != M24SR_SUCCESS){
00919         getCallback()->on_updated_binary(this,status,offset,data,length);
00920         return status;
00921     }
00922 
00923     if (IsSBlock(respBuffer) == M24SR_SUCCESS) {
00924         /*check the CRC */
00925         status = M24SR_IsCorrectCRC16Residue(respBuffer, M24SR_WATINGTIMEEXTRESPONSE_NBBYTE);
00926         // TODO: why if we check ==NFC_Commandsuccess it fail?
00927         if (status != M24SR_IO_ERROR_CRC) {
00928             /* send the FrameExension response*/
00929             status = M24SR_SendFWTExtension(respBuffer[M24SR_OFFSET_PCB + 1]);
00930             if(status!=M24SR_SUCCESS){ //something get wrong -> abort the update
00931                 getCallback()->on_updated_binary(this,status,offset,data,length);
00932             }//status
00933         }//if
00934     } else { //isSBlock
00935         status = M24SR_IsCorrectCRC16Residue(respBuffer, M24SR_STATUSRESPONSE_NBBYTE);
00936         getCallback()->on_updated_binary(this,status,offset,data,length);
00937     }//if else
00938 
00939     return status;
00940 }//M24SR_ReceiveUpdateBinary
00941 
00942 /**
00943  * @brief  This function sends the Verify command
00944  * @param   uPwdId   PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
00945  * @param   NbPwdByte   Number of bytes ( 0x00 or 0x10)
00946  * @param   pPwd   pointer to the password
00947  * @retval Status (SW1&SW2) Status of the operation to complete.
00948  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
00949  */
00950 M24SR::StatusTypeDef M24SR::M24SR_SendVerify(uint16_t uPwdId, uint8_t NbPwdByte, const uint8_t *pPwd) {
00951     C_APDU command;
00952     M24SR::StatusTypeDef status;
00953     uint8_t *pBuffer = uM24SRbuffer;
00954     uint16_t NbByte;
00955 
00956     /*check the parameters */
00957     if ((uPwdId > 0x0003)|| ((NbPwdByte != 0x00) && (NbPwdByte != 0x10))) {
00958         getCallback()->on_verified(this,M24SR_IO_ERROR_PARAMETER,constToPasswordType(uPwdId),pPwd);
00959         return M24SR_IO_ERROR_PARAMETER;
00960     }
00961 
00962     /* build the command */
00963     command.Header.CLA = C_APDU_CLA_DEFAULT;
00964     command.Header.INS = C_APDU_VERIFY;
00965     /* copy the Password Id */
00966     command.Header.P1 = GETMSB(uPwdId);
00967     command.Header.P2 = GETLSB(uPwdId);
00968     /* copy the number of bytes of the data field */
00969     command.Body.LC = NbPwdByte;
00970 
00971     if (NbPwdByte == 0x10) {
00972         /* copy the password */
00973         command.Body.pData = pPwd;
00974         /* build the I2C command */
00975         M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_VERIFYBINARYWITHPWD, &command, uDIDbyte, &NbByte, pBuffer);
00976     } else {
00977         command.Body.pData = NULL;
00978         /* build the I2C command */
00979         M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_VERIFYBINARYWOPWD, &command, uDIDbyte, &NbByte, pBuffer);
00980     }
00981 
00982     /* send the request */
00983     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
00984     if (status!=M24SR_SUCCESS) {
00985         getCallback()->on_verified(this,status,constToPasswordType(uPwdId),pPwd);
00986         return status;
00987     }
00988     mLastCommandSend=VERIFY;
00989     mLastCommandData.data=(uint8_t*)pPwd;
00990     mLastCommandData.offset=uPwdId;
00991 
00992     if (mCommunicationType==M24SR::SYNC) {
00993         status = M24SR_IO_PollI2C();
00994         if(status == M24SR_SUCCESS) {
00995             return M24SR_ReceiveVerify();
00996         } else {
00997             mLastCommandSend = NONE;
00998             getCallback()->on_verified(this,status,constToPasswordType(uPwdId),pPwd);
00999             return status;
01000         }
01001     }
01002 
01003     return M24SR_SUCCESS;
01004 }
01005 
01006 M24SR::StatusTypeDef M24SR::M24SR_ReceiveVerify() {
01007     M24SR::StatusTypeDef status;
01008     uint8_t respBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01009     mLastCommandSend=NONE;
01010 
01011     const uint8_t *data = mLastCommandData.data;
01012     const PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01013 
01014     status=M24SR_IO_ReceiveI2Cresponse (sizeof(respBuffer),respBuffer);
01015 
01016     if (status !=M24SR_SUCCESS) {
01017         getCallback()->on_verified(this,status,type,data);
01018         return status;
01019     }
01020 
01021     status = M24SR_IsCorrectCRC16Residue(respBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01022     getCallback()->on_verified(this,status,type,data);
01023     return status;
01024 }
01025 
01026 /**
01027  * @brief  This function sends the ChangeReferenceData command
01028  * @param   uPwdId   PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
01029  * @param   pPwd   pointer to the passwaord
01030  * @retval Status (SW1&SW2) Satus of the operation to complete.
01031  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01032  */
01033 M24SR::StatusTypeDef M24SR::M24SR_SendChangeReferenceData(uint16_t uPwdId, uint8_t *pPwd) {
01034     C_APDU command;
01035     M24SR::StatusTypeDef status;
01036     uint8_t *pBuffer = uM24SRbuffer;
01037     uint16_t NbByte;
01038 
01039     /*check the parameters */
01040     if (uPwdId > 0x0003) {
01041         getCallback()->on_change_reference_data(this,M24SR_IO_ERROR_PARAMETER, constToPasswordType(uPwdId), pPwd);
01042         return M24SR_IO_ERROR_PARAMETER;
01043     }
01044 
01045     /* build the command */
01046     command.Header.CLA = C_APDU_CLA_DEFAULT;
01047     command.Header.INS = C_APDU_CHANGE;
01048     /* copy the Password Id */
01049     command.Header.P1 = GETMSB(uPwdId);
01050     command.Header.P2 = GETLSB(uPwdId);
01051     /* copy the number of byte of the data field */
01052     command.Body.LC = M24SR_PASSWORD_NBBYTE;
01053     /* copy the password */
01054     command.Body.pData = pPwd;
01055     /* build the I²C command */
01056     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_CHANGEREFDATA, &command, uDIDbyte, &NbByte, pBuffer);
01057 
01058     /* send the request */
01059     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
01060     if (status != M24SR_SUCCESS) {
01061         getCallback()->on_change_reference_data(this,status, constToPasswordType(uPwdId), pPwd);
01062         return status;
01063     }
01064 
01065     mLastCommandSend = CHANGE_REFERENCE_DATA;
01066     mLastCommandData.data = pPwd;
01067     //use the offset filed for store the pwd id;
01068     mLastCommandData.offset = (uint8_t)uPwdId;
01069 
01070     if (mCommunicationType==M24SR::SYNC) {
01071         status = M24SR_IO_PollI2C();
01072         if (status == M24SR_SUCCESS) {
01073             return M24SR_ReceiveChangeReferenceData();
01074         } else {
01075             mLastCommandSend = NONE;
01076             getCallback()->on_change_reference_data(this, status, constToPasswordType(uPwdId), pPwd);
01077             return status;
01078         }//if-else
01079     }//if
01080 
01081     return M24SR_SUCCESS;
01082 }
01083 
01084 M24SR::StatusTypeDef M24SR::M24SR_ReceiveChangeReferenceData(){
01085     M24SR::StatusTypeDef status;
01086     //TODO the size is 3?
01087     uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01088 
01089     PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01090     uint8_t *data = mLastCommandData.data;
01091 
01092     status = M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
01093     if (status!=M24SR_SUCCESS) {
01094         getCallback()->on_change_reference_data(this,status,type,data);
01095         return status;
01096     }//else
01097 
01098     status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01099     getCallback()->on_change_reference_data(this,status,type,data);
01100     return status;
01101 }
01102 
01103 /**
01104  * @brief  This function sends the EnableVerificationRequirement command
01105  * @param   uReadOrWrite enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
01106  * @retval Status (SW1&SW2) Status of the operation to complete.
01107  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01108  */
01109 M24SR::StatusTypeDef M24SR::M24SR_SendEnableVerificationRequirement(uint16_t uReadOrWrite) {
01110     C_APDU command;
01111     M24SR::StatusTypeDef status;
01112     uint8_t *pBuffer = uM24SRbuffer;
01113     uint16_t NbByte;
01114 
01115     /*check the parameters */
01116     if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
01117         getCallback()->on_enable_verification_requirement(this,M24SR_IO_ERROR_PARAMETER, constToPasswordType(uReadOrWrite));
01118         return M24SR_IO_ERROR_PARAMETER;
01119     }
01120 
01121     /* build the command */
01122     command.Header.CLA = C_APDU_CLA_DEFAULT;
01123     command.Header.INS = C_APDU_ENABLE;
01124     /* copy the Password Id */
01125     command.Header.P1 = GETMSB(uReadOrWrite);
01126     command.Header.P2 = GETLSB(uReadOrWrite);
01127     /* build the I2C command */
01128     M24SR_BuildIBlockCommand( M24SR_CMDSTRUCT_ENABLEVERIFREQ, &command, uDIDbyte, &NbByte, pBuffer);
01129 
01130     /* send the request */
01131     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
01132     if (status != M24SR_SUCCESS) {
01133         getCallback()->on_enable_verification_requirement(this, status, constToPasswordType(uReadOrWrite));
01134         return status;
01135     }//if
01136 
01137     mLastCommandSend = ENABLE_VERIFICATION_REQUIREMENT;
01138     //use the offset filed for store the pwd id;
01139     mLastCommandData.offset = (uint8_t)uReadOrWrite;
01140 
01141     if (mCommunicationType==M24SR::SYNC) {
01142         status = M24SR_IO_PollI2C();
01143         if (status == M24SR_SUCCESS) {
01144             return M24SR_ReceiveEnableVerificationRequirement();
01145         } else {
01146             mLastCommandSend = NONE;
01147             getCallback()->on_enable_verification_requirement(this, status, constToPasswordType(uReadOrWrite));
01148             return status;
01149         }//if-else
01150     }//if
01151 
01152     return M24SR_SUCCESS;
01153 }
01154 
01155 M24SR::StatusTypeDef M24SR::M24SR_ReceiveEnableVerificationRequirement(){
01156     M24SR::StatusTypeDef status;
01157     //TODO the size is 3?
01158     uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01159 
01160     const PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01161 
01162     status = M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
01163     if (status!=M24SR_SUCCESS) {
01164         getCallback()->on_enable_verification_requirement(this,status,type);
01165         return status;
01166     }//else
01167 
01168     status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01169     getCallback()->on_enable_verification_requirement(this,status,type);
01170     return status;
01171 }
01172 
01173 /**
01174  * @brief  This function sends the DisableVerificationRequirement command
01175  * @param   uReadOrWrite enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
01176  * @retval Status (SW1&SW2)   Status of the operation to complete.
01177  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01178  */
01179 M24SR::StatusTypeDef M24SR::M24SR_SendDisableVerificationRequirement(uint16_t uReadOrWrite) {
01180     C_APDU command;
01181     M24SR::StatusTypeDef status;
01182     uint8_t *pBuffer = uM24SRbuffer;
01183     uint16_t NbByte;
01184 
01185     /*check the parameters */
01186     if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
01187         getCallback()->on_disable_verification_requirement(this,M24SR_IO_ERROR_PARAMETER, constToPasswordType(uReadOrWrite));
01188         return M24SR_IO_ERROR_PARAMETER;
01189     }
01190 
01191     /* build the command */
01192     command.Header.CLA = C_APDU_CLA_DEFAULT;
01193     command.Header.INS = C_APDU_DISABLE;
01194     /* copy the Password Id */
01195     command.Header.P1 = GETMSB(uReadOrWrite);
01196     command.Header.P2 = GETLSB(uReadOrWrite);
01197     /* build the I²C command */
01198     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_DISABLEVERIFREQ, &command, uDIDbyte, &NbByte, pBuffer);
01199 
01200     /* send the request */
01201     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
01202     if (status != M24SR_SUCCESS) {
01203         getCallback()->on_disable_verification_requirement(this, status, constToPasswordType(uReadOrWrite));
01204         return status;
01205     }
01206 
01207     mLastCommandSend = DISABLE_VERIFICATION_REQUIREMENT;
01208     //use the offset filed for store the pwd id;
01209     mLastCommandData.offset = (uint8_t)uReadOrWrite;
01210 
01211     if (mCommunicationType==M24SR::SYNC) {
01212         status = M24SR_IO_PollI2C();
01213         if (status==M24SR_SUCCESS) {
01214             return M24SR_ReceiveDisableVerificationRequirement();
01215         } else {
01216             mLastCommandSend = NONE;
01217             getCallback()->on_disable_verification_requirement(this, status, constToPasswordType(uReadOrWrite));
01218             return status;
01219         }//if-else
01220     }
01221 
01222     return M24SR_SUCCESS;
01223 }
01224 
01225 M24SR::StatusTypeDef M24SR::M24SR_ReceiveDisableVerificationRequirement() {
01226     M24SR::StatusTypeDef status;
01227     //TODO the size is 3?
01228     uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01229 
01230     PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01231 
01232     status = M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
01233     if (status!=M24SR_SUCCESS) {
01234         getCallback()->on_disable_verification_requirement(this,status,type);
01235         return status;
01236     }//else
01237 
01238     status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01239     getCallback()->on_disable_verification_requirement(this,status,type);
01240     return status;
01241 }
01242 
01243 /**
01244  * @brief  This function sends the EnablePermananentState command
01245  * @param   uReadOrWrite   enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
01246  * @retval Status (SW1&SW2)   Status of the operation to complete.
01247  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01248  */
01249 M24SR::StatusTypeDef M24SR::M24SR_SendEnablePermanentState(uint16_t uReadOrWrite) {
01250     C_APDU command;
01251     M24SR::StatusTypeDef status;
01252 
01253     uint8_t *pBuffer = uM24SRbuffer;
01254     uint16_t NbByte;
01255 
01256     /*check the parameters */
01257     if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
01258         getCallback()->on_enable_permanent_state(this, M24SR_IO_ERROR_PARAMETER, constToPasswordType(uReadOrWrite));
01259         return M24SR_IO_ERROR_PARAMETER;
01260     }
01261 
01262     /* build the command */
01263     command.Header.CLA = C_APDU_CLA_ST;
01264     command.Header.INS = C_APDU_ENABLE;
01265     /* copy the Password Id */
01266     command.Header.P1 = GETMSB(uReadOrWrite);
01267     command.Header.P2 = GETLSB(uReadOrWrite);
01268     /* build the I2C command */
01269     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_ENABLEVERIFREQ, &command, uDIDbyte, &NbByte, pBuffer);
01270 
01271     /* send the request */
01272     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
01273     if (status != M24SR_SUCCESS) {
01274         getCallback()->on_enable_permanent_state(this, status, constToPasswordType(uReadOrWrite));
01275         return status;
01276     }
01277 
01278     mLastCommandSend = ENABLE_PERMANET_STATE;
01279     //use the offset filed for store the pwd id;
01280     mLastCommandData.offset = (uint8_t)uReadOrWrite;
01281 
01282     if (mCommunicationType==M24SR::SYNC) {
01283         status = M24SR_IO_PollI2C();
01284         if (status == M24SR_SUCCESS) {
01285             return M24SR_ReceiveEnablePermanentState();
01286         } else {
01287             mLastCommandSend = NONE;
01288             getCallback()->on_enable_permanent_state(this, status, constToPasswordType(uReadOrWrite));
01289             return status;
01290         }//if-else
01291     }
01292 
01293     return M24SR_SUCCESS;
01294 }
01295 
01296 M24SR::StatusTypeDef M24SR::M24SR_ReceiveEnablePermanentState() {
01297     M24SR::StatusTypeDef status;
01298     //TODO the size is 3?
01299     uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01300 
01301     PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01302 
01303     status = M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
01304     if (status!=M24SR_SUCCESS) {
01305         getCallback()->on_enable_permanent_state(this,status,type);
01306         return status;
01307     }//else
01308 
01309     status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01310     getCallback()->on_enable_permanent_state(this,status,type);
01311     return status;
01312 }
01313 
01314 /**
01315  * @brief  This function sends the DisablePermanentState command
01316  * @param   uReadOrWrite enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
01317  * @retval Status (SW1&SW2)   Status of the operation to complete.
01318  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01319  */
01320 M24SR::StatusTypeDef M24SR::M24SR_SendDisablePermanentState(uint16_t uReadOrWrite) {
01321     C_APDU command;
01322     M24SR::StatusTypeDef status;
01323     uint8_t *pBuffer = uM24SRbuffer;
01324     uint16_t NbByte;
01325 
01326     /*check the parameters */
01327     if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
01328         getCallback()->on_disable_permanent_state(this, M24SR_IO_ERROR_PARAMETER, constToPasswordType(uReadOrWrite));
01329         return M24SR_IO_ERROR_PARAMETER;
01330     }
01331 
01332     /* build the command */
01333     command.Header.CLA = C_APDU_CLA_ST;
01334     command.Header.INS = C_APDU_DISABLE;
01335     /* copy the Password Id */
01336     command.Header.P1 = GETMSB(uReadOrWrite);
01337     command.Header.P2 = GETLSB(uReadOrWrite);
01338     /* build the I2C command */
01339     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_DISABLEVERIFREQ, &command, uDIDbyte, &NbByte, pBuffer);
01340 
01341     /* send the request */
01342     status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
01343     if (status != M24SR_SUCCESS) {
01344         getCallback()->on_enable_permanent_state(this, status, constToPasswordType(uReadOrWrite));
01345         return status;
01346     }
01347 
01348     mLastCommandSend = DISABLE_PERMANET_STATE;
01349     //use the offset filed for store the pwd id;
01350     mLastCommandData.offset = (uint8_t)uReadOrWrite;
01351 
01352     if (mCommunicationType == M24SR::SYNC) {
01353         status = M24SR_IO_PollI2C();
01354         if (status == M24SR_SUCCESS) {
01355             return M24SR_ReceiveDisablePermanentState();
01356         } else {
01357             mLastCommandSend = NONE;
01358             getCallback()->on_disable_permanent_state(this, status, constToPasswordType(uReadOrWrite));
01359             return status;
01360         }//if-else
01361     }
01362 
01363     return M24SR_SUCCESS;
01364 }
01365 
01366 M24SR::StatusTypeDef M24SR::M24SR_ReceiveDisablePermanentState() {
01367     M24SR::StatusTypeDef status;
01368     //TODO the size is 3?
01369     uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
01370 
01371     PasswordType_t type = constToPasswordType(mLastCommandData.offset);
01372 
01373     status = M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
01374     if (status!=M24SR_SUCCESS) {
01375         getCallback()->on_disable_permanent_state(this,status,type);
01376         return status;
01377     }//else
01378 
01379     status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01380     getCallback()->on_disable_permanent_state(this,status,type);
01381     return status;
01382 }
01383 
01384 /**
01385  * @brief  This function generates an interrupt on GPO pin
01386  * @param   None
01387  * @retval Status (SW1&SW2)   Status of the operation to complete.
01388  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01389  */
01390 M24SR::StatusTypeDef M24SR::M24SR_SendInterrupt(void) {
01391     C_APDU command;
01392 
01393     uint8_t *pBuffer = uM24SRbuffer;
01394     uint16_t uP1P2 = 0x001E;
01395     uint16_t NbByte;
01396 
01397 
01398     StatusTypeDef status = M24SR_ManageI2CGPO(INTERRUPT);
01399     if (status!=M24SR_SUCCESS) {
01400         return status;
01401     }
01402 
01403     /* build the command */
01404     command.Header.CLA = C_APDU_CLA_ST;
01405     command.Header.INS = C_APDU_INTERRUPT;
01406     /* copy the Password Id */
01407     command.Header.P1 = GETMSB(uP1P2);
01408     command.Header.P2 = GETLSB(uP1P2);
01409     command.Body.LC = 0x00;
01410     /* build the I2C command */
01411     M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SENDINTERRUPT, &command, uDIDbyte, &NbByte, pBuffer);
01412 
01413     /* send the request */
01414     errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
01415     errchk(M24SR_IO_PollI2C());
01416     /* read the response */
01417     errchk(M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
01418 
01419     return M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01420 
01421 }
01422 
01423 /**
01424  * @brief  This function forces GPO pin to low state or high Z
01425  * @param   uSetOrReset select if GPO must be low (reset) or HiZ
01426  * @retval Status (SW1&SW2) Status of the operation to complete.
01427  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
01428  */
01429 M24SR::StatusTypeDef M24SR::M24SR_StateControl(uint8_t uSetOrReset) {
01430     C_APDU command;
01431     uint8_t *pBuffer = uM24SRbuffer;
01432     uint16_t uP1P2 = 0x001F;
01433     uint16_t NbByte;
01434 
01435     /*check the parameters */
01436     if ((uSetOrReset != 0x01) && (uSetOrReset != 0x00)) {
01437         return M24SR_IO_ERROR_PARAMETER;
01438     }
01439 
01440 
01441     StatusTypeDef status = M24SR_ManageI2CGPO(STATE_CONTROL);
01442     if (status == M24SR_SUCCESS) {
01443         return status;
01444     }
01445 
01446     /* build the command */
01447     command.Header.CLA = C_APDU_CLA_ST;
01448     command.Header.INS = C_APDU_INTERRUPT;
01449     /* copy the Password Id */
01450     command.Header.P1 = GETMSB(uP1P2);
01451     command.Header.P2 = GETLSB(uP1P2);
01452     command.Body.LC = 0x01;
01453     command.Body.pData = &uSetOrReset;
01454     /* copy the data */
01455     //memcpy(command.Body.pData , &uSetOrReset, 0x01 );
01456     //command.Body.LE = 0x00 ;
01457     /* build the I2C command */
01458     M24SR_BuildIBlockCommand( M24SR_CMDSTRUCT_GPOSTATE, &command, uDIDbyte, &NbByte, pBuffer);
01459 
01460     /* send the request */
01461     errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
01462     errchk(M24SR_IO_PollI2C());
01463     /* read the response */
01464     errchk(M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
01465 
01466     return M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
01467 }
01468 
01469 M24SR::StatusTypeDef M24SR::M24SR_ManageI2CGPO(NFC_GPO_MGMT GPO_I2Cconfig) {
01470 
01471     if (GPOPin.is_connected() == 0) {
01472         return M24SR_IO_PIN_NOT_CONNECTED;
01473     }
01474     if (GPO_I2Cconfig > STATE_CONTROL) {
01475         return M24SR_IO_ERROR_PARAMETER;
01476     }
01477 
01478     //enable the callback for change the gpo
01479     mComponentCallback = &mManageGPOCallback;
01480     mManageGPOCallback.set_new_GPO_config(true,GPO_I2Cconfig);
01481 
01482     //start the manageGPO procedure
01483     return M24SR_SendSelectApplication();
01484 }
01485 
01486 M24SR::StatusTypeDef M24SR::M24SR_ManageRFGPO(NFC_GPO_MGMT GPO_I2Cconfig) {
01487 
01488     if(RFDisablePin.is_connected()==0) {
01489         return M24SR_IO_PIN_NOT_CONNECTED;
01490     }
01491     if (GPO_I2Cconfig > STATE_CONTROL) {
01492         return M24SR_IO_ERROR_PARAMETER;
01493     }
01494 
01495     //enable the callback for change the gpo
01496     mComponentCallback = &mManageGPOCallback;
01497     mManageGPOCallback.set_new_GPO_config(false,GPO_I2Cconfig);
01498 
01499     //start the manageGPO procedure
01500     return M24SR_SendSelectApplication();
01501 }
01502 
01503 M24SR::StatusTypeDef M24SR::M24SR_RFConfig(uint8_t OnOffChoice) {
01504     if (RFDisablePin.is_connected()==0) {
01505         return M24SR_IO_PIN_NOT_CONNECTED;
01506     }
01507     /* Disable RF */
01508     if (OnOffChoice != 0) {
01509         M24SR_IO_RFDIS_WritePin(GPIO_PIN_RESET);
01510     } else {
01511         M24SR_IO_RFDIS_WritePin(GPIO_PIN_SET);
01512     }
01513     return M24SR_SUCCESS;
01514 }
01515 
01516 M24SR::StatusTypeDef M24SR::M24SR_IO_SendI2Ccommand(uint8_t NbByte, uint8_t *pBuffer) {
01517     int ret = dev_I2C.write(address, (char*) pBuffer, NbByte);
01518     if (ret == 0) {
01519         return M24SR_SUCCESS;
01520     }
01521     return M24SR_IO_ERROR_I2CTIMEOUT;
01522 }
01523 
01524 M24SR::StatusTypeDef M24SR::M24SR_IO_ReceiveI2Cresponse(uint8_t NbByte, uint8_t *pBuffer) {
01525     int ret = dev_I2C.read(address, (char*) pBuffer, NbByte);
01526     if (ret == 0) {
01527         return M24SR_SUCCESS;
01528     }
01529 
01530     return M24SR_IO_ERROR_I2CTIMEOUT;
01531 }
01532 
01533 M24SR::StatusTypeDef M24SR::M24SR_IO_PollI2C(void) {
01534 
01535     int status = 1;
01536     while (status != 0 ) {
01537         //send the device address and wait to recevie an ack bit
01538         status = dev_I2C.write(address,NULL,0);
01539     }
01540     return M24SR_SUCCESS;
01541 }
01542 
01543 M24SR::StatusTypeDef M24SR::manage_event(void){
01544 
01545     switch(mLastCommandSend) {
01546         case SELECT_APPLICATION:
01547             return M24SR_ReceiveSelectApplication();
01548         case SELECT_CC_FILE:
01549             return M24SR_ReceiveSelectCCfile();
01550         case SELECT_NDEF_FILE:
01551             return M24SR_ReceiveSelectNDEFfile();
01552         case SELECT_SYSTEM_FILE:
01553             return M24SR_ReceiveSelectSystemfile();
01554         case READ:
01555             return M24SR_ReceiveReadBinary();
01556         case UPDATE:
01557             return M24SR_ReceiveUpdateBinary();
01558         case VERIFY:
01559             return M24SR_ReceiveVerify();
01560         case DESELECT:
01561             return M24SR_ReceiveDeselect();
01562         case CHANGE_REFERENCE_DATA:
01563             return M24SR_ReceiveChangeReferenceData();
01564         case ENABLE_VERIFICATION_REQUIREMENT:
01565             return M24SR_ReceiveEnableVerificationRequirement();
01566         case DISABLE_VERIFICATION_REQUIREMENT:
01567             return M24SR_ReceiveDisableVerificationRequirement();
01568         case ENABLE_PERMANET_STATE:
01569             return M24SR_ReceiveEnablePermanentState();
01570         case DISABLE_PERMANET_STATE:
01571             return M24SR_ReceiveDisablePermanentState();
01572         default:
01573             return M24SR_SUCCESS;
01574     }//switch
01575 }//manageInterrupt
01576 
01577 NDefLib::NDefNfcTag&M24SR::get_NDef_tag(){
01578     return *mNDefTagUtil;
01579 }
01580 
01581 
01582 /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/