Firmware library for the X-NUCLEO-NFC01A1 Dynamic NFC Tag board.

Dependencies:   M24SR

Dependents:   NFC M2M_2016_STM32 MyongjiElec_capstone1 IDW01M1_Cloud_IBM ... more

Fork of X_NUCLEO_NFC01A1 by ST Expansion SW Team

X-NUCLEO-NFC01A1 Dynamic NFC Tag Expansion Board Firmware Package

Introduction

This firmware package includes Components Device Drivers, Board Support Package and example applications for STMicroelectronics X-NUCLEO-NFC01A1 Dynamic NFC Tag Expansion Board based on M24SR.

Firmware Library

Class X_NUCLEO_NFC01A1 is intended to represent the Dynamic NFC Tag Expansion Board with the same name.
It provides an API to access to the M24SR component and to the three onboard LEDs.
It is intentionally implemented as a singleton because only one X_NUCLEO_NFC01A1 at a time might be deployed in a HW component stack.
The library also provides an implementation of the NDEF library API for M24SR, providing an simple way to read/write NDEF formatted messages from/to the M24SR dynamic NFC tag.

Example applications

1. Hello World
2. Asynchronous Hello World

Files at this revision

API Documentation at this revision

Comitter:
giovannivisentini
Date:
Thu Jan 28 14:01:18 2016 +0000
Parent:
18:10def2fefa8a
Child:
20:aad5727cb8c6
Child:
22:ac2e9a086341
Commit message:
add async api

Changed in this revision

Common/nfc.h Show annotated file Show diff for this revision Revisions of this file
Interfaces/Nfc_class.h Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_NFC01A1.cpp Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_NFC01A1.h Show annotated file Show diff for this revision Revisions of this file
m24sr/NDefNfcTagM24SR.cpp Show annotated file Show diff for this revision Revisions of this file
m24sr/NDefNfcTagM24SR.h Show annotated file Show diff for this revision Revisions of this file
m24sr/m24sr.h Show annotated file Show diff for this revision Revisions of this file
m24sr/m24sr_class.cpp Show annotated file Show diff for this revision Revisions of this file
m24sr/m24sr_class.h Show annotated file Show diff for this revision Revisions of this file
--- a/Common/nfc.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/Common/nfc.h	Thu Jan 28 14:01:18 2016 +0000
@@ -65,7 +65,7 @@
  * @brief  NFC status enumerator definition
  */
 typedef enum {
-	NFC_SUCCESS=0x0000,
+	NFC_SUCCESS=0x9000,
 	NFC_ERROR=0x6F00,
 	NFC_FILE_OVERFLOW_LE = 0x6280,
 	NFC_EOF = 0x6282,
@@ -106,6 +106,18 @@
 	NFC_M24SR_COMPONENT = 1
 } NFC_ComponentTypeDef;
 
+/**
+ * @brief  GPO state structure
+ */
+typedef enum {
+	HIGH_IMPEDANCE = 0,
+	SESSION_OPENED =1,
+	WIP=2,
+	I2C_ANSWER_READY=3,
+	INTERRUPT=4,
+	STATE_CONTROL=5
+} NFC_GPO_MGMT;
+
 
 /**
  * @brief  NFC driver structure definition
--- a/Interfaces/Nfc_class.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/Interfaces/Nfc_class.h	Thu Jan 28 14:01:18 2016 +0000
@@ -48,12 +48,20 @@
 /* Includes ------------------------------------------------------------------*/
 
 #include "Component_class.h"
-#include "nfc.h"
+#include "../Common/nfc.h"
 
 /* Classes  ------------------------------------------------------------------*/
 
 /**
  * An abstract class for Nfc components.
+ * This component has two operation mode, sync or async.
+ * In the sync mode each function will return only when the command is complete.
+ * In the async mode the function will only send the command and the answer will be notify
+ * thought a callback.
+ * The default behavior is sync mode.
+ * For enable the async mode you have to call the ManageI2CGPO(I2C_ANSWER_READY) function.
+ * Then when an interrupt happen you have to call the {@link ManageInterrupt} function.
+ * Note that when you call ManageI2CGPO with other parameters the component will return in sync mode.
  */
 class Nfc : public Component
 {
@@ -68,6 +76,127 @@
 		I2CPwd,    //!< Root password, used only thought nfc
 	}PasswordType_t;
 
