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 */
phFriNfc_NdefRecord_GetRecords(uint8_t * Buffer,uint32_t BufferLength,uint8_t * RawRecords[],uint8_t IsChunked[],uint32_t * NumberOfRawRecords)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 */
phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask)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
phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t * Record)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 */
phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t * Record,uint8_t * RawRecord)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 */
phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t * Record,uint8_t * Buffer,uint32_t MaxBufferSize,uint32_t * BytesWritten)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 */
phFriNfc_NdefRecord_RecordFlag(uint8_t * 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 */
phFriNfc_NdefRecord_TypeNameFormat(uint8_t * 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
phFriNfc_NdefRecord_RecordIDCheck(uint8_t * Record,uint8_t * TypeLength,uint8_t * TypeLengthByte,uint8_t * PayloadLengthByte,uint32_t * PayloadLength,uint8_t * IDLengthByte,uint8_t * IDLength)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