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.
Dependencies: ST_INTERFACES
Fork of M24SR by
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>© 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****/
Generated on Wed Jul 13 2022 05:23:50 by
1.7.2