+	typedef void(*gpoEventCallback)(void);
+
+	/**
+	 * Object that contains all the callback fired by this class, each command has its own callback.
+	 * The callback default implementation is an empty function.
+	 */
+	class Callback{
+	public:
+
+		/** call when GetSession or KillSession finish */
+		virtual void onSessionOpen(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onDeselect(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onSelectedApplication(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onSelectedCCFile(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onSelectedNDEFFile(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onSelectedSystemFile(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onReadByte(Nfc *nfc,NFC_StatusTypeDef status,
+				uint16_t offset,uint8_t *readByte, uint16_t nReadByte){
+			(void)nfc; (void)status;(void)offset; (void)readByte; (void)nReadByte;
+		}
+
+		virtual void onUpdatedBinary(Nfc *nfc,NFC_StatusTypeDef status,uint16_t offset,
+				uint8_t *writeByte,uint16_t nWriteByte){
+			(void)nfc; (void)status; (void)writeByte; (void)nWriteByte; (void)offset;
+		}
+
+		virtual void onVerifyed(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onManageI2CGPO(Nfc *nfc,NFC_StatusTypeDef status,NFC_GPO_MGMT newStatus){
+			(void)nfc; (void)status;(void)newStatus;
+		}
+
+		virtual void onManageRFGPO(Nfc *nfc,NFC_StatusTypeDef status,NFC_GPO_MGMT newStatus){
+			(void)nfc; (void)status;(void)newStatus;
+		}
+
+		virtual void onChangeReferenceData(Nfc *nfc ,NFC_StatusTypeDef status,PasswordType_t type,
+				uint8_t *data){
+			(void)nfc; (void)status;(void)type;(void)data;
+		}
+
+		virtual void onEnableVerificationRequirement(Nfc *nfc ,NFC_StatusTypeDef status,PasswordType_t type){
+			(void)nfc; (void)status;(void)type;
+		}
+
+		virtual void onDisableVerificationRequirement(Nfc *nfc , NFC_StatusTypeDef status,PasswordType_t type){
+			(void)nfc; (void)status;(void)type;
+		}
+
+		virtual void onEnablePermanentState(Nfc *nfc, NFC_StatusTypeDef status, PasswordType_t type){
+			(void)nfc; (void)status;(void)type;
+		}
+
+		virtual void onDisablePermanentState(Nfc *nfc, NFC_StatusTypeDef status, PasswordType_t type){
+			(void)nfc; (void)status;(void)type;
+		}
+
+		virtual void onReadId(Nfc *nfc, NFC_StatusTypeDef status, uint8_t *id){
+			(void)nfc; (void)status;(void)id;
+		}
+
+		virtual void onEnableReadPassword(Nfc *nfc, NFC_StatusTypeDef status,const uint8_t *newPwd){
+			(void)nfc; (void)status;(void)newPwd;
+		}
+
+		virtual void onEnableWritePassword(Nfc *nfc, NFC_StatusTypeDef status,const uint8_t *newPwd){
+			(void)nfc; (void)status;(void)newPwd;
+		}
+
+		virtual void onDisableReadPassword(Nfc *nfc, NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onDisableWritePassword(Nfc *nfc, NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onDisableAllPassword(Nfc *nfc, NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onEnableReadOnly(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onEnableWriteOnly(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onDisableReadOnly(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual void onDisableWriteOnly(Nfc *nfc,NFC_StatusTypeDef status){
+			(void)nfc; (void)status;
+		}
+
+		virtual ~Callback(){};
+	};
+
+	Nfc():mCallback(&defaultCallback){ }
 
 	/**
 	 * Open a I2C connection with the tag if an RF connection isn't already open.
@@ -200,7 +329,7 @@
 	 * @param  GPO_I2Cconfig GPO configuration to set.
  	 * @return NFC_SUCCESS if no errors
 	 */
-	virtual NFC_StatusTypeDef ManageI2CGPO(uint8_t GPO_I2Cconfig) = 0;
+	virtual NFC_StatusTypeDef ManageI2CGPO(NFC_GPO_MGMT GPO_I2Cconfig) = 0;
 	
 	/**
  	* @brief  This function configures GPO for RF session.
@@ -216,7 +345,40 @@
 	 */
 	virtual NFC_StatusTypeDef RFConfig(uint8_t OnOffChoice) = 0;
 
+	/**
+	 * Generates a negative pulse on the GPO pin.
+	 * Pulse starts immediately after the command is issued and ends at the end of the RF response.
+  	 * @return NFC_SUCCESS if no errors
+	 */
+	virtual NFC_StatusTypeDef SendInterrupt(void)=0;
+
+	/**
+	 * Change the function to call when a command ends
+	 * @param commandCallback object containings the callback, if NULL it will use empty callback
+	 */
+	void SetCallBack(Callback *commandCallback){
+		if(commandCallback!=NULL)
+			mCallback = commandCallback;
+		else
+			mCallback = &defaultCallback;
+	}
+
+	/**
+	 * function to call when the component fire an interrupt
+	 * @return last operation status
+	 */
+	virtual NFC_StatusTypeDef ManageEvent()=0;
+
 	virtual ~Nfc(){};
+
+private:
+	/** object containing empty callback to use in the default case*/
+	Callback defaultCallback;
+
+protected:
+	/** object containing the callback to use*/
+	Callback *mCallback;
+
 };
 
 #endif /* __NFC_CLASS_H */
--- a/X_NUCLEO_NFC01A1.cpp	Fri Jan 22 09:04:51 2016 +0000
+++ b/X_NUCLEO_NFC01A1.cpp	Thu Jan 28 14:01:18 2016 +0000
@@ -49,11 +49,13 @@
 
 X_NUCLEO_NFC01A1 *X_NUCLEO_NFC01A1::mInstance = NULL;
 
-X_NUCLEO_NFC01A1* X_NUCLEO_NFC01A1::Instance(I2C &devI2C,const PinName &gpoName,
-			const PinName &RFDisableName, const PinName &led1Name,
-			const PinName &led2Name, const PinName &led3Name) {
+X_NUCLEO_NFC01A1* X_NUCLEO_NFC01A1::Instance(I2C &devI2C,
+		Nfc::gpoEventCallback gpoEventCallback,	const PinName &gpoName,
+		const PinName &RFDisableName, const PinName &led1Name,
+		const PinName &led2Name, const PinName &led3Name) {
 	if (mInstance == NULL) { // the first time
-		mInstance = new X_NUCLEO_NFC01A1(devI2C,gpoName,RFDisableName,led1Name,led2Name,led3Name);
+		mInstance = new X_NUCLEO_NFC01A1(devI2C,gpoEventCallback,gpoName,
+				RFDisableName,led1Name,led2Name,led3Name);
 		if (mInstance != NULL) { //allocation ok
 			const int status = mInstance->mM24SR.Init(NULL);
 			if (status != NFC_SUCCESS) { //initialization failed
--- a/X_NUCLEO_NFC01A1.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/X_NUCLEO_NFC01A1.h	Thu Jan 28 14:01:18 2016 +0000
@@ -49,6 +49,8 @@
  */
 class X_NUCLEO_NFC01A1 {
 
+public:
+
 private:
 	/**
 	 * Ponter to the singleton instance, NULL if not allocated.
@@ -60,18 +62,20 @@
 	static const uint8_t M24SR_ADDR;
 
 	/**
-	 * constructor
+	 * Constructor
 	 * @param devI2C I2C channel used to communicate with the board.
+	 * @param eventCallback Function that will be called when the gpo pin status change.
 	 * @param gpoName Name of the gpio pin of the M24SR chip.
 	 * @param RFDisableName Pin that controls the rf antenna status.
 	 * @param led1Name Pin to control the led1 status.
 	 * @param led2Name Pin to control the led1 status.
 	 * @param led3Name Pin to control the led1 status.
 	 */
-	X_NUCLEO_NFC01A1(I2C &devI2C, const PinName &gpoName,
- 			const PinName &RFDisableName, const PinName &led1Name,
- 			const PinName &led2Name, const PinName &led3Name):
- 				mM24SR(M24SR_ADDR,devI2C,gpoName,RFDisableName),
+	X_NUCLEO_NFC01A1(I2C &devI2C,Nfc::gpoEventCallback eventCallback,
+			const PinName &gpoName,	const PinName &RFDisableName,
+			const PinName &led1Name, const PinName &led2Name,
+			const PinName &led3Name):
+ 				mM24SR(M24SR_ADDR,devI2C,eventCallback,gpoName,RFDisableName),
 				mNfcLed1(led1Name),mNfcLed2(led2Name),mNfcLed3(led3Name){}
 
 public:
@@ -79,13 +83,14 @@
 	static const PinName DEFAULT_SDL_PIN; //!< Default pin used for the M24SR SDL signal.
 	static const PinName DEFAULT_GPO_PIN; //!< Default pin used for the M24SR GPO signal.
 	static const PinName DEFAULT_RF_DISABLE_PIN; //!< Default pin used for M24SR RF_DISABLE signal.
-	static const PinName DEFAULT_LED1_PIN; //!< Default pin to controll the led 1.
-	static const PinName DEFAULT_LED2_PIN; //!< Default pin to controll the led 2.
-	static const PinName DEFAULT_LED3_PIN; //!< Default pin to controll the led 3.
+	static const PinName DEFAULT_LED1_PIN; //!< Default pin to control the led 1.
+	static const PinName DEFAULT_LED2_PIN; //!< Default pin to control the led 2.
+	static const PinName DEFAULT_LED3_PIN; //!< Default pin to control the led 3.
 
     /**
 	 * Create or return an instance of X_NUCLEO_NFC01A1.
 	 * @param devI2C I2C channel used to communicate with the board.
+	 * @param eventCallback Function that will be called when the gpo pin status change.
 	 * @param gpoName Name of the gpio pin of the M24SR chip.
 	 * @param RFDisableName Pin that controls the rf antenna status.
 	 * @param led1Name Pin to control the led1 status.
@@ -93,6 +98,7 @@
 	 * @param led3Name Pin to control the led1 status.
 	 */
 	static X_NUCLEO_NFC01A1* Instance(I2C &devI2C,
+			Nfc::gpoEventCallback eventCallback,
 			const PinName &gpoName = DEFAULT_GPO_PIN,
  			const PinName &RFDisableName = DEFAULT_RF_DISABLE_PIN,
  			const PinName &led1Name = DEFAULT_LED1_PIN,
--- a/m24sr/NDefNfcTagM24SR.cpp	Fri Jan 22 09:04:51 2016 +0000
+++ b/m24sr/NDefNfcTagM24SR.cpp	Thu Jan 28 14:01:18 2016 +0000
@@ -2,7 +2,7 @@
   ******************************************************************************
   * @file       NdefNfcTagSTM24SR.cpp
   * @author  	ST Central Labs
-  * @version 	V1.0.0 
+  * @version 	V1.0.0
   * @date       05 Nov 2015
   * @brief      wrapper class for use the NDefLib library for write/read ndef message
   ******************************************************************************
@@ -34,128 +34,163 @@
   *
   ******************************************************************************
   */
-#include "mbed.h"
+
+#include <cmath>
 
 #include "NDefNfcTagM24SR.h"
 
+
 /* wait 1sec, driver is configured to let 200ms for command to complete */
 /* which is enough for all commands except GetSession if RF session is already opened */
 /* Smartphone generally releases the session within the second, anyway the user can modify this value */
 #define OPENSESSION_NTRIALS 5
 
 #define CC_FILE_LENGTH_BYTE 15
+////////////////////////////START  OpenSessionCallBack/////////////////////////
+NDefNfcTagM24SR::OpenSessionCallBack::
+	OpenSessionCallBack(NDefNfcTagM24SR& sender):
+		mSender(sender),mNTrials(OPENSESSION_NTRIALS){}
+
+void NDefNfcTagM24SR::OpenSessionCallBack::onSessionOpen(Nfc *nfc,
+		NFC_StatusTypeDef status){
+	if(status==NFC_SUCCESS){
+		nfc->SelectApplication();
+	}else{
+		mSender.mCallBack->onSessionOpen(&mSender,false);
+	}
+}
+
+void NDefNfcTagM24SR::OpenSessionCallBack::onSelectedApplication(Nfc *nfc,
+		NFC_StatusTypeDef status){
+	if(status==NFC_SUCCESS){
+		nfc->SelectCCfile();
+	}else{
+		if(mNTrials==0)
+			mSender.mCallBack->onSessionOpen(&mSender,false);
+		else{
+			mNTrials--;
+			nfc->SelectApplication();
+		}//if-else
+	}//if-else
+}
+
+void NDefNfcTagM24SR::OpenSessionCallBack::onSelectedCCFile(Nfc *nfc,
+		NFC_StatusTypeDef status){
+	if(status==NFC_SUCCESS){
+		nfc->ReadBinary(0x0000, CC_FILE_LENGTH_BYTE, CCFile);
+	}else{
+		mSender.mCallBack->onSessionOpen(&mSender,false);
+	}
+}
+
+void NDefNfcTagM24SR::OpenSessionCallBack::onReadByte(Nfc *nfc,
+		NFC_StatusTypeDef status,uint16_t offset,uint8_t *readByte, uint16_t nReadByte){
+	(void)offset;
+	if(status!=NFC_SUCCESS || nReadByte!=CC_FILE_LENGTH_BYTE){
+		return mSender.mCallBack->onSessionOpen(&mSender,false);
+	}//else
+	uint16_t NDefFileId = (uint16_t) ((readByte[0x09] << 8) | readByte[0x0A]);
+	mSender.mMaxReadBytes = (uint16_t) ((readByte[0x03] << 8) | readByte[0x04]);
+	mSender.mMaxWriteBytes = (uint16_t) ((readByte[0x05] << 8) | readByte[0x06]);
+	nfc->SelectNDEFfile(NDefFileId);
+}
+
+void NDefNfcTagM24SR::OpenSessionCallBack::onSelectedNDEFFile(Nfc *nfc,
+		NFC_StatusTypeDef status){
+	(void)nfc;
+	mSender.mIsSessionOpen = status==NFC_SUCCESS;
+	mSender.mCallBack->onSessionOpen(&mSender,mSender.mIsSessionOpen);
+}
+////////////////////////////END  OpenSessionCallBack/////////////////////////
 
 bool NDefNfcTagM24SR::openSession(bool force) {
 
-	if (isSessionOpen())
+	if (isSessionOpen()){
+		mCallBack->onSessionOpen(this,true);
 		return true;
-	//else
-	if (force)
-		mDevice.KillSession();
-
-	int8_t nTrials = OPENSESSION_NTRIALS;
-	NFC_StatusTypeDef status = NFC_ERROR;
-	while (status != NFC_SUCCESS && nTrials) {
-		status = mDevice.GetSession();
-		nTrials--;
 	}
 
-	if (status != NFC_SUCCESS) {
-		return false;
-	} //else
-
-	//Select the NFC type 4 application
-	if (mDevice.SelectApplication() != NFC_SUCCESS){
-		return false;
-	}
-
-	if (mDevice.SelectCCfile() != NFC_SUCCESS){
-		return false;
-	}
+	mDevice.SetCallBack(&mOpenSessionCallback);
+	if(force)
+		return mDevice.KillSession() == NFC_SUCCESS;
+	else
+		return mDevice.GetSession() == NFC_SUCCESS;
 
-	uint8_t CCFile[CC_FILE_LENGTH_BYTE];
-	/* read the first 15 bytes of the CC file */
-	if (mDevice.ReadBinary(0x0000, CC_FILE_LENGTH_BYTE, CCFile) != NFC_SUCCESS)
-		return false;
 
-	//read the ndefFileId
-	uint16_t ndefFileId = (uint16_t) ((CCFile[0x09] << 8) | CCFile[0x0A]);
-	mMaxReadBytes = (uint16_t) ((CCFile[0x03] << 8) | CCFile[0x04]);
-	mMaxWriteBytes = (uint16_t) ((CCFile[0x05] << 8) | CCFile[0x06]);
-
-	//open it
-	if (mDevice.SelectNDEFfile(ndefFileId) != NFC_SUCCESS)
-		return false;
-
-	NDefNfcTag::openSession();
-	return true;
 }
 
 bool NDefNfcTagM24SR::closeSession() {
-
-	//no open session
-	if (!isSessionOpen())
-		return true;
-
-	//close the CC file
-	if (mDevice.Deselect() != NFC_SUCCESS)
-		return false;
-
-	NDefNfcTag::closeSession();
-	return true;
+	mDevice.SetCallBack(&mCloseSessionCallback);
+	return mDevice.Deselect() == NFC_SUCCESS;
 }
 
-bool NDefNfcTagM24SR::writeByte(const uint8_t *buffer, uint16_t length, uint16_t offset) {
+void NDefNfcTagM24SR::WriteByteCallback::onUpdatedBinary(Nfc *nfc,
+		NFC_StatusTypeDef status,uint16_t startOffset, uint8_t *writeByte,uint16_t nWriteByte){
 
-	//no open session
-	if (!isSessionOpen())
-		return false;
+	if(status!=NFC_SUCCESS){ // error -> finish to write
+		mCallback(mCallbackParam,false,mByteToWrite,mNByteToWrite);
+		return;
+	}//else
 
-	NFC_StatusTypeDef status = NFC_SUCCESS;
-	bool prevSessionStatus = isSessionOpen();
-	if (!prevSessionStatus) {
-		//try to acquire a session or fail
-		if (openSession(false))
-			return false;
-	} //if
+	mByteWrote+=nWriteByte;
+	if(mByteWrote==mNByteToWrite){ //write all -> finish
+		mCallback(mCallbackParam,true,mByteToWrite,mNByteToWrite);
+	}else{ //else write another slice
+		uint16_t tempLenght = std::min(mSender.mMaxWriteBytes,
+				(uint16_t)(mNByteToWrite-mByteWrote));
+		nfc->UpdateBinary(startOffset+nWriteByte,tempLenght,writeByte+nWriteByte);
+	}//if-else
+}
+
+bool NDefNfcTagM24SR::writeByte(const uint8_t *buffer, uint16_t length,uint16_t offset,
+		byteOperationCallback_t callback,CallbackStatus_t *callbackStatus){
+	if(!isSessionOpen())
+		callback(callbackStatus,false,buffer,length);
+	//else
+	mWriteByteCallback.setTask(buffer,length,callback,callbackStatus);
+	mDevice.SetCallBack(&mWriteByteCallback);
 
 	if (length > mMaxWriteBytes) {
-		do {
-			status = mDevice.UpdateBinary(offset, mMaxWriteBytes,(uint8_t*) buffer);
-			offset += mMaxWriteBytes;
-			buffer += mMaxWriteBytes;
-			length -= mMaxWriteBytes;
-		} while (length > mMaxWriteBytes && status == NFC_SUCCESS);
-	} //if
+		return mDevice.UpdateBinary(offset, mMaxWriteBytes,(uint8_t*) buffer) == NFC_SUCCESS;
+	}else{
+		return mDevice.UpdateBinary(offset,length,(uint8_t*)buffer) == NFC_SUCCESS;
+	}//if-else
 
-	//finish to write the buffer
-	if (status == NFC_SUCCESS && mMaxWriteBytes)
-		status = mDevice.UpdateBinary(offset, length,(uint8_t*) buffer);
-
-	return status==NFC_SUCCESS;
 }
 
-bool NDefNfcTagM24SR::readByte(uint16_t byteOffset, uint16_t byteLength,
-		uint8_t *buffer) {
-			
-	//no open session
-	if (!isSessionOpen())
-		return false;
-		
-	NFC_StatusTypeDef status = NFC_SUCCESS;
-	uint16_t offset = byteOffset;
-	if (byteLength > mMaxReadBytes) {
-		do {
-			status = mDevice.ReadBinary(offset, mMaxReadBytes, buffer);
-			offset += mMaxReadBytes;
-			buffer += mMaxReadBytes;
-			byteLength -= mMaxReadBytes;
-		} while (byteLength > mMaxWriteBytes && status == NFC_SUCCESS);
-	} //if
-	  //finish to write the buffer
-	if (status == NFC_SUCCESS && mMaxWriteBytes)
-		status = mDevice.ReadBinary(offset, byteLength, buffer);
+void NDefNfcTagM24SR::ReadByteCallback::onReadByte(Nfc *nfc,
+		NFC_StatusTypeDef status,uint16_t startOffset, uint8_t *readBffer,uint16_t nReadByte){
+
+	if(status!=NFC_SUCCESS){ // error -> finish to write
+		mCallback(mCallbackParam,false,mBuffer,mNByteToRead);
+		return;
+	}//else
 
-	return status == NFC_SUCCESS;
+	mByteRead += nReadByte;
+	if(mByteRead==mNByteToRead){ //read all -> finish
+		mCallback(mCallbackParam,true,mBuffer,mNByteToRead);
+	}else{ //else write another slice
+		uint16_t tempLenght = std::min(mSender.mMaxReadBytes,
+				(uint16_t)(mNByteToRead-mByteRead));
+		nfc->ReadBinary(startOffset+nReadByte,tempLenght,readBffer+nReadByte);
+	}//if-else
+
 }
 
+bool NDefNfcTagM24SR::readByte(const uint16_t byteOffset, const uint16_t length,
+		uint8_t *buffer, byteOperationCallback_t callback,CallbackStatus_t *callbackStatus){
+	if(!isSessionOpen()){
+		return callback(callbackStatus,false,buffer,length);
+	}
+	//else
+	mReadByteCallback.setTask(buffer,length,callback,callbackStatus);
+	mDevice.SetCallBack(&mReadByteCallback);
+
+	if (length > mMaxReadBytes) {
+		return mDevice.ReadBinary(byteOffset, mMaxReadBytes,buffer)== NFC_SUCCESS;;
+	}else{
+		return mDevice.ReadBinary(byteOffset,length,buffer)== NFC_SUCCESS;;
+	}//if-else
+
+}
+
--- a/m24sr/NDefNfcTagM24SR.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/m24sr/NDefNfcTagM24SR.h	Thu Jan 28 14:01:18 2016 +0000
@@ -35,8 +35,10 @@
   ******************************************************************************
   */
 
-#ifndef NDEFNFCTAGSTM24_H_
-#define NDEFNFCTAGSTM24_H_
+#ifndef X_NUCLEO_NFC01A1_M24SR_NDEFNFCTAGM24SR_H_
+#define X_NUCLEO_NFC01A1_M24SR_NDEFNFCTAGM24SR_H_
+
+#include <cstdlib>
 #include <stdint.h>
 
 #include "NDefLib/NDefNfcTag.h"
@@ -44,78 +46,244 @@
 #include "Nfc_class.h"
 
 /**
- * Implement all NDefLib abstract methods. */
+ * Helper class to use the NDefLib
+ */
 class NDefNfcTagM24SR: public NDefLib::NDefNfcTag {
 
 public:
+
 	/**
-	 * Create the object.
-	 * @param Device device to write the Ndef tags into.
+	 *
+	 * @param device device to use
 	 */
 	NDefNfcTagM24SR(Nfc &device) :
-			mDevice(device), mMaxReadBytes(0xFF), mMaxWriteBytes(
-					0xFF) {
+		NDefLib::NDefNfcTag(),
+		mDevice(device),mIsSessionOpen(false),
+		mMaxReadBytes(0xFF), mMaxWriteBytes(0xFF),
+		mOpenSessionCallback(*this),
+		mCloseSessionCallback(*this),
+		mWriteByteCallback(*this),
+		mReadByteCallback(*this){}
+
+	virtual bool openSession(bool force = false);
+
+	virtual bool closeSession();
+
+	virtual bool isSessionOpen(){
+		return mIsSessionOpen;
 	}
 
 	/**
-	 * Open the communication session with the nfc tag.
-	 * @par This method should be called at the end of an overriding implementation, just before returning.
-	 * @param Force force to open a communication.
-	 * @return true if success
-	 */
-	virtual bool openSession(bool force = false);
-	
-	/**
-	 * Close the communication with the nfc tag.
-	 * @par This method should be called at the end of an overriding implementation, just before returning.
-	 * @return true if success
-	 */
-	virtual bool closeSession();
-
-	/**
-	 * Close the open session.
-	 */
-	virtual ~NDefNfcTagM24SR() {
+	* Close the open session.
+	*/
+	virtual ~NDefNfcTagM24SR(){
 		if(isSessionOpen())
 			closeSession();
-	}//~Type4NfcTagM24SR
+	}//~NDefNfcTagM24SR
+
+	protected:
+
+		virtual bool writeByte(const uint8_t *buffer, uint16_t length,uint16_t offset,
+				byteOperationCallback_t callback,CallbackStatus_t *callbackStatus);
+
+		virtual bool readByte(const uint16_t byteOffset, const uint16_t byteLength,
+				uint8_t *buffer, byteOperationCallback_t callback,CallbackStatus_t *callbackStatus);
+
+	private:
+
+		Nfc &mDevice;
+
+		/**
+		 * true if the session is open
+		 */
+		bool mIsSessionOpen;
+
+		/**
+		* Max length for a read operation
+		*/
+		uint16_t mMaxReadBytes;
+
+		/**
+		* Max length for a write operation
+		*/
+		uint16_t mMaxWriteBytes;
+
+		/**
+		 * Class containing the callback needed to open a session and read the max
+		 * read/write size
+		 */
+		class OpenSessionCallBack: public Nfc::Callback{
+			public:
+				OpenSessionCallBack(NDefNfcTagM24SR &sender);
+				virtual void onSessionOpen(Nfc *nfc,NFC_StatusTypeDef status);
+				virtual void onSelectedApplication(Nfc *nfc,NFC_StatusTypeDef status);
+				virtual void onSelectedCCFile(Nfc *nfc,NFC_StatusTypeDef status);
+				virtual void onReadByte(Nfc *nfc,NFC_StatusTypeDef status,uint16_t offset,
+						uint8_t *readByte, uint16_t nReadByte);
+				virtual void onSelectedNDEFFile(Nfc *nfc,NFC_StatusTypeDef status);
 
-	
+			private:
+				NDefNfcTagM24SR &mSender;
+				uint32_t mNTrials;
+				uint8_t CCFile[15];
+		};
+
+		OpenSessionCallBack mOpenSessionCallback;
+
+		/**
+		 * Class containing the callback needed to close a session
+		 */
+		class CloseSessionCallBack : public Nfc::Callback{
+			public:
+				CloseSessionCallBack(NDefNfcTagM24SR &sender):
+					mSender(sender){}
+
+				virtual void onDeselect(Nfc *nfc,NFC_StatusTypeDef status){
+					(void)nfc;
+					if(status==NFC_SUCCESS){
+						mSender.mIsSessionOpen=false;
+						mSender.mCallBack->onSessionClose(&mSender,true);
+					}else{
+						mSender.mCallBack->onSessionClose(&mSender,false);
+					}//if-else
+				}
+			private:
+				NDefNfcTagM24SR &mSender;
+		};
+
+		CloseSessionCallBack mCloseSessionCallback;
+
+		/**
+		 * Class containing the callback needed to write a buffer
+		 */
+		class WriteByteCallback : public Nfc::Callback{
+			public:
+
+				/**
+				 *
+				 * @param sender tag where write the buffer
+				 */
+				WriteByteCallback(NDefNfcTagM24SR &sender):
+									mByteToWrite(NULL),
+									mNByteToWrite(0),
+									mByteWrote(0),
+									mCallback(NULL),
+									mCallbackParam(NULL),
+									mSender(sender){}
 
-protected:
-	
-	/**
-	 * Write a sequence of bytes to the NDEF file.
-	 * @param buffer Buffer to write.
-	 * @param length Number of bytes to write.
-	 * @param offset Write offset in bytes.
-	 * @return true if success
-	 */
-	virtual bool writeByte(const uint8_t *buffer, const uint16_t length, uint16_t offset);
-	
-	/**
-	 * Read a sequence of bytes from the NDEF file.
-	 * @param byteOffset Read offsetin bytes.
-	 * @param byteLength Number of bytes to read.
-	 * @param[out] buffer Buffer to store the read data into.
-	 * @return true if success
-	 */
-	virtual bool readByte(const uint16_t byteOffset, const uint16_t byteLength,
-			uint8_t *buffer);
+				/**
+				 * Set the buffer to write and the function to call when finish
+				 * @param buffer buffer to write
+				 * @param nByte number of bytes to write
+				 * @param callback function to call when the write ends
+				 * @param param parameter to pass to the callback function
+				 */
+				void setTask(const uint8_t *buffer,uint16_t nByte,
+						byteOperationCallback_t callback,CallbackStatus_t *param){
+					mByteToWrite=buffer;
+					mNByteToWrite=nByte;
+					mByteWrote=0;
+					mCallback = callback;
+					mCallbackParam = param;
+				}
+
+				virtual void onUpdatedBinary(Nfc *nfc,NFC_StatusTypeDef status,
+						uint16_t startOffset,uint8_t *writeByte,uint16_t nWriteByte);
+
+
+			private:
+				/** buffer to write */
+				const uint8_t *mByteToWrite;
+				/** length of the buffer */
+				uint16_t mNByteToWrite;
+				/** number of byte already wrote */
+				uint16_t mByteWrote;
+
+				/** function to call when all the bytes are write */
+				byteOperationCallback_t mCallback;
+				/** parameter to pass to the callback function*/
+				CallbackStatus_t* mCallbackParam;
+
+				/** tag where write the buffer*/
+				NDefNfcTagM24SR &mSender;
+		};
+
+		WriteByteCallback mWriteByteCallback;
+
+		/**
+		 * Class containing the callback needed to read a buffer
+		 */
+		class ReadByteCallback : public Nfc::Callback{
+			public:
+
+				/**
+				 *
+				 * @param Sender tag where read the buffer
+				 */
+				ReadByteCallback(NDefNfcTagM24SR &sender):
+										mBuffer(NULL),
+										mNByteToRead(0),
+										mByteRead(0),
+										mCallback(NULL),
+										mCallbackParam(NULL),
+										mSender(sender){}
 
-private:
+				/**
+				 * Set the buffer where read the data and the function to call when finish
+				 * @param buffer Buffer read
+				 * @param nByte Number of bytes to read
+				 * @param callback Function to call when the read ends
+				 * @param param Parameter to pass to the callback function
+				 */
+				void setTask(uint8_t *buffer,uint16_t nByte,
+						byteOperationCallback_t callback,CallbackStatus_t *param){
+					mBuffer=buffer;
+					mNByteToRead=nByte;
+					mByteRead=0;
+					mCallback = callback;
+					mCallbackParam = param;
+				}
 
-	Nfc &mDevice;
+				virtual void onReadByte(Nfc *nfc,NFC_StatusTypeDef status,
+						uint16_t offset,uint8_t *readByte, uint16_t nReadByte);
+
+
+			private:
+
+				/**
+				 * Buffer where read the data
+				 */
+				uint8_t *mBuffer;
 
-	/**
-	 * Max length for a read operation
-	 */
-	uint16_t mMaxReadBytes;
+				/**
+				 * Number of bytes to read
+				 */
+				uint16_t mNByteToRead;
+
+				/**
+				 * Number of bytes already read
+				 */
+				uint16_t mByteRead;
+
+				/**
+				 * Function to call when all the bytes are read
+				 */
+				byteOperationCallback_t mCallback;
 
-	/**
-	 * Max length for a write operation
-	 */
-	uint16_t mMaxWriteBytes;
+				/**
+				 * Parameter to pass to the callback function
+				 */
+				CallbackStatus_t* mCallbackParam;
+
+				/**
+				 * Tag where the data are read
+				 */
+				NDefNfcTagM24SR &mSender;
+		};
+
+		ReadByteCallback mReadByteCallback;
+
+
 };
 
-#endif /* NDEFNFCTAGSTM24_H_ */
+#endif /* X_NUCLEO_NFC01A1_M24SR_NDEFNFCTAGM24SR_H_ */
--- a/m24sr/m24sr.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/m24sr/m24sr.h	Thu Jan 28 14:01:18 2016 +0000
@@ -89,18 +89,6 @@
 	RF_GPO = 0, I2C_GPO = 1
 } M24SR_GPO_MODE;
 
-/**
- * @brief  GPO state structure
- */
-typedef enum {
-	HIGH_IMPEDANCE = 0,
-	SESSION_OPENED,
-	WIP,
-	I2C_ANSWER_READY,
-	INTERRUPT,
-	STATE_CONTROL
-} M24SR_GPO_MGMT;
-
 typedef enum {
 	M24SR_WAITINGTIME_POLLING,
 	M24SR_INTERRUPT_GPO
--- a/m24sr/m24sr_class.cpp	Fri Jan 22 09:04:51 2016 +0000
+++ b/m24sr/m24sr_class.cpp	Thu Jan 28 14:01:18 2016 +0000
@@ -51,6 +51,8 @@
 #endif
 #define GPIO_PIN_SET (1)
 
+#define M24SR_MAX_BYTE_OPERATION_LENGHT (246)
+
 /**
  * default password, also used to enable super user mode throught the I2C channel
  */
@@ -71,10 +73,9 @@
 
 /** value returned by the NFC chip when a command is successfully completed */
 #define NFC_COMMAND_SUCCESS 0x9000
-
+//TODO remove errchek from the async function
 /** call the fCall funtion and check that the return status is NFC_SUCCESS,
  *  otherwise return the error status*/
- //printf("call status: %x\n\r",status);
 #define errchk(fCall) {\
 	const NFC_StatusTypeDef status = (fCall); \
 	if((status!=NFC_SUCCESS)) \
@@ -236,7 +237,7 @@
  * @param	FWTbyte : FWT value
  * @return NFC_SUCCESS if no errors
  */
-NFC_StatusTypeDef M24SR::M24SR_FWTExtension(uint8_t FWTbyte) {
+NFC_StatusTypeDef M24SR::M24SR_SendFWTExtension(uint8_t FWTbyte) {
 	uint8_t pBuffer[M24SR_STATUSRESPONSE_NBBYTE];
 	NFC_StatusTypeDef status;
 	uint8_t NthByte = 0;
@@ -252,20 +253,44 @@
 	pBuffer[NthByte++] = GETMSB(uCRC16);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NthByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NthByte, pBuffer);
+	if(status != NFC_SUCCESS)
+		return status;
+
+	mLastCommandSend=UPDATE;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS)
+			return M24SR_ReceiveUpdateBinary();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onUpdatedBinary(this,status,mLastCommandData.offset,
+					mLastCommandData.data,mLastCommandData.length);
+			return status;
+		}//if-else
+	}//if
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+	return NFC_SUCCESS;
+}
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
-		return status;
+/**
+ * @brief  This function initialize the M24SR device
+ * @retval None
+ */
+NFC_StatusTypeDef M24SR::M24SR_Init(M24SR_InitTypeDef *notUsed) {
+	(void) notUsed;
+	//force to open a i2c session
+	errchk(M24SR_KillSession())
+	//leave the gpo always up
+	errchk(M24SR_ManageI2CGPO(DEFAULT_GPO_STATUS))
+	//close the session
+	errchk(M24SR_Deselect())
+	mGpoEventInterrupt.enable_irq();
+	return NFC_SUCCESS;
 }
 
+
 /**
  * @brief  This function sends the KillSession command to the M24SR device
  * @param  None
@@ -273,15 +298,21 @@
  */
 NFC_StatusTypeDef M24SR::M24SR_KillSession(void) {
 	uint8_t commandBuffer[] = M24SR_KILLSESSION_COMMAND;
-
-	errchk(M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer));
+	NFC_StatusTypeDef status;
+	status = M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer);
+	if(status!=NFC_SUCCESS){
+		mCallback->onSessionOpen(this,status);
+		return status;
+	}
 
 	/* 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 */
-	errchk(M24SR_IO_PollI2C());
+	status = M24SR_IO_PollI2C();
 
-	return NFC_SUCCESS;
+	getCallback()->onSessionOpen(this,status);
+	return status;
+
 }
 
 /**
@@ -290,31 +321,76 @@
  */
 NFC_StatusTypeDef M24SR::M24SR_Deselect(void) {
 	uint8_t pBuffer[] = M24SR_DESELECTREQUEST_COMMAND;
-
+	NFC_StatusTypeDef status;
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(sizeof(pBuffer), pBuffer));
+	status = M24SR_IO_SendI2Ccommand(sizeof(pBuffer), pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onDeselect(this,status);
+	}
+
+	mLastCommandSend=DESELECT;
 
-	errchk(M24SR_IO_IsAnswerReady());
-	/* flush the M24SR buffer */
-	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pBuffer), pBuffer));
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS)
+			return M24SR_ReceiveDeselect();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onSelectedApplication(this,status);
+			return status;
+		}//if-else
+
+	}
 
 	return NFC_SUCCESS;
 }
 
+NFC_StatusTypeDef M24SR::M24SR_ReceiveDeselect(void){
+	uint8_t pBuffer[4];
+	NFC_StatusTypeDef status;
+	status = M24SR_IO_ReceiveI2Cresponse(sizeof(pBuffer), pBuffer);
+	getCallback()->onDeselect(this,status);
+	return status;
+}
+
+
+
+/**
+ * @brief  This function sends the GetSession command to the M24SR device
+ * @retval NFC_SUCCESS the function is successful.
+ * @retval Status (SW1&SW2) if operation does not complete.
+ */
+NFC_StatusTypeDef M24SR::M24SR_GetSession(void) {
+	uint8_t commandBuffer[] = M24SR_OPENSESSION_COMMAND;
+
+	NFC_StatusTypeDef status;
+	status = M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSessionOpen(this,status);
+		return status;
+	}
+
+	/* 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 */
+	status = M24SR_IO_PollI2C();
+
+	getCallback()->onSessionOpen(this,status);
+	return status;
+}
+
 /**
  * @brief  This function sends the SelectApplication command
  * @return NFC_SUCCESS if no errors
  */
-NFC_StatusTypeDef M24SR::M24SR_SelectApplication(void) {
+NFC_StatusTypeDef M24SR::M24SR_SendSelectApplication(void) {
 
 	C_APDU command;
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
 	uint8_t pDataOut[] = M24SR_SELECTAPPLICATION_COMMAND;
 	uint8_t uLe = 0x00;
-	NFC_StatusTypeDef status;
-	uint16_t uP1P2 =0x0400,
-	NbByte;
+	uint16_t uP1P2 =0x0400,	NbByte;
 
 	/* build the command */
 	command.Header.CLA = C_APDU_CLA_DEFAULT;
@@ -328,73 +404,64 @@
 	command.Body.pData = pDataOut;
 	/* copy the number of byte to read */
 	command.Body.LE = uLe;
-	/* build the I²C command */
+	/* build the I2C command */
 	M24SR_BuildIBlockCommand( M24SR_CMDSTRUCT_SELECTAPPLICATION, &command,
 			uDIDbyte, &NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn));
-	
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onSelectedApplication(this,status);
+		return status;
+	}
+
+	mLastCommandSend=SELECT_APPLICATION;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS)
+			return M24SR_ReceiveSelectApplication();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onSelectedApplication(this,status);
+			return status;
+		}//if-else
+	}//if
+
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveSelectApplication(void) {
+
+	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
+	NFC_StatusTypeDef status;
+
+	mLastCommandSend = NONE;
+
+	status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedApplication(this,status);
+		return status;
+	}//else
 	status= M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
-	//printf("M24SR_IsCorrectCRC16Residue %x\r\n",status);
-
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
-		return status;
+	getCallback()->onSelectedApplication(this,status);
+	return status;
 
 }
 
-/**
- * @brief  This function initialize the M24SR device
- * @retval None
- */
-NFC_StatusTypeDef M24SR::M24SR_Init(M24SR_InitTypeDef *notUsed) {
-	(void) notUsed;
-	//until we don't set the gpo usage, just do a polling on the
-	//i2c read
-	M24SR_IO_SetI2CSynchroMode(M24SR_WAITINGTIME_POLLING);
-	//force to open a i2c session
-	errchk(M24SR_KillSession())
-	//ask to set the gpo low when the answer is ready, so we can use
-	//the interrupt for polling
-	errchk(M24SR_ManageI2CGPO(I2C_ANSWER_READY))
-	//close the session
-	errchk(M24SR_Deselect())
 
-	return NFC_SUCCESS;
-}
 
 NFC_StatusTypeDef M24SR::M24SR_ReadID(uint8_t *nfc_id) {
 	if (!nfc_id) {
 		return NFC_ERROR;
 	}
 
-	errchk(M24SR_SelectApplication())
-
-	return M24SR_ReadBinary(0x0011, 1, nfc_id);
-}
+	//enable the callback for change the gpo
+	mComponentCallback = &mReadIDCallback;
+	mReadIDCallback.readIdOn(nfc_id);
 
-/**
- * @brief  This function sends the GetSession command to the M24SR device
- * @retval NFC_SUCCESS the function is successful.
- * @retval Status (SW1&SW2) if operation does not complete.
- */
-NFC_StatusTypeDef M24SR::M24SR_GetSession(void) {
-	uint8_t commandBuffer[] = M24SR_OPENSESSION_COMMAND;
-
-	errchk(M24SR_IO_SendI2Ccommand(sizeof(commandBuffer), commandBuffer));
-
-	/* 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 */
-	errchk(M24SR_IO_PollI2C());
-
-	return NFC_SUCCESS;
-
+	//start the readID procedure
+	return M24SR_SendSelectApplication();
 }
 
 /**
@@ -403,13 +470,11 @@
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  * @retval Status (SW1&SW2)   if operation does not complete for another reason.
  */
-NFC_StatusTypeDef M24SR::M24SR_SelectCCfile(void) {
+NFC_StatusTypeDef M24SR::M24SR_SendSelectCCfile(void) {
 	C_APDU command;
-
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
 	uint8_t pDataOut[] = CC_FILE_ID_BYTES;
-	NFC_StatusTypeDef status;
 	uint16_t uP1P2 =0x000C,
 	NbByte;
 
@@ -427,17 +492,45 @@
 			&NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedCCFile(this,status);
+		return status;
+	}//else
+
+
+	mLastCommandSend=SELECT_CC_FILE;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS)
+			return M24SR_ReceiveSelectCCfile();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onSelectedCCFile(this,status);
+			return status;
+		}//if-else
+	}//if
 
-	status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveSelectCCfile(void){
+
+	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
+	NFC_StatusTypeDef status;
+
+	mLastCommandSend = NONE;
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedCCFile(this,status);
 		return status;
+	}//else
+	status= M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
+	getCallback()->onSelectedCCFile(this,status);
+	return status;
+
 }
 
 /**
@@ -445,15 +538,13 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_SelectSystemfile(void) {
+NFC_StatusTypeDef M24SR::M24SR_SendSelectSystemfile(void) {
 	C_APDU command;
 
 	uint8_t *pBuffer = uM24SRbuffer;
-	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
 	uint8_t pDataOut[] = SYSTEM_FILE_ID_BYTES;
 	NFC_StatusTypeDef status;
-	uint16_t uP1P2 =0x000C,
-	NbByte;
+	uint16_t uP1P2 =0x000C,	NbByte;
 
 	/* build the command */
 	command.Header.CLA = C_APDU_CLA_DEFAULT;
@@ -469,17 +560,44 @@
 			&NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedSystemFile(this,status);
+		return status;
+	}//else
+
+	mLastCommandSend=SELECT_SYSTEM_FILE;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS)
+			return M24SR_ReceiveSelectSystemfile();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onSelectedSystemFile(this,status);
+			return status;
+		}//if-else
+	}//if
 
