1639 lines
50 KiB
C
1639 lines
50 KiB
C
/**
|
||
******************************************************************************
|
||
* @file m24sr.c
|
||
* @author MCD Application Team
|
||
* @brief This file provides a set of functions to interface with the M24SR
|
||
* device.
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* <h2><center>© Copyright (c) 2017 STMicroelectronics.
|
||
* All rights reserved.</center></h2>
|
||
*
|
||
* This software component is licensed by ST under BSD 3-Clause license,
|
||
* the "License"; You may not use this file except in compliance with the
|
||
* License. You may obtain a copy of the License at:
|
||
* opensource.org/licenses/BSD-3-Clause
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
|
||
/* Includes ------------------------------------------------------------------*/
|
||
#include "string.h"
|
||
#include "m24sr.h"
|
||
|
||
/** @addtogroup BSP
|
||
* @{
|
||
*/
|
||
|
||
/** @addtogroup Components
|
||
* @{
|
||
*/
|
||
|
||
/** @addtogroup M24SR
|
||
* @{
|
||
* @brief <b>This folder contains the driver layer of M24SR family (M24SR64, M24SR16, M24SR04, M24SR02)</b>
|
||
*/
|
||
|
||
/** @defgroup M24SR_Private_Types M24SR Driver Private Types
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Synchronization Mechanism structure
|
||
*/
|
||
typedef enum{
|
||
M24SR_WAITINGTIME_UNKNOWN= 0,
|
||
M24SR_WAITINGTIME_POLLING,
|
||
M24SR_WAITINGTIME_TIMEOUT,
|
||
M24SR_WAITINGTIME_GPO,
|
||
M24SR_INTERRUPT_GPO
|
||
}M24SR_WAITINGTIME_MGMT;
|
||
|
||
/**
|
||
* @brief APDU-Header command structure
|
||
*/
|
||
typedef struct
|
||
{
|
||
uint8_t CLA; /* Command class */
|
||
uint8_t INS; /* Operation code */
|
||
uint8_t P1; /* Selection Mode */
|
||
uint8_t P2; /* Selection Option */
|
||
} C_APDU_Header;
|
||
|
||
/**
|
||
* @brief APDU-Body command structure
|
||
*/
|
||
typedef struct
|
||
{
|
||
uint8_t LC; /* Data field length */
|
||
uint8_t *pData ; /* Command parameters */
|
||
uint8_t LE; /* Expected length of data to be returned */
|
||
} C_APDU_Body;
|
||
|
||
/**
|
||
* @brief APDU Command structure
|
||
*/
|
||
typedef struct
|
||
{
|
||
C_APDU_Header Header;
|
||
C_APDU_Body Body;
|
||
} C_APDU;
|
||
|
||
/**
|
||
* @brief SC response structure
|
||
*/
|
||
typedef struct
|
||
{
|
||
uint8_t *pData ; /* Data returned from the card */
|
||
/* pointer on the transceiver buffer = ReaderRecBuf[CR95HF_DATA_OFFSET ]; */
|
||
uint8_t SW1; /* Command Processing status */
|
||
uint8_t SW2; /* Command Processing qualification */
|
||
} R_APDU;
|
||
|
||
/**
|
||
* @brief GPO state structure
|
||
*/
|
||
typedef enum{
|
||
HIGH_IMPEDANCE= 0,
|
||
SESSION_OPENED,
|
||
WIP,
|
||
I2C_ANSWER_READY,
|
||
INTERRUPT,
|
||
STATE_CONTROL
|
||
}M24SR_GPO_MGMT;
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
/** @defgroup M24SR_Private_Constants M24SR Driver Private Constants
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief M24SR_Private_Code_Status
|
||
*/
|
||
#define UB_STATUS_OFFSET 4
|
||
#define LB_STATUS_OFFSET 3
|
||
|
||
#define M24SR_NBBYTE_INVALID 0xFFFE
|
||
|
||
/**
|
||
* @brief M24SR_Private_File_Identifier
|
||
*/
|
||
#define SYSTEM_FILE_ID 0xE101
|
||
#define CC_FILE_ID 0xE103
|
||
#define NDEF_FILE_ID 0x0001
|
||
|
||
/**
|
||
* @brief M24SR_Private_Command_Management
|
||
*/
|
||
/* special M24SR command ----------------------------------------------------------------------*/
|
||
#define M24SR_OPENSESSION 0x26
|
||
#define M24SR_KILLSESSION 0x52
|
||
|
||
/* APDU Command: class list -------------------------------------------*/
|
||
#define C_APDU_CLA_DEFAULT 0x00
|
||
#define C_APDU_CLA_ST 0xA2
|
||
|
||
/*------------------------ Data Area Management Commands ---------------------*/
|
||
#define C_APDU_SELECT_FILE 0xA4
|
||
#define C_APDU_GET_RESPONCE 0xC0
|
||
#define C_APDU_STATUS 0xF2
|
||
#define C_APDU_UPDATE_BINARY 0xD6
|
||
#define C_APDU_READ_BINARY 0xB0
|
||
#define C_APDU_WRITE_BINARY 0xD0
|
||
#define C_APDU_UPDATE_RECORD 0xDC
|
||
#define C_APDU_READ_RECORD 0xB2
|
||
|
||
/*-------------------------- Safety Management Commands ----------------------*/
|
||
#define C_APDU_VERIFY 0x20
|
||
#define C_APDU_CHANGE 0x24
|
||
#define C_APDU_DISABLE 0x26
|
||
#define C_APDU_ENABLE 0x28
|
||
|
||
/*-------------------------- Gpio Management Commands ------------------------*/
|
||
#define C_APDU_INTERRUPT 0xD6
|
||
|
||
/* Length ----------------------------------------------------------------------------------*/
|
||
#define M24SR_STATUS_NBBYTE 2
|
||
#define M24SR_CRC_NBBYTE 2
|
||
#define M24SR_STATUSRESPONSE_NBBYTE 5
|
||
#define M24SR_DESELECTREQUEST_NBBYTE 3
|
||
#define M24SR_DESELECTRESPONSE_NBBYTE 3
|
||
#define M24SR_WATINGTIMEEXTRESPONSE_NBBYTE 4
|
||
#define M24SR_PASSWORD_NBBYTE 0x10
|
||
|
||
/* Command structure ------------------------------------------------------------------------*/
|
||
#define M24SR_CMDSTRUCT_SELECTAPPLICATION 0x01FF
|
||
#define M24SR_CMDSTRUCT_SELECTCCFILE 0x017F
|
||
#define M24SR_CMDSTRUCT_SELECTNDEFFILE 0x017F
|
||
#define M24SR_CMDSTRUCT_READBINARY 0x019F
|
||
#define M24SR_CMDSTRUCT_UPDATEBINARY 0x017F
|
||
#define M24SR_CMDSTRUCT_VERIFYBINARYWOPWD 0x013F
|
||
#define M24SR_CMDSTRUCT_VERIFYBINARYWITHPWD 0x017F
|
||
#define M24SR_CMDSTRUCT_CHANGEREFDATA 0x017F
|
||
#define M24SR_CMDSTRUCT_ENABLEVERIFREQ 0x011F
|
||
#define M24SR_CMDSTRUCT_DISABLEVERIFREQ 0x011F
|
||
#define M24SR_CMDSTRUCT_SENDINTERRUPT 0x013F
|
||
#define M24SR_CMDSTRUCT_GPOSTATE 0x017F
|
||
|
||
/* Command structure Mask -------------------------------------------------------------------*/
|
||
#define M24SR_PCB_NEEDED 0x0001 /* PCB byte present or not */
|
||
#define M24SR_CLA_NEEDED 0x0002 /* CLA byte present or not */
|
||
#define M24SR_INS_NEEDED 0x0004 /* Operation code present or not*/
|
||
#define M24SR_P1_NEEDED 0x0008 /* Selection Mode present or not*/
|
||
#define M24SR_P2_NEEDED 0x0010 /* Selection Option present or not*/
|
||
#define M24SR_LC_NEEDED 0x0020 /* Data field length byte present or not */
|
||
#define M24SR_DATA_NEEDED 0x0040 /* Data present or not */
|
||
#define M24SR_LE_NEEDED 0x0080 /* Expected length present or not */
|
||
#define M24SR_CRC_NEEDED 0x0100 /* 2 CRC bytes present or not */
|
||
|
||
#define M24SR_DID_NEEDED 0x08 /* DID byte present or not */
|
||
|
||
/**
|
||
* @brief M24SR_Private_Offset_and_masks
|
||
*/
|
||
|
||
/* Offset ----------------------------------------------------------------------------------*/
|
||
#define M24SR_OFFSET_PCB 0
|
||
#define M24SR_OFFSET_CLASS 1
|
||
#define M24SR_OFFSET_INS 2
|
||
#define M24SR_OFFSET_P1 3
|
||
|
||
/* mask ------------------------------------------------------------------------------------*/
|
||
#define M24SR_MASK_BLOCK 0xC0
|
||
#define M24SR_MASK_IBLOCK 0x00
|
||
#define M24SR_MASK_RBLOCK 0x80
|
||
#define M24SR_MASK_SBLOCK 0xC0
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
/** @defgroup M24SR_Private_Variables M24SR Private Global Variables
|
||
* @{
|
||
*/
|
||
|
||
static C_APDU Command;
|
||
static uint8_t DataBuffer[0xFF];
|
||
uint8_t uM24SRbuffer [0xFF];
|
||
static uint8_t uDIDbyte =0x00;
|
||
|
||
uint8_t uSynchroMode = M24SR_WAITINGTIME_POLLING;
|
||
uint8_t uGpoMode = M24SR_GPO_POLLING;
|
||
volatile uint8_t GPO_Low = 0;
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/** @defgroup M24SR_Private_Macros M24SR Private Macros
|
||
* @{
|
||
*/
|
||
|
||
/** @brief Get Most Significant Byte
|
||
* @param val: number where MSB must be extracted
|
||
* @retval MSB
|
||
*/
|
||
#define GETMSB(val) ( (uint8_t) ((val & 0xFF00 )>>8) )
|
||
|
||
/** @brief Get Least Significant Byte
|
||
* @param val: number where LSB must be extracted
|
||
* @retval LSB
|
||
*/
|
||
#define GETLSB(val) ( (uint8_t) (val & 0x00FF ))
|
||
|
||
/** @brief Used to toggle the block number by adding 0 or 1 to default block number value
|
||
* @param val: number to know if incrementation is needed
|
||
* @retval 0 or 1 if incrementation needed
|
||
*/
|
||
#define TOGGLE(val) ((val != 0x00)? 0x00 : 0x01)
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
/** @defgroup M24SR_Private_FunctionsPrototypes M24SR Private FunctionsPrototypes
|
||
* @{
|
||
*/
|
||
|
||
static uint16_t M24SR_UpdateCrc ( uint8_t ch, uint16_t *lpwCrc);
|
||
static uint16_t M24SR_ComputeCrc ( uint8_t *Data, uint8_t Length);
|
||
static uint16_t M24SR_IsCorrectCRC16Residue ( uint8_t *DataIn,uint8_t Length);
|
||
static void M24SR_BuildIBlockCommand ( uint16_t CommandStructure, C_APDU Command, uint16_t *NbByte , uint8_t *pCommand);
|
||
static uint16_t IsSBlock ( uint8_t *pBuffer);
|
||
static uint16_t M24SR_FWTExtension ( uint16_t DeviceAddr, uint8_t FWTbyte);
|
||
static void M24SR_SetI2CSynchroMode ( uint8_t WaitingMode );
|
||
static uint16_t M24SR_IsAnswerReady ( uint16_t DeviceAddr);
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
/** @defgroup M24SR_Private_Functions M24SR Private Functions
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief This function updates the CRC
|
||
* @param None
|
||
* @retval None
|
||
*/
|
||
static uint16_t M24SR_UpdateCrc (uint8_t ch, uint16_t *lpwCrc)
|
||
{
|
||
ch = (ch^(uint8_t)((*lpwCrc) & 0x00FF));
|
||
ch = (ch^(ch<<4));
|
||
*lpwCrc = (*lpwCrc >> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4);
|
||
|
||
return(*lpwCrc);
|
||
}
|
||
|
||
/**
|
||
* @brief This function returns the CRC 16
|
||
* @param Data : pointer on the data used to compute the CRC16
|
||
* @param Length : number of byte of the data
|
||
* @retval CRC16
|
||
*/
|
||
static uint16_t M24SR_ComputeCrc(uint8_t *Data, uint8_t Length)
|
||
{
|
||
uint8_t chBlock;
|
||
uint16_t wCrc;
|
||
|
||
wCrc = 0x6363; /* ITU-V.41 */
|
||
|
||
do {
|
||
chBlock = *Data++;
|
||
M24SR_UpdateCrc(chBlock, &wCrc);
|
||
} while (--Length);
|
||
|
||
return wCrc ;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function computes the CRC16 residue as defined by CRC ISO/IEC 13239
|
||
* @param DataIn : input to data
|
||
* @param Length : Number of bits of DataIn
|
||
* @retval Status (SW1&SW2) : CRC16 residue is correct
|
||
* @retval M24SR_ERROR_CRC : CRC16 residue is false
|
||
*/
|
||
static uint16_t M24SR_IsCorrectCRC16Residue (uint8_t *DataIn,uint8_t Length)
|
||
{
|
||
uint16_t ResCRC=0;
|
||
|
||
/* check the CRC16 Residue */
|
||
if (Length !=0)
|
||
ResCRC= M24SR_ComputeCrc (DataIn, Length);
|
||
|
||
if ( ResCRC == 0x0000)
|
||
{
|
||
/* Good CRC, but error status from M24SR */
|
||
return( ((DataIn[Length-UB_STATUS_OFFSET]<<8) & 0xFF00) | (DataIn[Length-LB_STATUS_OFFSET] & 0x00FF) );
|
||
}
|
||
else
|
||
{
|
||
ResCRC=0;
|
||
ResCRC= M24SR_ComputeCrc (DataIn, 5);
|
||
if ( ResCRC != 0x0000)
|
||
{
|
||
/* Bad CRC */
|
||
return M24SR_ERROR_CRC;
|
||
}
|
||
else
|
||
{
|
||
/* Good CRC, but error status from M24SR */
|
||
return( ((DataIn[1]<<8) & 0xFF00) | (DataIn[2] & 0x00FF) );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This functions creates an I block command according to the structures CommandStructure and Command.
|
||
* @param Command : structue which contains the field of the different parameter
|
||
* @param CommandStructure : structure that contain the structure of the command (if the different field are presnet or not
|
||
* @param NbByte : number of byte of the command
|
||
* @param pCommand : pointer of the command created
|
||
*/
|
||
static void M24SR_BuildIBlockCommand ( uint16_t CommandStructure, C_APDU Command, uint16_t *NbByte , uint8_t *pCommand)
|
||
{
|
||
uint16_t uCRC16;
|
||
static uint8_t BlockNumber = 0x01;
|
||
|
||
(*NbByte) = 0;
|
||
|
||
/* add the PCD byte */
|
||
if ((CommandStructure & M24SR_PCB_NEEDED) !=0)
|
||
{
|
||
/* toggle the block number */
|
||
BlockNumber = TOGGLE ( BlockNumber );
|
||
/* Add the I block byte */
|
||
pCommand[(*NbByte)++] = 0x02 | BlockNumber;
|
||
}
|
||
|
||
/* add the DID byte */
|
||
if ((BlockNumber & M24SR_DID_NEEDED) !=0)
|
||
{
|
||
/* Add the I block byte */
|
||
pCommand[(*NbByte)++] = uDIDbyte;
|
||
}
|
||
|
||
/* add the Class byte */
|
||
if ((CommandStructure & M24SR_CLA_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Header.CLA ;
|
||
}
|
||
/* add the instruction byte byte */
|
||
if ( (CommandStructure & M24SR_INS_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Header.INS ;
|
||
}
|
||
/* add the Selection Mode byte */
|
||
if ((CommandStructure & M24SR_P1_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Header.P1 ;
|
||
}
|
||
/* add the Selection Mode byte */
|
||
if ((CommandStructure & M24SR_P2_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Header.P2 ;
|
||
}
|
||
/* add Data field lengthbyte */
|
||
if ((CommandStructure & M24SR_LC_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Body.LC ;
|
||
}
|
||
/* add Data field */
|
||
if ((CommandStructure & M24SR_DATA_NEEDED) !=0)
|
||
{
|
||
memcpy(&(pCommand[(*NbByte)]) ,Command.Body.pData,Command.Body.LC ) ;
|
||
(*NbByte) += Command.Body.LC ;
|
||
}
|
||
/* add Le field */
|
||
if ((CommandStructure & M24SR_LE_NEEDED) !=0)
|
||
{
|
||
pCommand[(*NbByte)++] = Command.Body.LE ;
|
||
}
|
||
/* add CRC field */
|
||
if ((CommandStructure & M24SR_CRC_NEEDED) !=0)
|
||
{
|
||
uCRC16 = M24SR_ComputeCrc (pCommand,(uint8_t) (*NbByte));
|
||
/* append the CRC16 */
|
||
pCommand [(*NbByte)++] = GETLSB (uCRC16 ) ;
|
||
pCommand [(*NbByte)++] = GETMSB (uCRC16 ) ;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function return M24SR_STATUS_SUCCESS if the pBuffer is an s-block
|
||
* @param pBuffer : pointer of the data
|
||
* @retval M24SR_STATUS_SUCCESS : the data is a S-Block
|
||
* @retval M24SR_ERROR_DEFAULT : the data is not a S-Block
|
||
*/
|
||
static uint16_t IsSBlock (uint8_t *pBuffer)
|
||
{
|
||
|
||
if ((pBuffer[M24SR_OFFSET_PCB] & M24SR_MASK_BLOCK) == M24SR_MASK_SBLOCK)
|
||
{
|
||
return M24SR_STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
return M24SR_ERROR_DEFAULT;
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief This function sends the FWT extension command (S-Block format)
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param FWTbyte : FWT value
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
static uint16_t M24SR_FWTExtension (uint16_t DeviceAddr, uint8_t FWTbyte)
|
||
{
|
||
uint8_t pBuffer[M24SR_STATUSRESPONSE_NBBYTE];
|
||
uint16_t status ;
|
||
uint16_t NthByte = 0,
|
||
uCRC16;
|
||
|
||
/* create the response */
|
||
pBuffer[NthByte++] = 0xF2 ;
|
||
pBuffer[NthByte++] = FWTbyte ;
|
||
/* compute the CRC */
|
||
uCRC16 = M24SR_ComputeCrc (pBuffer,0x02);
|
||
/* append the CRC16 */
|
||
pBuffer [NthByte++] = GETLSB (uCRC16 ) ;
|
||
pBuffer [NthByte++]= GETMSB (uCRC16 ) ;
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NthByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
if ( NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
/** @defgroup M24SR_Exported_Functions M24SR Exported Functions
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief This function initialize the M24SR device
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param GpoMode: M24SR_GPO_POLLING / M24SR_GPO_SYNCHRO / M24SR_GPO_INTERRUPT
|
||
* @retval None
|
||
*/
|
||
void M24SR_Init(uint16_t DeviceAddr, uint8_t GpoMode)
|
||
{
|
||
uGpoMode = GpoMode; /* Global variable initialization */
|
||
|
||
if(uGpoMode == M24SR_GPO_INTERRUPT)
|
||
{
|
||
NFC_IO_Init(0x1);
|
||
}
|
||
else
|
||
{
|
||
NFC_IO_Init(0x0);
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = 0x00;
|
||
Command.Header.INS = 0x00;
|
||
/* copy the offset */
|
||
Command.Header.P1 = 0x00 ;
|
||
Command.Header.P2 = 0x00 ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = 0x00 ;
|
||
/* copy the number of byte to read */
|
||
Command.Body.LE = 0x00 ;
|
||
Command.Body.pData = DataBuffer;
|
||
|
||
if((uGpoMode == M24SR_GPO_SYNCHRO) || (uGpoMode == M24SR_GPO_INTERRUPT))
|
||
{
|
||
if( M24SR_KillSession(DeviceAddr) == M24SR_ACTION_COMPLETED)
|
||
{
|
||
M24SR_ManageI2CGPO(DeviceAddr, I2C_ANSWER_READY);
|
||
M24SR_Deselect (DeviceAddr);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief This function initialize the M24SR device
|
||
* @retval None
|
||
*/
|
||
void M24SR_GPO_Callback( void )
|
||
{
|
||
if( uSynchroMode == M24SR_INTERRUPT_GPO)
|
||
{
|
||
GPO_Low = 1;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief This function sends the GetSession command to the M24SR device
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_ACTION_COMPLETED : the function is succesful.
|
||
* @retval Status (SW1&SW2) : if operation does not complete.
|
||
*/
|
||
uint16_t M24SR_GetSession (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t Buffer = M24SR_OPENSESSION;
|
||
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, &Buffer, 0x01 ) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* Insure no access will be done just after open session */
|
||
/* The only way here is to poll I2C to know when M24SR is ready */
|
||
/* GPO can not be use with GetSession command */
|
||
if (NFC_IO_IsDeviceReady(DeviceAddr, NFC_IO_TRIALS) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
return M24SR_ACTION_COMPLETED;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the KillSession command to the M24SR device
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_ACTION_COMPLETED : the function is succesful.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_KillSession (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t pBuffer[] = {M24SR_KILLSESSION};
|
||
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, 0x01) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* Insure no access will be done just after open session */
|
||
/* The only way here is to poll I2C to know when M24SR is ready */
|
||
/* GPO can not be use with KillSession command */
|
||
if (NFC_IO_IsDeviceReady(DeviceAddr, NFC_IO_TRIALS) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
return M24SR_ACTION_COMPLETED;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the Deselect command (S-Block format)
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_ACTION_COMPLETED : the function is succesful.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_Deselect (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t pBuffer[] = {0xC2,0xE0,0xB4} ;
|
||
uint16_t status ;
|
||
|
||
/* send the request */
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, M24SR_DESELECTREQUEST_NBBYTE) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* flush the M24SR buffer */
|
||
if (NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_DESELECTREQUEST_NBBYTE) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
return M24SR_ACTION_COMPLETED;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the SelectApplication command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_ACTION_COMPLETED : the function is succesful.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_SelectApplication (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ,
|
||
NbByteToRead = M24SR_STATUSRESPONSE_NBBYTE;
|
||
uint8_t uLc = 0x07,
|
||
pData[] = {0xD2,0x76,0x00,0x00,0x85,0x01,0x01},
|
||
uLe = 0x00;
|
||
uint16_t status ;
|
||
uint16_t uP1P2 =0x0400,
|
||
NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_SELECT_FILE;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = uLc ;
|
||
/* copy the data */
|
||
memcpy(Command.Body.pData, pData, uLc);
|
||
/* copy the number of byte to read */
|
||
Command.Body.LE = uLe ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SELECTAPPLICATION, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
if (NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the SelectCCFile command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_ACTION_COMPLETED : the function is succesful.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
* @retval Status (SW1&SW2) : if operation does not complete for another reason.
|
||
*/
|
||
uint16_t M24SR_SelectCCfile (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ,
|
||
NbByteToRead = M24SR_STATUSRESPONSE_NBBYTE;
|
||
uint8_t uLc = 0x02;
|
||
uint16_t status ;
|
||
uint16_t uP1P2 =0x000C,
|
||
uNbFileId =CC_FILE_ID,
|
||
NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_SELECT_FILE;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = uLc ;
|
||
/* copy the File Id */
|
||
Command.Body.pData[0] = GETMSB (uNbFileId ) ;
|
||
Command.Body.pData[1] = GETLSB (uNbFileId ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SELECTCCFILE, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
if (NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the SelectSystemFile command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_SelectSystemfile (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ,
|
||
NbByteToRead = M24SR_STATUSRESPONSE_NBBYTE;
|
||
uint8_t uLc = 0x02;
|
||
uint16_t status ;
|
||
uint16_t uP1P2 =0x000C,
|
||
uNbFileId =SYSTEM_FILE_ID,
|
||
NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_SELECT_FILE;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = uLc ;
|
||
/* copy the File Id */
|
||
Command.Body.pData[0] = GETMSB (uNbFileId ) ;
|
||
Command.Body.pData[1] = GETLSB (uNbFileId ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SELECTCCFILE, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
if (NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the SelectNDEFfile command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param NDEFfileId: NDEF identification to select NDEF in M24SR
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_SelectNDEFfile (uint16_t DeviceAddr, uint16_t NDEFfileId)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ,
|
||
NbByteToRead = M24SR_STATUSRESPONSE_NBBYTE;
|
||
uint8_t uLc = 0x02;
|
||
uint16_t status ;
|
||
uint16_t uP1P2 =0x000C,
|
||
NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_SELECT_FILE;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = uLc ;
|
||
/* copy the offset */
|
||
Command.Body.pData[0] = GETMSB (NDEFfileId ) ;
|
||
Command.Body.pData[1] = GETLSB (NDEFfileId ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SELECTNDEFFILE, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
if (NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
if (NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends a read binary command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param Offset : first byte to read
|
||
* @param NbByteToRead : number of byte to read
|
||
* @param pBufferRead : pointer of the buffer read from the M24SR device
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_ReadBinary (uint16_t DeviceAddr, uint16_t Offset ,uint8_t NbByteToRead , uint8_t *pBufferRead)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_READ_BINARY;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (Offset ) ;
|
||
Command.Header.P2 = GETLSB (Offset ) ;
|
||
/* copy the number of byte to read */
|
||
Command.Body.LE = NbByteToRead ;
|
||
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_READBINARY, Command, &NbByte , pBuffer);
|
||
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead+ M24SR_STATUSRESPONSE_NBBYTE);
|
||
/* retrieve the data without SW1 & SW2 as provided as return value of the function */
|
||
memcpy(pBufferRead ,&pBuffer[1],NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends a ST read binary command (no error if access is not inside NDEF file)
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param Offset : first byte to read
|
||
* @param NbByteToRead : number of byte to read
|
||
* @param pBufferRead : pointer of the buffer read from the M24SR device
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_STReadBinary (uint16_t DeviceAddr, uint16_t Offset, uint8_t NbByteToRead, uint8_t *pBufferRead)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_ST;
|
||
Command.Header.INS = C_APDU_READ_BINARY;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (Offset ) ;
|
||
Command.Header.P2 = GETLSB (Offset ) ;
|
||
/* copy the number of byte to read */
|
||
Command.Body.LE = NbByteToRead ;
|
||
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_READBINARY, Command, &NbByte , pBuffer);
|
||
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead+ M24SR_STATUSRESPONSE_NBBYTE);
|
||
/* retrieve the data without SW1 & SW2 as provided as return value of the function */
|
||
memcpy(pBufferRead ,&pBuffer[1],NbByteToRead);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends a Update binary command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param Offset : first byte to read
|
||
* @param NbByteToWrite : number of byte to write
|
||
* @param pBufferRead : pointer of the buffer read from the M24SR device
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_UpdateBinary (uint16_t DeviceAddr, uint16_t Offset ,uint8_t NbByteToWrite,uint8_t *pDataToWrite)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_UPDATE_BINARY;
|
||
/* copy the offset */
|
||
Command.Header.P1 = GETMSB (Offset ) ;
|
||
Command.Header.P2 = GETLSB (Offset ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = NbByteToWrite ;
|
||
/* copy the File Id */
|
||
memcpy(Command.Body.pData ,pDataToWrite, NbByteToWrite );
|
||
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_UPDATEBINARY, Command, &NbByte , pBuffer);
|
||
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* if the response is a Watiting frame extenstion request */
|
||
if (IsSBlock (pBuffer) == M24SR_STATUS_SUCCESS)
|
||
{
|
||
/*check the CRC */
|
||
if (M24SR_IsCorrectCRC16Residue (pBuffer , M24SR_WATINGTIMEEXTRESPONSE_NBBYTE) != M24SR_ERROR_CRC)
|
||
{
|
||
/* send the FrameExension response*/
|
||
status = M24SR_FWTExtension (DeviceAddr, pBuffer [M24SR_OFFSET_PCB+1]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the Verify command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uPwdId : PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
|
||
* @param NbPwdByte : Number of byte ( 0x00 or 0x10)
|
||
* @param pPwd : pointer on the passwaord
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_Verify (uint16_t DeviceAddr, uint16_t uPwdId, uint8_t NbPwdByte ,uint8_t *pPwd)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer ;
|
||
uint16_t status = 0x0000 ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if (uPwdId > 0x0003)
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
if ( (NbPwdByte != 0x00) && (NbPwdByte != 0x10))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_VERIFY;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uPwdId ) ;
|
||
Command.Header.P2 = GETLSB (uPwdId ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = NbPwdByte ;
|
||
|
||
if (NbPwdByte == 0x10)
|
||
{
|
||
/* copy the password */
|
||
memcpy(Command.Body.pData, pPwd, NbPwdByte);
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_VERIFYBINARYWITHPWD, Command, &NbByte , pBuffer);
|
||
}
|
||
else
|
||
{
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_VERIFYBINARYWOPWD, Command, &NbByte , pBuffer);
|
||
}
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* wait for answer ready */
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the ChangeReferenceData command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uPwdId : PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
|
||
* @param pPwd : pointer on the passwaord
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_ChangeReferenceData (uint16_t DeviceAddr, uint16_t uPwdId, uint8_t *pPwd)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if (uPwdId > 0x0003)
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_CHANGE;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uPwdId ) ;
|
||
Command.Header.P2 = GETLSB (uPwdId ) ;
|
||
/* copy the number of byte of the data field */
|
||
Command.Body.LC = M24SR_PASSWORD_NBBYTE ;
|
||
/* copy the password */
|
||
memcpy(Command.Body.pData, pPwd, M24SR_PASSWORD_NBBYTE);
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_CHANGEREFDATA, Command, &NbByte , pBuffer);
|
||
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the EnableVerificationRequirement command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write )
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_EnableVerificationRequirement (uint16_t DeviceAddr, uint16_t uReadOrWrite)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_ENABLE;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uReadOrWrite ) ;
|
||
Command.Header.P2 = GETLSB (uReadOrWrite ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_ENABLEVERIFREQ, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* The right access to be updated in EEPROM need at least 6ms */
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the DisableVerificationRequirement command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write )
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_DisableVerificationRequirement (uint16_t DeviceAddr, uint16_t uReadOrWrite)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_DEFAULT;
|
||
Command.Header.INS = C_APDU_DISABLE;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uReadOrWrite ) ;
|
||
Command.Header.P2 = GETLSB (uReadOrWrite ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_DISABLEVERIFREQ, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
/* The right access to be updated in EEPROM need at least 6ms */
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the EnablePermananentState command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write )
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_EnablePermanentState (uint16_t DeviceAddr, uint16_t uReadOrWrite )
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_ST;
|
||
Command.Header.INS = C_APDU_ENABLE;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uReadOrWrite ) ;
|
||
Command.Header.P2 = GETLSB (uReadOrWrite ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_ENABLEVERIFREQ, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function sends the DisablePermanentState command
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write )
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_DisablePermanentState (uint16_t DeviceAddr, uint16_t uReadOrWrite )
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_ST;
|
||
Command.Header.INS = C_APDU_DISABLE;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uReadOrWrite ) ;
|
||
Command.Header.P2 = GETLSB (uReadOrWrite ) ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_DISABLEVERIFREQ, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @brief This function generates a interrupt on GPO pin
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_SendInterrupt (uint16_t DeviceAddr)
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t uP1P2 =0x001E;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
status = M24SR_ManageI2CGPO(DeviceAddr, INTERRUPT);
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_ST;
|
||
Command.Header.INS = C_APDU_INTERRUPT;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
Command.Body.LC = 0x00 ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SENDINTERRUPT, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @brief This function force GPO pin to low state or high Z
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param uSetOrReset : select if GPO must be low (reset) or HiZ
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
* @retval M24SR_ERROR_TIMEOUT : The I2C timeout occured.
|
||
*/
|
||
uint16_t M24SR_StateControl (uint16_t DeviceAddr, uint8_t uSetOrReset )
|
||
{
|
||
uint8_t *pBuffer = uM24SRbuffer;
|
||
uint16_t uP1P2 =0x001F;
|
||
uint16_t status ;
|
||
uint16_t NbByte;
|
||
|
||
/*check the parameters */
|
||
if ( (uSetOrReset != 0x01) && (uSetOrReset != 0x00))
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
status = M24SR_ManageI2CGPO(DeviceAddr, STATE_CONTROL);
|
||
|
||
/* build the command */
|
||
Command.Header.CLA = C_APDU_CLA_ST;
|
||
Command.Header.INS = C_APDU_INTERRUPT;
|
||
/* copy the Password Id */
|
||
Command.Header.P1 = GETMSB (uP1P2 ) ;
|
||
Command.Header.P2 = GETLSB (uP1P2 ) ;
|
||
Command.Body.LC = 0x01 ;
|
||
/* copy the data */
|
||
memcpy(Command.Body.pData , &uSetOrReset, 0x01 );
|
||
//Command.Body.LE = 0x00 ;
|
||
/* build the I<>C command */
|
||
M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_GPOSTATE, Command, &NbByte , pBuffer);
|
||
|
||
/* send the request */
|
||
status = NFC_IO_WriteMultiple(DeviceAddr, pBuffer, NbByte);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
status = M24SR_IsAnswerReady (DeviceAddr);
|
||
if (status != M24SR_STATUS_SUCCESS)
|
||
{
|
||
return status;
|
||
}
|
||
/* read the response */
|
||
status = NFC_IO_ReadMultiple (DeviceAddr , pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
if (status != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
|
||
status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @brief This function configure GPO purpose for I2C session
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param GPO_I2Cconfig: GPO configuration to set
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
*/
|
||
uint16_t M24SR_ManageI2CGPO(uint16_t DeviceAddr, uint8_t GPO_I2Cconfig)
|
||
{
|
||
uint16_t status;
|
||
uint8_t GPO_config;
|
||
uint8_t DefaultPassword[16]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||
|
||
if( GPO_I2Cconfig > STATE_CONTROL)
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
/* we must not be in interrupt mode for I2C synchro as we will change GPO purpose */
|
||
M24SR_SetI2CSynchroMode(M24SR_WAITINGTIME_POLLING);
|
||
|
||
M24SR_SelectApplication(DeviceAddr);
|
||
M24SR_SelectSystemfile(DeviceAddr);
|
||
M24SR_ReadBinary (DeviceAddr, 0x0004 , 0x01 , &GPO_config );
|
||
|
||
/* Update only GPO purpose for I2C */
|
||
GPO_config = (GPO_config & 0xF0) | GPO_I2Cconfig;
|
||
M24SR_SelectSystemfile(DeviceAddr);
|
||
M24SR_Verify(DeviceAddr, M24SR_I2C_PWD ,0x10 ,DefaultPassword );
|
||
status = M24SR_UpdateBinary (DeviceAddr, 0x0004 ,0x01, &(GPO_config) );
|
||
|
||
/* if we have set interrupt mode for I2C synchro we can enable interrupt mode */
|
||
if (GPO_I2Cconfig == I2C_ANSWER_READY && status == M24SR_ACTION_COMPLETED)
|
||
{
|
||
if(uGpoMode == M24SR_GPO_SYNCHRO)
|
||
{
|
||
M24SR_SetI2CSynchroMode(M24SR_WAITINGTIME_GPO);
|
||
}
|
||
else
|
||
{
|
||
M24SR_SetI2CSynchroMode(M24SR_INTERRUPT_GPO);
|
||
}
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @brief This function configure GPO purpose for RF session
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @param GPO_RFconfig: GPO configuration to set
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
*/
|
||
uint16_t M24SR_ManageRFGPO(uint16_t DeviceAddr, uint8_t GPO_RFconfig)
|
||
{
|
||
uint16_t status;
|
||
uint8_t GPO_config;
|
||
uint8_t DefaultPassword[16]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||
|
||
if( GPO_RFconfig > STATE_CONTROL)
|
||
{
|
||
return M24SR_ERROR_PARAMETER;
|
||
}
|
||
|
||
M24SR_SelectApplication(DeviceAddr);
|
||
M24SR_SelectSystemfile(DeviceAddr);
|
||
M24SR_ReadBinary (DeviceAddr, 0x0004 , 0x01 , &GPO_config );
|
||
|
||
/* Update only GPO purpose for I2C */
|
||
GPO_config = (GPO_config & 0x0F) | (GPO_RFconfig<<4);
|
||
M24SR_SelectSystemfile(DeviceAddr);
|
||
M24SR_Verify(DeviceAddr, M24SR_I2C_PWD ,0x10 ,DefaultPassword );
|
||
status = M24SR_UpdateBinary (DeviceAddr, 0x0004 ,0x01, &(GPO_config));
|
||
|
||
return status;
|
||
}
|
||
|
||
/**
|
||
* @brief This functions returns M24SR_STATUS_SUCCESS when a response is ready
|
||
* @param DeviceAddr: I2C address of the device
|
||
* @retval M24SR_STATUS_SUCCESS : a response of the M24LR is ready
|
||
* @retval M24SR_ERROR_DEFAULT : the response of the M24LR is not ready
|
||
*/
|
||
static uint16_t M24SR_IsAnswerReady (uint16_t DeviceAddr)
|
||
{
|
||
uint32_t retry = 0xFFFFF;
|
||
uint8_t stable = 0;
|
||
uint8_t PinState;
|
||
|
||
switch (uSynchroMode)
|
||
{
|
||
case M24SR_WAITINGTIME_POLLING :
|
||
if(NFC_IO_IsDeviceReady(DeviceAddr, NFC_IO_TRIALS) != NFC_IO_STATUS_SUCCESS)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
break;
|
||
|
||
case M24SR_WAITINGTIME_TIMEOUT :
|
||
/* M24SR FWI=5 => (256*16/fc)*2^5=9.6ms but M24SR ask for extended time to program up to 246Bytes. */
|
||
NFC_IO_Delay(M24SR_ANSWER_TIMEOUT);
|
||
break;
|
||
|
||
case M24SR_WAITINGTIME_GPO :
|
||
/* mbd does not support interrupt for the moment with nucleo board */
|
||
do
|
||
{
|
||
NFC_IO_ReadState(&PinState);
|
||
if( PinState == 0) /* RESET */
|
||
{
|
||
stable ++;
|
||
}
|
||
retry --;
|
||
}
|
||
while(stable < M24SR_ANSWER_STABLE && retry>0);
|
||
if(!retry)
|
||
{
|
||
return M24SR_ERROR_TIMEOUT;
|
||
}
|
||
break;
|
||
|
||
case M24SR_INTERRUPT_GPO :
|
||
/* Check if the GPIO is not already low before calling this function */
|
||
NFC_IO_ReadState(&PinState);
|
||
if(PinState == 1) /* SET */
|
||
{
|
||
while (GPO_Low == 0);
|
||
}
|
||
GPO_Low = 0;
|
||
break;
|
||
|
||
default :
|
||
return M24SR_ERROR_DEFAULT;
|
||
}
|
||
|
||
return M24SR_STATUS_SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief This function enable or disable RF communication
|
||
* @param OnOffChoice: GPO configuration to set
|
||
* @retval Status (SW1&SW2) : Status of the operation to complete.
|
||
*/
|
||
void M24SR_RFConfig( uint8_t OnOffChoice)
|
||
{
|
||
/* Disable RF */
|
||
if ( OnOffChoice != 0 )
|
||
{
|
||
NFC_IO_RfDisable(0); /* PIN RESET */
|
||
}
|
||
else
|
||
{
|
||
NFC_IO_RfDisable(1); /* PIN SET */
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief this functions configure I2C synchronization mode
|
||
* @param WaitingMode : interruption or polling
|
||
* @retval None
|
||
*/
|
||
static void M24SR_SetI2CSynchroMode( uint8_t WaitingMode)
|
||
{
|
||
if((uGpoMode == M24SR_GPO_SYNCHRO) || (uGpoMode == M24SR_GPO_INTERRUPT))
|
||
{
|
||
uSynchroMode = WaitingMode;
|
||
}
|
||
else /* GPO_POLLING */
|
||
{
|
||
if(WaitingMode == M24SR_WAITINGTIME_GPO || WaitingMode == M24SR_INTERRUPT_GPO)
|
||
uSynchroMode = M24SR_WAITINGTIME_POLLING; /* Force Polling */
|
||
else
|
||
uSynchroMode = WaitingMode;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/******************* (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|