diff --git a/src/ST25DVSensor.cpp b/src/ST25DVSensor.cpp index d659feb..d7ca549 100755 --- a/src/ST25DVSensor.cpp +++ b/src/ST25DVSensor.cpp @@ -20,6 +20,11 @@ #include "ST25DVSensor.h" int ST25DV::begin() +{ + return begin(NULL, 0); +} + +int ST25DV::begin(uint8_t *buffer, uint16_t bufferLength) { uint8_t nfctag_id = 0; @@ -39,17 +44,24 @@ int ST25DV::begin() return NFCTAG_ERROR; } - int ret = ndef.begin(); + int ret = ndef.begin(buffer, bufferLength); if (ret != NDEF_OK) { return ret; } } return NFCTAG_OK; -} +}; int ST25DV::writeURI(String protocol, String uri, String info) { sURI_Info _URI; + + // Unabridged protocols must be written using + // `writeUnabridgedURI()` + if (protocol.equals("")) { + return NDEF_ERROR; + } + strcpy(_URI.protocol, protocol.c_str()); strcpy(_URI.URI_Message, uri.c_str()); strcpy(_URI.Information, info.c_str()); @@ -62,15 +74,54 @@ int ST25DV::readURI(String *s) uint16_t ret; sURI_Info uri = {"", "", ""}; sRecordInfo_t recordInfo; - uint8_t NDEF_Buffer[100]; - // increase buffer size for bigger messages - ret = ndef.NDEF_ReadNDEF(NDEF_Buffer); + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); if (ret) { return ret; } - ret = ndef.NDEF_IdentifyBuffer(&recordInfo, NDEF_Buffer); + ret = ndef.NDEF_ReadURI(&recordInfo, &uri); + if (ret) { + return ret; + } + *s = String(uri.protocol) + String(uri.URI_Message); + + return 0; +} + +/* + * @brief Writes an unabbrieved URI + * + * The NFC NDEF format uses URI identifier code 0x00 + * to indicate a URI that is not abbreviated. + * + * @param uri the uri to write + * @param info to write + * @retval success or failure + */ +int ST25DV::writeUnabridgedURI(String uri, String info) +{ + sURI_Info _URI; + + strcpy(_URI.protocol, ""); + strcpy(_URI.URI_Message, uri.c_str()); + strcpy(_URI.Information, info.c_str()); + + return ndef.NDEF_WriteURI(&_URI); +} + +/* + * @brief Reads an unabbrieved URI + * @param s the uri read + * @retval success or failure + */ +int ST25DV::readUnabridgedURI(String *s) +{ + uint16_t ret; + sURI_Info uri = {"", "", ""}; + sRecordInfo_t recordInfo; + + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); if (ret) { return ret; } @@ -79,15 +130,171 @@ int ST25DV::readURI(String *s) if (ret) { return ret; } - *s = String(uri.protocol) + String(uri.URI_Message); + + // If the URI is abbreivated return error + if (strncmp("", uri.protocol, 1) != 0) { + return ret; //NDEF_ERROR; + } + + *s = String(uri.URI_Message); return 0; } +/* + * @brief Writes an SMS record + * + * @param phoneNumber + * @param message + * @param info + * @retval success or failure + */ +int ST25DV::writeSMS(String phoneNumber, String message, String info) +{ + sSMSInfo _SMS; + + strncpy(_SMS.PhoneNumber, phoneNumber.c_str(), 16); + strncpy(_SMS.Message, message.c_str(), 400); + strncpy(_SMS.Information, info.c_str(), 400); + + return ndef.NDEF_WriteSMS(&_SMS); +} + +/* + * @brief Reads an SMS record + * + * @param phoneNumber + * @param message + * @retval success or failure + */ +int ST25DV::readSMS(String *phoneNumber, String *message) +{ + uint16_t ret; + sSMSInfo _SMS; + sRecordInfo_t recordInfo; + + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); + if (ret) { + return ret; + } + + ret = ndef.NDEF_ReadSMS(&recordInfo, &_SMS); + if (ret) { + return ret; + } + + *phoneNumber = String(_SMS.PhoneNumber); + *message = String(_SMS.Message); + + return NDEF_OK; +} + +/* + * @brief Writes a GEO record + * + * @param latitude + * @param longitude + * @param info + * @retval success or failure + */ +int ST25DV::writeGEO(String latitude, String longitude, String info) +{ + sGeoInfo _GEO; + + strncpy(_GEO.Latitude, latitude.c_str(), 20); + strncpy(_GEO.Longitude, longitude.c_str(), 20); + strncpy(_GEO.Information, info.c_str(), 100); + + return ndef.NDEF_WriteGeo(&_GEO); +} + +/* + * @brief Reads a GEO record + * + * @param latitude + * @param longitude + * @retval success or failure + */ +int ST25DV::readGEO(String *latitude, String *longitude) +{ + uint16_t ret; + sGeoInfo _GEO; + sRecordInfo_t recordInfo; + + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); + if (ret) { + return ret; + } + + ret = ndef.NDEF_ReadGeo(&recordInfo, &_GEO); + if (ret) { + return ret; + } + + *latitude = String(_GEO.Latitude); + *longitude = String(_GEO.Longitude); + + return NDEF_OK; +} + + +int ST25DV::writeEMail(String emailAdd, String subject, String message, String info) +{ + sEmailInfo _EMAIL; + + strncpy(_EMAIL.EmailAdd, emailAdd.c_str(), 64); + strncpy(_EMAIL.Subject, subject.c_str(), 100); + strncpy(_EMAIL.Message, message.c_str(), 2000); + strncpy(_EMAIL.Information, info.c_str(), 400); + + return ndef.NDEF_WriteEmail(&_EMAIL); +} + +int ST25DV::readEMail(String *emailAdd, String *subject, String *message) +{ + uint16_t ret; + sEmailInfo _EMAIL; + sRecordInfo_t recordInfo; + + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); + if (ret) { + return ret; + } + + ret = ndef.NDEF_ReadEmail(&recordInfo, &_EMAIL); + if (ret) { + return ret; + } + + *emailAdd = String(_EMAIL.EmailAdd); + *subject = String(_EMAIL.Subject); + *message = String(_EMAIL.Message); + + return NDEF_OK; +} + +/** + * @brief reads the type of NDEF on the tag + * @param None + * @retval the type or UNKNOWN_TYPE if errors occur + */ +NDEF_TypeDef ST25DV::readNDEFType(void) +{ + uint16_t ret; + sRecordInfo_t recordInfo; + + ret = ndef.NDEF_IdentifyNDEF(&recordInfo); + if (ret) { + return UNKNOWN_TYPE; + } + + return recordInfo.NDEF_Type; +} + /** * @brief Returns the NDEF class instance used by the component * @param None - * @retval NDEF class + * @retval success or failure */ NDEF *ST25DV::getNDEF(void) { diff --git a/src/ST25DVSensor.h b/src/ST25DVSensor.h index 6f31fd8..bf6300c 100755 --- a/src/ST25DVSensor.h +++ b/src/ST25DVSensor.h @@ -35,8 +35,18 @@ class ST25DV { ST25DV(int32_t gpo, int32_t lpd, TwoWire *i2c, Stream *serial = NULL) : st25dv_io(gpo, lpd, i2c, serial), ndef(&st25dv_io) {} int begin(); + int begin(uint8_t *buffer, uint16_t bufferLength); int writeURI(String protocol, String uri, String info); int readURI(String *s); + int writeUnabridgedURI(String uri, String info); + int readUnabridgedURI(String *s); + int writeSMS(String phoneNumber, String message, String info); + int readSMS(String *phoneNumber, String *message); + int writeGEO(String latitude, String longitude, String info); + int readGEO(String *latitude, String *longitude); + int writeEMail(String emailAdd, String subject, String message, String info); + int readEMail(String *emailAdd, String *subject, String *message); + NDEF_TypeDef readNDEFType(); NDEF *getNDEF(); protected: diff --git a/src/libNDEF/NDEF_class.h b/src/libNDEF/NDEF_class.h index 1f39697..021b2a0 100755 --- a/src/libNDEF/NDEF_class.h +++ b/src/libNDEF/NDEF_class.h @@ -58,11 +58,16 @@ class NDEF { NDEF(ST25DV_IO *dev); uint16_t begin(); + uint16_t begin(uint8_t *buffer, uint16_t bufferLength); //lib_NDEF + uint16_t NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct); uint16_t NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF); + uint16_t NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF, uint16_t bufferLength); uint16_t NDEF_IdentifyBuffer(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF); + uint16_t NDEF_ReadNDEF(); uint16_t NDEF_ReadNDEF(uint8_t *pNDEF); + uint16_t NDEF_ReadNDEF(uint8_t *pNDEF, uint16_t bufferLength); uint16_t NDEF_WriteNDEF(uint16_t NDEF_Size, uint8_t *pNDEF); uint16_t NDEF_ClearNDEF(void); uint16_t NDEF_getNDEFSize(uint16_t *Size); @@ -131,6 +136,7 @@ class NDEF { //lib_wrapper uint16_t NfcTag_ReadNDEF(uint8_t *pData); + uint16_t NfcTag_ReadNDEF(uint8_t *pData, uint16_t MaxLength); uint16_t NfcTag_WriteNDEF(uint16_t Length, uint8_t *pData); uint16_t NfcTag_WriteProprietary(uint16_t Length, uint8_t *pData); uint16_t NfcTag_GetLength(uint16_t *Length); @@ -182,10 +188,12 @@ class NDEF { void NDEF_Read_WifiToken(struct sRecordInfo *pRecordStruct, sWifiTokenInfo *pWifiTokenStruct); //libNDEF.c + /** @brief This buffer is used if begin isn't called with a buffer. */ + uint8_t NDEF_Default_Buffer[NDEF_MAX_SIZE]; /** @brief This buffer is used to store the data sent/received by the TAG. */ - uint8_t NDEF_Buffer [NDEF_MAX_SIZE]; + uint8_t *NDEF_Buffer; /** @brief Size of the buffer used to build the NDEF messages. */ - uint32_t NDEF_Buffer_size = NDEF_MAX_SIZE; + uint32_t NDEF_Buffer_size; /** @brief This buffer is used when it's required to prepare a record before adding it to the NDEF_Buffer. */ uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE]; /** @brief Size of the buffer used when a record has to be prepared. */ diff --git a/src/libNDEF/lib_NDEF.cpp b/src/libNDEF/lib_NDEF.cpp index 682203c..e115924 100755 --- a/src/libNDEF/lib_NDEF.cpp +++ b/src/libNDEF/lib_NDEF.cpp @@ -67,9 +67,23 @@ NDEF::NDEF(ST25DV_IO *dev) } uint16_t NDEF::begin() +{ + return begin(NULL, 0); +} + +uint16_t NDEF::begin(uint8_t *buffer, uint16_t bufferLength) { int ret = NDEF_OK; + if (buffer == NULL) { + NDEF_Buffer = NDEF_Default_Buffer; + NDEF_Buffer_size = NDEF_MAX_SIZE; + } else { + // TODO should we check minimum buffer length? + NDEF_Buffer = buffer; + NDEF_Buffer_size = bufferLength; + } + if (NfcType5_NDEFDetection() != NDEF_OK) { CCFileStruct.MagicNumber = NFCT5_MAGICNUMBER_E1_CCFILE; CCFileStruct.Version = NFCT5_VERSION_V1_0; @@ -289,7 +303,7 @@ void NDEF::NDEF_ParseURI(sRecordInfo_t *pRecordStruct) } else if (!memcmp(pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING))) { pRecordStruct->NDEF_Type = URI_GEO_TYPE; } else { - pRecordStruct->NDEF_Type = UNKNOWN_TYPE; + pRecordStruct->NDEF_Type = UNABRIDGED_URI_TYPE; } } @@ -344,15 +358,39 @@ void NDEF::NDEF_ParseSP(sRecordInfo_t *pRecordStruct) * @{ */ +/** + * @brief This function identify the NDEF message stored in tag. + * @param pRecordStruct : Structure to fill with record information. + * @param pNDEF : pointer on the NDEF message data. + * @retval NDEF_OK : record struct filled. + * @retval NDEF_ERROR : record struct not updated. + */ +uint16_t NDEF::NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct) +{ + return NDEF_IdentifyNDEF(pRecordStruct, NDEF_Buffer, NDEF_Buffer_size); +} /** * @brief This function identify the NDEF message stored in tag. + * @deprecated use one-arg or three-arg variant * @param pRecordStruct : Structure to fill with record information. * @param pNDEF : pointer on the NDEF message data. * @retval NDEF_OK : record struct filled. * @retval NDEF_ERROR : record struct not updated. */ uint16_t NDEF::NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF) +{ + return NDEF_IdentifyNDEF(pRecordStruct, pNDEF, NDEF_MAX_SIZE); +} + +/** + * @brief This function identify the NDEF message stored in tag. + * @param pRecordStruct : Structure to fill with record information. + * @param pNDEF : pointer on the NDEF message data. + * @retval NDEF_OK : record struct filled. + * @retval NDEF_ERROR : record struct not updated. + */ +uint16_t NDEF::NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF, uint16_t bufferLength) { uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; @@ -361,67 +399,24 @@ uint16_t NDEF::NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF) return NDEF_ERROR; } - /* Read the NDEF file */ - NfcTag_ReadNDEF(pNDEF); - - /* Is ID length field present */ - if ((*pNDEF) & IL_Mask) { - IDLengthField = ID_LENGTH_FIELD; - } else { - IDLengthField = 0; - } - - /* it's a SR */ - if ((*pNDEF) & SR_Mask) { - /* Analyse short record layout */ - TypeNbByte = pNDEF[1]; - PayloadLengthField = 1; - if (IDLengthField == ID_LENGTH_FIELD) { - IDNbByte = pNDEF[3]; - } else { - IDNbByte = 0; - } - } else { - /* Analyse normal record layout */ - TypeNbByte = pNDEF[1]; - PayloadLengthField = 4; - if (IDLengthField == ID_LENGTH_FIELD) { - IDNbByte = pNDEF[6]; - } else { - IDNbByte = 0; - } - } - - SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; - - /* Read record header */ - /* it's a SR */ - if (pNDEF[0] & SR_Mask) { - pRecordStruct->RecordFlags = pNDEF[0]; - pRecordStruct->TypeLength = TypeNbByte; - pRecordStruct->PayloadLength = pNDEF[2]; - pRecordStruct->IDLength = IDNbByte; - memcpy(pRecordStruct->Type, &pNDEF[3 + IDNbByte], TypeNbByte); - memcpy(pRecordStruct->ID, &pNDEF[3 + IDNbByte + TypeNbByte], IDNbByte); - pRecordStruct->PayloadOffset = SizeOfRecordHeader; - } else { - pRecordStruct->RecordFlags = pNDEF[0]; - pRecordStruct->TypeLength = TypeNbByte; - pRecordStruct->PayloadLength = (((uint32_t)pNDEF[2]) << 24) | - (((uint32_t)pNDEF[3]) << 16) | - (((uint32_t)pNDEF[4]) << 8) - | pNDEF[5] ; - pRecordStruct->IDLength = IDNbByte; - memcpy(pRecordStruct->Type, &pNDEF[6 + IDNbByte], TypeNbByte); - memcpy(pRecordStruct->ID, &pNDEF[6 + IDNbByte + TypeNbByte], IDNbByte); - pRecordStruct->PayloadOffset = SizeOfRecordHeader; - } - - pRecordStruct->PayloadBufferAdd = pNDEF; + /* Read the NDEF file up to the max length of the record header*/ + NfcTag_ReadNDEF(pNDEF, bufferLength); - NDEF_ParseRecordHeader(pRecordStruct); + return NDEF_IdentifyBuffer(pRecordStruct, pNDEF); +} - return NDEF_OK; +/** + * @brief This function read the NDEF content of the TAG. + * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. + * @retval NDEF_ERROR : not able to read NDEF from tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. + */ +uint16_t NDEF::NDEF_ReadNDEF() +{ + return NfcTag_ReadNDEF(NDEF_Buffer, NDEF_Buffer_size); } /** @@ -436,9 +431,23 @@ uint16_t NDEF::NDEF_IdentifyNDEF(sRecordInfo_t *pRecordStruct, uint8_t *pNDEF) */ uint16_t NDEF::NDEF_ReadNDEF(uint8_t *pNDEF) { - return NfcTag_ReadNDEF(pNDEF); + return NfcTag_ReadNDEF(pNDEF, NDEF_MAX_SIZE); } +/** + * @brief This function read the NDEF content of the TAG. + * @param pNDEF : pointer on the buffer to store NDEF data. + * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. + * @retval NDEF_ERROR : not able to read NDEF from tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. + */ +uint16_t NDEF::NDEF_ReadNDEF(uint8_t *pNDEF, uint16_t bufferLength) +{ + return NfcTag_ReadNDEF(pNDEF, bufferLength); +} /** diff --git a/src/libNDEF/lib_NDEF.h b/src/libNDEF/lib_NDEF.h index 49bd702..4e46045 100755 --- a/src/libNDEF/lib_NDEF.h +++ b/src/libNDEF/lib_NDEF.h @@ -209,7 +209,7 @@ #define URI_ID_0x23_STRING "urn:nfc:\0" // exported variables -extern uint8_t NDEF_Buffer[NDEF_MAX_SIZE]; +extern uint8_t *NDEF_Buffer; extern uint32_t NDEF_Buffer_size; extern uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE]; extern uint32_t NDEF_Record_Buffer_size; @@ -217,6 +217,7 @@ extern uint32_t NDEF_Record_Buffer_size; typedef enum { UNKNOWN_TYPE = 0, VCARD_TYPE, + UNABRIDGED_URI_TYPE, WELL_KNOWN_ABRIDGED_URI_TYPE, URI_SMS_TYPE, URI_GEO_TYPE, diff --git a/src/libNDEF/lib_NDEF_URI.cpp b/src/libNDEF/lib_NDEF_URI.cpp index bf77b9b..4e7c796 100755 --- a/src/libNDEF/lib_NDEF_URI.cpp +++ b/src/libNDEF/lib_NDEF_URI.cpp @@ -283,7 +283,10 @@ uint16_t NDEF::NDEF_ReadURI(sRecordInfo_t *pRecordStruct, sURI_Info *pURI) uint32_t PayloadSize, RecordPosition; uint8_t *pData; - if (pRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE) { + if (pRecordStruct->NDEF_Type == UNABRIDGED_URI_TYPE) { + NDEF_Parse_WellKnowType(pRecordStruct, pURI); + status = NDEF_OK; + } else if (pRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE) { NDEF_Parse_WellKnowType(pRecordStruct, pURI); status = NDEF_OK; } else if (pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE) { diff --git a/src/libNDEF/tagtype5_wrapper.cpp b/src/libNDEF/tagtype5_wrapper.cpp index e7867ca..c366ccb 100755 --- a/src/libNDEF/tagtype5_wrapper.cpp +++ b/src/libNDEF/tagtype5_wrapper.cpp @@ -79,6 +79,19 @@ * @retval NDEF_OK NDEF message successfully read. */ uint16_t NDEF::NfcTag_ReadNDEF(uint8_t *pData) +{ + return NfcTag_ReadNDEF(pData, NDEF_MAX_SIZE); +} + +/** + * @brief This function reads the data stored in the NDEF message. + * @param pData Pointer on the buffer used to store the read data. + * @retval NDEF_ERROR_MEMORY_INTERNAL The buffer is too small for the NDEF message. + * @retval NDEF_ERROR_NOT_FORMATED No Capability Container detected. + * @retval NDEF_ERROR Error when reading the NDEF message. + * @retval NDEF_OK NDEF message successfully read. + */ +uint16_t NDEF::NfcTag_ReadNDEF(uint8_t *pData, uint16_t bufferLength) { uint16_t status = NDEF_ERROR; TT5_TLV_t tlv; @@ -105,8 +118,9 @@ uint16_t NDEF::NfcTag_ReadNDEF(uint8_t *pData) tlv_size = 2; DataLength = tlv.Length; } + /* If too many data to write return error */ - if (DataLength > NDEF_MAX_SIZE) { + if (DataLength > bufferLength) { return NDEF_ERROR_MEMORY_INTERNAL; }