-	status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveSelectSystemfile(){
+
+	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
+	NFC_StatusTypeDef status;
+
+	mLastCommandSend = NONE;
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedSystemFile(this,status);
 		return status;
+	}//else
+	status= M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
+	getCallback()->onSelectedSystemFile(this,status);
+	return status;
+
 }
 
 /**
@@ -487,12 +605,11 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_SelectNDEFfile(uint16_t NDEFfileId) {
+NFC_StatusTypeDef M24SR::M24SR_SendSelectNDEFfile(uint16_t NDEFfileId) {
 	C_APDU command;
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
 	uint8_t pDataOut[] = { GETMSB(NDEFfileId), GETLSB(NDEFfileId) };
-	NFC_StatusTypeDef status;
 	uint16_t uP1P2 = 0x000C, NbByte;
 
 	/* build the command */
@@ -505,21 +622,48 @@
 	command.Body.LC = sizeof(pDataOut);
 	command.Body.pData = pDataOut;
 	/* copy the offset */
-	/* build the I²C command */
+	/* build the I2C command */
 	M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SELECTNDEFFILE, &command, uDIDbyte,
 			&NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+
+	}
+
+	mLastCommandSend=SELECT_NDEF_FILE;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS)
+			return M24SR_ReceiveSelectNDEFfile();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onSelectedNDEFFile(this,status);
+			return status;
+		}
+	}
 
