Initialize Tizen 2.3
[adaptation/devices/nfc-plugin-nxp.git] / src / phFriNfc_NdefRecord.c
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         /* For Each Record Check whether it contains the ME bit set and CF bit Set
187             if YES return ERROR*/
188         if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
189                     PH_FRINFC_NDEFRECORD_FLAGS_CF  &&
190             (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
191              PH_FRINFC_NDEFRECORD_FLAGS_ME)
192         {
193             /* CF and ME Error */
194             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
195                     NFCSTATUS_INVALID_FORMAT);
196             break;
197         }
198
199         if (NoOfRecordsReturnFlag == 0)
200         {
201             /*  Harsha: Fix for 0000241: [gk], NDEF Tools: GetRecords() overshoots
202                 a given array boundary if the number of records != 0. */
203             /*  Actual Number of Records should not exceed Number of records
204                 required by caller*/
205             if(Count >= *NumberOfRawRecords)
206             {
207                 break;
208             }
209             /* To fix the mantis entry 0388 */
210             if(RawRecords!=NULL)/*QMOR FIX*/
211             {
212                 RawRecords[Count] = Buffer;
213             }
214             else
215             {
216                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
217                                     NFCSTATUS_INVALID_PARAMETER);
218                 break;
219             }
220         }
221
222         /* To Calculate the IDLength and PayloadLength for
223             short or normal record */
224         Status = phFriNfc_NdefRecord_RecordIDCheck (    Buffer,
225                                                         &TypeLength,
226                                                         &TypeLengthByte,
227                                                         &PayloadLengthByte,
228                                                         &PayloadLength,
229                                                         &IDLengthByte,
230                                                         &IDLength);
231         if (Status != NFCSTATUS_SUCCESS)
232         {
233             break;
234         }
235
236         /* Check for the Chunk Flag */
237         if (NoOfRecordsReturnFlag == 0)
238         {
239             /*  If NoOfRecordsReturnFlag = 0, that means we have enough space  */
240             /*  in the array IsChunked, to write  */
241             if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) ==
242                 PH_FRINFC_NDEFRECORD_FLAGS_CF)
243             {
244                 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET;
245             }
246             else
247             {
248                 IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO;
249             }
250         }
251
252         /* Check the record is not the first record */
253         if (Count > 0)
254         {
255             /* Not a first record, if chunk record is present and IL bit is set
256                 also if the MB bit is set */
257             if(((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF &&
258                 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL &&
259                 (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) ||
260                 (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB)
261             {
262                 /* IL or MB Error */
263                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
264                                     NFCSTATUS_INVALID_FORMAT);
265                 break;
266             }
267
268             /* Check for the Chunk Flag */
269             if (NoOfRecordsReturnFlag == 0)
270             {
271                 /*  If NoOfRecordsReturnFlag = 0, that means the array IsChunked
272                     contains valid values. So, cannot check the value
273                     of IsChunked if NoOfRecordsReturnFlag = 1.  */
274
275                 /*  Check whether the previous record has the chunk flag and
276                     TNF of present record is not 0x06 */
277                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
278                     (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) !=
279                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
280                 {
281                     /* CF or TNF  Error */
282                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
283                                         NFCSTATUS_INVALID_FORMAT);
284                     break;
285                 }
286
287                 /*  Check whether the previous record doesnot have the chunk flag and
288                     TNF of present record is 0x06 */
289                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO &&
290                     (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
291                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
292                 {
293                     /* CF or TNF  Error */
294                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
295                                         NFCSTATUS_INVALID_FORMAT);
296                     break;
297                 }
298
299                 /* Check for the last chunk */
300                 if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET &&
301                     IsChunked [Count] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO)
302                 {
303                     /* Check for the TypeLength, IDLength = 0 */
304                     if (TypeLength != 0 || IDLength != 0)
305                     {
306                         /* last chunk record Error */
307                         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
308                                             NFCSTATUS_INVALID_FORMAT);
309                         break;
310                     }
311                 }
312             }   /*  if (NoOfRecordsReturnFlag == 0)  */
313         }   /*  if (Count > 0)  */
314
315         /*  Calculate the bytes already traversed. */
316         BytesTraversed = (BytesTraversed + PayloadLengthByte + IDLengthByte + TypeLength
317                          + IDLength + TypeLengthByte + PayloadLength
318                          + PH_FRINFC_NDEFRECORD_BUF_INC1);
319
320         if(BytesTraversed == BufferLength)
321         {
322             /*  We have reached the last record, and everything is fine.  */
323             /*  Check for the ME Byte */
324             if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
325                 PH_FRINFC_NDEFRECORD_FLAGS_ME)
326             {
327                 Count++;
328                 break;
329             }
330             else
331             {
332                 /* Each message must have ME flag in the last record, Since
333                 ME is not set raise an error */
334                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
335                 NFCSTATUS_INVALID_FORMAT);
336                 break;
337             }
338         }
339        else
340         {
341             /* Buffer Overshoot: Inconsistency in the message length
342               and actual value of the bytes in the message detected.
343               Report error.*/
344             if(BytesTraversed > BufferLength)
345             {
346                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
347                                 NFCSTATUS_INVALID_FORMAT);
348                 break;
349             }
350         }
351         /*  For Each Record Check whether it contains the ME bit set
352             if YES return*/
353         if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) ==
354             PH_FRINFC_NDEFRECORD_FLAGS_ME)
355         {
356             Count++;
357             break;
358         }
359
360         /* +1 is for first byte */
361         Buffer = (Buffer + PayloadLengthByte + IDLengthByte + TypeLength
362                  + TypeLengthByte + IDLength + PayloadLength
363                  + PH_FRINFC_NDEFRECORD_BUF_INC1);
364
365         /*  Increment the number of valid records found in the message  */
366         Count++;
367     }
368
369     /*  Whatever is the error, update the NumberOfRawRecords with the number
370         of proper records found till the error was detected in the message. */
371     *NumberOfRawRecords = Count;
372     return Status;
373 }
374
375 /* to check the bitfields in the Flags Byte and return the status flag */
376 static uint8_t phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask)
377 {
378     uint8_t check_flag = 0x00;
379     check_flag = Flags & Mask;
380     return check_flag;
381 }
382
383 uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t *Record)
384 {
385     uint32_t RecordLength=1;
386     uint8_t  FlagCheck=0;
387
388     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
389     /* Type length is present only for following TNF
390                     PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN
391                     PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE
392                     PH_FRINFC_NDEFRECORD_TNF_ABSURI
393                     PH_FRINFC_NDEFRECORD_TNF_NFCEXT
394     */
395
396     /* ++ is for the Type Length Byte */
397     RecordLength++;
398     if( FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY &&
399         FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN &&
400         FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNCHANGED )
401     {
402         RecordLength += Record->TypeLength;
403     }
404
405     /* to check if payloadlength is 8bit or 32bit*/
406     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
407     if(FlagCheck!=0)
408     {
409         /* ++ is for the Payload Length Byte */
410         RecordLength++;/* for short record*/
411     }
412     else
413     {
414         /* + PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE is for the Payload Length Byte */
415         RecordLength += PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;/* for normal record*/
416     }
417
418     /* for non empty record */
419     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
420     if(FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY)
421     {
422         RecordLength += Record->PayloadLength;
423     }
424
425     /* ID and IDlength are present only if IL flag is set*/
426     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
427     if(FlagCheck!=0)
428     {
429         RecordLength +=Record->IdLength;
430         /* ++ is for the ID Length Byte */
431         RecordLength ++;
432     }
433     return RecordLength;
434 }
435
436 /*!
437  *
438  *  Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding
439  *  at least the entire NDEF record (received via the NFC link, for example).
440  *
441  * \param[out] Record               The NDEF record structure. The storage for the structure has to be provided by the
442  *                                  caller matching the requirements for \b Extraction, as described in the compound
443  *                                  documentation.
444  * \param[in]  RawRecord            The Pointer to the buffer, selected out of the array returned by
445  *                                  the \ref phFriNfc_NdefRecord_GetRecords function.
446  *
447  * \retval NFCSTATUS_SUCCESS                Operation successful.
448  * \retval NFCSTATUS_INVALID_PARAMETER      At least one parameter of the function is invalid.
449  *
450  * \note There are some caveats:
451  *       - The "RawRecord" Data buffer must exist at least as long as the function execution time plus the time
452  *         needed by the caller to evaluate the extracted information. No copying of the contained data is done.
453  *       - Using the "RawRecord" and "RawRecordMaxSize" parameters the function internally checks whether the
454  *         data to extract are within the bounds of the buffer.
455  *
456  *
457  */
458 NFCSTATUS phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t *Record,
459                                     uint8_t               *RawRecord)
460 {
461     NFCSTATUS       Status = NFCSTATUS_SUCCESS;
462     uint8_t         PayloadLengthByte = 0,
463                     TypeLengthByte = 0,
464                     TypeLength = 0,
465                     IDLengthByte = 0,
466                     IDLength = 0,
467                     Tnf     =   0;
468     uint32_t        PayloadLength = 0;
469
470     if (Record == NULL || RawRecord == NULL)
471     {
472         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
473                             NFCSTATUS_INVALID_PARAMETER);
474     }
475
476     else
477     {
478
479         /* Calculate the Flag Value */
480         Record->Flags = phFriNfc_NdefRecord_RecordFlag ( RawRecord);
481
482         /* Calculate the Type Namr format of the record */
483         Tnf = phFriNfc_NdefRecord_TypeNameFormat( RawRecord);
484         if(Tnf != 0xFF)
485         {
486             Record->Tnf = Tnf;
487             /* To Calculate the IDLength and PayloadLength for short or normal record */
488             Status = phFriNfc_NdefRecord_RecordIDCheck (    RawRecord,
489                                                             &TypeLength,
490                                                             &TypeLengthByte,
491                                                             &PayloadLengthByte,
492                                                             &PayloadLength,
493                                                             &IDLengthByte,
494                                                             &IDLength);
495             Record->TypeLength = TypeLength;
496             Record->PayloadLength = PayloadLength;
497             Record->IdLength = IDLength;
498             RawRecord = (RawRecord +  PayloadLengthByte + IDLengthByte + TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
499             Record->Type = RawRecord;
500
501             RawRecord = (RawRecord + Record->TypeLength);
502
503             if (Record->IdLength != 0)
504             {
505                 Record->Id = RawRecord;
506             }
507
508             RawRecord = RawRecord + Record->IdLength;
509             Record->PayloadData = RawRecord;
510         }
511         else
512         {
513             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
514                                 NFCSTATUS_INVALID_PARAMETER);
515         }
516     }
517     return Status;
518 }
519
520
521
522 /*!
523  *  The function writes one NDEF record to a specified memory location. Called within a loop, it is possible to
524  *  write more records into a contiguous buffer, in each cycle advancing by the number of bytes written for
525  *  each record.
526  *
527  * \param[in]     Record             The Array of NDEF record structures to append. The structures
528  *                                   have to be filled by the caller matching the requirements for
529  *                                   \b Composition, as described in the documentation of
530  *                                   the \ref phFriNfc_NdefRecord_t "NDEF Record" structure.
531  * \param[in]     Buffer             The pointer to the buffer.
532  * \param[in]     MaxBufferSize      The data buffer's maximum size, provided by the caller.
533  * \param[out]    BytesWritten       The actual number of bytes written to the buffer. This can be used by
534  *                                   the caller to serialise more than one record into the same buffer before
535  *                                   handing it over to another instance.
536  *
537  * \retval NFCSTATUS_SUCCESS                  Operation successful.
538  * \retval NFCSTATUS_INVALID_PARAMETER        At least one parameter of the function is invalid.
539  * \retval NFCSTATUS_BUFFER_TOO_SMALL         The data buffer, provided by the caller is to small to
540  *                                            hold the composed NDEF record. The existing content is not changed.
541  *
542  */
543  NFCSTATUS phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t *Record,
544                                         uint8_t               *Buffer,
545                                         uint32_t               MaxBufferSize,
546                                         uint32_t              *BytesWritten)
547 {
548     uint8_t     FlagCheck,
549                 TypeCheck=0,
550                 *temp,
551                 i;
552     uint32_t    i_data=0;
553
554     if(Record==NULL ||Buffer==NULL||BytesWritten==NULL||MaxBufferSize == 0)
555     {
556         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
557     }
558
559     if (Record->Tnf == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
560     {
561         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_FORMAT));
562     }
563
564      /* calculate the length of the record and check with the buffersize if it exceeds return */
565     i_data=phFriNfc_NdefRecord_GetLength(Record);
566     if(i_data > MaxBufferSize)
567     {
568         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_BUFFER_TOO_SMALL));
569     }
570     *BytesWritten = i_data;
571
572     /*fill the first byte of the message(all the flags) */
573     /*increment the buffer*/
574     *Buffer = ( (Record->Flags & PH_FRINFC_NDEFRECORD_FLAG_MASK) | (Record->Tnf & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK));
575     Buffer++;
576
577     /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_EMPTY */
578     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
579     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_EMPTY)
580     {
581         /* fill the typelength idlength and payloadlength with zero(empty message)*/
582         for(i=0;i<3;i++)
583         {
584             *Buffer=PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
585             Buffer++;
586         }
587         return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
588      }
589
590     /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_RESERVED */
591     /* TNF should not be reserved one*/
592     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
593     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_RESERVED)
594     {
595         return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER));
596     }
597
598     /* check for TNF Unknown or Unchanged */
599     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK);
600     if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNKNOWN || \
601         FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
602     {
603         *Buffer = PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE;
604         Buffer++;
605     }
606     else
607     {
608         *Buffer = Record->TypeLength;
609         Buffer++;
610         TypeCheck=1;
611     }
612
613     /* check for the short record bit if it is then payloadlength is only one byte */
614     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
615     if(FlagCheck!=0)
616     {
617         *Buffer = (uint8_t)(Record->PayloadLength & 0x000000ff);
618         Buffer++;
619     }
620     else
621     {
622         /* if it is normal record payloadlength is 4 byte(32 bit)*/
623         *Buffer = (uint8_t)((Record->PayloadLength & 0xff000000) >> PHNFCSTSHL24);
624         Buffer++;
625         *Buffer = (uint8_t)((Record->PayloadLength & 0x00ff0000) >> PHNFCSTSHL16);
626         Buffer++;
627         *Buffer = (uint8_t)((Record->PayloadLength & 0x0000ff00) >> PHNFCSTSHL8);
628         Buffer++;
629         *Buffer = (uint8_t)((Record->PayloadLength & 0x000000ff));
630         Buffer++;
631     }
632
633     /*check for IL bit set(Flag), if so then IDlength is present*/
634     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
635     if(FlagCheck!=0)
636     {
637         *Buffer=Record->IdLength;
638         Buffer++;
639     }
640
641     /*check for TNF and fill the Type*/
642     temp=Record->Type;
643     if(TypeCheck!=0)
644     {
645         for(i=0;i<(Record->TypeLength);i++)
646         {
647             *Buffer = *temp;
648             Buffer++;
649             temp++;
650         }
651     }
652
653     /*check for IL bit set(Flag), if so then IDlength is present and fill the ID*/
654     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL);
655     temp=Record->Id;
656     if(FlagCheck!=0)
657     {
658         for(i=0;i<(Record->IdLength);i++)
659         {
660             *Buffer = *temp;
661             Buffer++;
662             temp++;
663         }
664     }
665
666     temp=Record->PayloadData;
667     /*check for SR bit and then correspondingly use the payload length*/
668     FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR);
669     for(i_data=0;i_data < (Record->PayloadLength) ;i_data++)
670     {
671         *Buffer = *temp;
672         Buffer++;
673         temp++;
674     }
675
676     return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS));
677 }
678
679 /* Calculate the Flags of the record */
680 static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t    *Record)
681 {
682     uint8_t flag = 0;
683
684     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB )
685     {
686         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_MB;
687     }
688     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_ME) == PH_FRINFC_NDEFRECORD_FLAGS_ME )
689     {
690         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_ME;
691     }
692     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF )
693     {
694         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_CF;
695     }
696     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR )
697     {
698         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_SR;
699     }
700     if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL )
701     {
702         flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_IL;
703     }
704     return flag;
705 }
706
707 /* Calculate the Type Name Format for the record */
708 static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t    *Record)
709 {
710     uint8_t     tnf = 0xFF;
711
712     switch (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)
713     {
714     case PH_FRINFC_NDEFRECORD_TNF_EMPTY:
715         tnf = PH_FRINFC_NDEFRECORD_TNF_EMPTY;
716         break;
717
718     case PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN:
719         tnf = PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN;
720         break;
721
722     case PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE:
723         tnf = PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE;
724         break;
725
726     case PH_FRINFC_NDEFRECORD_TNF_ABSURI:
727         tnf = PH_FRINFC_NDEFRECORD_TNF_ABSURI;
728         break;
729
730     case PH_FRINFC_NDEFRECORD_TNF_NFCEXT:
731         tnf = PH_FRINFC_NDEFRECORD_TNF_NFCEXT;
732         break;
733
734     case PH_FRINFC_NDEFRECORD_TNF_UNKNOWN:
735         tnf = PH_FRINFC_NDEFRECORD_TNF_UNKNOWN;
736         break;
737
738     case PH_FRINFC_NDEFRECORD_TNF_UNCHANGED:
739         tnf = PH_FRINFC_NDEFRECORD_TNF_UNCHANGED;
740         break;
741
742     case PH_FRINFC_NDEFRECORD_TNF_RESERVED:
743         tnf = PH_FRINFC_NDEFRECORD_TNF_RESERVED;
744         break;
745     }
746
747     return tnf;
748 }
749
750
751 static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t       *Record,
752                                               uint8_t       *TypeLength,
753                                               uint8_t       *TypeLengthByte,
754                                               uint8_t       *PayloadLengthByte,
755                                               uint32_t      *PayloadLength,
756                                               uint8_t       *IDLengthByte,
757                                               uint8_t       *IDLength)
758 {
759     NFCSTATUS   Status = NFCSTATUS_SUCCESS;
760
761     /* Check for Tnf bits 0x07 is reserved for future use */
762     if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
763         PH_FRINFC_NDEFRECORD_TNF_RESERVED)
764     {
765         /* TNF 07  Error */
766         Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
767                             NFCSTATUS_INVALID_FORMAT);
768         return Status;
769     }
770
771     /* Check for Type Name Format  depending on the TNF,  Type Length value is set*/
772     if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)==
773         PH_FRINFC_NDEFRECORD_TNF_EMPTY)
774     {
775         *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
776
777         if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
778         {
779             /* Type Length  Error */
780             Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
781                                 NFCSTATUS_INVALID_FORMAT);
782             return Status;
783         }
784
785         *TypeLengthByte = 1;
786
787         /* Check for Short Record */
788         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR)
789         {
790             /* For Short Record, Payload Length Byte is 1 */
791             *PayloadLengthByte = 1;
792             /*  1 for Header byte */
793             *PayloadLength = *(Record + *TypeLengthByte + 1);
794             if (*PayloadLength != 0)
795             {
796                 /* PayloadLength  Error */
797                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
798                                     NFCSTATUS_INVALID_FORMAT);
799                 return Status;
800             }
801         }
802         else
803         {
804             /* For Normal Record, Payload Length Byte is 4 */
805             *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
806             *PayloadLength =    ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
807                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
808                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8)  +
809                                              *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
810             if (*PayloadLength != 0)
811             {
812                 /* PayloadLength  Error */
813                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
814                                     NFCSTATUS_INVALID_FORMAT);
815                 return Status;
816             }
817         }
818
819         /* Check for ID Length existence */
820         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL)
821         {
822             /* Length Byte exists and it is 1 byte */
823             *IDLengthByte = 1;
824             /*  1 for Header byte */
825             *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
826             if (*IDLength != 0)
827             {
828                 /* IDLength  Error */
829                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
830                                     NFCSTATUS_INVALID_FORMAT);
831                 return Status;
832             }
833         }
834         else
835         {
836             *IDLengthByte = 0;
837             *IDLength = 0;
838         }
839     }
840     else
841     {
842         if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== PH_FRINFC_NDEFRECORD_TNF_UNKNOWN
843                 || (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) ==
844                     PH_FRINFC_NDEFRECORD_TNF_UNCHANGED)
845         {
846             if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0)
847             {
848                 /* Type Length  Error */
849                 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD,
850                             NFCSTATUS_INVALID_FORMAT);
851                 return Status;
852             }
853             *TypeLength = 0;
854             *TypeLengthByte = 1;
855         }
856         else
857         {
858             /*  1 for Header byte */
859             *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1);
860             *TypeLengthByte = 1;
861         }
862
863         /* Check for Short Record */
864         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) ==
865                 PH_FRINFC_NDEFRECORD_FLAGS_SR)
866         {
867             /* For Short Record, Payload Length Byte is 1 */
868             *PayloadLengthByte = 1;
869             /*  1 for Header byte */
870             *PayloadLength = *(Record + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
871         }
872         else
873         {
874             /* For Normal Record, Payload Length Byte is 4 */
875             *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;
876             *PayloadLength =    ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) +
877                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) +
878                                 (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8)  +
879                                              *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5));
880         }
881
882         /* Check for ID Length existence */
883         if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) ==
884                 PH_FRINFC_NDEFRECORD_FLAGS_IL)
885         {
886             *IDLengthByte = 1;
887             /*  1 for Header byte */
888             *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1);
889         }
890         else
891         {
892             *IDLengthByte = 0;
893             *IDLength = 0;
894         }
895     }
896     return Status;
897 }
898