Utility library to read and write Ndef messages from/to a Type4 NFC tag

Dependents:   NFC M2M_2016_STM32 MyongjiElec_capstone1 IDW01M1_Cloud_IBM ... more

Fork of NDefLib by ST Expansion SW Team

NDEF NFC library

This library provides an abstract API to create NDEF formatted messages and records and to read/write them from/to a Type4 NFC Tag.

Implementations

At the moment, the NDEF API is implemented by X_NUCLEO_NFC01A1 and X_NUCLEO_NFC02A1 Dynamic NFC Tag libraries respectively driving the X-NUCLEO-NFC01A1 and X-NUCLEO-NFC02A1 boards.

Files at this revision

API Documentation at this revision

Comitter:
giovannivisentini
Date:
Thu Jan 28 14:01:07 2016 +0000
Parent:
13:dbf3a61d70b3
Child:
15:01fc5a4b8366
Commit message:
add async api

Changed in this revision

NDefNfcTag.h Show annotated file Show diff for this revision Revisions of this file
--- a/NDefNfcTag.h	Thu Jan 14 08:40:45 2016 +0000
+++ b/NDefNfcTag.h	Thu Jan 28 14:01:07 2016 +0000
@@ -3,8 +3,9 @@
  * @file    Type4NfcTag.h
  * @author  ST / Central Labs
  * @version V1.0.0
- * @date    1 Nov 2015
+ * @date    21 Jan 2016
  * @brief   Generic interface that a device must implement for use the NDefLib
+ * with async communication
  ******************************************************************************
  * @attention
  *
@@ -34,42 +35,117 @@
  *
  ******************************************************************************
  */