-	status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	return NFC_SUCCESS;
+
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveSelectNDEFfile(){
+
+	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
+	NFC_StatusTypeDef status;
+
+	mLastCommandSend = NONE;
+
+	status = M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onSelectedNDEFFile(this,status);
 		return status;
+	}//else
+	status= M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
+	getCallback()->onSelectedNDEFFile(this,status);
+	return status;
 
 }
 
@@ -531,12 +675,16 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_ReadBinary(uint16_t Offset, uint8_t NbByteToRead,
+NFC_StatusTypeDef M24SR::M24SR_SendReadBinary(uint16_t Offset, uint8_t NbByteToRead,
 		uint8_t *pBufferRead) {
+	//clamp the buffer to the max size
+	if(NbByteToRead>M24SR_MAX_BYTE_OPERATION_LENGHT)
+		NbByteToRead=M24SR_MAX_BYTE_OPERATION_LENGHT;
+
 	C_APDU command;
 	uint8_t *pBuffer = uM24SRbuffer;
+	uint16_t NbByte;
 	NFC_StatusTypeDef status;
-	uint16_t NbByte;
 
 	/* build the command */
 	command.Header.CLA = C_APDU_CLA_DEFAULT;
@@ -550,18 +698,53 @@
 	M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_READBINARY, &command, uDIDbyte,
 			&NbByte, pBuffer);
 
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onReadByte(this,status,Offset,pBufferRead,NbByteToRead);
+		return status;
+	}
+
+	mLastCommandSend=READ;
+	mLastCommandData.data=pBufferRead;
+	mLastCommandData.length=NbByteToRead;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveReadBinary();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onReadByte(this,status,Offset,pBufferRead,NbByteToRead);
+			return status;
+		}//if-else
+	}//if
+
+	return NFC_SUCCESS;
+}
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer,
-			NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE);
-	if(status != NFC_COMMAND_SUCCESS)
+NFC_StatusTypeDef M24SR::M24SR_ReceiveReadBinary(){
+
+	NFC_StatusTypeDef status;
+	const uint16_t length = mLastCommandData.length;
+	const uint16_t offset = mLastCommandData.offset;
+	uint8_t *data = mLastCommandData.data;
+
+	mLastCommandSend=NONE;
+
+	status = M24SR_IO_ReceiveI2Cresponse (length + M24SR_STATUSRESPONSE_NBBYTE , uM24SRbuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onReadByte(this,status,offset,data,length);
 		return status;
-	/* retrieve the data without SW1 & SW2 as provided as return value of the function */
-	memcpy(pBufferRead, &pBuffer[1], NbByteToRead);
-	return NFC_SUCCESS;
+	}
+	status = M24SR_IsCorrectCRC16Residue(uM24SRbuffer, length + M24SR_STATUSRESPONSE_NBBYTE);
+	if(status != NFC_SUCCESS)
+		getCallback()->onReadByte(this,status,offset,data,length);
+	else{
+		/* retrieve the data without SW1 & SW2 as provided as return value of the function */
+		memcpy(mLastCommandData.data, &uM24SRbuffer[1], length);
+		getCallback()->onReadByte(this,status,offset,data,length);
+	}
+	return status;
 
 }
 
@@ -573,12 +756,16 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_STReadBinary(uint16_t Offset,
+NFC_StatusTypeDef M24SR::M24SR_SendSTReadBinary(uint16_t Offset,
 		uint8_t NbByteToRead, uint8_t *pBufferRead) {
+	//clamp the buffer to the max size
+	if(NbByteToRead>M24SR_MAX_BYTE_OPERATION_LENGHT)
+		NbByteToRead=M24SR_MAX_BYTE_OPERATION_LENGHT;
+
 	C_APDU command;
 	uint8_t *pBuffer = uM24SRbuffer;
+	uint16_t NbByte;
 	NFC_StatusTypeDef status;
-	uint16_t NbByte;
 
 	/* build the command */
 	command.Header.CLA = C_APDU_CLA_ST;
@@ -592,18 +779,27 @@
 	M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_READBINARY, &command, uDIDbyte,
 			&NbByte, pBuffer);
 
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onReadByte(this,status,Offset,pBufferRead,NbByteToRead);
+		return status;
+	}
+
+	mLastCommandSend=READ;
+	mLastCommandData.data=pBufferRead;
+	mLastCommandData.length=NbByteToRead;
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer,
-			NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE);
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveReadBinary();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onReadByte(this,status,Offset,pBufferRead,NbByteToRead);
+			return status;
+		}//if-else
+	}//if
 
-	if(status != NFC_COMMAND_SUCCESS)
-		return status;
-	/* retrieve the data without SW1 & SW2 as provided as return value of the function */
-	memcpy(pBufferRead, &pBuffer[1], NbByteToRead);
 	return NFC_SUCCESS;
 }
 
@@ -615,13 +811,15 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_UpdateBinary(uint16_t Offset,
+NFC_StatusTypeDef M24SR::M24SR_SendUpdateBinary(uint16_t Offset,
 		uint8_t NbByteToWrite, uint8_t *pDataToWrite) {
-	//TODO check the length of the data to write
+	//clamp the buffer to the max size
+	if(NbByteToWrite>M24SR_MAX_BYTE_OPERATION_LENGHT)
+		NbByteToWrite=M24SR_MAX_BYTE_OPERATION_LENGHT;
+
 	C_APDU command;
-
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status;
 	uint16_t NbByte;
 
 	/* build the command */
@@ -638,32 +836,67 @@
 	M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_UPDATEBINARY, &command, uDIDbyte,
 			&NbByte, pBuffer);
 
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
-	/* if the response is a Watiting frame extenstion request */
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onUpdatedBinary(this,status,Offset,pDataToWrite,NbByteToWrite);
+		return status;
+	}
+
+	mLastCommandSend=UPDATE;
+	mLastCommandData.data=pDataToWrite;
+	mLastCommandData.length=NbByteToWrite;
+	mLastCommandData.offset=Offset;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveUpdateBinary();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onUpdatedBinary(this,status,Offset,pDataToWrite,NbByteToWrite);
+			return status;
+		}//if-else
+	}
 
-	if (IsSBlock(pBuffer) == NFC_SUCCESS) {
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveUpdateBinary() {
+
+	uint8_t respBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+	NFC_StatusTypeDef status;
+	const uint16_t length = mLastCommandData.length;
+	uint8_t *data = mLastCommandData.data;
+	const uint16_t offset = mLastCommandData.offset;
+
+	mLastCommandSend=NONE;
+
+	status= M24SR_IO_ReceiveI2Cresponse (sizeof(respBuffer) , respBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onUpdatedBinary(this,status,offset,data,length);
+		return status;
+	}
+
+	if (IsSBlock(respBuffer) == NFC_SUCCESS) {
 		/*check the CRC */
-		status =M24SR_IsCorrectCRC16Residue(pBuffer,
-				M24SR_WATINGTIMEEXTRESPONSE_NBBYTE);
+		status =M24SR_IsCorrectCRC16Residue(respBuffer,
+					M24SR_WATINGTIMEEXTRESPONSE_NBBYTE);
 		// TODO: why if we check ==NFC_Commandsuccess it fail?
 		if (status != NFC_IO_ERROR_CRC) {
 			/* send the FrameExension response*/
-			errchk(M24SR_FWTExtension(pBuffer[M24SR_OFFSET_PCB + 1]));
-		}else
-			return status;
-	} else {
-		status = M24SR_IsCorrectCRC16Residue(pBuffer,
+			status = M24SR_SendFWTExtension(respBuffer[M24SR_OFFSET_PCB + 1]);
+			if(status!=NFC_SUCCESS){ //something get wrong -> abort the update
+				getCallback()->onUpdatedBinary(this,status,offset,data,length);
+			}//status
+		}//if
+	} else { //isSBlock
+		status = M24SR_IsCorrectCRC16Residue(respBuffer,
 				M24SR_STATUSRESPONSE_NBBYTE);
-		if(status!=NFC_COMMAND_SUCCESS)
-			return status;
-	}
+		getCallback()->onUpdatedBinary(this,status,offset,data,length);
+	}//if else
+	return status;
+}//M24SR_ReceiveUpdateBinary
 
-	return NFC_SUCCESS;
-
-}
 
 /**
  * @brief  This function sends the Verify command
@@ -673,19 +906,16 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_Verify(uint16_t uPwdId, uint8_t NbPwdByte,
+NFC_StatusTypeDef M24SR::M24SR_SendVerify(uint16_t uPwdId, uint8_t NbPwdByte,
 		const uint8_t *pPwd) {
 	C_APDU command;
-
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status = NFC_SUCCESS;
 	uint16_t NbByte;
 
 	/*check the parameters */
