NFC NDEF library
Dependents: Nucleo_NFC_Example I2C_NFC_Master Print_Entire_Nucleo_NFC01A1_Memory
Fork of lib_NDEF by
lib_NDEF.c@0:3b093bd0819e, 2014-12-15 (annotated)
- Committer:
- EnricoG
- Date:
- Mon Dec 15 19:41:36 2014 +0000
- Revision:
- 0:3b093bd0819e
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
EnricoG | 0:3b093bd0819e | 1 | /** |
EnricoG | 0:3b093bd0819e | 2 | ****************************************************************************** |
EnricoG | 0:3b093bd0819e | 3 | * @file lib_NDEF.c |
EnricoG | 0:3b093bd0819e | 4 | * @author MMY Application Team |
EnricoG | 0:3b093bd0819e | 5 | * @version V1.0.0 |
EnricoG | 0:3b093bd0819e | 6 | * @date 20-November-2013 |
EnricoG | 0:3b093bd0819e | 7 | * @brief This file help to manage NDEF file, to parse and identify them. |
EnricoG | 0:3b093bd0819e | 8 | ****************************************************************************** |
EnricoG | 0:3b093bd0819e | 9 | * @attention |
EnricoG | 0:3b093bd0819e | 10 | * |
EnricoG | 0:3b093bd0819e | 11 | * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2> |
EnricoG | 0:3b093bd0819e | 12 | * |
EnricoG | 0:3b093bd0819e | 13 | * Licensed under MMY-ST Liberty SW License Agreement V2, (the "License"); |
EnricoG | 0:3b093bd0819e | 14 | * You may not use this file except in compliance with the License. |
EnricoG | 0:3b093bd0819e | 15 | * You may obtain a copy of the License at: |
EnricoG | 0:3b093bd0819e | 16 | * |
EnricoG | 0:3b093bd0819e | 17 | * http://www.st.com/software_license_agreement_liberty_v2 |
EnricoG | 0:3b093bd0819e | 18 | * |
EnricoG | 0:3b093bd0819e | 19 | * Unless required by applicable law or agreed to in writing, software |
EnricoG | 0:3b093bd0819e | 20 | * distributed under the License is distributed on an "AS IS" BASIS, |
EnricoG | 0:3b093bd0819e | 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
EnricoG | 0:3b093bd0819e | 22 | * See the License for the specific language governing permissions and |
EnricoG | 0:3b093bd0819e | 23 | * limitations under the License. |
EnricoG | 0:3b093bd0819e | 24 | * |
EnricoG | 0:3b093bd0819e | 25 | ****************************************************************************** |
EnricoG | 0:3b093bd0819e | 26 | */ |
EnricoG | 0:3b093bd0819e | 27 | |
EnricoG | 0:3b093bd0819e | 28 | /* Includes ------------------------------------------------------------------*/ |
EnricoG | 0:3b093bd0819e | 29 | #include "lib_NDEF.h" |
EnricoG | 0:3b093bd0819e | 30 | |
EnricoG | 0:3b093bd0819e | 31 | /** @addtogroup NFC_libraries |
EnricoG | 0:3b093bd0819e | 32 | * @{ |
EnricoG | 0:3b093bd0819e | 33 | * @brief <b>This is the library used to manage the content of the TAG (data) |
EnricoG | 0:3b093bd0819e | 34 | * But also the specific feature of the tag, for instance |
EnricoG | 0:3b093bd0819e | 35 | * password, gpo... </b> |
EnricoG | 0:3b093bd0819e | 36 | */ |
EnricoG | 0:3b093bd0819e | 37 | |
EnricoG | 0:3b093bd0819e | 38 | |
EnricoG | 0:3b093bd0819e | 39 | /** @addtogroup libNFC_FORUM |
EnricoG | 0:3b093bd0819e | 40 | * @{ |
EnricoG | 0:3b093bd0819e | 41 | * @brief This part of the library manage data which follow NFC forum organisation. |
EnricoG | 0:3b093bd0819e | 42 | */ |
EnricoG | 0:3b093bd0819e | 43 | |
EnricoG | 0:3b093bd0819e | 44 | /** @defgroup libNDEF_Private_Functions |
EnricoG | 0:3b093bd0819e | 45 | * @{ |
EnricoG | 0:3b093bd0819e | 46 | */ |
EnricoG | 0:3b093bd0819e | 47 | |
EnricoG | 0:3b093bd0819e | 48 | |
EnricoG | 0:3b093bd0819e | 49 | static uint16_t NDEF_IsNDEFPresent ( void ); |
EnricoG | 0:3b093bd0819e | 50 | static uint16_t NDEF_ParseRecordHeader ( sRecordInfo *pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 51 | static void NDEF_ParseWellKnownType ( sRecordInfo *pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 52 | static void NDEF_ParseMediaType ( sRecordInfo *pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 53 | static void NDEF_ParseForumExternalType ( sRecordInfo *pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 54 | static void NDEF_ParseURI(sRecordInfo *pRecordStruct); |
EnricoG | 0:3b093bd0819e | 55 | static void NDEF_ParseSP(sRecordInfo *pRecordStruct); |
EnricoG | 0:3b093bd0819e | 56 | static uint16_t NDEF_IdentifySPRecord ( sRecordInfo *pRecordStruct, uint8_t* pPayload ); |
EnricoG | 0:3b093bd0819e | 57 | |
EnricoG | 0:3b093bd0819e | 58 | /* In case of smart Poster composed with different record, 3 records supported so far */ |
EnricoG | 0:3b093bd0819e | 59 | sRecordInfo SPRecordStruct1, SPRecordStruct2, SPRecordStruct3; |
EnricoG | 0:3b093bd0819e | 60 | uint32_t SPRecordStructAdd[SP_MAX_RECORD] = { (uint32_t)&SPRecordStruct1, (uint32_t)&SPRecordStruct2, (uint32_t)&SPRecordStruct3 }; |
EnricoG | 0:3b093bd0819e | 61 | |
EnricoG | 0:3b093bd0819e | 62 | /** |
EnricoG | 0:3b093bd0819e | 63 | * @brief This fonction check that the tag contain a NDEF message |
EnricoG | 0:3b093bd0819e | 64 | * @param None : |
EnricoG | 0:3b093bd0819e | 65 | * @retval SUCCESS : There is a NDEF file stored in tag |
EnricoG | 0:3b093bd0819e | 66 | * @retval ERROR : No NDEF in the tag. |
EnricoG | 0:3b093bd0819e | 67 | */ |
EnricoG | 0:3b093bd0819e | 68 | static uint16_t NDEF_IsNDEFPresent ( void ) |
EnricoG | 0:3b093bd0819e | 69 | { |
EnricoG | 0:3b093bd0819e | 70 | uint16_t FileSize; |
EnricoG | 0:3b093bd0819e | 71 | uint8_t uM24SR_NDEFHeader [0x2]; |
EnricoG | 0:3b093bd0819e | 72 | |
EnricoG | 0:3b093bd0819e | 73 | /* Check NDEF existence */ |
EnricoG | 0:3b093bd0819e | 74 | ReadData ( NDEF_SIZE_OFFSET , 2 , uM24SR_NDEFHeader); |
EnricoG | 0:3b093bd0819e | 75 | FileSize = (uint16_t) ((uM24SR_NDEFHeader[0x00]<<8) | uM24SR_NDEFHeader[0x01]); |
EnricoG | 0:3b093bd0819e | 76 | |
EnricoG | 0:3b093bd0819e | 77 | if( FileSize != 0) |
EnricoG | 0:3b093bd0819e | 78 | return SUCCESS; |
EnricoG | 0:3b093bd0819e | 79 | else |
EnricoG | 0:3b093bd0819e | 80 | return ERROR; |
EnricoG | 0:3b093bd0819e | 81 | } |
EnricoG | 0:3b093bd0819e | 82 | |
EnricoG | 0:3b093bd0819e | 83 | /** |
EnricoG | 0:3b093bd0819e | 84 | * @brief This fonction identify the type of record |
EnricoG | 0:3b093bd0819e | 85 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 86 | * @param pPayload : pointer on the payload |
EnricoG | 0:3b093bd0819e | 87 | * @retval Status : Status of the operation. |
EnricoG | 0:3b093bd0819e | 88 | */ |
EnricoG | 0:3b093bd0819e | 89 | static uint16_t NDEF_IdentifySPRecord ( sRecordInfo *pRecordStruct, uint8_t* pPayload ) |
EnricoG | 0:3b093bd0819e | 90 | { |
EnricoG | 0:3b093bd0819e | 91 | uint16_t status = ERROR; |
EnricoG | 0:3b093bd0819e | 92 | uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; |
EnricoG | 0:3b093bd0819e | 93 | |
EnricoG | 0:3b093bd0819e | 94 | /* Is ID length field present */ |
EnricoG | 0:3b093bd0819e | 95 | if( (*pPayload)&IL_Mask) |
EnricoG | 0:3b093bd0819e | 96 | { |
EnricoG | 0:3b093bd0819e | 97 | IDLengthField = ID_LENGTH_FIELD; |
EnricoG | 0:3b093bd0819e | 98 | } |
EnricoG | 0:3b093bd0819e | 99 | else |
EnricoG | 0:3b093bd0819e | 100 | { |
EnricoG | 0:3b093bd0819e | 101 | IDLengthField = 0; |
EnricoG | 0:3b093bd0819e | 102 | } |
EnricoG | 0:3b093bd0819e | 103 | |
EnricoG | 0:3b093bd0819e | 104 | /* it's a SR */ |
EnricoG | 0:3b093bd0819e | 105 | if( (*pPayload)&SR_Mask) |
EnricoG | 0:3b093bd0819e | 106 | { |
EnricoG | 0:3b093bd0819e | 107 | TypeNbByte = pPayload[1]; |
EnricoG | 0:3b093bd0819e | 108 | PayloadLengthField = 1; |
EnricoG | 0:3b093bd0819e | 109 | if( IDLengthField == ID_LENGTH_FIELD) |
EnricoG | 0:3b093bd0819e | 110 | IDNbByte = pPayload[3]; |
EnricoG | 0:3b093bd0819e | 111 | else |
EnricoG | 0:3b093bd0819e | 112 | IDNbByte = 0; |
EnricoG | 0:3b093bd0819e | 113 | } |
EnricoG | 0:3b093bd0819e | 114 | else |
EnricoG | 0:3b093bd0819e | 115 | { |
EnricoG | 0:3b093bd0819e | 116 | TypeNbByte = pPayload[1]; |
EnricoG | 0:3b093bd0819e | 117 | PayloadLengthField = 4; |
EnricoG | 0:3b093bd0819e | 118 | if( IDLengthField == ID_LENGTH_FIELD) |
EnricoG | 0:3b093bd0819e | 119 | IDNbByte = pPayload[6]; |
EnricoG | 0:3b093bd0819e | 120 | else |
EnricoG | 0:3b093bd0819e | 121 | IDNbByte = 0; |
EnricoG | 0:3b093bd0819e | 122 | } |
EnricoG | 0:3b093bd0819e | 123 | |
EnricoG | 0:3b093bd0819e | 124 | SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; |
EnricoG | 0:3b093bd0819e | 125 | |
EnricoG | 0:3b093bd0819e | 126 | /* it's a SR */ |
EnricoG | 0:3b093bd0819e | 127 | if( pPayload[0]&SR_Mask) |
EnricoG | 0:3b093bd0819e | 128 | { |
EnricoG | 0:3b093bd0819e | 129 | pRecordStruct->RecordFlags = pPayload[0]; |
EnricoG | 0:3b093bd0819e | 130 | pRecordStruct->TypeLength = TypeNbByte; |
EnricoG | 0:3b093bd0819e | 131 | pRecordStruct->PayloadLength3 = 0; |
EnricoG | 0:3b093bd0819e | 132 | pRecordStruct->PayloadLength2 = 0; |
EnricoG | 0:3b093bd0819e | 133 | pRecordStruct->PayloadLength1 = 0; |
EnricoG | 0:3b093bd0819e | 134 | pRecordStruct->PayloadLength0 = pPayload[2]; |
EnricoG | 0:3b093bd0819e | 135 | pRecordStruct->IDLength = IDNbByte; |
EnricoG | 0:3b093bd0819e | 136 | memcpy(pRecordStruct->Type, &pPayload[3+IDNbByte] , TypeNbByte); |
EnricoG | 0:3b093bd0819e | 137 | memcpy(pRecordStruct->ID, &pPayload[3+IDNbByte+TypeNbByte] , IDNbByte); |
EnricoG | 0:3b093bd0819e | 138 | pRecordStruct->PayloadOffset = SizeOfRecordHeader; |
EnricoG | 0:3b093bd0819e | 139 | } |
EnricoG | 0:3b093bd0819e | 140 | else |
EnricoG | 0:3b093bd0819e | 141 | { |
EnricoG | 0:3b093bd0819e | 142 | pRecordStruct->RecordFlags = pPayload[0]; |
EnricoG | 0:3b093bd0819e | 143 | pRecordStruct->TypeLength = TypeNbByte; |
EnricoG | 0:3b093bd0819e | 144 | pRecordStruct->PayloadLength3 = pPayload[2]; |
EnricoG | 0:3b093bd0819e | 145 | pRecordStruct->PayloadLength2 = pPayload[3]; |
EnricoG | 0:3b093bd0819e | 146 | pRecordStruct->PayloadLength1 = pPayload[4]; |
EnricoG | 0:3b093bd0819e | 147 | pRecordStruct->PayloadLength0 = pPayload[5]; |
EnricoG | 0:3b093bd0819e | 148 | pRecordStruct->IDLength = IDNbByte; |
EnricoG | 0:3b093bd0819e | 149 | memcpy(pRecordStruct->Type, &pPayload[6+IDNbByte] , TypeNbByte); |
EnricoG | 0:3b093bd0819e | 150 | memcpy(pRecordStruct->ID, &pPayload[6+IDNbByte+TypeNbByte] , IDNbByte); |
EnricoG | 0:3b093bd0819e | 151 | pRecordStruct->PayloadOffset = SizeOfRecordHeader; |
EnricoG | 0:3b093bd0819e | 152 | } |
EnricoG | 0:3b093bd0819e | 153 | |
EnricoG | 0:3b093bd0819e | 154 | pRecordStruct->PayloadBufferAdd = (uint32_t)(pPayload+SizeOfRecordHeader); |
EnricoG | 0:3b093bd0819e | 155 | |
EnricoG | 0:3b093bd0819e | 156 | status = NDEF_ParseRecordHeader(pRecordStruct); |
EnricoG | 0:3b093bd0819e | 157 | |
EnricoG | 0:3b093bd0819e | 158 | return status; |
EnricoG | 0:3b093bd0819e | 159 | } |
EnricoG | 0:3b093bd0819e | 160 | |
EnricoG | 0:3b093bd0819e | 161 | /** |
EnricoG | 0:3b093bd0819e | 162 | * @brief This fonction parse the record header and dispatch regarding TNF value |
EnricoG | 0:3b093bd0819e | 163 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 164 | * @retval SUCCESS : record identified and structure filled |
EnricoG | 0:3b093bd0819e | 165 | * @retval ERROR : Not supported |
EnricoG | 0:3b093bd0819e | 166 | */ |
EnricoG | 0:3b093bd0819e | 167 | static uint16_t NDEF_ParseRecordHeader ( sRecordInfo *pRecordStruct ) |
EnricoG | 0:3b093bd0819e | 168 | { |
EnricoG | 0:3b093bd0819e | 169 | uint16_t status = SUCCESS; |
EnricoG | 0:3b093bd0819e | 170 | |
EnricoG | 0:3b093bd0819e | 171 | switch( (pRecordStruct->RecordFlags&TNF_Mask)) |
EnricoG | 0:3b093bd0819e | 172 | { |
EnricoG | 0:3b093bd0819e | 173 | case TNF_WellKnown: |
EnricoG | 0:3b093bd0819e | 174 | NDEF_ParseWellKnownType ( pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 175 | break; |
EnricoG | 0:3b093bd0819e | 176 | |
EnricoG | 0:3b093bd0819e | 177 | case TNF_MediaType: |
EnricoG | 0:3b093bd0819e | 178 | NDEF_ParseMediaType ( pRecordStruct ); |
EnricoG | 0:3b093bd0819e | 179 | break; |
EnricoG | 0:3b093bd0819e | 180 | |
EnricoG | 0:3b093bd0819e | 181 | case TNF_NFCForumExternal: |
EnricoG | 0:3b093bd0819e | 182 | NDEF_ParseForumExternalType ( pRecordStruct); |
EnricoG | 0:3b093bd0819e | 183 | break; |
EnricoG | 0:3b093bd0819e | 184 | |
EnricoG | 0:3b093bd0819e | 185 | default: |
EnricoG | 0:3b093bd0819e | 186 | /* currently not supported or unknown*/ |
EnricoG | 0:3b093bd0819e | 187 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 188 | status = ERROR; |
EnricoG | 0:3b093bd0819e | 189 | } |
EnricoG | 0:3b093bd0819e | 190 | return status; |
EnricoG | 0:3b093bd0819e | 191 | } |
EnricoG | 0:3b093bd0819e | 192 | |
EnricoG | 0:3b093bd0819e | 193 | /** |
EnricoG | 0:3b093bd0819e | 194 | * @brief This fonction parse the Well Known type record |
EnricoG | 0:3b093bd0819e | 195 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 196 | * @retval None |
EnricoG | 0:3b093bd0819e | 197 | */ |
EnricoG | 0:3b093bd0819e | 198 | static void NDEF_ParseWellKnownType ( sRecordInfo *pRecordStruct ) |
EnricoG | 0:3b093bd0819e | 199 | { |
EnricoG | 0:3b093bd0819e | 200 | uint8_t* pPayload; |
EnricoG | 0:3b093bd0819e | 201 | |
EnricoG | 0:3b093bd0819e | 202 | pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); |
EnricoG | 0:3b093bd0819e | 203 | |
EnricoG | 0:3b093bd0819e | 204 | if( !memcmp( &(pRecordStruct->Type), SMART_POSTER_TYPE_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 205 | { |
EnricoG | 0:3b093bd0819e | 206 | /* special case where we have to parse others records */ |
EnricoG | 0:3b093bd0819e | 207 | pRecordStruct->NDEF_Type = SMARTPOSTER_TYPE; |
EnricoG | 0:3b093bd0819e | 208 | NDEF_ParseSP(pRecordStruct); |
EnricoG | 0:3b093bd0819e | 209 | } |
EnricoG | 0:3b093bd0819e | 210 | |
EnricoG | 0:3b093bd0819e | 211 | else if( !memcmp( &(pRecordStruct->Type), URI_TYPE_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 212 | { |
EnricoG | 0:3b093bd0819e | 213 | /* it's an URI Type check if it's an URL or SMS or ... */ |
EnricoG | 0:3b093bd0819e | 214 | /* check identifier */ |
EnricoG | 0:3b093bd0819e | 215 | if( *pPayload == URI_ID_0x00) |
EnricoG | 0:3b093bd0819e | 216 | { |
EnricoG | 0:3b093bd0819e | 217 | NDEF_ParseURI(pRecordStruct); |
EnricoG | 0:3b093bd0819e | 218 | } |
EnricoG | 0:3b093bd0819e | 219 | else if ( *pPayload > URI_ID_0x00 && *pPayload < URI_RFU ) |
EnricoG | 0:3b093bd0819e | 220 | { |
EnricoG | 0:3b093bd0819e | 221 | /* email special case */ |
EnricoG | 0:3b093bd0819e | 222 | if ( *pPayload == (uint8_t) URI_ID_0x06) |
EnricoG | 0:3b093bd0819e | 223 | { |
EnricoG | 0:3b093bd0819e | 224 | pRecordStruct->NDEF_Type = URI_EMAIL_TYPE; |
EnricoG | 0:3b093bd0819e | 225 | } |
EnricoG | 0:3b093bd0819e | 226 | else |
EnricoG | 0:3b093bd0819e | 227 | { |
EnricoG | 0:3b093bd0819e | 228 | pRecordStruct->NDEF_Type = WELL_KNOWN_ABRIDGED_URI_TYPE; |
EnricoG | 0:3b093bd0819e | 229 | } |
EnricoG | 0:3b093bd0819e | 230 | } |
EnricoG | 0:3b093bd0819e | 231 | else |
EnricoG | 0:3b093bd0819e | 232 | { |
EnricoG | 0:3b093bd0819e | 233 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 234 | } |
EnricoG | 0:3b093bd0819e | 235 | } |
EnricoG | 0:3b093bd0819e | 236 | |
EnricoG | 0:3b093bd0819e | 237 | else if( !memcmp( &(pRecordStruct->Type), TEXT_TYPE_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 238 | { |
EnricoG | 0:3b093bd0819e | 239 | pRecordStruct->NDEF_Type = TEXT_TYPE; |
EnricoG | 0:3b093bd0819e | 240 | } |
EnricoG | 0:3b093bd0819e | 241 | else |
EnricoG | 0:3b093bd0819e | 242 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 243 | |
EnricoG | 0:3b093bd0819e | 244 | } |
EnricoG | 0:3b093bd0819e | 245 | |
EnricoG | 0:3b093bd0819e | 246 | /** |
EnricoG | 0:3b093bd0819e | 247 | * @brief This fonction parse the Media type record |
EnricoG | 0:3b093bd0819e | 248 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 249 | * @retval None |
EnricoG | 0:3b093bd0819e | 250 | */ |
EnricoG | 0:3b093bd0819e | 251 | static void NDEF_ParseMediaType ( sRecordInfo *pRecordStruct ) |
EnricoG | 0:3b093bd0819e | 252 | { |
EnricoG | 0:3b093bd0819e | 253 | if( !memcmp( &(pRecordStruct->Type), VCARD_TYPE_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 254 | pRecordStruct->NDEF_Type = VCARD_TYPE; |
EnricoG | 0:3b093bd0819e | 255 | else if( !memcmp( &(pRecordStruct->Type), XVCARD_TYPE_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 256 | pRecordStruct->NDEF_Type = VCARD_TYPE; |
EnricoG | 0:3b093bd0819e | 257 | else |
EnricoG | 0:3b093bd0819e | 258 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 259 | } |
EnricoG | 0:3b093bd0819e | 260 | |
EnricoG | 0:3b093bd0819e | 261 | /** |
EnricoG | 0:3b093bd0819e | 262 | * @brief This fonction parse the Forum External type record |
EnricoG | 0:3b093bd0819e | 263 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 264 | * @retval None |
EnricoG | 0:3b093bd0819e | 265 | */ |
EnricoG | 0:3b093bd0819e | 266 | static void NDEF_ParseForumExternalType ( sRecordInfo *pRecordStruct ) |
EnricoG | 0:3b093bd0819e | 267 | { |
EnricoG | 0:3b093bd0819e | 268 | if( !memcmp( &(pRecordStruct->Type), M24SR_DISCOVERY_APP_STRING, pRecordStruct->TypeLength)) |
EnricoG | 0:3b093bd0819e | 269 | pRecordStruct->NDEF_Type = M24SR_DISCOVERY_APP_TYPE; |
EnricoG | 0:3b093bd0819e | 270 | else |
EnricoG | 0:3b093bd0819e | 271 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 272 | } |
EnricoG | 0:3b093bd0819e | 273 | |
EnricoG | 0:3b093bd0819e | 274 | /** |
EnricoG | 0:3b093bd0819e | 275 | * @brief This fonction parse the URI type record |
EnricoG | 0:3b093bd0819e | 276 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 277 | * @retval None |
EnricoG | 0:3b093bd0819e | 278 | */ |
EnricoG | 0:3b093bd0819e | 279 | static void NDEF_ParseURI(sRecordInfo *pRecordStruct) |
EnricoG | 0:3b093bd0819e | 280 | { |
EnricoG | 0:3b093bd0819e | 281 | uint8_t* pPayload; |
EnricoG | 0:3b093bd0819e | 282 | |
EnricoG | 0:3b093bd0819e | 283 | pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); |
EnricoG | 0:3b093bd0819e | 284 | pPayload ++; /* to skip URI identifier first URI payload byte */ |
EnricoG | 0:3b093bd0819e | 285 | |
EnricoG | 0:3b093bd0819e | 286 | if( !memcmp( pPayload, SMS_TYPE_STRING, strlen(SMS_TYPE_STRING)) ) |
EnricoG | 0:3b093bd0819e | 287 | { |
EnricoG | 0:3b093bd0819e | 288 | pRecordStruct->NDEF_Type = URI_SMS_TYPE; |
EnricoG | 0:3b093bd0819e | 289 | } |
EnricoG | 0:3b093bd0819e | 290 | else if( !memcmp( pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING)) ) |
EnricoG | 0:3b093bd0819e | 291 | { |
EnricoG | 0:3b093bd0819e | 292 | pRecordStruct->NDEF_Type = URI_GEO_TYPE; |
EnricoG | 0:3b093bd0819e | 293 | } |
EnricoG | 0:3b093bd0819e | 294 | else |
EnricoG | 0:3b093bd0819e | 295 | pRecordStruct->NDEF_Type = UNKNOWN_TYPE; |
EnricoG | 0:3b093bd0819e | 296 | |
EnricoG | 0:3b093bd0819e | 297 | } |
EnricoG | 0:3b093bd0819e | 298 | |
EnricoG | 0:3b093bd0819e | 299 | /** |
EnricoG | 0:3b093bd0819e | 300 | * @brief This fonction parse the Smart Poster |
EnricoG | 0:3b093bd0819e | 301 | * @param pRecordStruct : pointer on the record structure to fill |
EnricoG | 0:3b093bd0819e | 302 | * @retval None |
EnricoG | 0:3b093bd0819e | 303 | */ |
EnricoG | 0:3b093bd0819e | 304 | static void NDEF_ParseSP(sRecordInfo *pRecordStruct) |
EnricoG | 0:3b093bd0819e | 305 | { |
EnricoG | 0:3b093bd0819e | 306 | uint8_t* pPayload; |
EnricoG | 0:3b093bd0819e | 307 | uint32_t PayloadSize = 0; |
EnricoG | 0:3b093bd0819e | 308 | uint32_t SPPayloadSize = 0; |
EnricoG | 0:3b093bd0819e | 309 | uint32_t OffsetInSPPayload =0; |
EnricoG | 0:3b093bd0819e | 310 | uint32_t RecordPosition = 0; |
EnricoG | 0:3b093bd0819e | 311 | sRecordInfo *pSPRecordStruct; |
EnricoG | 0:3b093bd0819e | 312 | |
EnricoG | 0:3b093bd0819e | 313 | /* initialize variable with size of the payload and poiter on data */ |
EnricoG | 0:3b093bd0819e | 314 | PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3)<<24) | ((uint32_t)(pRecordStruct->PayloadLength2)<<16) | |
EnricoG | 0:3b093bd0819e | 315 | ((uint32_t)(pRecordStruct->PayloadLength1)<<8) | pRecordStruct->PayloadLength0; |
EnricoG | 0:3b093bd0819e | 316 | |
EnricoG | 0:3b093bd0819e | 317 | pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); |
EnricoG | 0:3b093bd0819e | 318 | |
EnricoG | 0:3b093bd0819e | 319 | pSPRecordStruct = (sRecordInfo *)SPRecordStructAdd[0]; |
EnricoG | 0:3b093bd0819e | 320 | |
EnricoG | 0:3b093bd0819e | 321 | /* Initailize the number of record find in the SP payload */ |
EnricoG | 0:3b093bd0819e | 322 | pRecordStruct->NbOfRecordInSPPayload = 0; |
EnricoG | 0:3b093bd0819e | 323 | |
EnricoG | 0:3b093bd0819e | 324 | do |
EnricoG | 0:3b093bd0819e | 325 | { |
EnricoG | 0:3b093bd0819e | 326 | pSPRecordStruct = (sRecordInfo *)SPRecordStructAdd[RecordPosition]; |
EnricoG | 0:3b093bd0819e | 327 | /* identify the 1st record in the SP payload */ |
EnricoG | 0:3b093bd0819e | 328 | if( NDEF_IdentifySPRecord ( pSPRecordStruct, pPayload )) |
EnricoG | 0:3b093bd0819e | 329 | { |
EnricoG | 0:3b093bd0819e | 330 | /* store add of structure that will contain the other record information */ |
EnricoG | 0:3b093bd0819e | 331 | pRecordStruct->NbOfRecordInSPPayload ++; |
EnricoG | 0:3b093bd0819e | 332 | pRecordStruct->SPRecordStructAdd[RecordPosition] = (uint32_t) pSPRecordStruct; |
EnricoG | 0:3b093bd0819e | 333 | |
EnricoG | 0:3b093bd0819e | 334 | /* After SPRecord + First Record check if we are at the end of NDEF file */ |
EnricoG | 0:3b093bd0819e | 335 | SPPayloadSize = ((uint32_t)(pSPRecordStruct->PayloadLength3)<<24) | ((uint32_t)(pSPRecordStruct->PayloadLength2)<<16) | |
EnricoG | 0:3b093bd0819e | 336 | ((uint32_t)(pSPRecordStruct->PayloadLength1)<<8) | pSPRecordStruct->PayloadLength0; |
EnricoG | 0:3b093bd0819e | 337 | |
EnricoG | 0:3b093bd0819e | 338 | OffsetInSPPayload += pSPRecordStruct->PayloadOffset + SPPayloadSize; |
EnricoG | 0:3b093bd0819e | 339 | pPayload += OffsetInSPPayload; |
EnricoG | 0:3b093bd0819e | 340 | RecordPosition++; |
EnricoG | 0:3b093bd0819e | 341 | } |
EnricoG | 0:3b093bd0819e | 342 | } |
EnricoG | 0:3b093bd0819e | 343 | while( OffsetInSPPayload < PayloadSize && RecordPosition<SP_MAX_RECORD); /* there is another record */ |
EnricoG | 0:3b093bd0819e | 344 | |
EnricoG | 0:3b093bd0819e | 345 | } |
EnricoG | 0:3b093bd0819e | 346 | |
EnricoG | 0:3b093bd0819e | 347 | /** |
EnricoG | 0:3b093bd0819e | 348 | * @} |
EnricoG | 0:3b093bd0819e | 349 | */ |
EnricoG | 0:3b093bd0819e | 350 | |
EnricoG | 0:3b093bd0819e | 351 | /** @defgroup libNDEF_Public_Functions |
EnricoG | 0:3b093bd0819e | 352 | * @{ |
EnricoG | 0:3b093bd0819e | 353 | */ |
EnricoG | 0:3b093bd0819e | 354 | |
EnricoG | 0:3b093bd0819e | 355 | |
EnricoG | 0:3b093bd0819e | 356 | /** |
EnricoG | 0:3b093bd0819e | 357 | * @brief This fonction identify the NDEF message stored in tag |
EnricoG | 0:3b093bd0819e | 358 | * @param pRecordStruct : Structure to fill with record information |
EnricoG | 0:3b093bd0819e | 359 | * @param pNDEF : pointer on the NDEF message data |
EnricoG | 0:3b093bd0819e | 360 | * @retval SUCCESS : record struct filled |
EnricoG | 0:3b093bd0819e | 361 | * @retval ERROR : record struct not updated |
EnricoG | 0:3b093bd0819e | 362 | */ |
EnricoG | 0:3b093bd0819e | 363 | |
EnricoG | 0:3b093bd0819e | 364 | uint16_t NDEF_IdentifyNDEF ( sRecordInfo *pRecordStruct, uint8_t* pNDEF ) |
EnricoG | 0:3b093bd0819e | 365 | { |
EnricoG | 0:3b093bd0819e | 366 | uint16_t status = ERROR; |
EnricoG | 0:3b093bd0819e | 367 | uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; |
EnricoG | 0:3b093bd0819e | 368 | uint32_t PayloadSize; |
EnricoG | 0:3b093bd0819e | 369 | |
EnricoG | 0:3b093bd0819e | 370 | /* check NDEF present */ |
EnricoG | 0:3b093bd0819e | 371 | if(NDEF_IsNDEFPresent() != SUCCESS) |
EnricoG | 0:3b093bd0819e | 372 | { |
EnricoG | 0:3b093bd0819e | 373 | return ERROR; |
EnricoG | 0:3b093bd0819e | 374 | } |
EnricoG | 0:3b093bd0819e | 375 | |
EnricoG | 0:3b093bd0819e | 376 | /* Analyse record layout */ |
EnricoG | 0:3b093bd0819e | 377 | ReadData ( FIRST_RECORD_OFFSET , 1 , pNDEF); |
EnricoG | 0:3b093bd0819e | 378 | |
EnricoG | 0:3b093bd0819e | 379 | /* Is ID length field present */ |
EnricoG | 0:3b093bd0819e | 380 | if( (*pNDEF)&IL_Mask) |
EnricoG | 0:3b093bd0819e | 381 | { |
EnricoG | 0:3b093bd0819e | 382 | IDLengthField = ID_LENGTH_FIELD; |
EnricoG | 0:3b093bd0819e | 383 | } |
EnricoG | 0:3b093bd0819e | 384 | else |
EnricoG | 0:3b093bd0819e | 385 | { |
EnricoG | 0:3b093bd0819e | 386 | IDLengthField = 0; |
EnricoG | 0:3b093bd0819e | 387 | } |
EnricoG | 0:3b093bd0819e | 388 | |
EnricoG | 0:3b093bd0819e | 389 | /* it's a SR */ |
EnricoG | 0:3b093bd0819e | 390 | if( (*pNDEF)&SR_Mask) |
EnricoG | 0:3b093bd0819e | 391 | { |
EnricoG | 0:3b093bd0819e | 392 | /* Analyse short record layout */ |
EnricoG | 0:3b093bd0819e | 393 | ReadData ( FIRST_RECORD_OFFSET , 4 , pNDEF); |
EnricoG | 0:3b093bd0819e | 394 | TypeNbByte = pNDEF[1]; |
EnricoG | 0:3b093bd0819e | 395 | PayloadLengthField = 1; |
EnricoG | 0:3b093bd0819e | 396 | if( IDLengthField == ID_LENGTH_FIELD) |
EnricoG | 0:3b093bd0819e | 397 | IDNbByte = pNDEF[3]; |
EnricoG | 0:3b093bd0819e | 398 | else |
EnricoG | 0:3b093bd0819e | 399 | IDNbByte = 0; |
EnricoG | 0:3b093bd0819e | 400 | } |
EnricoG | 0:3b093bd0819e | 401 | else |
EnricoG | 0:3b093bd0819e | 402 | { |
EnricoG | 0:3b093bd0819e | 403 | /* Analyse normal record layout */ |
EnricoG | 0:3b093bd0819e | 404 | ReadData ( FIRST_RECORD_OFFSET , 7 , pNDEF); |
EnricoG | 0:3b093bd0819e | 405 | TypeNbByte = pNDEF[1]; |
EnricoG | 0:3b093bd0819e | 406 | PayloadLengthField = 4; |
EnricoG | 0:3b093bd0819e | 407 | if( IDLengthField == ID_LENGTH_FIELD) |
EnricoG | 0:3b093bd0819e | 408 | IDNbByte = pNDEF[6]; |
EnricoG | 0:3b093bd0819e | 409 | else |
EnricoG | 0:3b093bd0819e | 410 | IDNbByte = 0; |
EnricoG | 0:3b093bd0819e | 411 | } |
EnricoG | 0:3b093bd0819e | 412 | |
EnricoG | 0:3b093bd0819e | 413 | SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; |
EnricoG | 0:3b093bd0819e | 414 | |
EnricoG | 0:3b093bd0819e | 415 | /* Read record header */ |
EnricoG | 0:3b093bd0819e | 416 | ReadData ( FIRST_RECORD_OFFSET , SizeOfRecordHeader , pNDEF); |
EnricoG | 0:3b093bd0819e | 417 | /* it's a SR */ |
EnricoG | 0:3b093bd0819e | 418 | if( pNDEF[0]&SR_Mask) |
EnricoG | 0:3b093bd0819e | 419 | { |
EnricoG | 0:3b093bd0819e | 420 | pRecordStruct->RecordFlags = pNDEF[0]; |
EnricoG | 0:3b093bd0819e | 421 | pRecordStruct->TypeLength = TypeNbByte; |
EnricoG | 0:3b093bd0819e | 422 | pRecordStruct->PayloadLength3 = 0; |
EnricoG | 0:3b093bd0819e | 423 | pRecordStruct->PayloadLength2 = 0; |
EnricoG | 0:3b093bd0819e | 424 | pRecordStruct->PayloadLength1 = 0; |
EnricoG | 0:3b093bd0819e | 425 | pRecordStruct->PayloadLength0 = pNDEF[2]; |
EnricoG | 0:3b093bd0819e | 426 | pRecordStruct->IDLength = IDNbByte; |
EnricoG | 0:3b093bd0819e | 427 | memcpy(pRecordStruct->Type, &pNDEF[3+IDNbByte] , TypeNbByte); |
EnricoG | 0:3b093bd0819e | 428 | memcpy(pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte] , IDNbByte); |
EnricoG | 0:3b093bd0819e | 429 | pRecordStruct->PayloadOffset = SizeOfRecordHeader; |
EnricoG | 0:3b093bd0819e | 430 | } |
EnricoG | 0:3b093bd0819e | 431 | else |
EnricoG | 0:3b093bd0819e | 432 | { |
EnricoG | 0:3b093bd0819e | 433 | pRecordStruct->RecordFlags = pNDEF[0]; |
EnricoG | 0:3b093bd0819e | 434 | pRecordStruct->TypeLength = TypeNbByte; |
EnricoG | 0:3b093bd0819e | 435 | pRecordStruct->PayloadLength3 = pNDEF[2]; |
EnricoG | 0:3b093bd0819e | 436 | pRecordStruct->PayloadLength2 = pNDEF[3]; |
EnricoG | 0:3b093bd0819e | 437 | pRecordStruct->PayloadLength1 = pNDEF[4]; |
EnricoG | 0:3b093bd0819e | 438 | pRecordStruct->PayloadLength0 = pNDEF[5]; |
EnricoG | 0:3b093bd0819e | 439 | pRecordStruct->IDLength = IDNbByte; |
EnricoG | 0:3b093bd0819e | 440 | memcpy(pRecordStruct->Type, &pNDEF[6+IDNbByte] , TypeNbByte); |
EnricoG | 0:3b093bd0819e | 441 | memcpy(pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte] , IDNbByte); |
EnricoG | 0:3b093bd0819e | 442 | pRecordStruct->PayloadOffset = SizeOfRecordHeader; |
EnricoG | 0:3b093bd0819e | 443 | } |
EnricoG | 0:3b093bd0819e | 444 | |
EnricoG | 0:3b093bd0819e | 445 | PayloadSize = ((uint32_t)(pRecordStruct->PayloadLength3)<<24) | ((uint32_t)(pRecordStruct->PayloadLength2)<<16) | |
EnricoG | 0:3b093bd0819e | 446 | ((uint32_t)(pRecordStruct->PayloadLength1)<<8) | pRecordStruct->PayloadLength0; |
EnricoG | 0:3b093bd0819e | 447 | |
EnricoG | 0:3b093bd0819e | 448 | /* read Payload */ |
EnricoG | 0:3b093bd0819e | 449 | status = ReadData ( (uint16_t)((FIRST_RECORD_OFFSET) + pRecordStruct->PayloadOffset) , PayloadSize , pNDEF); |
EnricoG | 0:3b093bd0819e | 450 | |
EnricoG | 0:3b093bd0819e | 451 | if( status != NDEF_ACTION_COMPLETED) |
EnricoG | 0:3b093bd0819e | 452 | return status; |
EnricoG | 0:3b093bd0819e | 453 | else |
EnricoG | 0:3b093bd0819e | 454 | pRecordStruct->PayloadBufferAdd = (uint32_t)(pNDEF); |
EnricoG | 0:3b093bd0819e | 455 | |
EnricoG | 0:3b093bd0819e | 456 | NDEF_ParseRecordHeader(pRecordStruct); |
EnricoG | 0:3b093bd0819e | 457 | |
EnricoG | 0:3b093bd0819e | 458 | return SUCCESS; |
EnricoG | 0:3b093bd0819e | 459 | } |
EnricoG | 0:3b093bd0819e | 460 | |
EnricoG | 0:3b093bd0819e | 461 | /** |
EnricoG | 0:3b093bd0819e | 462 | * @brief This fonction read the NDEF content of the TAG |
EnricoG | 0:3b093bd0819e | 463 | * @param pNDEF : pointer on the buffer to store NDEF data |
EnricoG | 0:3b093bd0819e | 464 | * @retval SUCCESS : NDEF file data retrieve and store in the buffer |
EnricoG | 0:3b093bd0819e | 465 | * @retval ERROR : not able to read NDEF |
EnricoG | 0:3b093bd0819e | 466 | */ |
EnricoG | 0:3b093bd0819e | 467 | uint16_t NDEF_ReadNDEF( uint8_t* pNDEF) |
EnricoG | 0:3b093bd0819e | 468 | { |
EnricoG | 0:3b093bd0819e | 469 | uint16_t status = ERROR; |
EnricoG | 0:3b093bd0819e | 470 | uint16_t NDEF_Size = 0; |
EnricoG | 0:3b093bd0819e | 471 | |
EnricoG | 0:3b093bd0819e | 472 | status = ReadData( 0 , 2 , pNDEF); |
EnricoG | 0:3b093bd0819e | 473 | |
EnricoG | 0:3b093bd0819e | 474 | if( status == NDEF_ACTION_COMPLETED) |
EnricoG | 0:3b093bd0819e | 475 | { |
EnricoG | 0:3b093bd0819e | 476 | NDEF_Size = (uint16_t) (*pNDEF << 8); |
EnricoG | 0:3b093bd0819e | 477 | NDEF_Size = NDEF_Size | (uint16_t) (*++pNDEF ); |
EnricoG | 0:3b093bd0819e | 478 | |
EnricoG | 0:3b093bd0819e | 479 | status = ReadData( 0 , NDEF_Size+2 , --pNDEF); |
EnricoG | 0:3b093bd0819e | 480 | } |
EnricoG | 0:3b093bd0819e | 481 | |
EnricoG | 0:3b093bd0819e | 482 | if( status == NDEF_ACTION_COMPLETED) |
EnricoG | 0:3b093bd0819e | 483 | return SUCCESS; |
EnricoG | 0:3b093bd0819e | 484 | else |
EnricoG | 0:3b093bd0819e | 485 | return ERROR; |
EnricoG | 0:3b093bd0819e | 486 | |
EnricoG | 0:3b093bd0819e | 487 | } |
EnricoG | 0:3b093bd0819e | 488 | |
EnricoG | 0:3b093bd0819e | 489 | /** |
EnricoG | 0:3b093bd0819e | 490 | * @brief This fonction write the NDEF in the TAG |
EnricoG | 0:3b093bd0819e | 491 | * @param pNDEF : pointer on the buffer containing the NDEF data |
EnricoG | 0:3b093bd0819e | 492 | * @retval SUCCESS : NDEF file data written in the tag |
EnricoG | 0:3b093bd0819e | 493 | * @retval ERROR : not able to store NDEF in tag |
EnricoG | 0:3b093bd0819e | 494 | */ |
EnricoG | 0:3b093bd0819e | 495 | uint16_t NDEF_WriteNDEF( uint8_t *pNDEF) |
EnricoG | 0:3b093bd0819e | 496 | { |
EnricoG | 0:3b093bd0819e | 497 | uint16_t status = ERROR; |
EnricoG | 0:3b093bd0819e | 498 | uint16_t NDEF_Size = 0; |
EnricoG | 0:3b093bd0819e | 499 | |
EnricoG | 0:3b093bd0819e | 500 | NDEF_Size = (uint16_t) (*pNDEF << 8); |
EnricoG | 0:3b093bd0819e | 501 | NDEF_Size = NDEF_Size | (uint16_t) (*++pNDEF ); |
EnricoG | 0:3b093bd0819e | 502 | |
EnricoG | 0:3b093bd0819e | 503 | status = WriteData( 0 , NDEF_Size+2 , --pNDEF); |
EnricoG | 0:3b093bd0819e | 504 | |
EnricoG | 0:3b093bd0819e | 505 | if( status == NDEF_ACTION_COMPLETED) |
EnricoG | 0:3b093bd0819e | 506 | return SUCCESS; |
EnricoG | 0:3b093bd0819e | 507 | else |
EnricoG | 0:3b093bd0819e | 508 | return ERROR; |
EnricoG | 0:3b093bd0819e | 509 | |
EnricoG | 0:3b093bd0819e | 510 | } |
EnricoG | 0:3b093bd0819e | 511 | |
EnricoG | 0:3b093bd0819e | 512 | |
EnricoG | 0:3b093bd0819e | 513 | /** |
EnricoG | 0:3b093bd0819e | 514 | * @} |
EnricoG | 0:3b093bd0819e | 515 | */ |
EnricoG | 0:3b093bd0819e | 516 | |
EnricoG | 0:3b093bd0819e | 517 | /** |
EnricoG | 0:3b093bd0819e | 518 | * @} |
EnricoG | 0:3b093bd0819e | 519 | */ |
EnricoG | 0:3b093bd0819e | 520 | |
EnricoG | 0:3b093bd0819e | 521 | /** |
EnricoG | 0:3b093bd0819e | 522 | * @} |
EnricoG | 0:3b093bd0819e | 523 | */ |
EnricoG | 0:3b093bd0819e | 524 | |
EnricoG | 0:3b093bd0819e | 525 | /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/ |
EnricoG | 0:3b093bd0819e | 526 |