- 
-#ifndef NDefNFCTAG_H_
-#define NDefNFCTAG_H_
+
+#ifndef NDEFLIB_NDEFNFCTAG_H_
+#define NDEFLIB_NDEFNFCTAG_H_
 
 #include "NDefLib/Message.h"
 
 namespace NDefLib {
 
 /**
- * Abstract class used to write/read NDef messages to/from a nfc tag
+ * Abstract class used to write/read NDef messages to/from a nfc tag.
+ * This class is made for handle also asynchronous communication with the nfc component.
+ * All the function in this class will return immediately, when the operation end a proper callback function will
+ * be called.
  */
 class NDefNfcTag {
+
 public:
 
-	NDefNfcTag():mSessionIsOpen(false){}
+	/**
+	 * Class that contains all the function called when a command finish.
+	 * The default implementation is an empty function.
+	 */
+	class Callback {
+		public:
+
+			/**
+			 * Called when a session is open.
+			 * @param tag tag where the session is open.
+			 * @param success true if the operation has success.
+			 */
+			virtual void onSessionOpen(NDefNfcTag *tag,bool success){
+				(void)tag;(void)success;
+			};
+
+			/**
+			 * Called when a message is write.
+			 * @param tag tag where the message is wrote.
+			 * @param success true if the operation has success.
+			 */
+			virtual void onMessageWrite(NDefNfcTag *tag,bool success,
+					const Message &msg){
+				(void)tag;(void)success; (void)msg;
+
+			};
+
+			/**
+			 * Called when a message is read.
+			 * @param tag tag where the message is read.
+			 * @param success true if the operation has success.
+			 */
+			virtual void onMessageRead(NDefNfcTag *tag,bool success,
+					const Message *msg){
+				(void)tag;(void)success; (void)msg;
+			};
+
+
+			/**
+			 * Called when a session is close.
+			 * @param tag tag where the session is close.
+			 * @param success true if the operation has success.
+			 */
+			virtual void onSessionClose(NDefNfcTag *tag,bool success){
+				(void)tag;(void)success;
+			};
+
+			virtual ~Callback(){};
+	};
+
+private:
+
+	/**
+	 * Data used for store the callback status.
+	 */
+	struct CallbackStatus{
+		/**object that start the callback */
+		NDefNfcTag *callOwner;
+		/** message that the callback is manage */
+		Message *msg;
+	};
+
+public:
+
+	NDefNfcTag():mCallBack(&mDefaultCallBack){}
+
+	/**
+	 * Set the callback.
+	 * @param c object contains the callback.
+	 */
+	void setCallBack(Callback *c){
+		mCallBack=c;
+	}//setCallBack
+
 
 	/**
 	 * 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){
-		mSessionIsOpen=true;
-		return true;
-	}
+	virtual bool openSession(bool force = false)=0;
 
 	/**
 	 * 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(){
-		mSessionIsOpen=false;
-		return true;
-	}
+	virtual bool closeSession()=0;
+
+	/**
+	 * Returns true if a communication with the nfc tag is open.
+	 * @return true if a communication with the nfc tag is open
+	 */
+	virtual bool isSessionOpen()=0;
 
 	/**
 	 * Write a message in the nfc tag.
@@ -77,18 +153,25 @@
 	 * @param msg Message to write.
 	 * @return true if success
 	 */
-	bool write(const Message &msg) {
-		if(!mSessionIsOpen)
+	virtual bool write(Message &msg) {
+		if(!isSessionOpen()){
+			mCallBack->onMessageWrite(this,false,msg);
 			return false;
+		}
 
 		const uint16_t length = msg.getByteLength();
 		uint8_t *buffer = new uint8_t[length];
-		if(buffer==NULL) //impossible to allocate the buffer 
+		if(buffer==NULL){ //impossible to allocate the buffer
+			mCallBack->onMessageWrite(this,false,msg);
 			return false;
+		}
+
 		msg.write(buffer);
-		bool retValue = writeByte(buffer, length);
-		delete[] buffer;
-		return retValue;
+
+		mCallBackStatus.callOwner=this;
+		mCallBackStatus.msg=&msg;
+
+		return writeByte(buffer, length,0,NDefNfcTag::onWriteMessageCallback,&mCallBackStatus);
 	}
 
 	/**
@@ -96,79 +179,149 @@
 	 * @param[in,out] msg Message object the read records are added to.
 	 * @return true if success
 	 */
-	bool read(Message *msg) {
-		if(!mSessionIsOpen)
-			return false;
-
-		uint16_t length = getMessageLength();
-		if (length == 0)
+	virtual bool read(Message *msg) {
+		if(!isSessionOpen()){
+			mCallBack->onMessageRead(this,false,msg);
 			return false;
-		//else
-		uint8_t *buffer = new uint8_t[length];
-		if(buffer==NULL)
-			return false;
+		}
 
-		//read all the message contents
-		bool retValue = readByte(2, length, buffer);
-		if (retValue) {
-			Message::parseMessage(buffer, length, msg);
+		uint8_t *buffer = new uint8_t[2];
+		if(buffer==NULL){
+			mCallBack->onMessageRead(this,false,msg);
+			return false;
 		}
-		delete[] buffer;
-		return retValue;
+
+		mCallBackStatus.callOwner=this;
+		mCallBackStatus.msg=msg;
+		return readByte(0,2,buffer,NDefNfcTag::onReadMessageLength,&mCallBackStatus);
 	}
 
 	virtual ~NDefNfcTag() {}
 
+protected:
+
+	typedef struct CallbackStatus CallbackStatus_t;
+
 	/**
-	 * Returns true if a communication with the nfc tag is open.
-	 * @return true if a communication with the nfc tag is open
+	 * Function that the component has to call when it finish a read/write operation
+	 * @param interalState callback internal state data
+	 * @param status true if the operation success
+	 * @param buffer buffer write/read
+	 * @param length number of byte read/write
+	 * @return true if the operation had success
 	 */
-	bool isSessionOpen(){
-		return mSessionIsOpen;
-	}
-
-
-protected:
+	typedef bool(*byteOperationCallback_t)(CallbackStatus_t *interalState,
+			bool status,const uint8_t *buffer, uint16_t length);
 
 	/**
 	 * 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
+	 * @param buffer buffer to write
+	 * @param length number of bytes to write
+	 * @param offset offset where start to write
+	 * @param callback function to call when the operation ended
+	 * @param callbackStatus parameter to pass to the callback function
+	 * @return true if the operation has success
 	 */
-	virtual bool writeByte(const uint8_t *buffer, uint16_t length, uint16_t offset=0)=0;
+	virtual bool writeByte(const uint8_t *buffer, uint16_t length,uint16_t offset,
+			byteOperationCallback_t callback,CallbackStatus_t *callbackStatus)=0;
 
 	/**
 	 * Read a sequence of bytes from the NDEF file.
-	 * @param byteOffset Read offsetin bytes.
+	 * @param byteOffset Read offset in bytes.
 	 * @param byteLength Number of bytes to read.
 	 * @param[out] buffer Buffer to store the read data into.
+	 * @param callback function to call when the operation ended
+	 * @param callbackStatus parameter to pass to the callback function
 	 * @return true if success
 	 */
 	virtual bool readByte(const uint16_t byteOffset, const uint16_t byteLength,
-			uint8_t *buffer)=0;
+			uint8_t *buffer, byteOperationCallback_t callback,CallbackStatus_t *callbackStatus)=0;
+
 
+	/** object with the user callback */
+	Callback *mCallBack;
 private:
 
+	/** object with the current callback status */
+	CallbackStatus_t mCallBackStatus;
+	/** default callback object, all the function are empty */
+	Callback mDefaultCallBack;
+
 	/**
-	 * Provides the status of a communication channel with the tag.
+	 * function that the user will call when a write end, it will invoke onMessageWrite
+	 * @param internalState object that invoke the write operation
+	 * @param status true if the operation had success
+	 * @param buffer buffer wrote
+	 * @param length number of byte wrote
+	 * @return true if the write had success
 	 */
-	bool mSessionIsOpen;
+	static bool onWriteMessageCallback(CallbackStatus_t *internalState,
+			bool status,const uint8_t *buffer, uint16_t ){
+		delete [] buffer;
+
+		internalState->callOwner->mCallBack->
+			onMessageWrite(internalState->callOwner,status,*internalState->msg);
+		return status;
+	}
 
 	/**
-	 * Read the NDEF message length.
-	 * @return NDEF message length
+	 * function that the use will call after a read operation.
+	 * in this case we read the message length, this function will read all the message
+	 * @param internalState object that invoke the write operation
+	 * @param status true if the operation had success
+	 * @param buffer buffer read
+	 * @param length number of byte read
+	 * @return true if the read had success
 	 */
-	uint16_t getMessageLength() {
-		uint8_t lenghtByte[2];
-		if (readByte(0, 2, lenghtByte))
-			return (((uint16_t) lenghtByte[0]) << 8 | lenghtByte[1]);
-		return 0;
-	} //getMessageLength
+	static bool onReadMessageLength(CallbackStatus_t *internalState,
+			bool status,const uint8_t *buffer, uint16_t length){
+
+		if(!status || length!=2){
+			internalState->callOwner->mCallBack->
+					onMessageRead(internalState->callOwner,false,internalState->msg);
+			return false;
+		}//if
+
+		length = (((uint16_t) buffer[0]) << 8 | buffer[1]);
+		delete [] buffer;
+
+		uint8_t *readBuffer = new uint8_t[length];
+		if(readBuffer==NULL){
+			internalState->callOwner->mCallBack->
+					onMessageRead(internalState->callOwner,false,internalState->msg);
+			return false;
+		}//readBuffer
+
+		internalState->callOwner->readByte(2,length,readBuffer,
+				&NDefNfcTag::onReadMessageCallback,internalState);
+		return status;
+	}
+
 
-};
+	/**
+	 * function that the user will call when it read all the message
+	 * @param internalState object that invoke the write operation
+	 * @param status true if the operation had success
+	 * @param buffer buffer read
+	 * @param length number of byte read
+	 * @return true if the read had success
+	 */
+	static bool onReadMessageCallback(CallbackStatus_t *internalState,
+			bool status,const uint8_t *buffer, uint16_t length){
+		if(!status){
+			internalState->callOwner->mCallBack->
+					onMessageRead(internalState->callOwner,false,internalState->msg);
+			return false;
+		}
+		Message::parseMessage(buffer, length, internalState->msg);
+		delete [] buffer;
+		internalState->callOwner->mCallBack->
+			onMessageRead(internalState->callOwner,true,internalState->msg);
+		return status ;
+	}
 
-} /* namespace NDefLib */
+}; //class NDefNfcTagASync
 
-#endif /* NDefNFCTAG_H_ */
+}// namespace NDefLib
+
+#endif /* NDEFLIB_NDEFNFCTAG_H_ */