-	if (uPwdId > 0x0003) {
-		return NFC_IO_ERROR_PARAMETER;
-	}
-	if ((NbPwdByte != 0x00) && (NbPwdByte != 0x10)) {
+	if ((uPwdId > 0x0003)|| ((NbPwdByte != 0x00) && (NbPwdByte != 0x10))) {
+		getCallback()->onVerifyed(this,NFC_IO_ERROR_PARAMETER);
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -712,19 +942,41 @@
 	}
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	/* wait for answer ready */
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status!=NFC_SUCCESS){
+		getCallback()->onVerifyed(this,status);
+		return status;
+	}
+	mLastCommandSend=VERIFY;
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS)
+			return M24SR_ReceiveVerify();
+		else{
+			mLastCommandSend = NONE;
+			getCallback()->onVerifyed(this,status);
+			return status;
+		}
+	}
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveVerify(){
+	NFC_StatusTypeDef status;
+	uint8_t respBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+	mLastCommandSend=NONE;
+
+	status=M24SR_IO_ReceiveI2Cresponse (sizeof(respBuffer),respBuffer);
+
+	if(status !=NFC_SUCCESS){
+		getCallback()->onVerifyed(this,status);
 		return status;
+	}
 
+	status = M24SR_IsCorrectCRC16Residue(respBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+	getCallback()->onVerifyed(this,status);
+	return status;
 }
 
 /**
@@ -734,15 +986,17 @@
  * @retval Status (SW1&SW2) Satus of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_ChangeReferenceData(uint16_t uPwdId,
+NFC_StatusTypeDef M24SR::M24SR_SendChangeReferenceData(uint16_t uPwdId,
 		uint8_t *pPwd) {
 	C_APDU command;
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status;
 	uint16_t NbByte;
 
 	/*check the parameters */
 	if (uPwdId > 0x0003) {
+		getCallback()->onChangeReferenceData(this,NFC_IO_ERROR_PARAMETER,
+				constToPasswordType(uPwdId), pPwd);
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -761,18 +1015,52 @@
 			&NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onChangeReferenceData(this,status,
+							constToPasswordType(uPwdId), pPwd);
+		return status;
+	}
+
+	mLastCommandSend = CHANGE_REFERENCE_DATA;
+	mLastCommandData.data = pPwd;
+	//use the offset filed for store the pwd id;
+	mLastCommandData.offset = (uint8_t)uPwdId;
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS){
+			return M24SR_ReceiveChangeReferenceData();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onChangeReferenceData(this,status,
+					constToPasswordType(uPwdId), pPwd);
+			return status;
+		}//if-else
+	}//if
+
+	return NFC_SUCCESS;
+}
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+NFC_StatusTypeDef M24SR::M24SR_ReceiveChangeReferenceData(){
+	NFC_StatusTypeDef status;
+	//TODO the size is 3?
+	uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+
+	PasswordType_t type = constToPasswordType(mLastCommandData.offset);
+	uint8_t *data = mLastCommandData.data;
+
+	status =M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onChangeReferenceData(this,status,type,data);
 		return status;
+	}//else
+
+	status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+
+	status = (status == NFC_COMMAND_SUCCESS) ? NFC_SUCCESS : status;
+	getCallback()->onChangeReferenceData(this,status,type,data);
+	return status;
 }
 
 /**
@@ -781,15 +1069,17 @@
  * @retval Status (SW1&SW2) Status of the operation to complete.
  * @retval M24SR_ERROR_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_EnableVerificationRequirement(
+NFC_StatusTypeDef M24SR::M24SR_SendEnableVerificationRequirement(
 		uint16_t uReadOrWrite) {
 	C_APDU command;
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status = NFC_SUCCESS;
 	uint16_t NbByte;
 
 	/*check the parameters */
 	if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
+		getCallback()->onEnableVerificationRequirement(this,NFC_IO_ERROR_PARAMETER,
+				constToPasswordType(uReadOrWrite));
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -804,35 +1094,70 @@
 			uDIDbyte, &NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	/* The right access to be updated in EEPROM need at least 6ms */
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onEnableVerificationRequirement(this,status,
+				constToPasswordType(uReadOrWrite));
+		return status;
+	}//if
+
+	mLastCommandSend = ENABLE_VERIFICATION_REQUIREMENT;
+	//use the offset filed for store the pwd id;
+	mLastCommandData.offset = (uint8_t)uReadOrWrite;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status == NFC_SUCCESS){
+			return M24SR_ReceiveEnableVerificationRequirement();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onEnableVerificationRequirement(this,status,
+							constToPasswordType(uReadOrWrite));
+			return status;
+		}//if-else
+	}//if
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveEnableVerificationRequirement(){
+	NFC_StatusTypeDef status;
+	//TODO the size is 3?
+	uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+
+	const PasswordType_t type = constToPasswordType(mLastCommandData.offset);
+
+	status =M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onEnableVerificationRequirement(this,status,type);
 		return status;
+	}//else
+
+	status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+
+	status = (status == NFC_COMMAND_SUCCESS) ? NFC_SUCCESS : status;
+	getCallback()->onEnableVerificationRequirement(this,status,type);
+	return status;
 }
 
+
 /**
  * @brief  This function sends the DisableVerificationRequirement command
  * @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_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_DisableVerificationRequirement(
+NFC_StatusTypeDef M24SR::M24SR_SendDisableVerificationRequirement(
 		uint16_t uReadOrWrite) {
 	C_APDU command;
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status = NFC_SUCCESS;
 	uint16_t NbByte;
 
 	/*check the parameters */
 	if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
+		getCallback()->onDisableVerificationRequirement(this,NFC_IO_ERROR_PARAMETER,
+				 constToPasswordType(uReadOrWrite));
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -847,37 +1172,71 @@
 			uDIDbyte, &NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	/* The right access to be updated in EEPROM need at least 6ms */
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onDisableVerificationRequirement(this,status,
+				constToPasswordType(uReadOrWrite));
+		return status;
+	}
+
+	mLastCommandSend = DISABLE_VERIFICATION_REQUIREMENT;
+	//use the offset filed for store the pwd id;
+	mLastCommandData.offset = (uint8_t)uReadOrWrite;
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveDisableVerificationRequirement();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onDisableVerificationRequirement(this,status,
+							constToPasswordType(uReadOrWrite));
+			return status;
+		}//if-else
+	}
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
-		return status;
+	return NFC_SUCCESS;
 
 }
 
+NFC_StatusTypeDef M24SR::M24SR_ReceiveDisableVerificationRequirement(){
+	NFC_StatusTypeDef status;
+	//TODO the size is 3?
+	uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+
+	PasswordType_t type = constToPasswordType(mLastCommandData.offset);
+
+	status =M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onDisableVerificationRequirement(this,status,type);
+		return status;
+	}//else
+
+	status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+
+	status = (status == NFC_COMMAND_SUCCESS) ? NFC_SUCCESS : status;
+	getCallback()->onDisableVerificationRequirement(this,status,type);
+	return status;
+}
+
+
 /**
  * @brief  This function sends the EnablePermananentState command
  * @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_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_EnablePermanentState(uint16_t uReadOrWrite) {
+NFC_StatusTypeDef M24SR::M24SR_SendEnablePermanentState(uint16_t uReadOrWrite) {
 	C_APDU command;
+	NFC_StatusTypeDef status;
 
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status = NFC_SUCCESS;
 	uint16_t NbByte;
 
 	/*check the parameters */
 	if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
+		getCallback()->onEnablePermanentState(this,NFC_IO_ERROR_PARAMETER,
+						constToPasswordType(uReadOrWrite));
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -892,34 +1251,69 @@
 			&NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onEnablePermanentState(this,status,
+				constToPasswordType(uReadOrWrite));
+		return status;
+	}
+
+	mLastCommandSend = ENABLE_PERMANET_STATE;
+	//use the offset filed for store the pwd id;
+	mLastCommandData.offset = (uint8_t)uReadOrWrite;
+
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveEnablePermanentState();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onEnablePermanentState(this,status,
+							constToPasswordType(uReadOrWrite));
+			return status;
+		}//if-else
+	}
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+	return NFC_SUCCESS;
+}
+
+NFC_StatusTypeDef M24SR::M24SR_ReceiveEnablePermanentState(){
+	NFC_StatusTypeDef status;
+	//TODO the size is 3?
+	uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+
+	PasswordType_t type = constToPasswordType(mLastCommandData.offset);
+
+	status =M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onEnablePermanentState(this,status,type);
 		return status;
+	}//else
+
+	status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+
+	status = (status == NFC_COMMAND_SUCCESS) ? NFC_SUCCESS : status;
+	getCallback()->onEnablePermanentState(this,status,type);
+	return status;
 }
 
+
 /**
  * @brief  This function sends the DisablePermanentState command
  * @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_I2CTIMEOUT I2C timeout occurred.
  */
