1 /* 2 * Copyright (C) 2010 NXP Semiconductors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /*! 18 * \file phFriNfc_NdefRecord.c 19 * \brief NFC Ndef Record component file. 20 * 21 * Project: NFC-FRI 22 * 23 * $Date: Thu Jun 25 11:01:24 2009 $ 24 * $Author: ing07336 $ 25 * $Revision: 1.4 $ 26 * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ 27 * 28 */ 29 30 31 /*! \ingroup grp_file_attributes 32 * \name \name NDEF Record Tools Header 33 * 34 * File: \ref phFriNfc_NdefRecord.h 35 * 36 */ 37 /*@{*/ 38 #define PHFRINFCNDEFRECORD_FILEREVISION "$Revision: 1.4 $" 39 #define PHFRINFCNDEFRECORD_FILEALIASES "$Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" 40 /*@}*/ 41 42 #include <phFriNfc_NdefRecord.h> 43 #include <phNfcCompId.h> 44 #include <stdlib.h> 45 46 /* Harsha: To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */ 47 #include <string.h> 48 49 50 /*! 51 * 52 * Get a specific NDEF record from the data, provided by the caller. The data is a buffer holding 53 * one or more (nested) NDEF records within a NDEF packet (received via the NFC link, for example). 54 * 55 * \param[in] Buffer The data buffer holding the NDEF Message, as provided by the caller. 56 * \param[in] BufferLength The data length, as provided by the caller. 57 * \param[in,out] RawRecords Array of pointers, receiving the references to the found Ndef Records 58 * in the Message. The caller has to provide the array of pointers. 59 * The array is filled with valid pointers up to the number of records 60 * found or the array size if the number of found records exceeds the size. 61 * If the value is NULL the function only yields the number of records 62 * without filling in pointers. 63 * \param[in] IsChunked This boolean tells the user that the record of a certain position within 64 * an array has the CHUNKED flag set (is a partial record). The number 65 * of caller-provided array positions has to be the same as "NumberOfRawRecords". 66 * In case that this parameter is NULL the function ignores it. 67 * \param[in,out] NumberOfRawRecords Length of the Record pointer array. The caller has to provide 68 * the number of pointers provided in the NDEF Type array. \n 69 * The value is set by the extracting function to the actual number of 70 * records found in the data. If the user specifies 0 (zero) the function 71 * only yields the number of records without filling in pointers.\n 72 * The value of NULL is invalid. 73 * 74 * \retval NFCSTATUS_SUCCESS Operation successful. 75 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 76 * 77 * \note The correct number of found records is returned by the function also in case that: 78 * - The "RawRecords" array is too short to hold all values: It is filled up to the allowed maximum. 79 * - The "RawRecords" array is NULL: Only the number is returned. 80 * - The "NumberOfRawRecords" parameter is 0 (zero): The array is not filled, just the number is returned. 81 * . 82 * This can be exploited for targeted memory allocation: Specify NULL for "RawRecords" and/or 83 * 0 (zero) for "NumberOfRawRecords" and the function yields the correct array size to allocate 84 * for a second call. 85 * 86 */ 87 NFCSTATUS phFriNfc_NdefRecord_GetRecords( uint8_t *Buffer, 88 uint32_t BufferLength, 89 uint8_t *RawRecords[], 90 uint8_t IsChunked[], 91 uint32_t *NumberOfRawRecords) 92 { 93 NFCSTATUS Status = NFCSTATUS_SUCCESS; 94 uint8_t PayloadLengthByte = 0, 95 TypeLengthByte = 0, 96 TypeLength = 0, 97 IDLengthByte = 0, 98 NoOfRecordsReturnFlag = 0, 99 IDLength = 0; 100 uint32_t Count = 0, 101 PayloadLength = 0, 102 BytesTraversed = 0; 103 104 /* Validate the input parameters */ 105 if (Buffer == NULL || BufferLength == 0 || NumberOfRawRecords == NULL) 106 { 107 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 108 NFCSTATUS_INVALID_PARAMETER); 109 return Status; 110 } 111 112 if((*NumberOfRawRecords) > 0) 113 { 114 /* The number of caller-provided array positions for the array IsChunked 115 has to be the same as NumberOfRawRecords. Hence, 116 if NumberOfRawRecords > 0, the array IsChunked cannot be null */ 117 if(IsChunked == NULL) 118 { 119 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 120 NFCSTATUS_INVALID_PARAMETER); 121 return Status; 122 } 123 } 124 125 /* Check Raw Records input is NULL and Number of Raw records is 0*/ 126 if ( RawRecords == NULL || *NumberOfRawRecords == 0) 127 { 128 /* This flag is set, to return only number of records 129 this is done when the Raw Records is NULL or 130 Number of Raw records is 0 */ 131 NoOfRecordsReturnFlag = 1; 132 } 133 134 /* Check for the MB bit*/ 135 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) != 136 PH_FRINFC_NDEFRECORD_FLAGS_MB ) 137 { 138 /* MB Error */ 139 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 140 NFCSTATUS_INVALID_FORMAT); 141 142 /* Number of valid records found in the message is 0 */ 143 *NumberOfRawRecords = 0; 144 return Status; 145 } 146 147 /* Check for Tnf bits 0x07 is reserved for future use */ 148 if ((*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == 149 PH_FRINFC_NDEFRECORD_TNF_RESERVED) 150 { 151 /* TNF 07 Error */ 152 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 153 NFCSTATUS_INVALID_FORMAT); 154 /* Number of valid records found in the message is 0 */ 155 *NumberOfRawRecords = 0; 156 return Status; 157 } 158 159 /* Check the First Record(MB = 0) for TNF = 0x06(Unchanged) */ 160 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB && 161 (*Buffer & PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) 162 { 163 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 164 NFCSTATUS_INVALID_FORMAT); 165 /* Number of valid records found in the message is 0 */ 166 *NumberOfRawRecords = 0; 167 return Status; 168 } 169 170 /* First Record i.e., MB = 1, TNF != 0x05 and TypeLength = 0 */ 171 if ( (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB && 172 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN && 173 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_EMPTY && 174 *(Buffer + 1) == 0) 175 { 176 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 177 NFCSTATUS_INVALID_FORMAT); 178 /* Number of valid records found in the message is 0 */ 179 *NumberOfRawRecords = 0; 180 return Status; 181 } 182 183 /* Check till Buffer Length exceeds */ 184 while ( BytesTraversed < BufferLength ) 185 { 186 if (Buffer == NULL) 187 { 188 break; 189 } 190 191 /* For Each Record Check whether it contains the ME bit set and CF bit Set 192 if YES return ERROR*/ 193 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == 194 PH_FRINFC_NDEFRECORD_FLAGS_CF && 195 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == 196 PH_FRINFC_NDEFRECORD_FLAGS_ME) 197 { 198 /* CF and ME Error */ 199 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 200 NFCSTATUS_INVALID_FORMAT); 201 break; 202 } 203 204 if (NoOfRecordsReturnFlag == 0) 205 { 206 /* Harsha: Fix for 0000241: [gk], NDEF Tools: GetRecords() overshoots 207 a given array boundary if the number of records != 0. */ 208 /* Actual Number of Records should not exceed Number of records 209 required by caller*/ 210 if(Count >= *NumberOfRawRecords) 211 { 212 break; 213 } 214 /* To fix the mantis entry 0388 */ 215 if((Buffer != NULL)&&(RawRecords!=NULL))/*QMOR FIX*/ 216 { 217 RawRecords[Count] = Buffer; 218 } 219 else 220 { 221 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 222 NFCSTATUS_INVALID_PARAMETER); 223 break; 224 } 225 } 226 227 /* To Calculate the IDLength and PayloadLength for 228 short or normal record */ 229 Status = phFriNfc_NdefRecord_RecordIDCheck ( Buffer, 230 &TypeLength, 231 &TypeLengthByte, 232 &PayloadLengthByte, 233 &PayloadLength, 234 &IDLengthByte, 235 &IDLength); 236 if (Status != NFCSTATUS_SUCCESS) 237 { 238 break; 239 } 240 241 /* Check for the Chunk Flag */ 242 if (NoOfRecordsReturnFlag == 0) 243 { 244 /* If NoOfRecordsReturnFlag = 0, that means we have enough space */ 245 /* in the array IsChunked, to write */ 246 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == 247 PH_FRINFC_NDEFRECORD_FLAGS_CF) 248 { 249 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET; 250 } 251 else 252 { 253 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO; 254 } 255 } 256 257 /* Check the record is not the first record */ 258 if (Count > 0) 259 { 260 /* Not a first record, if chunk record is present and IL bit is set 261 also if the MB bit is set */ 262 if(((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF && 263 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL && 264 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) || 265 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB) 266 { 267 /* IL or MB Error */ 268 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 269 NFCSTATUS_INVALID_FORMAT); 270 break; 271 } 272 273 /* Check for the Chunk Flag */ 274 if (NoOfRecordsReturnFlag == 0) 275 { 276 /* If NoOfRecordsReturnFlag = 0, that means the array IsChunked 277 contains valid values. So, cannot check the value 278 of IsChunked if NoOfRecordsReturnFlag = 1. */ 279 280 /* Check whether the previous record has the chunk flag and 281 TNF of present record is not 0x06 */ 282 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET && 283 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != 284 PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) 285 { 286 /* CF or TNF Error */ 287 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 288 NFCSTATUS_INVALID_FORMAT); 289 break; 290 } 291 292 /* Check whether the previous record doesnot have the chunk flag and 293 TNF of present record is 0x06 */ 294 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO && 295 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == 296 PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) 297 { 298 /* CF or TNF Error */ 299 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 300 NFCSTATUS_INVALID_FORMAT); 301 break; 302 } 303 304 /* Check for the last chunk */ 305 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET && 306 IsChunked [Count] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO) 307 { 308 /* Check for the TypeLength, IDLength = 0 */ 309 if (TypeLength != 0 || IDLength != 0) 310 { 311 /* last chunk record Error */ 312 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 313 NFCSTATUS_INVALID_FORMAT); 314 break; 315 } 316 } 317 } /* if (NoOfRecordsReturnFlag == 0) */ 318 } /* if (Count > 0) */ 319 320 /* Calculate the bytes already traversed. */ 321 BytesTraversed = (BytesTraversed + PayloadLengthByte + IDLengthByte + TypeLength 322 + IDLength + TypeLengthByte + PayloadLength 323 + PH_FRINFC_NDEFRECORD_BUF_INC1); 324 325 if(BytesTraversed == BufferLength) 326 { 327 /* We have reached the last record, and everything is fine. */ 328 /* Check for the ME Byte */ 329 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == 330 PH_FRINFC_NDEFRECORD_FLAGS_ME) 331 { 332 Count++; 333 break; 334 } 335 else 336 { 337 /* Each message must have ME flag in the last record, Since 338 ME is not set raise an error */ 339 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 340 NFCSTATUS_INVALID_FORMAT); 341 break; 342 } 343 } 344 else 345 { 346 /* Buffer Overshoot: Inconsistency in the message length 347 and actual value of the bytes in the message detected. 348 Report error.*/ 349 if(BytesTraversed > BufferLength) 350 { 351 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 352 NFCSTATUS_INVALID_FORMAT); 353 break; 354 } 355 } 356 /* For Each Record Check whether it contains the ME bit set 357 if YES return*/ 358 if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == 359 PH_FRINFC_NDEFRECORD_FLAGS_ME) 360 { 361 Count++; 362 break; 363 } 364 365 /* +1 is for first byte */ 366 Buffer = (Buffer + PayloadLengthByte + IDLengthByte + TypeLength 367 + TypeLengthByte + IDLength + PayloadLength 368 + PH_FRINFC_NDEFRECORD_BUF_INC1); 369 370 /* Increment the number of valid records found in the message */ 371 Count++; 372 } 373 374 /* Whatever is the error, update the NumberOfRawRecords with the number 375 of proper records found till the error was detected in the message. */ 376 *NumberOfRawRecords = Count; 377 return Status; 378 } 379 380 /* to check the bitfields in the Flags Byte and return the status flag */ 381 static uint8_t phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask) 382 { 383 uint8_t check_flag = 0x00; 384 check_flag = Flags & Mask; 385 return check_flag; 386 } 387 388 uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t *Record) 389 { 390 uint32_t RecordLength=1; 391 uint8_t FlagCheck=0; 392 393 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); 394 /* Type length is present only for following TNF 395 PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN 396 PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE 397 PH_FRINFC_NDEFRECORD_TNF_ABSURI 398 PH_FRINFC_NDEFRECORD_TNF_NFCEXT 399 */ 400 401 /* ++ is for the Type Length Byte */ 402 RecordLength++; 403 if( FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY && 404 FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN && 405 FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNCHANGED ) 406 { 407 RecordLength += Record->TypeLength; 408 } 409 410 /* to check if payloadlength is 8bit or 32bit*/ 411 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); 412 if(FlagCheck!=0) 413 { 414 /* ++ is for the Payload Length Byte */ 415 RecordLength++;/* for short record*/ 416 } 417 else 418 { 419 /* + PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE is for the Payload Length Byte */ 420 RecordLength += PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;/* for normal record*/ 421 } 422 423 /* for non empty record */ 424 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); 425 if(FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY) 426 { 427 RecordLength += Record->PayloadLength; 428 } 429 430 /* ID and IDlength are present only if IL flag is set*/ 431 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); 432 if(FlagCheck!=0) 433 { 434 RecordLength +=Record->IdLength; 435 /* ++ is for the ID Length Byte */ 436 RecordLength ++; 437 } 438 return RecordLength; 439 } 440 441 /*! 442 * 443 * Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding 444 * at least the entire NDEF record (received via the NFC link, for example). 445 * 446 * \param[out] Record The NDEF record structure. The storage for the structure has to be provided by the 447 * caller matching the requirements for \b Extraction, as described in the compound 448 * documentation. 449 * \param[in] RawRecord The Pointer to the buffer, selected out of the array returned by 450 * the \ref phFriNfc_NdefRecord_GetRecords function. 451 * 452 * \retval NFCSTATUS_SUCCESS Operation successful. 453 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 454 * 455 * \note There are some caveats: 456 * - The "RawRecord" Data buffer must exist at least as long as the function execution time plus the time 457 * needed by the caller to evaluate the extracted information. No copying of the contained data is done. 458 * - Using the "RawRecord" and "RawRecordMaxSize" parameters the function internally checks whether the 459 * data to extract are within the bounds of the buffer. 460 * 461 * 462 */ 463 NFCSTATUS phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t *Record, 464 uint8_t *RawRecord) 465 { 466 NFCSTATUS Status = NFCSTATUS_SUCCESS; 467 uint8_t PayloadLengthByte = 0, 468 TypeLengthByte = 0, 469 TypeLength = 0, 470 IDLengthByte = 0, 471 IDLength = 0, 472 Tnf = 0; 473 uint32_t PayloadLength = 0; 474 475 if (Record == NULL || RawRecord == NULL) 476 { 477 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 478 NFCSTATUS_INVALID_PARAMETER); 479 } 480 481 else 482 { 483 484 /* Calculate the Flag Value */ 485 Record->Flags = phFriNfc_NdefRecord_RecordFlag ( RawRecord); 486 487 /* Calculate the Type Namr format of the record */ 488 Tnf = phFriNfc_NdefRecord_TypeNameFormat( RawRecord); 489 if(Tnf != 0xFF) 490 { 491 Record->Tnf = Tnf; 492 /* To Calculate the IDLength and PayloadLength for short or normal record */ 493 Status = phFriNfc_NdefRecord_RecordIDCheck ( RawRecord, 494 &TypeLength, 495 &TypeLengthByte, 496 &PayloadLengthByte, 497 &PayloadLength, 498 &IDLengthByte, 499 &IDLength); 500 Record->TypeLength = TypeLength; 501 Record->PayloadLength = PayloadLength; 502 Record->IdLength = IDLength; 503 RawRecord = (RawRecord + PayloadLengthByte + IDLengthByte + TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); 504 Record->Type = RawRecord; 505 506 RawRecord = (RawRecord + Record->TypeLength); 507 508 if (Record->IdLength != 0) 509 { 510 Record->Id = RawRecord; 511 } 512 513 RawRecord = RawRecord + Record->IdLength; 514 Record->PayloadData = RawRecord; 515 } 516 else 517 { 518 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 519 NFCSTATUS_INVALID_PARAMETER); 520 } 521 } 522 return Status; 523 } 524 525 526 527 /*! 528 * The function writes one NDEF record to a specified memory location. Called within a loop, it is possible to 529 * write more records into a contiguous buffer, in each cycle advancing by the number of bytes written for 530 * each record. 531 * 532 * \param[in] Record The Array of NDEF record structures to append. The structures 533 * have to be filled by the caller matching the requirements for 534 * \b Composition, as described in the documentation of 535 * the \ref phFriNfc_NdefRecord_t "NDEF Record" structure. 536 * \param[in] Buffer The pointer to the buffer. 537 * \param[in] MaxBufferSize The data buffer's maximum size, provided by the caller. 538 * \param[out] BytesWritten The actual number of bytes written to the buffer. This can be used by 539 * the caller to serialise more than one record into the same buffer before 540 * handing it over to another instance. 541 * 542 * \retval NFCSTATUS_SUCCESS Operation successful. 543 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. 544 * \retval NFCSTATUS_BUFFER_TOO_SMALL The data buffer, provided by the caller is to small to 545 * hold the composed NDEF record. The existing content is not changed. 546 * 547 */ 548 NFCSTATUS phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t *Record, 549 uint8_t *Buffer, 550 uint32_t MaxBufferSize, 551 uint32_t *BytesWritten) 552 { 553 uint8_t FlagCheck, 554 TypeCheck=0, 555 *temp, 556 i; 557 uint32_t i_data=0; 558 559 if(Record==NULL ||Buffer==NULL||BytesWritten==NULL||MaxBufferSize == 0) 560 { 561 return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER)); 562 } 563 564 if (Record->Tnf == PH_FRINFC_NDEFRECORD_TNF_RESERVED) 565 { 566 return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_FORMAT)); 567 } 568 569 /* calculate the length of the record and check with the buffersize if it exceeds return */ 570 i_data=phFriNfc_NdefRecord_GetLength(Record); 571 if(i_data > MaxBufferSize) 572 { 573 return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_BUFFER_TOO_SMALL)); 574 } 575 *BytesWritten = i_data; 576 577 /*fill the first byte of the message(all the flags) */ 578 /*increment the buffer*/ 579 *Buffer = ( (Record->Flags & PH_FRINFC_NDEFRECORD_FLAG_MASK) | (Record->Tnf & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)); 580 Buffer++; 581 582 /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_EMPTY */ 583 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); 584 if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_EMPTY) 585 { 586 /* fill the typelength idlength and payloadlength with zero(empty message)*/ 587 for(i=0;i<3;i++) 588 { 589 *Buffer=PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE; 590 Buffer++; 591 } 592 return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS)); 593 } 594 595 /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_RESERVED */ 596 /* TNF should not be reserved one*/ 597 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); 598 if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_RESERVED) 599 { 600 return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER)); 601 } 602 603 /* check for TNF Unknown or Unchanged */ 604 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); 605 if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNKNOWN || \ 606 FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) 607 { 608 *Buffer = PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE; 609 Buffer++; 610 } 611 else 612 { 613 *Buffer = Record->TypeLength; 614 Buffer++; 615 TypeCheck=1; 616 } 617 618 /* check for the short record bit if it is then payloadlength is only one byte */ 619 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); 620 if(FlagCheck!=0) 621 { 622 *Buffer = (uint8_t)(Record->PayloadLength & 0x000000ff); 623 Buffer++; 624 } 625 else 626 { 627 /* if it is normal record payloadlength is 4 byte(32 bit)*/ 628 *Buffer = (uint8_t)((Record->PayloadLength & 0xff000000) >> PHNFCSTSHL24); 629 Buffer++; 630 *Buffer = (uint8_t)((Record->PayloadLength & 0x00ff0000) >> PHNFCSTSHL16); 631 Buffer++; 632 *Buffer = (uint8_t)((Record->PayloadLength & 0x0000ff00) >> PHNFCSTSHL8); 633 Buffer++; 634 *Buffer = (uint8_t)((Record->PayloadLength & 0x000000ff)); 635 Buffer++; 636 } 637 638 /*check for IL bit set(Flag), if so then IDlength is present*/ 639 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); 640 if(FlagCheck!=0) 641 { 642 *Buffer=Record->IdLength; 643 Buffer++; 644 } 645 646 /*check for TNF and fill the Type*/ 647 temp=Record->Type; 648 if(TypeCheck!=0) 649 { 650 for(i=0;i<(Record->TypeLength);i++) 651 { 652 *Buffer = *temp; 653 Buffer++; 654 temp++; 655 } 656 } 657 658 /*check for IL bit set(Flag), if so then IDlength is present and fill the ID*/ 659 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); 660 temp=Record->Id; 661 if(FlagCheck!=0) 662 { 663 for(i=0;i<(Record->IdLength);i++) 664 { 665 *Buffer = *temp; 666 Buffer++; 667 temp++; 668 } 669 } 670 671 temp=Record->PayloadData; 672 /*check for SR bit and then correspondingly use the payload length*/ 673 FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); 674 for(i_data=0;i_data < (Record->PayloadLength) ;i_data++) 675 { 676 *Buffer = *temp; 677 Buffer++; 678 temp++; 679 } 680 681 return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS)); 682 } 683 684 /* Calculate the Flags of the record */ 685 static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t *Record) 686 { 687 uint8_t flag = 0; 688 689 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB ) 690 { 691 flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_MB; 692 } 693 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_ME) == PH_FRINFC_NDEFRECORD_FLAGS_ME ) 694 { 695 flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_ME; 696 } 697 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF ) 698 { 699 flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_CF; 700 } 701 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR ) 702 { 703 flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_SR; 704 } 705 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL ) 706 { 707 flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_IL; 708 } 709 return flag; 710 } 711 712 /* Calculate the Type Name Format for the record */ 713 static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t *Record) 714 { 715 uint8_t tnf = 0; 716 717 switch (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) 718 { 719 case PH_FRINFC_NDEFRECORD_TNF_EMPTY: 720 tnf = PH_FRINFC_NDEFRECORD_TNF_EMPTY; 721 break; 722 723 case PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN: 724 tnf = PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN; 725 break; 726 727 case PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE: 728 tnf = PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE; 729 break; 730 731 case PH_FRINFC_NDEFRECORD_TNF_ABSURI: 732 tnf = PH_FRINFC_NDEFRECORD_TNF_ABSURI; 733 break; 734 735 case PH_FRINFC_NDEFRECORD_TNF_NFCEXT: 736 tnf = PH_FRINFC_NDEFRECORD_TNF_NFCEXT; 737 break; 738 739 case PH_FRINFC_NDEFRECORD_TNF_UNKNOWN: 740 tnf = PH_FRINFC_NDEFRECORD_TNF_UNKNOWN; 741 break; 742 743 case PH_FRINFC_NDEFRECORD_TNF_UNCHANGED: 744 tnf = PH_FRINFC_NDEFRECORD_TNF_UNCHANGED; 745 break; 746 747 case PH_FRINFC_NDEFRECORD_TNF_RESERVED: 748 tnf = PH_FRINFC_NDEFRECORD_TNF_RESERVED; 749 break; 750 default : 751 tnf = 0xFF; 752 break; 753 } 754 755 return tnf; 756 } 757 758 759 static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t *Record, 760 uint8_t *TypeLength, 761 uint8_t *TypeLengthByte, 762 uint8_t *PayloadLengthByte, 763 uint32_t *PayloadLength, 764 uint8_t *IDLengthByte, 765 uint8_t *IDLength) 766 { 767 NFCSTATUS Status = NFCSTATUS_SUCCESS; 768 769 /* Check for Tnf bits 0x07 is reserved for future use */ 770 if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == 771 PH_FRINFC_NDEFRECORD_TNF_RESERVED) 772 { 773 /* TNF 07 Error */ 774 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 775 NFCSTATUS_INVALID_FORMAT); 776 return Status; 777 } 778 779 /* Check for Type Name Format depending on the TNF, Type Length value is set*/ 780 if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== 781 PH_FRINFC_NDEFRECORD_TNF_EMPTY) 782 { 783 *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1); 784 785 if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0) 786 { 787 /* Type Length Error */ 788 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 789 NFCSTATUS_INVALID_FORMAT); 790 return Status; 791 } 792 793 *TypeLengthByte = 1; 794 795 /* Check for Short Record */ 796 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR) 797 { 798 /* For Short Record, Payload Length Byte is 1 */ 799 *PayloadLengthByte = 1; 800 /* 1 for Header byte */ 801 *PayloadLength = *(Record + *TypeLengthByte + 1); 802 if (*PayloadLength != 0) 803 { 804 /* PayloadLength Error */ 805 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 806 NFCSTATUS_INVALID_FORMAT); 807 return Status; 808 } 809 } 810 else 811 { 812 /* For Normal Record, Payload Length Byte is 4 */ 813 *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE; 814 *PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) + 815 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) + 816 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) + 817 *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5)); 818 if (*PayloadLength != 0) 819 { 820 /* PayloadLength Error */ 821 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 822 NFCSTATUS_INVALID_FORMAT); 823 return Status; 824 } 825 } 826 827 /* Check for ID Length existence */ 828 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL) 829 { 830 /* Length Byte exists and it is 1 byte */ 831 *IDLengthByte = 1; 832 /* 1 for Header byte */ 833 *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); 834 if (*IDLength != 0) 835 { 836 /* IDLength Error */ 837 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 838 NFCSTATUS_INVALID_FORMAT); 839 return Status; 840 } 841 } 842 else 843 { 844 *IDLengthByte = 0; 845 *IDLength = 0; 846 } 847 } 848 else 849 { 850 if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== PH_FRINFC_NDEFRECORD_TNF_UNKNOWN 851 || (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == 852 PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) 853 { 854 if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0) 855 { 856 /* Type Length Error */ 857 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, 858 NFCSTATUS_INVALID_FORMAT); 859 return Status; 860 } 861 *TypeLength = 0; 862 *TypeLengthByte = 1; 863 } 864 else 865 { 866 /* 1 for Header byte */ 867 *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1); 868 *TypeLengthByte = 1; 869 } 870 871 /* Check for Short Record */ 872 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == 873 PH_FRINFC_NDEFRECORD_FLAGS_SR) 874 { 875 /* For Short Record, Payload Length Byte is 1 */ 876 *PayloadLengthByte = 1; 877 /* 1 for Header byte */ 878 *PayloadLength = *(Record + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); 879 } 880 else 881 { 882 /* For Normal Record, Payload Length Byte is 4 */ 883 *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE; 884 *PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) + 885 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) + 886 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) + 887 *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5)); 888 } 889 890 /* Check for ID Length existence */ 891 if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == 892 PH_FRINFC_NDEFRECORD_FLAGS_IL) 893 { 894 *IDLengthByte = 1; 895 /* 1 for Header byte */ 896 *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); 897 } 898 else 899 { 900 *IDLengthByte = 0; 901 *IDLength = 0; 902 } 903 } 904 return Status; 905 } 906 907