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.

NDefNfcTag.h

Committer:
giovannivisentini
Date:
2016-02-01
Revision:
15:01fc5a4b8366
Parent:
14:ba0c186ae6d6
Child:
16:030e7ffdf512

File content as of revision 15:01fc5a4b8366:

/**
 ******************************************************************************
 * @file    NDefNfcTag.h
 * @author  ST / Central Labs
 * @version V1.0.0
 * @date    21 Jan 2016
 * @brief   Generic interface that a device must implement for use the NDefLib
 * with async communication
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of STMicroelectronics nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

#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.
 * This class is made for handle also asynchronous communication with the nfc component.
 * All the function in this class will return immediately, when a command end a proper callback function will
 * be called.
 */
class NDefNfcTag {

public:

	/**
	 * 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.
	 * @param force Force to open a communication.
	 * @return true if success
	 */
	virtual bool openSession(bool force = false)=0;

	/**
	 * Close the communication with the nfc tag.
	 * @return true if success
	 */
	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.
	 * @par This call will delete the previous message.
	 * @param msg Message to write.
	 * @return true if success
	 */
	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
			mCallBack->onMessageWrite(this,false,msg);
			return false;
		}

		msg.write(buffer);

		mCallBackStatus.callOwner=this;
		mCallBackStatus.msg=&msg;

		return writeByte(buffer, length,0,NDefNfcTag::onWriteMessageCallback,&mCallBackStatus);
	}

	/**
	 * Read a message from the tag.
	 * @param[in,out] msg Message object the read records are added to.
	 * @return true if success
	 */
	virtual bool read(Message *msg) {
		if(!isSessionOpen()){
			mCallBack->onMessageRead(this,false,msg);
			return false;
		}

		uint8_t *buffer = new uint8_t[2];
		if(buffer==NULL){
			mCallBack->onMessageRead(this,false,msg);
			return false;
		}

		mCallBackStatus.callOwner=this;
		mCallBackStatus.msg=msg;
		return readByte(0,2,buffer,NDefNfcTag::onReadMessageLength,&mCallBackStatus);
	}

	virtual ~NDefNfcTag() {}

protected:

	typedef struct CallbackStatus CallbackStatus_t;

	/**
	 * 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
	 */
	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 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,
			byteOperationCallback_t callback,CallbackStatus_t *callbackStatus)=0;

	/**
	 * Read a sequence of bytes from the NDEF file.
	 * @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, 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;

	/**
	 * 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
	 */
	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;
	}

	/**
	 * 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
	 */
	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 ;
	}

}; //class NDefNfcTagASync

}// namespace NDefLib

#endif /* NDEFLIB_NDEFNFCTAG_H_ */