-NFC_StatusTypeDef M24SR::M24SR_DisablePermanentState(uint16_t uReadOrWrite) {
+NFC_StatusTypeDef M24SR::M24SR_SendDisablePermanentState(uint16_t uReadOrWrite) {
 	C_APDU command;
-
+	NFC_StatusTypeDef status;
 	uint8_t *pBuffer = uM24SRbuffer;
-	NFC_StatusTypeDef status = NFC_SUCCESS;
 	uint16_t NbByte;
 
 	/*check the parameters */
 	if ((uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002)) {
+		getCallback()->onDisablePermanentState(this,NFC_IO_ERROR_PARAMETER,
+				constToPasswordType(uReadOrWrite));
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
@@ -934,18 +1328,50 @@
 			uDIDbyte, &NbByte, pBuffer);
 
 	/* send the request */
-	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
-	/* read the response */
-	errchk(
-			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
+	status = M24SR_IO_SendI2Ccommand(NbByte, pBuffer);
+	if(status != NFC_SUCCESS){
+		getCallback()->onEnablePermanentState(this,status,
+				constToPasswordType(uReadOrWrite));
+		return status;
+	}
+
+	mLastCommandSend = ENABLE_PERMANET_STATE;
+	//use the offset filed for store the pwd id;
+	mLastCommandData.offset = (uint8_t)uReadOrWrite;
 
-	status = M24SR_IsCorrectCRC16Residue(pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+	if(mCommunicationType==M24SR::SYNC){
+		status = M24SR_IO_PollI2C();
+		if(status==NFC_SUCCESS){
+			return M24SR_ReceiveDisablePermanentState();
+		}else{
+			mLastCommandSend = NONE;
+			getCallback()->onDisablePermanentState(this,status,
+							constToPasswordType(uReadOrWrite));
+			return status;
+		}//if-else
+	}
+
+	return NFC_SUCCESS;
+}
 
-	if(status == NFC_COMMAND_SUCCESS)
-		return NFC_SUCCESS;
-	else
+NFC_StatusTypeDef M24SR::M24SR_ReceiveDisablePermanentState(){
+	NFC_StatusTypeDef status;
+	//TODO the size is 3?
+	uint8_t rensponseBuffer[M24SR_STATUSRESPONSE_NBBYTE];
+
+	PasswordType_t type = constToPasswordType(mLastCommandData.offset);
+
+	status =M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , rensponseBuffer );
+	if(status!=NFC_SUCCESS){
+		getCallback()->onDisablePermanentState(this,status,type);
 		return status;
+	}//else
+
+	status = M24SR_IsCorrectCRC16Residue(rensponseBuffer, M24SR_STATUSRESPONSE_NBBYTE);
+
+	status = (status == NFC_COMMAND_SUCCESS) ? NFC_SUCCESS : status;
+	getCallback()->onDisablePermanentState(this,status,type);
+	return status;
 }
 
 /**
@@ -977,7 +1403,7 @@
 
 	/* send the request */
 	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
+	errchk(M24SR_IO_PollI2C());
 	/* read the response */
 	errchk(
 			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
@@ -1028,7 +1454,7 @@
 
 	/* send the request */
 	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
-	errchk(M24SR_IO_IsAnswerReady());
+	errchk(M24SR_IO_PollI2C());
 	/* read the response */
 	errchk(
 			M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
@@ -1042,55 +1468,32 @@
 }
 
 
-NFC_StatusTypeDef M24SR::M24SR_ManageI2CGPO(M24SR_GPO_MGMT GPO_I2Cconfig) {
-	uint8_t GPO_config = 0;
+NFC_StatusTypeDef M24SR::M24SR_ManageI2CGPO(NFC_GPO_MGMT GPO_I2Cconfig) {
 
 	if (GPO_I2Cconfig > STATE_CONTROL) {
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
-	errchk(M24SR_SelectApplication());
-
-	errchk(M24SR_SelectSystemfile());
+	//enable the callback for change the gpo
+	mComponentCallback = &mManageGPOCallback;
+	mManageGPOCallback.setNewGpoConfig(true,GPO_I2Cconfig);
 
-	errchk(M24SR_ReadBinary(0x0004, 0x01, &GPO_config))
-	errchk(M24SR_Verify(I2C_PWD, 0x10, DEFAULT_PASSWORD));
-	
-	/* Update only GPO purpose for I2C */
-	GPO_config = (GPO_config & 0xF0) | GPO_I2Cconfig;
-	
-	errchk(M24SR_UpdateBinary(0x0004, 0x01, &(GPO_config)));
-		
-	/* if we use the gpo for know when the asnwer is ready,
-	  we can use the interrupt for do the polling, otherwise just wait on the
-	  i2c read */
-	if (GPO_I2Cconfig == I2C_ANSWER_READY)
-		M24SR_IO_SetI2CSynchroMode(M24SR_INTERRUPT_GPO);
-	else
-		M24SR_IO_SetI2CSynchroMode(M24SR_WAITINGTIME_POLLING);
-
-	return NFC_SUCCESS;
+	//start the manageGPO procedure
+	return M24SR_SendSelectApplication();
 }
 
-NFC_StatusTypeDef M24SR::M24SR_ManageRFGPO(M24SR_GPO_MGMT GPO_RFconfig) {
-	uint8_t GPO_config;
+NFC_StatusTypeDef M24SR::M24SR_ManageRFGPO(NFC_GPO_MGMT GPO_I2Cconfig) {
 
-	if (GPO_RFconfig > STATE_CONTROL) {
+	if (GPO_I2Cconfig > STATE_CONTROL) {
 		return NFC_IO_ERROR_PARAMETER;
 	}
 
-	errchk(M24SR_SelectApplication())
-	errchk(M24SR_SelectSystemfile())
-	errchk(M24SR_ReadBinary(0x0004, 0x01, &GPO_config))
+	//enable the callback for change the gpo
+	mComponentCallback = &mManageGPOCallback;
+	mManageGPOCallback.setNewGpoConfig(false,GPO_I2Cconfig);
 
-	/* Update only GPO purpose for I2C */
-	GPO_config = (GPO_config & 0x0F) | (GPO_RFconfig << 4);
-
-	errchk(M24SR_SelectSystemfile())
-	errchk(M24SR_Verify(I2C_PWD, 0x10, DEFAULT_PASSWORD))
-	errchk(M24SR_UpdateBinary(0x0004, 0x01, &(GPO_config)))
-
-	return NFC_SUCCESS;
+	//start the manageGPO procedure
+	return M24SR_SendSelectApplication();
 }
 
 NFC_StatusTypeDef M24SR::M24SR_RFConfig(uint8_t OnOffChoice) {
@@ -1134,100 +1537,107 @@
 	return NFC_IO_ERROR_I2CTIMEOUT;
 }
 
-NFC_StatusTypeDef M24SR::M24SR_IO_IsAnswerReady(void) {
-		
-	switch (syncMode) {
-	case M24SR_WAITINGTIME_POLLING:
-		return M24SR_IO_PollI2C();
-
-	case M24SR_INTERRUPT_GPO:
+NFC_StatusTypeDef M24SR::ManageEvent(void){
 
-		while (!interruptIsFired ){
-			__WFE();
-		}//while
-		interruptIsFired = false;
+	switch(mLastCommandSend){
+		case SELECT_APPLICATION:
+			return M24SR_ReceiveSelectApplication();
+		case SELECT_CC_FILE:
+			return M24SR_ReceiveSelectCCfile();
+		case SELECT_NDEF_FILE:
+			return M24SR_ReceiveSelectNDEFfile();
+		case SELECT_SYSTEM_FILE:
+			return M24SR_ReceiveSelectSystemfile();
+		case READ:
+			return M24SR_ReceiveReadBinary();
+		case UPDATE:
+			return M24SR_ReceiveUpdateBinary();
+		case VERIFY:
+			return M24SR_ReceiveVerify();
+		case DESELECT:
+			return M24SR_ReceiveDeselect();
+		case CHANGE_REFERENCE_DATA:
+			return M24SR_ReceiveChangeReferenceData();
+		case ENABLE_VERIFICATION_REQUIREMENT:
+			return M24SR_ReceiveEnableVerificationRequirement();
+		case DISABLE_VERIFICATION_REQUIREMENT:
+			return M24SR_ReceiveDisableVerificationRequirement();
 
-		return NFC_SUCCESS;
-
-	default:
-		return NFC_IO_ERROR_I2CTIMEOUT;
-	}
-
-}
+		default:
+			return NFC_SUCCESS;
+	}//switch
+}//manageInterrupt
 
 ////////////////////////hight level utility function //////////////////////////
 
 NFC_StatusTypeDef M24SR::enableReadPassword(const uint8_t* pCurrentWritePassword,
-			const uint8_t* pNewPassword) {		
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	/* Set new password */
-	errchk(ChangeReferenceData(M24SR::ReadPwd, pNewPassword));
-	return EnableVerificationRequirement(M24SR::ReadPwd);
+			const uint8_t* pNewPassword) {
+
+	//enable the callback for change the gpo
+	mComponentCallback = &mChangePasswordRequestStatusCallback;
+	mChangePasswordRequestStatusCallback.setTask(ReadPwd,pNewPassword);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 }
 
 NFC_StatusTypeDef M24SR::disableReadPassword(const uint8_t* pCurrentWritePassword) {
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	return DisableVerificationRequirement(M24SR::ReadPwd);
+	mComponentCallback = &mChangePasswordRequestStatusCallback;
+	mChangePasswordRequestStatusCallback.setTask(ReadPwd,NULL);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 }
 
 NFC_StatusTypeDef M24SR::enableWritePassword(const uint8_t* pCurrentWritePassword,
 			uint8_t* pNewPassword) {
-	/* check we have the good password */
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	/* Set new password */
-	errchk(ChangeReferenceData(M24SR::WritePwd, pNewPassword));
-	return EnableVerificationRequirement(M24SR::WritePwd);
+	//enable the callback for change the gpo
+	mComponentCallback = &mChangePasswordRequestStatusCallback;
+	mChangePasswordRequestStatusCallback.setTask(WritePwd,pNewPassword);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 }
 
 NFC_StatusTypeDef M24SR::disableWritePassword(const uint8_t* pCurrentWritePassword) {
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	return(DisableVerificationRequirement(M24SR::WritePwd));
+	mComponentCallback = &mChangePasswordRequestStatusCallback;
+	mChangePasswordRequestStatusCallback.setTask(WritePwd,NULL);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 }
 
 NFC_StatusTypeDef M24SR::disableAllPassword(const uint8_t* pSuperUserPassword){
-	errchk(Verify(M24SR::I2CPwd, 0x10, pSuperUserPassword));
-
-	errchk(DisablePermanentState(M24SR::ReadPwd));
-	errchk(DisablePermanentState(M24SR::WritePwd));
-
-	errchk(DisableVerificationRequirement(M24SR::ReadPwd));
-	errchk(DisableVerificationRequirement(M24SR::WritePwd));
-
-	/* reset password */
-	errchk(ChangeReferenceData(M24SR::ReadPwd, M24SR::DEFAULT_PASSWORD));
-	return(ChangeReferenceData(M24SR::WritePwd, M24SR::DEFAULT_PASSWORD));
+	mComponentCallback = &mChangePasswordRequestStatusCallback;
+	return Verify(M24SR::I2CPwd, 0x10, pSuperUserPassword);
 }
 
 NFC_StatusTypeDef M24SR::enableReadOnly(const uint8_t* pCurrentWritePassword){
 
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	/* lock write to have read only */
-	return EnablePermanentState(M24SR::WritePwd);
+	mComponentCallback = &mChangeAccessStateCallback;
+	//disable write = read only
+	mChangeAccessStateCallback.changeAccessState(ChangeAccessStateCallback::WRITE,false);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 }
 
 NFC_StatusTypeDef M24SR::disableReadOnly() {
-
-	errchk(Verify(M24SR::I2CPwd, 0x10, M24SR::DEFAULT_PASSWORD));
-	/* disable write protection to disable read only mode */
-	errchk(DisablePermanentState(M24SR::WritePwd));
-	return(DisableVerificationRequirement(M24SR::WritePwd));
+	mComponentCallback = &mChangeAccessStateCallback;
+	mChangeAccessStateCallback.changeAccessState(ChangeAccessStateCallback::WRITE,true);
+	return Verify(M24SR::I2CPwd, 0x10, M24SR::DEFAULT_PASSWORD);
 }
 
 	
 NFC_StatusTypeDef M24SR::enableWriteOnly(const uint8_t* pCurrentWritePassword) {
 
-	errchk(Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword));
-	/* disable read access and keep write */
-	return(EnablePermanentState(M24SR::ReadPwd));
+	mComponentCallback = &mChangeAccessStateCallback;
+	//disable read = enable write only
+	mChangeAccessStateCallback.changeAccessState(ChangeAccessStateCallback::READ,false);
+
+	return Verify(M24SR::WritePwd, 0x10, pCurrentWritePassword);
 
 }
 
 NFC_StatusTypeDef M24SR::disableWriteOnly() {
-
-	errchk(Verify(M24SR::I2CPwd, 0x10, M24SR::DEFAULT_PASSWORD));
-	/* disable write only -> enable write acces */
-	errchk(DisablePermanentState(M24SR::ReadPwd))
-	return DisableVerificationRequirement(M24SR::ReadPwd);
+	mComponentCallback = &mChangeAccessStateCallback;
+	mChangeAccessStateCallback.changeAccessState(ChangeAccessStateCallback::READ,true);
+	return Verify(M24SR::I2CPwd, 0x10, M24SR::DEFAULT_PASSWORD);
 }
 
 /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/
--- a/m24sr/m24sr_class.h	Fri Jan 22 09:04:51 2016 +0000
+++ b/m24sr/m24sr_class.h	Thu Jan 28 14:01:18 2016 +0000
@@ -69,28 +69,49 @@
 	 * Default password used to change the write/read permission
 	 */
 	static const uint8_t DEFAULT_PASSWORD[16];
-	
+
+	/**
+	 * Default gpo status
+	 */
+	static const NFC_GPO_MGMT DEFAULT_GPO_STATUS=HIGH_IMPEDANCE;
+
 	/*** Constructor and Destructor Methods ***/
 
 	/**
 	 * @brief Constructor.
 	 * @param address I2C address of the component.
 	 * @param I2C     I2C device to be used for communication.
+	 * @param eventCallback Function that will be called when the gpo pin status change.
 	 * @param GPOPinName Pin used as GPIO.
 	 * @param RFDISPinName Pin used to disable the RF function.
 	 */
-	M24SR(const uint8_t address, I2C &I2C, const PinName& GPOPinName,
+	M24SR(const uint8_t address, I2C &I2C,gpoEventCallback eventCallback, const PinName& GPOPinName,
 			const PinName& RFDISPinName) :
-			Nfc(), address(address), dev_I2C(I2C), GPOPin(GPOPinName), RFDisablePin(
-					RFDISPinName), answerReadyInterrupt(GPOPinName), interruptIsFired(
-					false),NDefTagUtil(*this) {
+			Nfc(),
+			who_am_i(0),
+			type(0),
+			address(address),
+			dev_I2C(I2C),
+			GPOPin(GPOPinName),
+			RFDisablePin(RFDISPinName),
+			NDefTagUtil(*this),
+			mCommunicationType(SYNC),
+			mLastCommandSend(NONE),
+			mGpoEventInterrupt(GPOPinName),
+			mComponentCallback(NULL),
+			mManageGPOCallback(*this),
+			mReadIDCallback(*this),
+			mChangePasswordRequestStatusCallback(*this),
+			mRemoveAllPasswordCallback(*this),
+			mChangeAccessStateCallback(*this){
+
 		memset(uM24SRbuffer, 0, 0xFF * sizeof(int8_t));
 		uDIDbyte = 0;
 		RFDisablePin = 0;
-		GPOPin.mode(PullNone);
-		answerReadyInterrupt.fall(this,
-				&M24SR::M24SR_AnswerReadyInterruptCallback);
-		answerReadyInterrupt.mode(PullUp);
+
+		mGpoEventInterrupt.fall(eventCallback);
+		mGpoEventInterrupt.mode(PullUp);
+		mGpoEventInterrupt.disable_irq();
 	}
 
 	/**
@@ -130,30 +151,30 @@
 	////////// tag4 command ////////////////////
 	
 	virtual NFC_StatusTypeDef SelectApplication(void) {
-		return (NFC_StatusTypeDef) M24SR_SelectApplication();
+		return M24SR_SendSelectApplication();
 	}
 
 	virtual NFC_StatusTypeDef SelectCCfile(void) {
-		return (NFC_StatusTypeDef) M24SR_SelectCCfile();
+		return M24SR_SendSelectCCfile();
 	}
 
 	virtual NFC_StatusTypeDef SelectNDEFfile(uint16_t NDEFfileId) {
-		return (NFC_StatusTypeDef) M24SR_SelectNDEFfile((uint16_t) NDEFfileId);
+		return M24SR_SendSelectNDEFfile(NDEFfileId);
 	}
 
 	virtual NFC_StatusTypeDef SelectSystemfile(void) {
-		return (NFC_StatusTypeDef) M24SR_SelectSystemfile();
+		return M24SR_SendSelectSystemfile();
 	}
 
 	virtual NFC_StatusTypeDef ReadBinary(uint16_t Offset, uint8_t NbByteToRead,
 			uint8_t *pBufferRead) {
-		return (NFC_StatusTypeDef) M24SR_ReadBinary((uint16_t) Offset,
+		return (NFC_StatusTypeDef) M24SR_SendReadBinary((uint16_t) Offset,
 				(uint8_t) NbByteToRead, (uint8_t *) pBufferRead);
 	}
 
 	virtual NFC_StatusTypeDef UpdateBinary(uint16_t Offset,
-			uint8_t NbByteToWrite, uint8_t *pDataToWrite) {
-		return (NFC_StatusTypeDef) M24SR_UpdateBinary((uint16_t) Offset,
+			uint8_t NbByteToWrite,uint8_t *pDataToWrite) {
+		return (NFC_StatusTypeDef) M24SR_SendUpdateBinary((uint16_t) Offset,
 				(uint8_t) NbByteToWrite, (uint8_t *) pDataToWrite);
 	}
 
@@ -161,25 +182,25 @@
 	
 	virtual NFC_StatusTypeDef Verify(PasswordType_t pwdId, uint8_t NbPwdByte,
 			const uint8_t *pPwd) {
-		return (NFC_StatusTypeDef) M24SR_Verify(passwordTypeToConst(pwdId),
+		return (NFC_StatusTypeDef) M24SR_SendVerify(passwordTypeToConst(pwdId),
 				(uint8_t) NbPwdByte, pPwd);
 	}
 
 	virtual NFC_StatusTypeDef ChangeReferenceData(PasswordType_t pwdId,
 			const uint8_t *pPwd) {
-		return (NFC_StatusTypeDef) M24SR_ChangeReferenceData(passwordTypeToConst(pwdId),
+		return (NFC_StatusTypeDef) M24SR_SendChangeReferenceData(passwordTypeToConst(pwdId),
 				(uint8_t *) pPwd);
 	}
 
 	virtual NFC_StatusTypeDef EnableVerificationRequirement(
 			PasswordType_t uReadOrWrite) {
-		return (NFC_StatusTypeDef) M24SR_EnableVerificationRequirement(
+		return (NFC_StatusTypeDef) M24SR_SendEnableVerificationRequirement(
 				passwordTypeToConst(uReadOrWrite));
 	}
 
 	virtual NFC_StatusTypeDef DisableVerificationRequirement(
 			PasswordType_t uReadOrWrite) {
-		return (NFC_StatusTypeDef) M24SR_DisableVerificationRequirement(
+		return (NFC_StatusTypeDef) M24SR_SendDisableVerificationRequirement(
 				passwordTypeToConst(uReadOrWrite));
 	}
 
@@ -187,17 +208,17 @@
 
 	virtual NFC_StatusTypeDef STReadBinary(uint16_t Offset,
 			uint8_t NbByteToRead, uint8_t *pBufferRead) {
-		return (NFC_StatusTypeDef) M24SR_STReadBinary((uint16_t) Offset,
+		return (NFC_StatusTypeDef) M24SR_SendSTReadBinary((uint16_t) Offset,
 				(uint8_t) NbByteToRead, (uint8_t *) pBufferRead);
 	}
 
 	virtual NFC_StatusTypeDef EnablePermanentState(PasswordType_t uReadOrWrite) {
-		return (NFC_StatusTypeDef) M24SR_EnablePermanentState(
+		return (NFC_StatusTypeDef) M24SR_SendEnablePermanentState(
 				passwordTypeToConst(uReadOrWrite));
 	}
 
 	virtual NFC_StatusTypeDef DisablePermanentState(PasswordType_t uReadOrWrite) {
-		return (NFC_StatusTypeDef) M24SR_DisablePermanentState(
+		return (NFC_StatusTypeDef) M24SR_SendDisablePermanentState(
 				passwordTypeToConst(uReadOrWrite));
 	}
 
@@ -206,25 +227,20 @@
 		return (NFC_StatusTypeDef) M24SR_StateControl((uint8_t) uSetOrReset);
 	}
 
-	virtual NFC_StatusTypeDef ManageI2CGPO(uint8_t GPO_I2Cconfig) {
-		return (NFC_StatusTypeDef) M24SR_ManageI2CGPO(
-				(M24SR_GPO_MGMT) GPO_I2Cconfig);
+	virtual NFC_StatusTypeDef ManageI2CGPO(NFC_GPO_MGMT GPO_I2Cconfig) {
+		return (NFC_StatusTypeDef) M24SR_ManageI2CGPO(GPO_I2Cconfig);
 	}
 
 	virtual NFC_StatusTypeDef ManageRFGPO(uint8_t GPO_RFconfig) {
 		return (NFC_StatusTypeDef) M24SR_ManageRFGPO(
-				(M24SR_GPO_MGMT) GPO_RFconfig);
+				(NFC_GPO_MGMT) GPO_RFconfig);
 	}
 
 	virtual NFC_StatusTypeDef RFConfig(uint8_t OnOffChoice) {
 		return (NFC_StatusTypeDef) M24SR_RFConfig((uint8_t) OnOffChoice);
 	}
 
-	/**
-	 * Generates a negative pulse on the GPO pin.
-	 * Pulse starts immediately after the command is issued and ends at the end of the RF response.
-  	 * @return NFC_SUCCESS if no errors
-	 */
+
 	virtual NFC_StatusTypeDef SendInterrupt(void) {
 		return (NFC_StatusTypeDef) M24SR_SendInterrupt();
 	}
@@ -316,6 +332,8 @@
 	 */
 	NFC_StatusTypeDef disableWriteOnly();
 
+	virtual NFC_StatusTypeDef ManageEvent();
+
 protected:
 
 	/*** Protected Component Related Methods ***/
@@ -324,41 +342,66 @@
 	NFC_StatusTypeDef M24SR_ReadID(uint8_t *nfc_id);
 	NFC_StatusTypeDef M24SR_GetSession(void);
 	NFC_StatusTypeDef M24SR_KillSession(void);
+
 	NFC_StatusTypeDef M24SR_Deselect(void);
-	NFC_StatusTypeDef M24SR_SelectApplication(void);
-	NFC_StatusTypeDef M24SR_SelectCCfile(void);
-	NFC_StatusTypeDef M24SR_SelectNDEFfile(uint16_t NDEFfileId);
-	NFC_StatusTypeDef M24SR_SelectSystemfile(void);
-	NFC_StatusTypeDef M24SR_ReadBinary(uint16_t Offset, uint8_t NbByteToRead,
-			uint8_t *pBufferRead);
-	NFC_StatusTypeDef M24SR_STReadBinary(uint16_t Offset, uint8_t NbByteToRead,
+	NFC_StatusTypeDef M24SR_ReceiveDeselect(void);
+
+	NFC_StatusTypeDef M24SR_SendSelectApplication(void);
+	NFC_StatusTypeDef M24SR_ReceiveSelectApplication(void);
+
+	NFC_StatusTypeDef M24SR_SendSelectCCfile(void);
+	NFC_StatusTypeDef M24SR_ReceiveSelectCCfile(void);
+
+	NFC_StatusTypeDef M24SR_SendSelectNDEFfile(uint16_t NDEFfileId);
+	NFC_StatusTypeDef M24SR_ReceiveSelectNDEFfile();
+
+	NFC_StatusTypeDef M24SR_SendSelectSystemfile(void);
+	NFC_StatusTypeDef M24SR_ReceiveSelectSystemfile(void);
+
+	NFC_StatusTypeDef M24SR_SendReadBinary(uint16_t Offset, uint8_t NbByteToRead,
 			uint8_t *pBufferRead);
-	NFC_StatusTypeDef M24SR_UpdateBinary(uint16_t Offset, uint8_t NbByteToWrite,
+	NFC_StatusTypeDef M24SR_SendSTReadBinary(uint16_t Offset, uint8_t NbByteToRead,
+				uint8_t *pBufferRead);
+	NFC_StatusTypeDef M24SR_ReceiveReadBinary(void);
+
+	NFC_StatusTypeDef M24SR_SendUpdateBinary(uint16_t Offset, uint8_t NbByteToWrite,
 			uint8_t *pDataToWrite);
-	NFC_StatusTypeDef M24SR_Verify(uint16_t uPwdId, uint8_t NbPwdByte,
+	NFC_StatusTypeDef M24SR_ReceiveUpdateBinary();
+
+	NFC_StatusTypeDef M24SR_SendVerify(uint16_t uPwdId, uint8_t NbPwdByte,
 			const uint8_t *pPwd);
-	NFC_StatusTypeDef M24SR_ChangeReferenceData(uint16_t uPwdId, uint8_t *pPwd);
-	NFC_StatusTypeDef M24SR_EnableVerificationRequirement(
+	NFC_StatusTypeDef M24SR_ReceiveVerify();
+
+	NFC_StatusTypeDef M24SR_SendChangeReferenceData(uint16_t uPwdId, uint8_t *pPwd);
+	NFC_StatusTypeDef M24SR_ReceiveChangeReferenceData();
+
+	NFC_StatusTypeDef M24SR_SendEnableVerificationRequirement(
 			uint16_t uReadOrWrite);
-	NFC_StatusTypeDef M24SR_DisableVerificationRequirement(
+	NFC_StatusTypeDef M24SR_ReceiveEnableVerificationRequirement();
+
+	NFC_StatusTypeDef M24SR_SendDisableVerificationRequirement(
 			uint16_t uReadOrWrite);
-	NFC_StatusTypeDef M24SR_EnablePermanentState(uint16_t uReadOrWrite);
-	NFC_StatusTypeDef M24SR_DisablePermanentState(uint16_t uReadOrWrite);
+	NFC_StatusTypeDef M24SR_ReceiveDisableVerificationRequirement();
+
+	NFC_StatusTypeDef M24SR_SendEnablePermanentState(uint16_t uReadOrWrite);
+	NFC_StatusTypeDef M24SR_ReceiveEnablePermanentState();
+
+	NFC_StatusTypeDef M24SR_SendDisablePermanentState(uint16_t uReadOrWrite);
+	NFC_StatusTypeDef M24SR_ReceiveDisablePermanentState();
+
 	NFC_StatusTypeDef M24SR_SendInterrupt(void);
 	NFC_StatusTypeDef M24SR_StateControl(uint8_t uSetOrReset);
-	NFC_StatusTypeDef M24SR_ManageI2CGPO(M24SR_GPO_MGMT GPO_I2Cconfig);
-	NFC_StatusTypeDef M24SR_ManageRFGPO(M24SR_GPO_MGMT GPO_RFconfig);
-	NFC_StatusTypeDef M24SR_RFConfig(uint8_t OnOffChoice);
-	NFC_StatusTypeDef M24SR_FWTExtension(uint8_t FWTbyte);
+
+	NFC_StatusTypeDef M24SR_ManageI2CGPO(NFC_GPO_MGMT GPO_I2Cconfig);
+	NFC_StatusTypeDef M24SR_ManageRFGPO(NFC_GPO_MGMT GPO_RFconfig);
 
-	/**
-	 * Wait until the answer is ready.
-	 */
-	NFC_StatusTypeDef M24SR_IO_IsAnswerReady(void);
+	NFC_StatusTypeDef M24SR_RFConfig(uint8_t OnOffChoice);
+	NFC_StatusTypeDef M24SR_SendFWTExtension(uint8_t FWTbyte);
+
 	
 	/**
 	 * Send a command to the component.
-	 * @param NbByte Lenght of the command.
+	 * @param NbByte Length of the command.
 	 * @param pBuffer Buffer containing the command.
 	 * @return NFC_SUCCESS if no errors
 	 */
@@ -398,27 +441,6 @@
 			RFDisablePin = 1;
 	}
 
-	/**
-	 * Set the command synchronous answer mode.
-	 * @param mode How to wait the I2C rensponse.
-	 */
-	void M24SR_IO_SetI2CSynchroMode(M24SR_WAITINGTIME_MGMT mode) {
-		syncMode = mode;
-	}
-
-	/**
-	 * Callback triggers when a command is completed.
-	 */
-	void M24SR_AnswerReadyInterruptCallback() {
-		/**
-		 * register the interrupt only if we are waiting for it
-		 * the gpo can became low also for other reason 
-		 */
-		if(syncMode==M24SR_INTERRUPT_GPO){ 
-			interruptIsFired=true;
-		}//if
-	}
-
 	/*** Component's Instance Variables ***/
 
 	/* Identity */
@@ -442,16 +464,6 @@
 	DigitalOut RFDisablePin;
 
 	/**
-	 * Pin used as interrupt.
-	 */
-	InterruptIn answerReadyInterrupt;
-
-	/**
-	 * Method used to wait the chip response.
-	 */
-	M24SR_WAITINGTIME_MGMT syncMode;
-
-	/**
 	 * Buffer used to build the command to send to the chip.
 	 */
 	uint8_t uM24SRbuffer[0xFF];//max command length is 255
@@ -462,18 +474,564 @@
 	uint8_t uDIDbyte;
 
 	/**
-	 * State variable changes when the interrupt is fired.
-	 */
-	volatile bool interruptIsFired;
-	
-	/**
 	 * Object implementing the interface to use the NDefLib.
 	 */
 	NDefNfcTagM24SR NDefTagUtil;
-	
+
+	/**
+	 * command that the component can accept
+	 */
+	typedef enum{
+		NONE,                            //!< NONE
+		DESELECT,                        //!< DESELECT
+		SELECT_APPLICATION,              //!< SELECT_APPLICATION
+		SELECT_CC_FILE,                  //!< SELECT_CC_FILE
+		SELECT_NDEF_FILE,                //!< SELECT_NDEF_FILE
+		SELECT_SYSTEM_FILE,              //!< SELECT_SYSTEM_FILE
+		READ,                            //!< READ
+		UPDATE,                          //!< UPDATE
+		VERIFY,                          //!< VERIFY
+		MANAGE_I2C_GPO,                  //!< MANAGE_I2C_GPO
+		MANAGE_RF_GPO,                   //!< MANAGE_RF_GPO
+		CHANGE_REFERENCE_DATA,           //!< CHANGE_REFERENCE_DATA
+		ENABLE_VERIFICATION_REQUIREMENT, //!< ENABLE_VERIFICATION_REQUIREMENT
+		DISABLE_VERIFICATION_REQUIREMENT,//!< DISABLE_VERIFICATION_REQUIREMENT
+		ENABLE_PERMANET_STATE,           //!< ENABLE_PERMANET_STATE
+		DISABLE_PERMANET_STATE,          //!< DISABLE_PERMANET_STATE
+	}M24SR_command_t;
+
+	/**
+	 * parameter used for invoke the command
+	 */
+	typedef struct{
+		uint8_t *data; //!< data
+		uint16_t length; //!< number of byte in the data array
+		uint16_t offset; //!< offset parameter used in the read/write command
+	}M24SR_command_data_t;
+
+	/**
+	 * communication mode used by this device
+	 */
+	typedef enum{
+		SYNC,//!< SYNC wait the command response before return
+		ASYNC//!< ASYNC use a callback for notify the end of a command
+	}M24SR_communication_t;
+
+	/**
+	 * type of communication that we are using
+	 */
+	M24SR_communication_t mCommunicationType;
+
+	/**
+	 * the class is wait the answer of this command
+	 */
+	M24SR_command_t mLastCommandSend;
+
+	/**
+	 * parameter used for invoke the last command
+	 */
+	M24SR_command_data_t mLastCommandData;
+
+	InterruptIn mGpoEventInterrupt;
 private:
 	
 	/**
+	 * Object with private callback used for hide height level commands
+	 * that require more than one low level command.
+	 * This object has an height priority comparing the user callback
+	 */
+	Nfc::Callback *mComponentCallback;
+
+	/**
+	 * get the callback object to use
+	 * @return callback object to use
+	 */
+	Nfc::Callback * getCallback(){
+		if(mComponentCallback!=NULL)
+			return mComponentCallback;
+		return mCallback;
+	}//getCallback
+
+
+	/**
+	 * Object with the callback used to send a ManageGPO command.
+	 * This class is equivalent to call the method:
+	 * <ul>
+	 *   <li> SelectedApplication </li>
+	 *   <li> SelectSystemfile </li>
+	 *   <li> ReadBinar: read the old value </li>
+	 *   <li> onVerifyed </li>
+	 *   <li> onUpdatedBinary: write the new value</li>
+	 * </ul>
+	 */
+	class ManageGPOCallback : public Nfc::Callback{
+
+	public:
+
+		/**
+		 * Create the MamageGpoCallback command chain.
+		 * @param parent component where run the command.
+		 */
+		ManageGPOCallback(M24SR &parent):mParent(parent),
+				mGpoConfig(HIGH_IMPEDANCE),mReadGpoConfig(0),mI2CGpo(true){}
+
+
+		/**
+		 * Command parameters
+		 * @param i2cGpo true if you want change the i2c gpo, false for change the rf gpo.
+		 * @param newConfig new gpo function.
+		 */
+		void setNewGpoConfig(bool i2cGpo,NFC_GPO_MGMT newConfig){
+			mGpoConfig=newConfig;
+			mI2CGpo =i2cGpo;
+		}
+
+		virtual void onSelectedApplication(Nfc *nfc,NFC_StatusTypeDef status){
+			if(status==NFC_SUCCESS)
+				nfc->SelectSystemfile();
+			else
+				onFinishCommand(nfc,status);
+		}
+
+		virtual void onSelectedSystemFile(Nfc *nfc,NFC_StatusTypeDef status){
+			if(status==NFC_SUCCESS)
+				nfc->ReadBinary(0x0004, 0x01, &mReadGpoConfig);
+			else
+				onFinishCommand(nfc,status);
+		}
+
+		virtual void onReadByte(Nfc *nfc,NFC_StatusTypeDef status,
+				uint16_t,uint8_t*, uint16_t ){
+			if(status==NFC_SUCCESS)
+				nfc->Verify(M24SR::I2CPwd, 0x10, M24SR::DEFAULT_PASSWORD);
+			else
+				onFinishCommand(nfc,status);
+		}
+
+		virtual void onVerifyed(Nfc *nfc,NFC_StatusTypeDef status){
+			if(status!=NFC_SUCCESS)
+				return onFinishCommand(nfc,status);
+
+			if(mI2CGpo)
+				mReadGpoConfig = (mReadGpoConfig & 0xF0) | (uint8_t)mGpoConfig;
+			else
+				mReadGpoConfig = (mReadGpoConfig & 0x0F) | (((uint8_t)mGpoConfig)<<4);
+
+			nfc->UpdateBinary(0x0004, 0x01, &mReadGpoConfig);
+		}
+
+		virtual void onUpdatedBinary(Nfc *nfc,NFC_StatusTypeDef status,
+				uint16_t , uint8_t*, uint16_t ){
+
+			if(status==NFC_SUCCESS){
+				if (mGpoConfig == I2C_ANSWER_READY){
+					mParent.mCommunicationType = ASYNC;
+				}else{
+					mParent.mCommunicationType = SYNC;
+				}//if-else
+			}//status
+			onFinishCommand(nfc,status);
+		}
+
+	private:
+
+		/**
+		 * Remove the private callback and call the user callback
+		 * @param nfc Object where the command complete
+		 * @param status Command status
+		 */
+		void onFinishCommand(Nfc *nfc,NFC_StatusTypeDef status){
+			mParent.mComponentCallback=NULL;
+			if(mI2CGpo){
+				mParent.mCallback->onManageI2CGPO(nfc,status,mGpoConfig);
+			}else{
+				mParent.mCallback->onManageRFGPO(nfc,status,mGpoConfig);
+			}//if-else
+		}//onFinishCommand
+
+		/**
+		 * component where run the command
+		 */
+		M24SR &mParent;
+
+		/** new gpo function that this class has to write */
+		NFC_GPO_MGMT mGpoConfig;
+
+		/**
+		 * variable where store the read gpo configuration
+		 */
+		uint8_t mReadGpoConfig;
+
+		/**
+		 * true for change the i2c gpo, false for change the rf gpo
+		 */
+		bool mI2CGpo;
+
+	};
+
+	/**
+	 * Object containing the callback chain needed to change the gpo function
+	 */
+	ManageGPOCallback mManageGPOCallback;
+
+
+	/**
+	 * Object with the callback used to read the component ID
+	 * This class is equivalent to call the method:
+	 * <ul>
+	 *   <li> SelectedApplication </li>
+	 *   <li> SelectSystemfile </li>
+	 *   <li> ReadBinary </li>
+	 * </ul>
+	 */
+	class ReadIDCallback : public Nfc::Callback{
+
+	public:
+
+		/**
+		 * build the chain of callback
+		 * @param parent object where send the command
+		 */
+		ReadIDCallback(M24SR &parent):mParent(parent),mIdPtr(NULL){}
+
+		/**
+		 * set the location where write the result
+		 * @param idPtr
+		 */
+		void readIdOn(uint8_t *idPtr){
+			mIdPtr=idPtr;
+		}
+
+		virtual void onSelectedApplication(Nfc *nfc,NFC_StatusTypeDef status){
+			if(status==NFC_SUCCESS){
+				nfc->SelectSystemfile();
+			}else
+				onFinishCommand(nfc,status);
+
+		}
+
+		virtual void onSelectedSystemFile(Nfc *nfc,NFC_StatusTypeDef status){
+			if(status==NFC_SUCCESS){
+				nfc->ReadBinary(0x0011, 0x01, mIdPtr);
+			}else
+				onFinishCommand(nfc,status);
+		}
+
+		virtual void onReadByte(Nfc *nfc,NFC_StatusTypeDef status,
+			uint16_t ,uint8_t *, uint16_t ){
+			onFinishCommand(nfc,status);
+		}
+
+	private:
+
+		/**
+		 * remove the private callback and call the user onReadId function
+		 * @param nfc object where the command run
+		 * @param status command status
+		 */
+		void onFinishCommand(Nfc *nfc,NFC_StatusTypeDef status){
+			mParent.mComponentCallback=NULL;
+			mParent.getCallback()->onReadId(nfc,status,mIdPtr);
+		}
+
+		/**
+		 * component where run the command
+		 */
+		M24SR &mParent;
+
+		/**
+		 * location where write the read id
+		 */
+		uint8_t *mIdPtr;
+	};
+
+	/**
+	 * Object containing the callback chain needed to read the component id
+	 */
+	ReadIDCallback mReadIDCallback;
+
+	/**
+	 * This class permit to enable/disable the password request for read/write into the tag
+	 * This class is equivalent to call the method:
+	 * To enable the request:
+	 * <ul>
+	 *   <li> Verify </li>
+	 *   <li> ChangeReferenceData </li>
+	 *   <li> EnablePermanentState </li>
+	 * </ul>
+	 * To disable the request:
+	 * <ul>
+	 *   <li> Verify </li>
+	 *   <li> DisableVerificationRequirement </li>
+	 * </ul>
+	 */
+	class ChangePasswordRequestStatusCallback : public Nfc::Callback{
+
+		public:
+
+			/**
+			 * Build the chain of callback.
+			 * @param parent object where send the command
+			 */
+			ChangePasswordRequestStatusCallback(M24SR &parent):
+				mParent(parent),mNewPwd(NULL),
+				mType(I2CPwd),mEnable(false){}
+
+			/**
+			 * Set the password to enable/disable.
+			 * @param type Type of password to enable/disable.
+			 * @param newPwd Array of 16bytes with the new password, if null the request will be disabled.
+			 */
+			void setTask(PasswordType_t type, const uint8_t *newPwd){
+				mNewPwd=newPwd;
+				mType=type;
+				mEnable=newPwd!=NULL;
+			}//setTask
+
+			virtual void onVerifyed(Nfc *nfc, NFC_StatusTypeDef status){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+				if(mEnable)
+					nfc->ChangeReferenceData(mType,mNewPwd);
+				else
+					nfc->DisableVerificationRequirement(mType);
+			}
+
+			virtual void onDisableVerificationRequirement(Nfc *nfc,
+					NFC_StatusTypeDef status, PasswordType_t ){
+				onFinishCommand(nfc,status);
+			}
+
+			virtual void onChangeReferenceData(Nfc *nfc, NFC_StatusTypeDef status,
+					PasswordType_t type,
+					uint8_t *){
+				if(status==NFC_SUCCESS)
+					nfc->EnablePermanentState(type);
+				else
+					onFinishCommand(nfc,status);
+			}
+
+			virtual void onEnablePermanentState(Nfc *nfc, NFC_StatusTypeDef status,
+					PasswordType_t ){
+				onFinishCommand(nfc,status);
+			}
+
+
+		private:
+
+			/**
+			 * Remove the private callback and call the user callback.
+			 * @param nfc Object where the command is run.
+			 * @param status Command status.
+			 */
+			void onFinishCommand(Nfc *nfc,NFC_StatusTypeDef status){
+				mParent.mComponentCallback=NULL;
+				if(mEnable){
+					if(mType==ReadPwd){
+						mParent.getCallback()->onEnableReadPassword(nfc,status,mNewPwd);
+					}else
+						mParent.getCallback()->onEnableWritePassword(nfc,status,mNewPwd);
+				}else{
+					if(mType==ReadPwd){
+						mParent.getCallback()->onDisableReadPassword(nfc,status);
+					}else
+						mParent.getCallback()->onDisableWritePassword(nfc,status);
+				}//if-else enable
+			}//onFinish
+
+			M24SR &mParent;
+
+			const uint8_t *mNewPwd;
+			Nfc::PasswordType_t mType;
+			bool mEnable;
+
+	};
+
+	/**
+	 * Object containing the callback chain needed to change the password request
+	 */
+	ChangePasswordRequestStatusCallback mChangePasswordRequestStatusCallback;
+
+	/**
+	 * This class permit to disable all the password request for read/write into the tag
+	 * This class is equivalent to call the methods:
+	 * <ul>
+	 *   <li> Verify(i2c) </li>
+	 *   <li> DisablePermanentState(Read) </li>
+	 *   <li> DisablePermanentState(write) </li>
+	 *   <li> DisableVerificationRequirement(Read) </li>
+	 *   <li> DisableVerificationRequirement(write) </li>
+	 *   <li> ChangeReferenceData(Read) </li>
+	 *   <li> ChangeReferenceData(write) </li>
+	 * </ul>
+	 */
+	class RemoveAllPasswordCallback : public Nfc::Callback{
+
+		public:
+
+			/**
+			 * Build the chain of callback.
+			 * @param parent object where send the command
+			 */
+			RemoveAllPasswordCallback(M24SR &parent):
+				mParent(parent){}
+
+			virtual void onVerifyed(Nfc *nfc,NFC_StatusTypeDef status){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+				nfc->DisablePermanentState(ReadPwd);
+			}
+
+			virtual void onDisablePermanentState(Nfc *nfc , NFC_StatusTypeDef status,
+					PasswordType_t type){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+				if(type==ReadPwd)
+					nfc->DisablePermanentState(WritePwd);
+				else
+					nfc->DisableVerificationRequirement(ReadPwd);
+			}
+
+			virtual void onDisableVerificationRequirement(Nfc *nfc ,
+					NFC_StatusTypeDef status,PasswordType_t type){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+				if(type==ReadPwd)
+					nfc->DisableVerificationRequirement(WritePwd);
+				else
+					nfc->ChangeReferenceData(ReadPwd,DEFAULT_PASSWORD);
+			}
+
+			virtual void onChangeReferenceData(Nfc *nfc ,NFC_StatusTypeDef status,PasswordType_t type,
+					uint8_t *data){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+				if(type==ReadPwd)
+					nfc->ChangeReferenceData(WritePwd,data);
+				else
+					onFinishCommand(nfc,status);
+			}
+
+		private:
+
+			/**
+			 * Remove the private callback and call the onDisableAllPassword callback.
+			 * @param nfc Object where the command is run.
+			 * @param status Command status.
+			 */
+			void onFinishCommand(Nfc *nfc,NFC_StatusTypeDef status){
+				mParent.mComponentCallback=NULL;
+				mParent.getCallback()->onDisableAllPassword(nfc,status);
+			}//onFinish
+
+			M24SR &mParent;
+	};
+
+	/**
+	 * Object containing the callback chain needed remove the password request
+	 */
+	RemoveAllPasswordCallback mRemoveAllPasswordCallback;
+
+	/**
+	 * This class permit set the tag as read/write only
+	 * This class is equivalent to call the methods:
+	 * <ul>
+	 *   <li> Verify(i2c) </li>
+	 *   <li> EnablePermanentState(Read/write) </li>
+	 * </ul>
+	 * or:
+	 * <ul>
+	 *   <li> Verify(i2c) </li>
+	 *   <li> DisableVerificationRequirement(Read/write) </li>
+	 * </ul>
+	 */
+	class ChangeAccessStateCallback : public Nfc::Callback{
+
+		public:
+
+			typedef enum{
+				WRITE,
+				READ
+			}AccessType_t;
+
+			/**
+			 * Build the chain of callback.
+			 * @param parent object where send the command
+			 */
+			ChangeAccessStateCallback(M24SR &parent):
+				mParent(parent),mType(WRITE),mEnable(false){}
+
+			/**
+			 * Set the access to enable/disable
+			 * @param type Type to enable or disable
+			 * @param enable true for enable the state, false for disable it
+			 */
+			void changeAccessState(AccessType_t type,bool enable){
+				mType=type;
+				mEnable=enable;
+			}
+
+			virtual void onVerifyed(Nfc *nfc,NFC_StatusTypeDef status){
+				if(status!=NFC_SUCCESS)
+					return onFinishCommand(nfc,status);
+
+				if(mEnable){
+					nfc->EnablePermanentState(mType==WRITE? WritePwd : ReadPwd);
+				}else
+					nfc->DisableVerificationRequirement(mType==WRITE? WritePwd : ReadPwd);
+			}
+
+			virtual void onDisableVerificationRequirement(Nfc *nfc , NFC_StatusTypeDef status,
+					PasswordType_t ){
+				onFinishCommand(nfc,status);
+			}
+
+			virtual void onEnablePermanentState(Nfc *nfc ,NFC_StatusTypeDef status,PasswordType_t ){
+				onFinishCommand(nfc,status);
+			}
+
+
+		private:
+
+			/**
+			 * Remove the private callback and call the user callback.
+			 * @param nfc Object where the command is run.
+			 * @param status Command status.
+			 */
+			void onFinishCommand(Nfc *nfc,NFC_StatusTypeDef status){
+				mParent.mComponentCallback=NULL;
+				if(mEnable){
+					if(mType==READ){
+						//enable read = disable write only
+						mParent.getCallback()->onDisableWriteOnly(nfc,status);
+					}else
+						//enable write = disable read only
+						mParent.getCallback()->onDisableReadOnly(nfc,status);
+				}else{
+					if(mType==WRITE){
+						//disable write = enable read only
+						mParent.getCallback()->onEnableReadOnly(nfc,status);
+					}else{
+						//
+						mParent.getCallback()->onEnableWriteOnly(nfc,status);
+					}
+				}//if-else enable
+			}//onFinish
+
+			M24SR &mParent;
+
+			AccessType_t mType;
+			bool mEnable;
+
+	};
+
+	/**
+	 * Object containing the callback chain needed to change the access state
+	 */
+	ChangeAccessStateCallback mChangeAccessStateCallback;
+
+
+	/**
 	 * Convert a generic enum to the value used by the M24SR chip.
 	 * @param type Password type.
 	 * @return equivalent value used inside the m24sr chip */
@@ -486,9 +1044,25 @@
 			case I2CPwd:
 			default:
 				return I2C_PWD;
-		}
+		}//switch
 	}//passwordTypeToConst
 	
+	/**
+	 * convert  a uint16 into an enum value
+	 * @param type
+	 * @return
+	 */
+	PasswordType_t constToPasswordType(const uint16_t type)const{
+		switch(type){
+			case READ_PWD:
+				return ReadPwd;
+			case WRITE_PWD:
+				return WritePwd;
+			case I2C_PWD:
+			default:
+				return I2CPwd;
+		}//switch
+	}//passwordTypeToConst
 };
 
 #endif // __M24SR_CLASS_H